diff --git a/apps/web/src/appSettings.test.ts b/apps/web/src/appSettings.test.ts index b65c8c1a..20ef20e1 100644 --- a/apps/web/src/appSettings.test.ts +++ b/apps/web/src/appSettings.test.ts @@ -80,6 +80,20 @@ describe("getProviderStartOptions", () => { }, }); }); + + it("does not emit Claude start options without a Claude binary path", () => { + expect( + getProviderStartOptions({ + claudeBinaryPath: "", + codexBinaryPath: "", + codexHomePath: "", + copilotBinaryPath: "", + copilotConfigDir: "", + openclawGatewayUrl: "", + openclawPassword: "", + }), + ).toBeUndefined(); + }); }); describe("resolveBrowserPreviewStartPageUrl", () => { diff --git a/apps/web/src/appSettings.ts b/apps/web/src/appSettings.ts index 3b5d3685..e63e9186 100644 --- a/apps/web/src/appSettings.ts +++ b/apps/web/src/appSettings.ts @@ -91,9 +91,6 @@ export const AppSettingsSchema = Schema.Struct({ claudeBinaryPath: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), copilotBinaryPath: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), copilotConfigDir: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), - claudeAuthTokenHelperCommand: Schema.String.check(Schema.isMaxLength(4096)).pipe( - withDefaults(() => ""), - ), codexBinaryPath: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), codexHomePath: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), backgroundImageUrl: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), @@ -392,9 +389,7 @@ export function getProviderStartOptions( | "codexHomePath" | "openclawGatewayUrl" | "openclawPassword" - > & { - claudeAuthTokenHelperCommand?: AppSettings["claudeAuthTokenHelperCommand"]; - }, + >, ): ProviderStartOptions | undefined { const providerOptions: ProviderStartOptions = { ...(settings.codexBinaryPath || settings.codexHomePath @@ -405,13 +400,10 @@ export function getProviderStartOptions( }, } : {}), - ...(settings.claudeBinaryPath || settings.claudeAuthTokenHelperCommand + ...(settings.claudeBinaryPath ? { claudeAgent: { - ...(settings.claudeBinaryPath ? { binaryPath: settings.claudeBinaryPath } : {}), - ...(settings.claudeAuthTokenHelperCommand - ? { authTokenHelperCommand: settings.claudeAuthTokenHelperCommand } - : {}), + binaryPath: settings.claudeBinaryPath, }, } : {}), diff --git a/apps/web/src/components/settings/SettingsRouteContext.tsx b/apps/web/src/components/settings/SettingsRouteContext.tsx index b49d6f9b..11cd0ccc 100644 --- a/apps/web/src/components/settings/SettingsRouteContext.tsx +++ b/apps/web/src/components/settings/SettingsRouteContext.tsx @@ -90,7 +90,6 @@ export function SettingsRouteContextProvider({ children }: { children: ReactNode currentGitTextGenerationModel !== defaultGitTextGenerationModel; const isInstallSettingsDirty = settings.claudeBinaryPath !== defaults.claudeBinaryPath || - settings.claudeAuthTokenHelperCommand !== defaults.claudeAuthTokenHelperCommand || settings.copilotBinaryPath !== defaults.copilotBinaryPath || settings.copilotConfigDir !== defaults.copilotConfigDir || settings.codexBinaryPath !== defaults.codexBinaryPath || diff --git a/apps/web/src/lib/claudeAuthTokenHelperPresets.ts b/apps/web/src/lib/claudeAuthTokenHelperPresets.ts deleted file mode 100644 index 59dc2c6d..00000000 --- a/apps/web/src/lib/claudeAuthTokenHelperPresets.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface ClaudeAuthTokenHelperPreset { - readonly label: string; - readonly command: string; - readonly description: string; -} - -export const CLAUDE_AUTH_TOKEN_HELPER_PRESETS: readonly ClaudeAuthTokenHelperPreset[] = [ - { - label: "1Password", - command: "op read op://shared/anthropic/token --no-newline", - description: "Reads an Anthropic auth token from 1Password CLI.", - }, - { - label: "Bitwarden", - command: "bw get notes anthropic-auth-token", - description: "Reads an Anthropic auth token from Bitwarden CLI notes.", - }, - { - label: "Doppler", - command: "doppler secrets get ANTHROPIC_AUTH_TOKEN --plain", - description: "Reads ANTHROPIC_AUTH_TOKEN from Doppler.", - }, -] as const; diff --git a/apps/web/src/lib/providerAvailability.test.ts b/apps/web/src/lib/providerAvailability.test.ts index 220ebf36..da867a20 100644 --- a/apps/web/src/lib/providerAvailability.test.ts +++ b/apps/web/src/lib/providerAvailability.test.ts @@ -49,7 +49,7 @@ describe("providerAvailability", () => { ).toBe(false); }); - it("blocks claudeAgent when status is error even if claudeAuthTokenHelperCommand is set and available is true", () => { + it("blocks claudeAgent when status is error", () => { expect( isProviderReadyForThreadSelection({ provider: "claudeAgent", @@ -60,12 +60,11 @@ describe("providerAvailability", () => { authStatus: "unauthenticated", }), ], - claudeAuthTokenHelperCommand: "my-token-helper", }), ).toBe(false); }); - it("allows claudeAgent with claudeAuthTokenHelperCommand when status is ready but auth is unauthenticated", () => { + it("blocks unauthenticated claudeAgent even when the status is otherwise ready", () => { expect( isProviderReadyForThreadSelection({ provider: "claudeAgent", @@ -76,9 +75,8 @@ describe("providerAvailability", () => { authStatus: "unauthenticated", }), ], - claudeAuthTokenHelperCommand: "my-token-helper", }), - ).toBe(true); + ).toBe(false); }); it("treats configured OpenClaw as selectable even when server auth state is unknown", () => { diff --git a/apps/web/src/lib/providerAvailability.ts b/apps/web/src/lib/providerAvailability.ts index c6765010..64017e8a 100644 --- a/apps/web/src/lib/providerAvailability.ts +++ b/apps/web/src/lib/providerAvailability.ts @@ -31,7 +31,6 @@ export function isProviderReadyForThreadSelection(input: { provider: ProviderKind; statuses: ReadonlyArray; openclawGatewayUrl?: string | null | undefined; - claudeAuthTokenHelperCommand?: string | null | undefined; }): boolean { const status = getProviderStatusByKind(input.statuses, input.provider); @@ -46,16 +45,6 @@ export function isProviderReadyForThreadSelection(input: { return false; } - if ( - input.provider === "claudeAgent" && - (input.claudeAuthTokenHelperCommand ?? "").trim().length > 0 && - status.available && - status.status === "ready" && - (status.authStatus ?? status.auth?.status) === "unauthenticated" - ) { - return true; - } - const authStatus = status.authStatus ?? status.auth?.status; return Boolean(status.available && status.status === "ready" && authStatus !== "unauthenticated"); } @@ -63,14 +52,12 @@ export function isProviderReadyForThreadSelection(input: { export function getSelectableThreadProviders(input: { statuses: ReadonlyArray; openclawGatewayUrl?: string | null | undefined; - claudeAuthTokenHelperCommand?: string | null | undefined; }): ProviderKind[] { return THREAD_PROVIDER_ORDER.filter((provider) => isProviderReadyForThreadSelection({ provider, statuses: input.statuses, openclawGatewayUrl: input.openclawGatewayUrl, - claudeAuthTokenHelperCommand: input.claudeAuthTokenHelperCommand, }), ); } diff --git a/apps/web/src/routes/_chat.settings.index.tsx b/apps/web/src/routes/_chat.settings.index.tsx index 272a1fef..657488a0 100644 --- a/apps/web/src/routes/_chat.settings.index.tsx +++ b/apps/web/src/routes/_chat.settings.index.tsx @@ -81,7 +81,6 @@ import { getProviderStatusDescription, getProviderStatusHeading, } from "../components/chat/providerStatusPresentation"; -import { CLAUDE_AUTH_TOKEN_HELPER_PRESETS } from "../lib/claudeAuthTokenHelperPresets"; import { INSTALL_PROVIDER_SETTINGS, PROVIDER_AUTH_GUIDES, @@ -236,7 +235,6 @@ function getAuthenticationBadgeCopy(input: { status: ServerProviderStatus | null; provider: ProviderKind; openclawGatewayUrl: string; - claudeAuthTokenHelperCommand: string; }): { tone: "success" | "warning" | "error"; label: string; @@ -246,7 +244,6 @@ function getAuthenticationBadgeCopy(input: { provider: input.provider, statuses: input.status ? [input.status] : [], openclawGatewayUrl: input.openclawGatewayUrl, - claudeAuthTokenHelperCommand: input.claudeAuthTokenHelperCommand, }) ) { return { tone: "success", label: "Available in thread picker" }; @@ -271,19 +268,16 @@ function AuthenticationStatusCard({ provider, status, openclawGatewayUrl, - claudeAuthTokenHelperCommand, }: { provider: ProviderKind; status: ServerProviderStatus | null; openclawGatewayUrl: string; - claudeAuthTokenHelperCommand: string; }) { const guide = PROVIDER_AUTH_GUIDES[provider]; const badge = getAuthenticationBadgeCopy({ status, provider, openclawGatewayUrl, - claudeAuthTokenHelperCommand, }); const badgeClassName = badge.tone === "success" @@ -419,7 +413,7 @@ function SettingsRouteView() { const [openKeybindingsError, setOpenKeybindingsError] = useState(null); const [openInstallProviders, setOpenInstallProviders] = useState>({ codex: Boolean(settings.codexBinaryPath || settings.codexHomePath), - claudeAgent: Boolean(settings.claudeBinaryPath || settings.claudeAuthTokenHelperCommand), + claudeAgent: Boolean(settings.claudeBinaryPath), gemini: false, copilot: Boolean(settings.copilotBinaryPath || settings.copilotConfigDir), openclaw: Boolean(settings.openclawGatewayUrl || settings.openclawPassword), @@ -474,18 +468,12 @@ function SettingsRouteView() { const codexBinaryPath = settings.codexBinaryPath; const codexHomePath = settings.codexHomePath; const claudeBinaryPath = settings.claudeBinaryPath; - const claudeAuthTokenHelperCommand = settings.claudeAuthTokenHelperCommand; - const selectedClaudeAuthTokenHelperPreset = - CLAUDE_AUTH_TOKEN_HELPER_PRESETS.find( - (preset) => preset.command === claudeAuthTokenHelperCommand, - )?.label ?? ""; const keybindingsConfigPath = serverConfigQuery.data?.keybindingsConfigPath ?? null; const availableEditors = serverConfigQuery.data?.availableEditors; const providerStatuses = serverConfigQuery.data?.providers ?? []; const selectableProviders = getSelectableThreadProviders({ statuses: providerStatuses, openclawGatewayUrl: settings.openclawGatewayUrl, - claudeAuthTokenHelperCommand, }); const gitTextGenerationModelOptions = getAppModelOptions( @@ -527,7 +515,6 @@ function SettingsRouteView() { : savedCustomModelRows.slice(0, 5); const isInstallSettingsDirty = settings.claudeBinaryPath !== defaults.claudeBinaryPath || - settings.claudeAuthTokenHelperCommand !== defaults.claudeAuthTokenHelperCommand || settings.copilotBinaryPath !== defaults.copilotBinaryPath || settings.copilotConfigDir !== defaults.copilotConfigDir || settings.codexBinaryPath !== defaults.codexBinaryPath || @@ -1361,7 +1348,6 @@ function SettingsRouteView() { provider={provider} status={providerStatuses.find((status) => status.provider === provider) ?? null} openclawGatewayUrl={settings.openclawGatewayUrl} - claudeAuthTokenHelperCommand={claudeAuthTokenHelperCommand} /> ))} @@ -1378,7 +1364,6 @@ function SettingsRouteView() { onClick={() => { updateSettings({ claudeBinaryPath: defaults.claudeBinaryPath, - claudeAuthTokenHelperCommand: defaults.claudeAuthTokenHelperCommand, codexBinaryPath: defaults.codexBinaryPath, codexHomePath: defaults.codexHomePath, copilotBinaryPath: defaults.copilotBinaryPath, @@ -1405,9 +1390,7 @@ function SettingsRouteView() { ? settings.codexBinaryPath !== defaults.codexBinaryPath || settings.codexHomePath !== defaults.codexHomePath : providerSettings.provider === "claudeAgent" - ? settings.claudeBinaryPath !== defaults.claudeBinaryPath || - settings.claudeAuthTokenHelperCommand !== - defaults.claudeAuthTokenHelperCommand + ? settings.claudeBinaryPath !== defaults.claudeBinaryPath : settings.copilotBinaryPath !== defaults.copilotBinaryPath || settings.copilotConfigDir !== defaults.copilotConfigDir; const binaryPathValue = @@ -1494,76 +1477,6 @@ function SettingsRouteView() { - {providerSettings.provider === "claudeAgent" ? ( - - ) : null} - {homePathKey ? (