diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index dfb36db66157..407c930fd55b 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -427,20 +427,28 @@ function ProviderConnection(props: { const loading = createMemo(() => integration.loading) const methods = createMemo(() => { const values = integration.latest?.methods.filter( - (method): method is ConnectMethod => method.type === "key" || method.type === "oauth", + (method): method is ConnectMethod => + (method.type === "key" || method.type === "oauth") && !(method.label ?? "").startsWith("Stored API key "), ) return values?.length ? values : fallback() }) const storedKeys = createMemo(() => - (integration.latest?.connections?.filter((c) => c.type === "credential") ?? []) as Array<{ - type: "credential" - id: string - label: string - displayPrefix?: string - displaySuffix?: string - createdAt?: number - cooldownUntil?: number - }>, + (integration.latest?.methods ?? []).flatMap((method) => { + if (method.type !== "key") return [] + const match = (method.label ?? "").match(/^Stored API key (\d+) \(([^.]+)\.\.\.([^)]+)\)$/) + if (!match) return [] + return [ + { + type: "credential" as const, + id: `${props.provider}:${Number(match[1]) - 1}`, + label: `Workspace ${match[1]}`, + displayPrefix: match[2], + displaySuffix: match[3], + createdAt: undefined, + cooldownUntil: undefined, + }, + ] + }), ) const [store, setStore] = createStore({ methodIndex: undefined as undefined | number, diff --git a/packages/app/src/utils/server-compat.ts b/packages/app/src/utils/server-compat.ts index 3b44a720a82e..0199e8803ca6 100644 --- a/packages/app/src/utils/server-compat.ts +++ b/packages/app/src/utils/server-compat.ts @@ -396,20 +396,30 @@ function createV1Api(input: CompatibleInput): CompatibleApi { createdAt?: number cooldownUntil?: number }> - const methods = authMethods.filter((method) => !method.credentialID).map((method, index) => + const stored = authMethods.map((method) => { + if (method.credentialID) return method.credentialID + const match = method.type === "api" ? method.label.match(/^Stored API key (\d+) \(([^.]+)\.\.\.([^)]+)\)$/) : undefined + if (!match) return undefined + return { + credentialID: `${value.integrationID}:${Number(match[1]) - 1}`, + displayPrefix: match[2], + displaySuffix: match[3], + } + }) + const methods = authMethods.map((method, index) => method.type === "api" ? { type: "key" as const, label: method.label } : { type: "oauth" as const, id: String(index), label: method.label, prompts: method.prompts }, ) - const connections = authMethods.flatMap((method) => - method.type === "api" && method.credentialID + const connections = authMethods.flatMap((method, index) => + method.type === "api" && stored[index] ? [ { type: "credential" as const, - id: method.credentialID, + id: typeof stored[index] === "string" ? stored[index] : stored[index].credentialID, label: method.label, - displayPrefix: method.displayPrefix, - displaySuffix: method.displaySuffix, + displayPrefix: typeof stored[index] === "string" ? method.displayPrefix : stored[index].displayPrefix, + displaySuffix: typeof stored[index] === "string" ? method.displaySuffix : stored[index].displaySuffix, createdAt: method.createdAt, cooldownUntil: method.cooldownUntil, }, diff --git a/packages/opencode/src/provider/auth.ts b/packages/opencode/src/provider/auth.ts index b76f6ecf6458..49d5812ecf67 100644 --- a/packages/opencode/src/provider/auth.ts +++ b/packages/opencode/src/provider/auth.ts @@ -181,7 +181,7 @@ const layer: Layer.Layer = Layer. .map((key, index) => Schema.decodeUnknownSync(Method)({ type: "api", - label: `API key ${index + 1}`, + label: `Stored API key ${index + 1} (${key.slice(0, 4)}...${key.slice(-4)})`, prompts: [], credentialID: `${providerID}:${index}`, displayPrefix: key.slice(0, 4),