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
This commit is contained in:
ZacharyZhang-NY committed 2026-04-17 01:28:26 -04:00
1 parent 2b63588604
commit bee5535349
2 files changed
+18 -6

No files matched your search

+4 -3
View File
@@ -31,12 +31,13 @@ export class OAuthLoginService {
async start(connectorId: string): Promise<void> {
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)) {
+14 -3
View File
@@ -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<DesktopResult<{ ok: boolean; message: string }>> => {
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,