Skip to content

Commit 1348bcd

Browse files
feat(web): sync provider accounts to other devices from Providers settings
Settings > Providers gains a "Sync accounts" button, a "Sync to…" action on each account, and a settings-search entry. The dialog picks accounts and devices, then shows each copy's live state on the other device with a link that opens its provider editor to finish sign-in there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 61972b9 commit 1348bcd

5 files changed

Lines changed: 477 additions & 0 deletions

File tree

‎apps/web/src/components/settings/ProviderInstanceCard.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ interface ProviderInstanceCardProps {
576576
readonly onUpdate: (nextInstance: ProviderInstanceConfig) => void;
577577
readonly onDelete?: (() => void) | undefined;
578578
readonly headerAction?: ReactNode | undefined;
579+
readonly syncAction?: ReactNode;
579580
readonly setup?: ReactNode;
580581
readonly runtime?: ReactNode;
581582
readonly hiddenModels: ReadonlyArray<string>;
@@ -627,6 +628,7 @@ export function ProviderInstanceCard({
627628
onUpdate,
628629
onDelete,
629630
headerAction,
631+
syncAction,
630632
setup,
631633
runtime,
632634
hiddenModels,
@@ -1075,6 +1077,7 @@ export function ProviderInstanceCard({
10751077
className={cn("inline-flex items-center gap-1", readOnly && "opacity-50")}
10761078
>
10771079
{titleTailNode}
1080+
{syncAction}
10781081
{onDelete ? (
10791082
<Button
10801083
type="button"

‎apps/web/src/components/settings/ProviderSettingsPanel.tsx‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import { stackedThreadToast, toastManager } from "../ui/toast";
9898
import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog";
9999
import { ExpandableText } from "./ExpandableText";
100100
import { ProviderInstanceCard } from "./ProviderInstanceCard";
101+
import { SyncProviderAccountsAction } from "./SyncProviderAccountsDialog";
101102
import { UsageProviderSettings } from "./UsageProviderSettings";
102103
import { ProviderSetupSection, readAntigravityAuthMethod } from "./ProviderSetupSection";
103104
import { ProviderAuthenticationSection } from "./ProviderAuthenticationSection";
@@ -1012,6 +1013,7 @@ export function EnvironmentProviderSettings({
10121013
}
10131014
headerAction={
10141015
<div className="flex min-w-0 items-center gap-2">
1016+
<SyncProviderAccountsAction sourceEnvironmentId={environmentId} readOnly={readOnly} />
10151017
<ProviderUpdatesAction />
10161018
<Tooltip>
10171019
<TooltipTrigger
@@ -1409,6 +1411,15 @@ function ProviderInstanceRow({
14091411
? () => actions.deleteInstance(instanceId, instance)
14101412
: undefined
14111413
}
1414+
syncAction={
1415+
mode === "editor" ? (
1416+
<SyncProviderAccountsAction
1417+
sourceEnvironmentId={environmentId}
1418+
readOnly={readOnly}
1419+
instanceIds={[instanceId]}
1420+
/>
1421+
) : undefined
1422+
}
14121423
headerAction={
14131424
mode === "editor" && isDefault && isDirty ? (
14141425
<SettingResetButton

0 commit comments

Comments
 (0)