From bee5535349ef1e7847be064e0aa1472b817e780d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 01:28:26 -0400 Subject: [PATCH] fix(credentials): guard optional auth/provider when resolving credentials - oauth-login-service.start: require definition.auth to be present and oauth kind before dispatching; captures oauthId in a local so the rest of the flow does not re-assert the nullable chain - ipc-credentials-handlers save: reject connectors without an auth schema instead of crashing on property access - ipc-credentials-handlers test: require provider and defaultModel to be set before calling into pi-ai, returning a diagnostic result otherwise --- src/main/credentials/oauth-login-service.ts | 7 ++++--- src/main/ipc-credentials-handlers.ts | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/credentials/oauth-login-service.ts b/src/main/credentials/oauth-login-service.ts index 60cf8877..73881468 100644 --- a/src/main/credentials/oauth-login-service.ts +++ b/src/main/credentials/oauth-login-service.ts @@ -31,12 +31,13 @@ export class OAuthLoginService { async start(connectorId: string): Promise { const definition = getConnectorDefinition(connectorId); - if (definition.auth.type !== "oauth") { + if (!definition.auth || definition.auth.type !== "oauth" || !definition.auth.oauthId) { throw new Error(`Connector ${connectorId} does not use OAuth.`); } - const provider = getOAuthProvider(definition.auth.oauthId); + const oauthId = definition.auth.oauthId; + const provider = getOAuthProvider(oauthId); if (!provider) { - throw new Error(`Unknown OAuth provider: ${definition.auth.oauthId}`); + throw new Error(`Unknown OAuth provider: ${oauthId}`); } if (this.active.has(connectorId)) { diff --git a/src/main/ipc-credentials-handlers.ts b/src/main/ipc-credentials-handlers.ts index 99a09695..c147674e 100644 --- a/src/main/ipc-credentials-handlers.ts +++ b/src/main/ipc-credentials-handlers.ts @@ -89,6 +89,9 @@ export function registerCredentialIpcHandlers(deps: CredentialHandlerDeps): () = if (typeof definition === "string") return deps.fail("UNKNOWN_CONNECTOR", definition); const payload = parsed.data.payload; + if (!definition.auth) { + return deps.fail("UNSUPPORTED_PAYLOAD", `Connector ${parsed.data.connectorId} has no auth schema.`); + } if (definition.auth.type === "oauth") { return deps.fail("UNSUPPORTED_PAYLOAD", "Use OAuth login flow for OAuth connectors."); } @@ -141,9 +144,17 @@ export function registerCredentialIpcHandlers(deps: CredentialHandlerDeps): () = const runTest = async (): Promise> => { try { - const model = resolveModel(definition.provider, definition.defaultModel); - if (!model) return ok({ ok: false, message: `Unknown model ${definition.defaultModel} for provider ${definition.provider}` }); - const extraHeaders = resolveExtraStreamHeaders(definition.provider, resolved.apiKey); + if (!definition.provider) { + return ok({ ok: false, message: `Connector ${parsed.data.connectorId} has no pi-ai provider id configured.` }); + } + if (!definition.defaultModel) { + return ok({ ok: false, message: `Connector ${parsed.data.connectorId} has no default model configured.` }); + } + const provider = definition.provider; + const defaultModel = definition.defaultModel; + const model = resolveModel(provider, defaultModel); + if (!model) return ok({ ok: false, message: `Unknown model ${defaultModel} for provider ${provider}` }); + const extraHeaders = resolveExtraStreamHeaders(provider, resolved.apiKey); const options: SimpleStreamOptions = { apiKey: resolved.apiKey, maxTokens: 1,