diff --git a/packages/squad-cli/src/cli/shell/index.ts b/packages/squad-cli/src/cli/shell/index.ts index 251da8249..775b3c31b 100644 --- a/packages/squad-cli/src/cli/shell/index.ts +++ b/packages/squad-cli/src/cli/shell/index.ts @@ -87,7 +87,7 @@ const storage = new FSStorageProvider(); * Approve all permission requests. CLI runs locally with user trust, * so no interactive confirmation is needed. */ -const approveAllPermissions: SquadPermissionHandler = () => ({ kind: 'approved' }); +const approveAllPermissions: SquadPermissionHandler = () => ({ kind: 'approve-once' }); /** Debug logger — writes to stderr only when SQUAD_DEBUG=1. */ function debugLog(...args: unknown[]): void { diff --git a/packages/squad-sdk/src/adapter/client.ts b/packages/squad-sdk/src/adapter/client.ts index 6f654e5f7..d508417c9 100644 --- a/packages/squad-sdk/src/adapter/client.ts +++ b/packages/squad-sdk/src/adapter/client.ts @@ -505,7 +505,7 @@ export class SquadClient { if (msg.includes('onPermissionRequest')) { throw new Error( 'Session creation failed: an onPermissionRequest handler is required. ' + - 'Pass { onPermissionRequest: () => ({ kind: "approved" }) } in your session config ' + + 'Pass { onPermissionRequest: () => ({ kind: "approve-once" }) } in your session config ' + 'to approve all permissions, or provide a custom handler.' ); } diff --git a/packages/squad-sdk/src/adapter/types.ts b/packages/squad-sdk/src/adapter/types.ts index 8dc73dade..900a61e99 100644 --- a/packages/squad-sdk/src/adapter/types.ts +++ b/packages/squad-sdk/src/adapter/types.ts @@ -588,17 +588,17 @@ export interface SquadPermissionRequest { /** * Result of a permission request. - */ -export interface SquadPermissionRequestResult { - /** Outcome of the permission request */ - kind: - | "approved" - | "denied-by-rules" - | "denied-no-approval-rule-and-could-not-request-from-user" - | "denied-interactively-by-user"; - /** Rules that influenced the decision */ - rules?: unknown[]; -} + * + * Mirrors Copilot SDK PermissionDecision semantics (v1.0.54+). + */ +export type SquadPermissionRequestResult = + | { kind: "approve-once" } + | { kind: "approve-for-session"; approval?: unknown; domain?: string } + | { kind: "approve-for-location"; approval: unknown; locationKey: string } + | { kind: "approve-permanently"; domain: string } + | { kind: "reject"; feedback?: string } + | { kind: "user-not-available" } + | { kind: "no-result" }; /** * Handler for permission requests from the agent. diff --git a/test/adapter-client.test.ts b/test/adapter-client.test.ts index b2efe2415..255a9d369 100644 --- a/test/adapter-client.test.ts +++ b/test/adapter-client.test.ts @@ -286,6 +286,18 @@ describe('SquadClient — Auto-Reconnection', () => { await expect(client.createSession()).rejects.toThrow('ECONNREFUSED'); }); + it('should provide approve-once guidance for permission handler errors', async () => { + const client = new SquadClient({ autoReconnect: false }); + await client.connect(); + + const MockedCopilotClient = CopilotClient as unknown as ReturnType; + const instance = MockedCopilotClient.mock.results[0].value; + + instance.createSession.mockRejectedValue(new Error('onPermissionRequest is required')); + + await expect(client.createSession()).rejects.toThrow('kind: "approve-once"'); + }); + it('should not auto-reconnect after manual disconnect', async () => { const client = new SquadClient({ autoReconnect: true, autoStart: false }); await client.connect();