diff --git a/src/renderer/src/components/dashboard/AgentDashboardExperimentalSetting.tsx b/src/renderer/src/components/dashboard/AgentDashboardExperimentalSetting.tsx index 0d87a50538c..c3eebc3c1ed 100644 --- a/src/renderer/src/components/dashboard/AgentDashboardExperimentalSetting.tsx +++ b/src/renderer/src/components/dashboard/AgentDashboardExperimentalSetting.tsx @@ -32,7 +32,7 @@ export function AgentDashboardExperimentalSetting({ 'Kanban board for monitoring agents across worktrees, in-window or as a pop-out.' )} keywords={getExperimentalSearchEntry().agentDashboard.keywords} - className="space-y-3 py-2" + className="space-y-3 py-3" id="experimental-agent-dashboard" >
diff --git a/src/renderer/src/components/settings/accounts/AccountsPane.tsx b/src/renderer/src/components/settings/accounts/AccountsPane.tsx index 68d35e3676f..0cc92a621d8 100644 --- a/src/renderer/src/components/settings/accounts/AccountsPane.tsx +++ b/src/renderer/src/components/settings/accounts/AccountsPane.tsx @@ -385,7 +385,7 @@ export function AccountsPane({ return (
{renderAccountsRemovalDialogs(model, removeCodexTarget, removeClaudeTarget)} - +
) } diff --git a/src/renderer/src/components/settings/accounts/claude/accounts-pane-claude-section.tsx b/src/renderer/src/components/settings/accounts/claude/accounts-pane-claude-section.tsx index 6ea0e74a4c9..66c2cd00294 100644 --- a/src/renderer/src/components/settings/accounts/claude/accounts-pane-claude-section.tsx +++ b/src/renderer/src/components/settings/accounts/claude/accounts-pane-claude-section.tsx @@ -29,6 +29,7 @@ import { cancelAccountAddition, trackAccountAddition } from '../sign-in/account-add-cancel-target' +import { SettingsGroup } from '../../section-layout/SettingsGroup' export function renderClaudeAccountsSection(model: AccountsPaneSectionModel): React.JSX.Element { const { @@ -78,317 +79,321 @@ export function renderClaudeAccountsSection(model: AccountsPaneSectionModel): Re ) ) return ( -
-
-

- - {translate('auto.components.settings.AccountsPane.26ef4b55be', 'Claude')} -

-

- {translate( - 'auto.components.settings.AccountsPane.72b36ea174', - 'Optional. Orca can use your normal Claude login; add accounts only if you want quick switching without moving chat sessions.' - )} -

-
- - + + + {translate('auto.components.settings.AccountsPane.26ef4b55be', 'Claude')} + + } description={translate( - 'accounts.claude.profileSwitching', - 'Switching applies to the next Claude you start in any tab.' + 'auto.components.settings.AccountsPane.72b36ea174', + 'Optional. Orca can use your normal Claude login; add accounts only if you want quick switching without moving chat sessions.' )} - keywords={['claude', 'account', 'rate limit', 'status bar', 'quota']} - className="space-y-3 py-2" > -
-
- -

- {isRemoteAccountScope - ? translate( - 'accounts.remoteScopeAccountsAddHere', - 'Showing accounts managed by {{value0}}. New accounts sign in there; you finish in this device’s browser.', - { value0: accountRuntimeSentenceLabel } - ) - : translate( - 'auto.components.settings.AccountsPane.c0a52abfc5', - 'Showing accounts for {{value0}}. New accounts are added there.', - { value0: accountRuntimeSentenceLabel } - )} -

-
-
- - - {!isRemoteAccountScope && canOfferClaudeSignInLink(accountRuntime.runtime) ? ( - void addClaudeAccount(true)} - /> - ) : null} - - {/* Follow the running addition; hide Cancel only when its server prompt already offers it. */} - {claudeAction === 'adding' && !accountAdditionShownInPrompt('claude', accountOwner) ? ( - - ) : null} -
-
- {remoteAccountScopeNotice} - {isRemoteAccountScope ? ( - - ) : null} - -
- - {systemDefaultIsSaved ? ( -
+ +
+
+

- {translate( - 'accounts.claude.systemDefaultIsSaved', - 'System default is signed in as {{value0}}, which is also a saved account. An earlier Orca version may have copied that login there. If it is not your own login, select System default and run claude /login.', - { value0: systemDefaultEmail } - )} + {isRemoteAccountScope + ? translate( + 'accounts.remoteScopeAccountsAddHere', + 'Showing accounts managed by {{value0}}. New accounts sign in there; you finish in this device’s browser.', + { value0: accountRuntimeSentenceLabel } + ) + : translate( + 'auto.components.settings.AccountsPane.c0a52abfc5', + 'Showing accounts for {{value0}}. New accounts are added there.', + { value0: accountRuntimeSentenceLabel } + )}

-
+
+ + + {!isRemoteAccountScope && canOfferClaudeSignInLink(accountRuntime.runtime) ? ( + void addClaudeAccount(true)} + /> + ) : null} + + {/* Follow the running addition; hide Cancel only when its server prompt already offers it. */} + {claudeAction === 'adding' && + !accountAdditionShownInPrompt('claude', accountOwner) ? ( + + ) : null} +
+
+ {remoteAccountScopeNotice} + {isRemoteAccountScope ? ( + ) : null} - {visibleClaudeAccounts.length === 0 ? ( -
- {isRemoteAccountScope - ? translate( - 'auto.components.settings.AccountsPane.remoteEmptyClaudeAccounts', - 'No managed Claude accounts on {{value0}}. It uses its system default Claude login; add accounts on that server.', - { value0: accountRuntimeSentenceLabel } - ) - : translate( - 'auto.components.settings.AccountsPane.3fe7862418', - "No managed Claude accounts for {{value0}}. Orca will use that environment's system default Claude login until you add one here.", + +
+ + {systemDefaultIsSaved ? ( +
+

+ {translate( + 'accounts.claude.systemDefaultIsSaved', + 'System default is signed in as {{value0}}, which is also a saved account. An earlier Orca version may have copied that login there. If it is not your own login, select System default and run claude /login.', + { value0: systemDefaultEmail } + )} +

+ +
+ ) : null} + {visibleClaudeAccounts.length === 0 ? ( +
+ {isRemoteAccountScope + ? translate( + 'auto.components.settings.AccountsPane.remoteEmptyClaudeAccounts', + 'No managed Claude accounts on {{value0}}. It uses its system default Claude login; add accounts on that server.', + { value0: accountRuntimeSentenceLabel } + ) + : translate( + 'auto.components.settings.AccountsPane.3fe7862418', + "No managed Claude accounts for {{value0}}. Orca will use that environment's system default Claude login until you add one here.", + { value0: accountRuntimeSentenceLabel } + )} +
+ ) : ( + visibleClaudeAccounts.map((account) => { + const isActive = providerAccountIsActiveInView( + account, + claudeAccounts, + accountRuntime, + accountVisibilityOptions + ) + const isReauthing = claudeAction === `reauth:${account.id}` + const isBusy = claudeAction !== 'idle' || accountRuntimeUnavailable + const accountRuntimeView = getProviderAccountRuntime(account) + const reauthenticate = (copyLink: boolean): Promise => + runClaudeAccountAction( + `reauth:${account.id}`, + () => + withCopiedClaudeLink( + copyLink, + window.api.claudeAccounts.reauthenticate({ + accountId: account.id, + copyLink + }) + ), + accountRuntimeView + ) + + return ( +
+
+ -
- + {isActive ? ( + + {translate( + 'auto.components.settings.AccountsPane.e74831fb6b', + 'Active' + )} + + ) : null} +
+ + {account.needsSignIn + ? translate( + 'accounts.claude.signInRequired', + 'Sign in again to use this account' + ) + : account.organizationName + ? `${account.organizationName} · ${formatAccountTimestamp(account.lastAuthenticatedAt)}` + : formatAccountTimestamp(account.lastAuthenticatedAt)} + + +
+ + + {canOfferClaudeSignInLink(accountRuntimeView.runtime) ? ( + void reauthenticate(true)} + /> + ) : null} + - {canOfferClaudeSignInLink(accountRuntimeView.runtime) ? ( - void reauthenticate(true)} - /> - ) : null} - - +
-
- ) - }) - )} -
-
- {isRemoteAccountScope ? null : ( - - )} -
+ ) + }) + )} +
+ + {isRemoteAccountScope ? null : ( + + )} + + ) } diff --git a/src/renderer/src/components/settings/accounts/claude/claude-running-session-switch-setting.tsx b/src/renderer/src/components/settings/accounts/claude/claude-running-session-switch-setting.tsx index bd8b65b63c9..1fa6b9fa3b8 100644 --- a/src/renderer/src/components/settings/accounts/claude/claude-running-session-switch-setting.tsx +++ b/src/renderer/src/components/settings/accounts/claude/claude-running-session-switch-setting.tsx @@ -31,7 +31,7 @@ export function ClaudeRunningSessionSwitchSetting({ title={title} description={description} keywords={['claude', 'account', 'switch', 'restart', 'running', 'session']} - className="flex items-center justify-between gap-4 py-2" + className="flex items-center justify-between gap-4 py-3" >
diff --git a/src/renderer/src/components/settings/accounts/codex/accounts-pane-codex-section.tsx b/src/renderer/src/components/settings/accounts/codex/accounts-pane-codex-section.tsx index 55a7f917d32..d5468983467 100644 --- a/src/renderer/src/components/settings/accounts/codex/accounts-pane-codex-section.tsx +++ b/src/renderer/src/components/settings/accounts/codex/accounts-pane-codex-section.tsx @@ -18,6 +18,7 @@ import { cancelAccountAddition, trackAccountAddition } from '../sign-in/account-add-cancel-target' +import { SettingsGroup } from '../../section-layout/SettingsGroup' export function renderCodexAccountsSection(model: AccountsPaneSectionModel): React.JSX.Element { const { @@ -41,260 +42,275 @@ export function renderCodexAccountsSection(model: AccountsPaneSectionModel): Rea wslCapabilitiesLoading } = model return ( -
-
-

- - {translate('auto.components.settings.AccountsPane.ef91cfa06b', 'Codex')} -

-

- {translate( - 'auto.components.settings.AccountsPane.cedfab35ab', - 'Optional. Orca can use your normal Codex login; add accounts only if you want quick switching in Orca.' - )} -

-

- {isRemoteAccountScope - ? translate( - 'auto.components.settings.AccountsPane.remoteScopeAuthContext', - 'Each account keeps its own sign-in context on {{value0}}.', - { value0: accountRuntimeSentenceLabel } - ) - : translate( - 'auto.components.settings.AccountsPane.340d6f7a85', - 'Each account keeps its own local sign-in context in Orca. Account auth stays on this device.' +

+ + + {translate('auto.components.settings.AccountsPane.ef91cfa06b', 'Codex')} + + } + description={ + <> + + {translate( + 'auto.components.settings.AccountsPane.cedfab35ab', + 'Optional. Orca can use your normal Codex login; add accounts only if you want quick switching in Orca.' )} -

-
- - [ - entry.title, - entry.description ?? '', - ...(entry.keywords ?? []) - ])} - className="space-y-3 py-2" - > - {/* Keep a stable anchor for status-bar account-switcher deep links. */} - {activeCodexAuthWarning ? ( -
- - - {systemCodexMissingSignIn - ? translate( - 'auto.components.settings.AccountsPane.codexSystemDefaultNeedsSignIn', - 'No Codex sign-in was found for {{value0}}.', - { value0: accountRuntimeSentenceLabel } - ) - : activeCodexAccountId - ? translate( - 'auto.components.settings.AccountsPane.75ca9b718e', - 'Codex reported that the active account needs a fresh sign-in. Re-authenticate it before starting new Codex sessions.' - ) - : translate( - 'auto.components.settings.AccountsPane.e4a28e8894', - 'Codex reported that the {{value0}} login needs a fresh sign-in. Sign in again before starting new Codex sessions.', - { value0: accountRuntimeSentenceLabel } - )} -
- ) : null} - {codexConfigSyncWarning ? ( -
- - - {codexConfigSyncWarning === 'managed-home-unavailable' - ? translate( - 'auto.components.settings.AccountsPane.codexConfigSyncManagedHomeUnavailable', - 'Orca could not read this account’s Codex files just now, so settings may not be syncing. This usually clears on its own — antivirus or a backup tool briefly locks them.' - ) - : codexConfigSyncWarning === 'missing-source' - ? translate( - 'auto.components.settings.AccountsPane.codexConfigSyncMissingSource', - 'Codex is still using the settings it last synced because {{value0}} is missing. Restore that file to resume syncing.', - { value0: codexConfigSync?.systemConfigPath ?? '' } - ) - : codexConfigSyncWarning === 'blank-source' - ? translate( - 'auto.components.settings.AccountsPane.codexConfigSyncBlankSource', - 'Codex is still using the settings it last synced because {{value0}} is empty. That is expected while a synced folder finishes downloading.', - { value0: codexConfigSync?.systemConfigPath ?? '' } - ) - : translate( - 'auto.components.settings.AccountsPane.codexConfigSyncUnreadableSource', - "Codex is still using the settings it last synced because {{value0}} could not be read. Check that file's permissions.", - { value0: codexConfigSync?.systemConfigPath ?? '' } - )} - -
- ) : null} -
-
- -

+ {isRemoteAccountScope ? translate( - 'accounts.remoteScopeAccountsAddHere', - 'Showing accounts managed by {{value0}}. New accounts sign in there; you finish in this device’s browser.', + 'auto.components.settings.AccountsPane.remoteScopeAuthContext', + 'Each account keeps its own sign-in context on {{value0}}.', { value0: accountRuntimeSentenceLabel } ) : translate( - 'auto.components.settings.AccountsPane.c0a52abfc5', - 'Showing accounts for {{value0}}. New accounts are added there.', - { value0: accountRuntimeSentenceLabel } + 'auto.components.settings.AccountsPane.340d6f7a85', + 'Each account keeps its own local sign-in context in Orca. Account auth stays on this device.' )} -

-
-
- - {/* Follow the running addition; hide Cancel only when its server prompt already offers it. */} - {codexAction === 'adding' && !accountAdditionShownInPrompt('codex', accountOwner) ? ( + + + } + > + [ + entry.title, + entry.description ?? '', + ...(entry.keywords ?? []) + ])} + className="space-y-3 py-3" + > + {/* Keep a stable anchor for status-bar account-switcher deep links. */} + {activeCodexAuthWarning ? ( +
+ + + {systemCodexMissingSignIn + ? translate( + 'auto.components.settings.AccountsPane.codexSystemDefaultNeedsSignIn', + 'No Codex sign-in was found for {{value0}}.', + { value0: accountRuntimeSentenceLabel } + ) + : activeCodexAccountId + ? translate( + 'auto.components.settings.AccountsPane.75ca9b718e', + 'Codex reported that the active account needs a fresh sign-in. Re-authenticate it before starting new Codex sessions.' + ) + : translate( + 'auto.components.settings.AccountsPane.e4a28e8894', + 'Codex reported that the {{value0}} login needs a fresh sign-in. Sign in again before starting new Codex sessions.', + { value0: accountRuntimeSentenceLabel } + )} + +
+ ) : null} + {codexConfigSyncWarning ? ( +
+ + + {codexConfigSyncWarning === 'managed-home-unavailable' + ? translate( + 'auto.components.settings.AccountsPane.codexConfigSyncManagedHomeUnavailable', + 'Orca could not read this account’s Codex files just now, so settings may not be syncing. This usually clears on its own — antivirus or a backup tool briefly locks them.' + ) + : codexConfigSyncWarning === 'missing-source' + ? translate( + 'auto.components.settings.AccountsPane.codexConfigSyncMissingSource', + 'Codex is still using the settings it last synced because {{value0}} is missing. Restore that file to resume syncing.', + { value0: codexConfigSync?.systemConfigPath ?? '' } + ) + : codexConfigSyncWarning === 'blank-source' + ? translate( + 'auto.components.settings.AccountsPane.codexConfigSyncBlankSource', + 'Codex is still using the settings it last synced because {{value0}} is empty. That is expected while a synced folder finishes downloading.', + { value0: codexConfigSync?.systemConfigPath ?? '' } + ) + : translate( + 'auto.components.settings.AccountsPane.codexConfigSyncUnreadableSource', + "Codex is still using the settings it last synced because {{value0}} could not be read. Check that file's permissions.", + { value0: codexConfigSync?.systemConfigPath ?? '' } + )} + +
+ ) : null} +
+
+ +

+ {isRemoteAccountScope + ? translate( + 'accounts.remoteScopeAccountsAddHere', + 'Showing accounts managed by {{value0}}. New accounts sign in there; you finish in this device’s browser.', + { value0: accountRuntimeSentenceLabel } + ) + : translate( + 'auto.components.settings.AccountsPane.c0a52abfc5', + 'Showing accounts for {{value0}}. New accounts are added there.', + { value0: accountRuntimeSentenceLabel } + )} +

+
+
- ) : null} + {/* Follow the running addition; hide Cancel only when its server prompt already offers it. */} + {codexAction === 'adding' && !accountAdditionShownInPrompt('codex', accountOwner) ? ( + + ) : null} +
-
- {remoteAccountScopeNotice} - {/* Local login links cannot describe the selected server’s sign-in. */} - {isRemoteAccountScope ? ( - - ) : ( - - )} - -
- - {visibleCodexAccounts.length === 0 ? ( -
- {isRemoteAccountScope - ? translate( - 'auto.components.settings.AccountsPane.remoteEmptyCodexAccounts', - 'No managed Codex accounts on {{value0}}. It uses its system default Codex login; add accounts on that server.', - { value0: accountRuntimeSentenceLabel } - ) - : translate( - 'auto.components.settings.AccountsPane.b4c9450319', - "No managed Codex accounts for {{value0}}. Orca will use that environment's system default Codex login until you add one here.", - { value0: accountRuntimeSentenceLabel } - )} -
+ {remoteAccountScopeNotice} + {/* Local login links cannot describe the selected server’s sign-in. */} + {isRemoteAccountScope ? ( + ) : ( - visibleCodexAccounts.map((account) => renderCodexAccountRow(account, model)) + )} -
- -
+ +
+ + {visibleCodexAccounts.length === 0 ? ( +
+ {isRemoteAccountScope + ? translate( + 'auto.components.settings.AccountsPane.remoteEmptyCodexAccounts', + 'No managed Codex accounts on {{value0}}. It uses its system default Codex login; add accounts on that server.', + { value0: accountRuntimeSentenceLabel } + ) + : translate( + 'auto.components.settings.AccountsPane.b4c9450319', + "No managed Codex accounts for {{value0}}. Orca will use that environment's system default Codex login until you add one here.", + { value0: accountRuntimeSentenceLabel } + )} +
+ ) : ( + visibleCodexAccounts.map((account) => renderCodexAccountRow(account, model)) + )} +
+ + +
) } diff --git a/src/renderer/src/components/settings/accounts/providers/AntigravityAccountsSection.tsx b/src/renderer/src/components/settings/accounts/providers/AntigravityAccountsSection.tsx index 46fb5df4abb..c338e41d01e 100644 --- a/src/renderer/src/components/settings/accounts/providers/AntigravityAccountsSection.tsx +++ b/src/renderer/src/components/settings/accounts/providers/AntigravityAccountsSection.tsx @@ -25,6 +25,7 @@ import { openAppHttpLinkFromAnchor } from '@/lib/browser/navigation/app-http-lin import { formatTimeAgo } from '../../../status-bar/tooltip' import { ChatUnavailableOnWindowsNote } from '../../../agent/launch-settings/AgentChatChoiceControls' import { structuredChatUnavailableOnPlatform } from '../../../../../../shared/agent-session/structured-chat-platform-support' +import { SettingsGroup } from '../../section-layout/SettingsGroup' function formatUsageReading(usage: ProviderRateLimits): string { return translate( @@ -182,191 +183,214 @@ export function AntigravityAccountsSection({ } return ( -
-

- - {translate('accounts.antigravity.title', 'Antigravity')} -

-

- {translate( - 'accounts.antigravity.signIn', - 'Start agy on this host and complete its browser sign-in, then save the current account. To add a different account, use /logout in agy and sign in again.' - )}{' '} - - {translate('accounts.antigravity.docs', 'Sign-in instructions')} - -

- {error && ( -

- {error} -

- )} - {!state && error && ( - - )} - {state && ( -
-

- {state.currentAccount - ? (state.currentAccount.email ?? - translate('accounts.antigravity.identityUnknown', 'Signed-in identity unavailable')) - : translate('accounts.antigravity.signedOut', 'No native agy account is signed in.')} +

+ + + {translate('accounts.antigravity.title', 'Antigravity')} + + } + > +
+

+ {translate( + 'accounts.antigravity.signIn', + 'Start agy on this host and complete its browser sign-in, then save the current account. To add a different account, use /logout in agy and sign in again.' + )}{' '} + + {translate('accounts.antigravity.docs', 'Sign-in instructions')} +

- {state.selectedAccountId && state.activeAccountId !== state.selectedAccountId && ( -

- {windowsHost - ? translate( - 'accounts.antigravity.windowsChanged', - 'The host default account changed. Select a saved account to apply it again.' - ) - : translate( - 'accounts.antigravity.changed', - 'The native account changed. Select a saved account again before launching agy.' - )} + {error && ( +

+ {error}

)} -
- + {!state && error && ( - - {busy && ( - - )} -
- {usage && ( -

- {usage.error ?? formatUsageReading(usage)} -

)} - {state.accounts.map((account) => ( -
-
-

- {account.email ?? translate('accounts.antigravity.saved', 'Saved Google account')} + {state && ( +

+

+ {state.currentAccount + ? (state.currentAccount.email ?? + translate( + 'accounts.antigravity.identityUnknown', + 'Signed-in identity unavailable' + )) + : translate( + 'accounts.antigravity.signedOut', + 'No native agy account is signed in.' + )} +

+ {state.selectedAccountId && state.activeAccountId !== state.selectedAccountId && ( +

+ {windowsHost + ? translate( + 'accounts.antigravity.windowsChanged', + 'The host default account changed. Select a saved account to apply it again.' + ) + : translate( + 'accounts.antigravity.changed', + 'The native account changed. Select a saved account again before launching agy.' + )}

- {account.usage !== undefined && ( -

- {account.usage - ? translate( - 'accounts.antigravity.lastReading', - '{{reading}} · Read {{time}}', - { - reading: formatUsageReading(account.usage), - time: formatTimeAgo(account.usage.updatedAt) - } - ) - : translate('accounts.antigravity.noReading', 'Usage unknown: not read yet')} -

- )} - {state.activeAccountId === account.id && ( - - {translate('accounts.antigravity.nativeActive', 'Native account')} - - )} -
-
- - -
-
- ))} -
- )} -

- {windowsHost - ? translate( - 'accounts.antigravity.windowsSessions', - 'Select applies and verifies the host default agy credential. Command choices and later account changes are handled by agy. Existing sessions may keep their previous account.' - ) - : translate( - 'accounts.antigravity.sessions', - 'Selection applies to new agy sessions on this host. Existing sessions may keep their previous account.' - )} -

- {chats && chatRuntime.kind === 'active' ? ( - - {(line, actions) => ( -
-
-

- {translate('settings.agents.chatRuntime', 'Chat runtime')} -

-
{line}
-
-
{actions}
-
)} - - } - /> - ) : chats && structuredChatUnavailableOnPlatform('antigravity', ownerPlatform) ? ( - - ) : null} -
+
+ + + + {busy && ( + + )} +
+ {usage && ( +

+ {usage.error ?? formatUsageReading(usage)} +

+ )} + {state.accounts.map((account) => ( +
+
+

+ {account.email ?? + translate('accounts.antigravity.saved', 'Saved Google account')} +

+ {account.usage !== undefined && ( +

+ {account.usage + ? translate( + 'accounts.antigravity.lastReading', + '{{reading}} · Read {{time}}', + { + reading: formatUsageReading(account.usage), + time: formatTimeAgo(account.usage.updatedAt) + } + ) + : translate( + 'accounts.antigravity.noReading', + 'Usage unknown: not read yet' + )} +

+ )} + {state.activeAccountId === account.id && ( + + {translate('accounts.antigravity.nativeActive', 'Native account')} + + )} +
+
+ + +
+
+ ))} + + )} +

+ {windowsHost + ? translate( + 'accounts.antigravity.windowsSessions', + 'Select applies and verifies the host default agy credential. Command choices and later account changes are handled by agy. Existing sessions may keep their previous account.' + ) + : translate( + 'accounts.antigravity.sessions', + 'Selection applies to new agy sessions on this host. Existing sessions may keep their previous account.' + )} +

+ {chats && chatRuntime.kind === 'active' ? ( + + {(line, actions) => ( +
+
+

+ {translate('settings.agents.chatRuntime', 'Chat runtime')} +

+
{line}
+
+
{actions}
+
+ )} + + } + /> + ) : chats && structuredChatUnavailableOnPlatform('antigravity', ownerPlatform) ? ( + + ) : null} + + + ) } diff --git a/src/renderer/src/components/settings/accounts/providers/CursorAccountsSection.tsx b/src/renderer/src/components/settings/accounts/providers/CursorAccountsSection.tsx index fed197fd171..4431b103d1b 100644 --- a/src/renderer/src/components/settings/accounts/providers/CursorAccountsSection.tsx +++ b/src/renderer/src/components/settings/accounts/providers/CursorAccountsSection.tsx @@ -9,6 +9,7 @@ import { Button } from '../../../ui/button' import type { CursorAccountStatus } from '../../../../../../shared/rate-limit-types' import { SearchableSetting } from '../../section-layout/SearchableSetting' import { openAppHttpLinkFromAnchor } from '@/lib/browser/navigation/app-http-link-open' +import { SettingsGroup } from '../../section-layout/SettingsGroup' const CURSOR_USAGE_DASHBOARD_URL = 'https://cursor.com/dashboard/spending' const SEARCH_KEYWORDS = ['cursor', 'usage', 'plan', 'spend', 'billing', 'rate limit'] @@ -102,177 +103,177 @@ export function CursorAccountsSection(): React.JSX.Element { : null return ( -
-
-
-

+
+ {translate('auto.components.settings.CursorAccountsSection.title', 'Cursor')} -

-

- {translate( - 'auto.components.settings.CursorAccountsSection.subtitle', - 'Shows your Cursor plan usage from the sign-in already on this computer. Orca only reads it — it never changes your Cursor login.' - )} -

-
- - {translate( - 'auto.components.settings.CursorAccountsSection.dashboardLink', - 'Cursor dashboard' - )} - - -
- -
+ } + description={translate( + 'auto.components.settings.CursorAccountsSection.subtitle', + 'Shows your Cursor plan usage from the sign-in already on this computer. Orca only reads it — it never changes your Cursor login.' )} + action={ + + {translate( + 'auto.components.settings.CursorAccountsSection.dashboardLink', + 'Cursor dashboard' + )} + + + } > - -
- {loading ? ( -

- {translate('auto.components.settings.CursorAccountsSection.loading', 'Loading…')} -

- ) : signedIn ? ( - <> -

- {status?.email ?? - status?.displayName ?? - translate('auto.components.settings.CursorAccountsSection.signedIn', 'Signed in')} -

+
+ +
+ {loading ? (

- {tokenFresh - ? sourceLabel - ? translate( - 'auto.components.settings.CursorAccountsSection.signedInFrom', - 'Signed in. Orca reads the session stored in {{source}}.', - { source: sourceLabel } - ) - : translate( - 'auto.components.settings.CursorAccountsSection.signedInGeneric', - 'Signed in. Orca reads the Cursor session stored on this computer.' - ) - : translate( - 'auto.components.settings.CursorAccountsSection.expired', - 'Sign-in expired — run cursor-agent login on the computer running Orca, then click Refresh usage.' + {translate('auto.components.settings.CursorAccountsSection.loading', 'Loading…')} +

+ ) : signedIn ? ( + <> +

+ {status?.email ?? + status?.displayName ?? + translate( + 'auto.components.settings.CursorAccountsSection.signedIn', + 'Signed in' )} -

- - ) : ( - <> -

- {translate( - 'auto.components.settings.CursorAccountsSection.signedOut', - 'No Cursor sign-in found on this computer' - )} -

-

- {translate( - 'auto.components.settings.CursorAccountsSection.signedOutHelp', - 'Sign in with Cursor IDE, or run cursor-agent login in a terminal, then click Refresh usage here.' - )} -

- - )} - {status?.error ?

{status.error}

: null} -
- -
- - {pools.length > 0 || monthly ? ( - -
- {pools.map((pool) => ( -
- - {Math.round(pool.usedPercent)}% - - {pool.name} -
- ))} - {monthly ? ( -
- - {Math.round(monthly.usedPercent)}% - - - {translate('auto.components.settings.CursorAccountsSection.planTotal', 'Plan')} - -
- ) : null} - {(monthly ?? pools[0])?.resetDescription ? ( -

- {translate( - 'auto.components.settings.CursorAccountsSection.resets', - 'Resets {{when}}', - { when: (monthly ?? pools[0])?.resetDescription ?? '' } - )} -

- ) : null} - {staleUsageError ? ( -

- {translate( - 'auto.components.settings.CursorAccountsSection.staleUsage', - 'Last known usage — the latest refresh failed: {{reason}}', - { reason: staleUsageError } - )} -

- ) : null} +

+

+ {tokenFresh + ? sourceLabel + ? translate( + 'auto.components.settings.CursorAccountsSection.signedInFrom', + 'Signed in. Orca reads the session stored in {{source}}.', + { source: sourceLabel } + ) + : translate( + 'auto.components.settings.CursorAccountsSection.signedInGeneric', + 'Signed in. Orca reads the Cursor session stored on this computer.' + ) + : translate( + 'auto.components.settings.CursorAccountsSection.expired', + 'Sign-in expired — run cursor-agent login on the computer running Orca, then click Refresh usage.' + )} +

+ + ) : ( + <> +

+ {translate( + 'auto.components.settings.CursorAccountsSection.signedOut', + 'No Cursor sign-in found on this computer' + )} +

+

+ {translate( + 'auto.components.settings.CursorAccountsSection.signedOutHelp', + 'Sign in with Cursor IDE, or run cursor-agent login in a terminal, then click Refresh usage here.' + )} +

+ + )} + {status?.error ?

{status.error}

: null}
-
- ) : unavailableReason ? ( - -

{unavailableReason}

-
- ) : null} -
+ + + + {pools.length > 0 || monthly ? ( + +
+ {pools.map((pool) => ( +
+ + {Math.round(pool.usedPercent)}% + + {pool.name} +
+ ))} + {monthly ? ( +
+ + {Math.round(monthly.usedPercent)}% + + + {translate('auto.components.settings.CursorAccountsSection.planTotal', 'Plan')} + +
+ ) : null} + {(monthly ?? pools[0])?.resetDescription ? ( +

+ {translate( + 'auto.components.settings.CursorAccountsSection.resets', + 'Resets {{when}}', + { when: (monthly ?? pools[0])?.resetDescription ?? '' } + )} +

+ ) : null} + {staleUsageError ? ( +

+ {translate( + 'auto.components.settings.CursorAccountsSection.staleUsage', + 'Last known usage — the latest refresh failed: {{reason}}', + { reason: staleUsageError } + )} +

+ ) : null} +
+
+ ) : unavailableReason ? ( + +

{unavailableReason}

+
+ ) : null} + + ) } diff --git a/src/renderer/src/components/settings/accounts/providers/GrokAccountsSection.tsx b/src/renderer/src/components/settings/accounts/providers/GrokAccountsSection.tsx index d384aaaddd9..87db4fb27ac 100644 --- a/src/renderer/src/components/settings/accounts/providers/GrokAccountsSection.tsx +++ b/src/renderer/src/components/settings/accounts/providers/GrokAccountsSection.tsx @@ -9,6 +9,7 @@ import { Button } from '../../../ui/button' import type { GrokAccountStatus } from '../../../../../../shared/rate-limit-types' import { SearchableSetting } from '../../section-layout/SearchableSetting' import { openAppHttpLinkFromAnchor } from '@/lib/browser/navigation/app-http-link-open' +import { SettingsGroup } from '../../section-layout/SettingsGroup' const GROK_CLI_DOCS_URL = 'https://docs.x.ai/build/overview' export function GrokAccountsSection(): React.JSX.Element { @@ -63,159 +64,159 @@ export function GrokAccountsSection(): React.JSX.Element { : null return ( -
-
-
-

+
+ {translate('auto.components.settings.GrokAccountsSection.a1b2c3d4e5', 'Grok (xAI)')} -

-

- {translate( - 'auto.components.settings.GrokAccountsSection.f6e5d4c3b2', - 'Shows weekly credit usage from your Grok CLI sign-in (session file ~/.grok/auth.json).' - )} -

-
- - {translate('auto.components.settings.GrokAccountsSection.0d8e77bc40', 'Grok CLI docs')} - - -
- -
+ } + description={translate( + 'auto.components.settings.GrokAccountsSection.f6e5d4c3b2', + 'Shows weekly credit usage from your Grok CLI sign-in (session file ~/.grok/auth.json).' )} + action={ + + {translate('auto.components.settings.GrokAccountsSection.0d8e77bc40', 'Grok CLI docs')} + + + } > - -
- {loading ? ( -

- {translate('auto.components.settings.GrokAccountsSection.ad47a33f72', 'Loading…')} -

- ) : signedIn ? ( - <> -

- {status?.email ?? - translate('auto.components.settings.GrokAccountsSection.b2c3d4e5f6', 'Signed in')} -

+
+ +
+ {loading ? (

- {tokenFresh - ? translate( - 'auto.components.settings.GrokAccountsSection.b36fa2c908', - 'Signed in. Orca reads the Grok CLI session stored on disk.' - ) - : translate( - 'auto.components.settings.GrokAccountsSection.f08c41de73', - 'Session expired — run grok on the computer running Orca and wait for it to start. If prompted, complete sign-in, then click Refresh usage. No chat message is needed.' + {translate('auto.components.settings.GrokAccountsSection.ad47a33f72', 'Loading…')} +

+ ) : signedIn ? ( + <> +

+ {status?.email ?? + translate( + 'auto.components.settings.GrokAccountsSection.b2c3d4e5f6', + 'Signed in' )} -

- - ) : ( - <> -

- {translate( - 'auto.components.settings.GrokAccountsSection.e5f6a7b8c9', - 'Not signed in to Grok CLI' - )} -

-

- {translate( - 'auto.components.settings.GrokAccountsSection.f6a7b8c9d0', - 'In a terminal, run grok login, then click Refresh usage here.' - )} -

- - )} - {status?.error ?

{status.error}

: null} -
- -
- - {usageWindow ? ( - -
- - {Math.round(usageWindow.usedPercent)}% - - {usageWindow.resetDescription ? ( - - {translate( - 'auto.components.settings.GrokAccountsSection.c6d1a8f4e2', - 'Resets {{when}}', - { when: usageWindow.resetDescription } - )} - - ) : null} - {grokUsage?.usageMetadata?.authProvenance ? ( - - {grokUsage.usageMetadata.authProvenance} - - ) : null} +

+

+ {tokenFresh + ? translate( + 'auto.components.settings.GrokAccountsSection.b36fa2c908', + 'Signed in. Orca reads the Grok CLI session stored on disk.' + ) + : translate( + 'auto.components.settings.GrokAccountsSection.f08c41de73', + 'Session expired — run grok on the computer running Orca and wait for it to start. If prompted, complete sign-in, then click Refresh usage. No chat message is needed.' + )} +

+ + ) : ( + <> +

+ {translate( + 'auto.components.settings.GrokAccountsSection.e5f6a7b8c9', + 'Not signed in to Grok CLI' + )} +

+

+ {translate( + 'auto.components.settings.GrokAccountsSection.f6a7b8c9d0', + 'In a terminal, run grok login, then click Refresh usage here.' + )} +

+ + )} + {status?.error ?

{status.error}

: null}
-
- ) : unavailableReason ? ( - -

{unavailableReason}

-
- ) : null} -
+ + + + {usageWindow ? ( + +
+ + {Math.round(usageWindow.usedPercent)}% + + {usageWindow.resetDescription ? ( + + {translate( + 'auto.components.settings.GrokAccountsSection.c6d1a8f4e2', + 'Resets {{when}}', + { when: usageWindow.resetDescription } + )} + + ) : null} + {grokUsage?.usageMetadata?.authProvenance ? ( + + {grokUsage.usageMetadata.authProvenance} + + ) : null} +
+
+ ) : unavailableReason ? ( + +

{unavailableReason}

+
+ ) : null} + + ) } diff --git a/src/renderer/src/components/settings/accounts/providers/ManagedDataAccountsSection.tsx b/src/renderer/src/components/settings/accounts/providers/ManagedDataAccountsSection.tsx index 62fc2b10ce6..283460744aa 100644 --- a/src/renderer/src/components/settings/accounts/providers/ManagedDataAccountsSection.tsx +++ b/src/renderer/src/components/settings/accounts/providers/ManagedDataAccountsSection.tsx @@ -16,6 +16,7 @@ import { DialogDescription, DialogFooter } from '../../../ui/dialog' +import { SettingsGroup } from '../../section-layout/SettingsGroup' type Snapshot = { opencode?: ManagedDataAccountsState; devin?: ManagedDataAccountsState } @@ -86,61 +87,62 @@ export function ManagedDataAccountsSection({ const command = `orca account add --agent ${provider}` return ( -
-

- {provider === 'opencode' + -

- {translate( - 'accounts.managedData.description', - 'Add accounts by running this command in a terminal on the Orca host. Selection applies to new explicit agent launches on that host; direct SSH relay and Windows-hosted WSL launches use their own credentials.' + : translate('auto.lib.agent.catalog.fc80296033', 'Devin') + } + description={translate( + 'accounts.managedData.description', + 'Add accounts by running this command in a terminal on the Orca host. Selection applies to new explicit agent launches on that host; direct SSH relay and Windows-hosted WSL launches use their own credentials.' + )} + > +

+ {command} +
+ + +
+ {!state && !error && ( +

+ {translate( + 'accounts.managedData.upgrade', + 'If accounts do not appear, update or restart the Orca host.' + )} +

+ )} + {error && ( +

+ {error} +

)} -

- {command} -
- -
- {!state && !error && ( -

- {translate( - 'accounts.managedData.upgrade', - 'If accounts do not appear, update or restart the Orca host.' - )} -

- )} - {error && ( -

- {error} -

- )} {state && ( <> -
+
{translate('accounts.managedData.system', 'System default')} @@ -158,7 +160,11 @@ export function ManagedDataAccountsSection({
{state.accounts.map((account) => ( -
+
{account.label}

{account.integrations.join(', ')}

@@ -232,6 +238,6 @@ export function ManagedDataAccountsSection({ -

+ ) } diff --git a/src/renderer/src/components/settings/accounts/providers/accounts-pane-provider-setting-sections.tsx b/src/renderer/src/components/settings/accounts/providers/accounts-pane-provider-setting-sections.tsx index bef390de34c..3c971a225e1 100644 --- a/src/renderer/src/components/settings/accounts/providers/accounts-pane-provider-setting-sections.tsx +++ b/src/renderer/src/components/settings/accounts/providers/accounts-pane-provider-setting-sections.tsx @@ -7,216 +7,217 @@ import { SearchableSetting } from '../../section-layout/SearchableSetting' import type { AccountsPaneSectionModel } from '../accounts-pane-types' import { OpenCodeGoCredentials } from '../usage/accounts-pane-opencode-credentials' import { DebouncedSettingsTextInput } from '../../form-controls/DebouncedSettingsTextInput' +import { SettingsGroup } from '../../section-layout/SettingsGroup' export function renderGeminiAccountsSection(model: AccountsPaneSectionModel): React.JSX.Element { const { localAccountRuntimeSentenceLabel, recordFeatureInteraction, settings, updateSettings } = model return ( -
-
-

- - {translate('auto.components.settings.AccountsPane.0c64dc2a64', 'Gemini CLI (legacy)')} -

-

- {translate( - 'auto.components.settings.AccountsPane.973741a871', - 'Keep existing Gemini CLI sessions available. Gemini credentials do not sign you into Antigravity.' - )} -

-
- - + + + {translate('auto.components.settings.AccountsPane.0c64dc2a64', 'Gemini CLI (legacy)')} + + } description={translate( - 'auto.components.settings.AccountsPane.d676c41fc6', - 'Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google. This uses credentials issued to the Gemini CLI app, not Orca. May break if Google updates the CLI. Use at your own risk.' + 'auto.components.settings.AccountsPane.973741a871', + 'Keep existing Gemini CLI sessions available. Gemini credentials do not sign you into Antigravity.' )} - keywords={[ - 'gemini', - 'cli', - 'oauth', - 'credentials', - 'experimental', - 'rate limit', - 'status bar' - ]} - className="flex items-center justify-between gap-4 py-2" > -
-
- { - recordFeatureInteraction('usage-tracking') - updateSettings({ - geminiCliOAuthEnabled: checked - }) - }} - /> -
-
+ checked={settings.geminiCliOAuthEnabled} + onCheckedChange={(checked) => { + recordFeatureInteraction('usage-tracking') + updateSettings({ + geminiCliOAuthEnabled: checked + }) + }} + /> + + + ) } export function renderOpenCodeAccountsSection(model: AccountsPaneSectionModel): React.JSX.Element { const { recordFeatureInteraction, recordOpenCodeSettingEdit, settings, updateSettings } = model return ( -
-
-

- - {translate('auto.components.settings.AccountsPane.4ac10b4d08', 'OpenCode Go')} -

-

- {translate( - 'auto.components.settings.AccountsPane.ea631977b5', - 'Configure OpenCode Go provider settings.' - )} -

-
- - recordOpenCodeSettingEdit('apiKey')} /> - - + + + {translate('auto.components.settings.AccountsPane.4ac10b4d08', 'OpenCode Go')} + + } description={translate( - 'auto.components.settings.AccountsPane.0335bd31d5', - 'Paste the full opencode.ai Cookie header, including __Host-console_session, for rate limit fetching.' + 'auto.components.settings.AccountsPane.ea631977b5', + 'Configure OpenCode Go provider settings.' )} - keywords={['opencode', 'cookie', 'session', 'console', 'rate limit', 'status bar']} - className="space-y-2" > - -
- recordOpenCodeSettingEdit('cookie')} - commit={(opencodeSessionCookie) => updateSettings({ opencodeSessionCookie })} - placeholder={translate( - 'auto.components.settings.AccountsPane.37b4b4a3f7', - 'auth=…; __Host-console_session=…' - )} - spellCheck={false} - className="flex-1 text-xs" - /> - {settings.opencodeSessionCookie && ( - - )} -
-

- {translate( - 'auto.components.settings.AccountsPane.62ab430f94', - "Paste the full Cookie header from your browser's DevTools → Network → any opencode.ai request, including __Host-console_session (e.g." - )}{' '} - - {translate( - 'auto.components.settings.AccountsPane.37b4b4a3f7', - 'auth=…; __Host-console_session=…' - )} - - {translate( - 'auto.components.settings.AccountsPane.d5267cce63', - '). The auth cookie still covers workspace discovery; auth alone is not enough for usage. OpenCode Go auth is web-based and shared across Windows and WSL terminals.' - )} -

-
+ recordOpenCodeSettingEdit('apiKey')} /> - - -
- recordOpenCodeSettingEdit('workspaceId')} - commit={(opencodeWorkspaceId) => updateSettings({ opencodeWorkspaceId })} - placeholder={translate( - 'auto.components.settings.AccountsPane.a122332371', - 'wrk_… (leave blank for automatic lookup)' - )} - spellCheck={false} - className="flex-1 text-xs" - /> - {settings.opencodeWorkspaceId && ( - + -

- {translate( - 'auto.components.settings.AccountsPane.51c9104e13', - 'Find this in the URL after logging into opencode.ai (e.g.' - )}{' '} - + description={translate( + 'auto.components.settings.AccountsPane.0335bd31d5', + 'Paste the full opencode.ai Cookie header, including __Host-console_session, for rate limit fetching.' + )} + keywords={['opencode', 'cookie', 'session', 'console', 'rate limit', 'status bar']} + className="space-y-2 py-3" + > + - ). -

-
-
+ +
+ recordOpenCodeSettingEdit('cookie')} + commit={(opencodeSessionCookie) => updateSettings({ opencodeSessionCookie })} + placeholder={translate( + 'auto.components.settings.AccountsPane.37b4b4a3f7', + 'auth=…; __Host-console_session=…' + )} + spellCheck={false} + className="flex-1 text-xs" + /> + {settings.opencodeSessionCookie && ( + + )} +
+

+ {translate( + 'auto.components.settings.AccountsPane.62ab430f94', + "Paste the full Cookie header from your browser's DevTools → Network → any opencode.ai request, including __Host-console_session (e.g." + )}{' '} + + {translate( + 'auto.components.settings.AccountsPane.37b4b4a3f7', + 'auth=…; __Host-console_session=…' + )} + + {translate( + 'auto.components.settings.AccountsPane.d5267cce63', + '). The auth cookie still covers workspace discovery; auth alone is not enough for usage. OpenCode Go auth is web-based and shared across Windows and WSL terminals.' + )} +

+ + + + +
+ recordOpenCodeSettingEdit('workspaceId')} + commit={(opencodeWorkspaceId) => updateSettings({ opencodeWorkspaceId })} + placeholder={translate( + 'auto.components.settings.AccountsPane.a122332371', + 'wrk_… (leave blank for automatic lookup)' + )} + spellCheck={false} + className="flex-1 text-xs" + /> + {settings.opencodeWorkspaceId && ( + + )} +
+

+ {translate( + 'auto.components.settings.AccountsPane.51c9104e13', + 'Find this in the URL after logging into opencode.ai (e.g.' + )}{' '} + + {translate( + 'auto.components.settings.AccountsPane.ae3b21eb6c', + 'opencode.ai/workspace/wrk_…/go' + )} + + ). +

+
+ + ) } diff --git a/src/renderer/src/components/settings/accounts/scope/accounts-pane-location-section.tsx b/src/renderer/src/components/settings/accounts/scope/accounts-pane-location-section.tsx index 4c4cca3ba03..36878270e3b 100644 --- a/src/renderer/src/components/settings/accounts/scope/accounts-pane-location-section.tsx +++ b/src/renderer/src/components/settings/accounts/scope/accounts-pane-location-section.tsx @@ -7,6 +7,7 @@ import { getHostRuntimeLabel } from './accounts-pane-runtime' import { WSL_DEFAULT_DISTRO_KEY } from '../../../provider-accounts/provider-account-visibility' import type { GlobalSettings } from '../../../../../../shared/global-settings-types' import type { AccountsPaneSectionModel } from '../accounts-pane-types' +import { SettingsGroup } from '../../section-layout/SettingsGroup' export function renderAccountsLocationSection( model: AccountsPaneSectionModel @@ -126,8 +127,8 @@ export function renderAccountsLocationSection( ) : null return ( -
- {accountRuntimeControls} -
+
+ {accountRuntimeControls} +
) } diff --git a/src/renderer/src/components/settings/accounts/usage/MiniMaxAccountsSection.tsx b/src/renderer/src/components/settings/accounts/usage/MiniMaxAccountsSection.tsx index a7c94d08c2b..272258c83eb 100644 --- a/src/renderer/src/components/settings/accounts/usage/MiniMaxAccountsSection.tsx +++ b/src/renderer/src/components/settings/accounts/usage/MiniMaxAccountsSection.tsx @@ -16,6 +16,7 @@ import { type UsageCredentialHost } from './usage-credential-host' import type { UsageHostSettingsModel } from './use-usage-host-settings' +import { SettingsGroup } from '../../section-layout/SettingsGroup' export function MiniMaxAccountsSection({ host, @@ -47,176 +48,177 @@ export function MiniMaxAccountsSection({ void usageSettings.update({ minimaxEndpoint: value }) } return ( -
-
-
-

+
+ {translate('auto.components.settings.AccountsPane.5d63bbfbec', 'MiniMax')} -

-

- {translate( - 'auto.components.settings.AccountsPane.usageTracking', - 'Configure MiniMax usage tracking for your account.' - )} -

-
- - {translate('auto.components.settings.AccountsPane.0d8e77bc40', 'Open console')} - - -
- -
- -
- {accessNotice ? ( -

{accessNotice}

- ) : ( -

- {configured - ? usageCredentialStoredLabel(host) - : translate( - 'auto.components.settings.AccountsPane.credentialsNotSet', - 'Credentials not set' - )} -

- )} -

{miniMaxStorageHelp(host)}

-
-
- - + } description={translate( - 'auto.components.settings.AccountsPane.0b3a9f6c2e', - 'Pick the host that matches your account. Both overseas (platform.minimax.io) and China (platform.minimaxi.com) accept either a session cookie or an API key.' + 'auto.components.settings.AccountsPane.usageTracking', + 'Configure MiniMax usage tracking for your account.' )} - keywords={['minimax', 'endpoint', 'region', 'host', 'cn', 'china', 'overseas', 'api key']} - className="space-y-2" + action={ + + {translate('auto.components.settings.AccountsPane.0d8e77bc40', 'Open console')} + + + } > - - - - - - -
-
-
-

- {translate('auto.components.settings.AccountsPane.9dd50d3f75', 'Advanced')} -

-

- {translate( - 'auto.components.settings.AccountsPane.174fb408f9', - 'Leave these defaults alone unless MiniMax usage refresh points at the wrong workspace or model.' - )} -

+
+ +
+ {accessNotice ? ( +

{accessNotice}

+ ) : ( +

+ {configured + ? usageCredentialStoredLabel(host) + : translate( + 'auto.components.settings.AccountsPane.credentialsNotSet', + 'Credentials not set' + )} +

+ )} +

{miniMaxStorageHelp(host)}

- - - - void usageSettings.update({ minimaxUsageModels })} - disabled={settingsUnavailable} - placeholder={translate('auto.components.settings.AccountsPane.3c92b0d31c', 'general')} - spellCheck={false} - className="text-xs" - /> - -
-
+ + +
+
+
+

+ {translate('auto.components.settings.AccountsPane.9dd50d3f75', 'Advanced')} +

+

+ {translate( + 'auto.components.settings.AccountsPane.174fb408f9', + 'Leave these defaults alone unless MiniMax usage refresh points at the wrong workspace or model.' + )} +

+
+
+ + + + void usageSettings.update({ minimaxGroupId })} + disabled={settingsUnavailable} + placeholder={translate( + 'auto.components.settings.AccountsPane.0747d6391a', + 'Use group ID from cookie' + )} + spellCheck={false} + className="text-xs" + /> + + + + + void usageSettings.update({ minimaxUsageModels })} + disabled={settingsUnavailable} + placeholder={translate('auto.components.settings.AccountsPane.3c92b0d31c', 'general')} + spellCheck={false} + className="text-xs" + /> + +
+ + ) } diff --git a/src/renderer/src/components/settings/accounts/usage/ZcodePlanAccountsSection.tsx b/src/renderer/src/components/settings/accounts/usage/ZcodePlanAccountsSection.tsx index 6453cfb2db0..9a875d74bf0 100644 --- a/src/renderer/src/components/settings/accounts/usage/ZcodePlanAccountsSection.tsx +++ b/src/renderer/src/components/settings/accounts/usage/ZcodePlanAccountsSection.tsx @@ -28,6 +28,7 @@ import { type UsageCredentialHost } from './usage-credential-host' import type { UsageHostSettingsModel } from './use-usage-host-settings' +import { SettingsGroup } from '../../section-layout/SettingsGroup' const SEARCH_KEYWORDS = [ 'glm', @@ -103,308 +104,304 @@ export function ZcodePlanAccountsSection({ const staleUsageError = usage?.status === 'error' ? (usage.error ?? null) : null return ( -
-
-
-

+
+ {translate( 'auto.components.settings.ZcodePlanAccountsSection.title', 'GLM Coding Plan' )} -

-

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.subtitle', - 'Track Z.AI or Zhipu (BigModel) GLM Coding Plan usage in the status bar. Save the plan API key here — no ZCode CLI setup needed.' - )} -

-
- {consoleUrl ? ( - - {translate( - 'auto.components.settings.ZcodePlanAccountsSection.consoleLink', - 'Get API key' - )} - - - ) : null} -
- -
- -
- {accessNotice ? ( -

{accessNotice}

- ) : detailsUnavailable ? ( -

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.detailsUnavailable', - 'Plan credential details are only readable on the computer running Orca.' - )} -

- ) : apiKeyConfigured ? ( - <> -

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.keyStored', - 'API key saved · {{value0}}', - { value0: siteLabel(site ?? 'zai') } - )} -

-

- {hostLabel === null - ? translate( - 'auto.components.settings.ZcodePlanAccountsSection.keyStoredHelp', - 'Stored locally and sent only to the selected site for usage refreshes. It takes priority over the ZCode CLI sign-in.' - ) - : translate( - 'auto.components.settings.ZcodePlanAccountsSection.keyStoredOnHostHelp', - 'Stored on {{host}} and sent from there only to the selected site for usage refreshes. It takes priority over the ZCode CLI sign-in.', - { host: hostLabel } - )} -

- - ) : status?.zcodeCliConfigured ? ( - <> -

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.usingCli', - 'Using the ZCode CLI sign-in' - )} -

-

- {hostLabel === null - ? translate( - 'auto.components.settings.ZcodePlanAccountsSection.usingCliHelp', - 'Orca reads the selected Coding Plan from the ZCode CLI credential store on this computer. Save an API key below to link the plan here instead.' - ) - : translate( - 'auto.components.settings.ZcodePlanAccountsSection.usingCliOnHostHelp', - 'Orca reads the selected Coding Plan from the ZCode CLI credential store on {{host}}. Save an API key below to link the plan there instead.', - { host: hostLabel } - )} -

- - ) : ( - <> -

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.notConfigured', - 'No GLM Coding Plan linked' - )} -

-

- {hostLabel === null - ? translate( - 'auto.components.settings.ZcodePlanAccountsSection.notConfiguredHelp', - 'Save the plan API key below, or sign in with the ZCode CLI on this computer.' - ) - : translate( - 'auto.components.settings.ZcodePlanAccountsSection.notConfiguredOnHostHelp', - 'Save the plan API key below, or sign in with the ZCode CLI on {{host}}.', - { host: hostLabel } - )} -

- - )} - {staleUsageError ?

{staleUsageError}

: null} -
- {hostLabel === null ? ( - - ) : null} -
- - {webClient ? ( -

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.hostOnly', - 'Change the plan site and API key in the desktop app on the computer running Orca.' - )} -

- ) : null} - - + } description={translate( - 'auto.components.settings.ZcodePlanAccountsSection.siteDescription', - 'Pick the console your Coding Plan belongs to: Z.AI for the international site, Zhipu BigModel for the mainland site.' + 'auto.components.settings.ZcodePlanAccountsSection.subtitle', + 'Track Z.AI or Zhipu (BigModel) GLM Coding Plan usage in the status bar. Save the plan API key here — no ZCode CLI setup needed.' )} - keywords={SEARCH_KEYWORDS} - className="space-y-2" - > - - - - - -
-
- - {!detailsUnavailable ? ( - - {apiKeyConfigured ? : } - {apiKeyConfigured - ? translate('auto.components.settings.ZcodePlanAccountsSection.saved', 'Saved') - : translate( - 'auto.components.settings.ZcodePlanAccountsSection.notSaved', - 'Not saved' - )} - - ) : null} -
-
- - {unreadableNotice ? ( -

{unreadableNotice}

- ) : null} -
- setApiKeyDraft(e.target.value)} - placeholder={translate( - 'auto.components.settings.ZcodePlanAccountsSection.keyPlaceholder', - 'Paste your GLM Coding Plan API key' - )} - spellCheck={false} - className="flex-1" - /> - - {apiKeyConfigured ? ( - ) : null}
-

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.keyHelp', - 'The same key your coding tools use for the plan (for example Claude Code with ANTHROPIC_BASE_URL pointed at the site). Switching the site above changes which host receives it.' - )} -

-
- {!webClient && hostLabel === null ? : null} + {webClient ? ( +

+ {translate( + 'auto.components.settings.ZcodePlanAccountsSection.hostOnly', + 'Change the plan site and API key in the desktop app on the computer running Orca.' + )} +

+ ) : null} - {usageWindows.length > 0 ? ( -
- {usageWindows.map((row) => ( - - ))} - {usage?.planType ? ( -

- {translate( - 'auto.components.settings.ZcodePlanAccountsSection.planLevel', - 'Plan: {{value0}}', - { value0: usage.planType } + + + + + +

+
+ + {!detailsUnavailable ? ( + + {apiKeyConfigured ? : } + {apiKeyConfigured + ? translate('auto.components.settings.ZcodePlanAccountsSection.saved', 'Saved') + : translate( + 'auto.components.settings.ZcodePlanAccountsSection.notSaved', + 'Not saved' + )} + + ) : null} +
+
+ + {unreadableNotice ? ( +

{unreadableNotice}

+ ) : null} +
+ setApiKeyDraft(e.target.value)} + placeholder={translate( + 'auto.components.settings.ZcodePlanAccountsSection.keyPlaceholder', + 'Paste your GLM Coding Plan API key' + )} + spellCheck={false} + className="flex-1" + /> + + {apiKeyConfigured ? ( + ) : null}
+

+ {translate( + 'auto.components.settings.ZcodePlanAccountsSection.keyHelp', + 'The same key your coding tools use for the plan (for example Claude Code with ANTHROPIC_BASE_URL pointed at the site). Switching the site above changes which host receives it.' + )} +

- ) : null} -
+ + {!webClient && hostLabel === null ? : null} + + {usageWindows.length > 0 ? ( + +
+ {usageWindows.map((row) => ( + + ))} + {usage?.planType ? ( +

+ {translate( + 'auto.components.settings.ZcodePlanAccountsSection.planLevel', + 'Plan: {{value0}}', + { value0: usage.planType } + )} +

+ ) : null} +
+
+ ) : null} + + ) } diff --git a/src/renderer/src/components/settings/accounts/usage/accounts-pane-minimax-credentials.tsx b/src/renderer/src/components/settings/accounts/usage/accounts-pane-minimax-credentials.tsx index 18863eeafd7..480db0a9843 100644 --- a/src/renderer/src/components/settings/accounts/usage/accounts-pane-minimax-credentials.tsx +++ b/src/renderer/src/components/settings/accounts/usage/accounts-pane-minimax-credentials.tsx @@ -145,7 +145,7 @@ export function MiniMaxCredentials({ 'Paste your MiniMax session cookie for local rate-limit fetching.' )} keywords={['minimax', 'cookie', 'session', 'rate limit', 'status bar']} - className="space-y-2" + className="space-y-2 py-3" >
@@ -277,7 +277,7 @@ export function MiniMaxCredentials({ ) } keywords={['minimax', 'api', 'key', 'cn', 'china', 'bearer', 'rate limit']} - className="space-y-2" + className="space-y-2 py-3" >
diff --git a/src/renderer/src/components/settings/accounts/usage/accounts-pane-opencode-credentials.tsx b/src/renderer/src/components/settings/accounts/usage/accounts-pane-opencode-credentials.tsx index 9feadb68e50..1fec09e663b 100644 --- a/src/renderer/src/components/settings/accounts/usage/accounts-pane-opencode-credentials.tsx +++ b/src/renderer/src/components/settings/accounts/usage/accounts-pane-opencode-credentials.tsx @@ -65,7 +65,7 @@ export function OpenCodeGoCredentials({ onSaved }: { onSaved: () => void }): Rea 'Optional override. Orca otherwise uses the key OpenCode saved when you ran /connect, then OPENCODE_API_KEY.' )} keywords={['opencode', 'go', 'api', 'key', 'connect', 'rate limit', 'status bar']} - className="space-y-2" + className="space-y-2 py-3" >
) diff --git a/src/renderer/src/components/settings/artifacts/ArtifactsSettingsPane.tsx b/src/renderer/src/components/settings/artifacts/ArtifactsSettingsPane.tsx index 21ec2c5d1ac..0e8f40b6e2e 100644 --- a/src/renderer/src/components/settings/artifacts/ArtifactsSettingsPane.tsx +++ b/src/renderer/src/components/settings/artifacts/ArtifactsSettingsPane.tsx @@ -2,6 +2,7 @@ import { ArrowRight, Files } from 'lucide-react' import type { GlobalSettings } from '../../../../../shared/global-settings-types' import { Button } from '@/components/ui/button' import { SettingsSwitchRow } from '../form-controls/SettingsFormControls' +import { SettingsGroup } from '../section-layout/SettingsGroup' import { useOrcaProfileAuthStatusRefresh } from '@/hooks/use-orca-profile-auth-status-refresh' import { useAppStore } from '@/store/index' import { isWebClientLocation } from '@/lib/web-client-location' @@ -77,115 +78,123 @@ export function ArtifactsSettingsPane({ ] return ( -
- void updateSettings({ artifactSharingEnabled: !sharingEnabled })} - /> - void updateSettings({ showArtifactsButton: !settings.showArtifactsButton })} - /> - {!signedIn ? ( -
-
-

- {translate( - 'auto.components.settings.artifacts.signInTitle', - 'Sign in to share artifacts' - )} -

-

- {translate( - 'auto.components.settings.artifacts.signInDescription', - 'Use your Orca account to upload artifacts and manage their public links.' - )} -

-
- - {authStatus?.state === 'reconnect-required' - ? translate('auto.components.settings.artifacts.signInAgain', 'Sign in again') - : translate('auto.components.settings.artifacts.signIn', 'Sign in to Orca')} - - -
- ) : null} -
-
-

- {translate('auto.components.settings.artifacts.howToTitle', 'How to use Artifacts')} -

-

- {sharingEnabled +

+ + void updateSettings({ artifactSharingEnabled: !sharingEnabled })} + /> + + void updateSettings({ showArtifactsButton: !settings.showArtifactsButton }) + } + /> + {!signedIn ? ( +
+
+

+ {translate( + 'auto.components.settings.artifacts.signInTitle', + 'Sign in to share artifacts' )} -

-

+ +

+ {translate( + 'auto.components.settings.artifacts.signInDescription', + 'Use your Orca account to upload artifacts and manage their public links.' + )} +

+
+ + {authStatus?.state === 'reconnect-required' + ? translate('auto.components.settings.artifacts.signInAgain', 'Sign in again') + : translate('auto.components.settings.artifacts.signIn', 'Sign in to Orca')} + + +
+ ) : null} + + +
+
    + {howToSteps.map((step, index) => ( +
  1. + + {index + 1} + +
    +

    {step.title}

    +

    + {step.description} +

    +
    +
  2. + ))} +
-
    - {howToSteps.map((step, index) => ( -
  1. - - {index + 1} +
  2. - ))} -
- - - + + +
+
) } diff --git a/src/renderer/src/components/settings/automations/AutomationsSettingsPane.tsx b/src/renderer/src/components/settings/automations/AutomationsSettingsPane.tsx index b119ed41d87..f6198b8e032 100644 --- a/src/renderer/src/components/settings/automations/AutomationsSettingsPane.tsx +++ b/src/renderer/src/components/settings/automations/AutomationsSettingsPane.tsx @@ -2,6 +2,7 @@ import { ArrowRight, CalendarClock } from 'lucide-react' import type { GlobalSettings } from '../../../../../shared/global-settings-types' import { Button } from '@/components/ui/button' import { SettingsSwitchRow } from '../form-controls/SettingsFormControls' +import { SettingsGroup } from '../section-layout/SettingsGroup' import { useAppStore } from '@/store/index' import { translate } from '@/i18n/i18n' @@ -15,125 +16,124 @@ export function AutomationsSettingsPane({ const openAutomationsPage = useAppStore((state) => state.openAutomationsPage) return ( -
- + + + void updateSettings({ + showAutomationsButton: settings.showAutomationsButton === false + }) + } + /> + + - void updateSettings({ - showAutomationsButton: settings.showAutomationsButton === false - }) - } - /> -
-
-

- {translate( - 'auto.components.settings.automations.howItWorksTitle', - 'How Automations work' - )} -

-

- {translate( - 'auto.components.settings.automations.howItWorksDescription', - 'Schedule agent work once, then let Orca create each run and keep its results together.' - )} -

+ bodyClassName="py-4" + > +
+
    +
  1. + + 1 + +
    +

    + {translate( + 'auto.components.settings.automations.defineStepTitle', + 'Describe the work' + )} +

    +

    + {translate( + 'auto.components.settings.automations.defineStepDescription', + 'Choose a project, agent, prompt, and schedule.' + )} +

    +
    +
  2. +
  3. + + 2 + +
    +

    + {translate( + 'auto.components.settings.automations.runStepTitle', + 'Orca starts each run' + )} +

    +

    + {translate( + 'auto.components.settings.automations.runStepDescription', + 'The selected agent gets a fresh workspace when the schedule is due.' + )} +

    +
    +
  4. +
  5. + + 3 + +
    +

    + {translate( + 'auto.components.settings.automations.reviewStepTitle', + 'Review the results' + )} +

    +

    + {translate( + 'auto.components.settings.automations.reviewStepDescription', + 'Inspect recent runs and continue the work whenever you need to.' + )} +

    +
    +
  6. +
+ +
- -
    -
  1. - - 1 - -
    -

    - {translate( - 'auto.components.settings.automations.defineStepTitle', - 'Describe the work' - )} -

    -

    - {translate( - 'auto.components.settings.automations.defineStepDescription', - 'Choose a project, agent, prompt, and schedule.' - )} -

    -
    -
  2. -
  3. - - 2 - -
    -

    - {translate( - 'auto.components.settings.automations.runStepTitle', - 'Orca starts each run' - )} -

    -

    - {translate( - 'auto.components.settings.automations.runStepDescription', - 'The selected agent gets a fresh workspace when the schedule is due.' - )} -

    -
    -
  4. -
  5. - - 3 - -
    -

    - {translate( - 'auto.components.settings.automations.reviewStepTitle', - 'Review the results' - )} -

    -

    - {translate( - 'auto.components.settings.automations.reviewStepDescription', - 'Inspect recent runs and continue the work whenever you need to.' - )} -

    -
    -
  6. -
- - -
+
) } diff --git a/src/renderer/src/components/settings/browser/BrowserDefaultZoomSetting.tsx b/src/renderer/src/components/settings/browser/BrowserDefaultZoomSetting.tsx index 7e6f5aa7e8f..5c264e0594c 100644 --- a/src/renderer/src/components/settings/browser/BrowserDefaultZoomSetting.tsx +++ b/src/renderer/src/components/settings/browser/BrowserDefaultZoomSetting.tsx @@ -30,7 +30,7 @@ export function BrowserDefaultZoomSetting({ "Zoom for sites you haven't zoomed." )} keywords={['browser', 'zoom', 'scale', 'default', 'page zoom', 'site', 'percentage']} - className="flex items-center justify-between gap-4 py-2" + className="flex items-center justify-between gap-4 py-3" >