Fix Claude bypass mode after query restarts

Closes #127
This commit is contained in:
Mohamed Boudra
2026-04-01 23:58:00 +07:00
parent cc09b61b19
commit a4326ec5c0
3 changed files with 75 additions and 0 deletions
@@ -213,6 +213,25 @@ describe("ClaudeAgentSession integration", () => {
}
}, 60_000);
test.runIf(canRunClaudeIntegration)(
"keeps bypassPermissions available after a thinking-option restart",
async () => {
const handle = await createSession({
cwdPrefix: "claude-agent-bypass-restart-",
modeId: "bypassPermissions",
});
try {
await handle.session.setMode("acceptEdits");
await handle.session.setThinkingOption("high");
await expect(handle.session.setMode("bypassPermissions")).resolves.toBeUndefined();
} finally {
await cleanupSession(handle);
}
},
60_000,
);
test.runIf(canRunClaudeIntegration)(
"supportedModels returns the current abstract Claude SDK model shape",
async () => {
@@ -783,6 +783,58 @@ describe("ClaudeAgentSession redesign invariants", () => {
}
});
test("preserves bypass capability across query restarts triggered by thinking changes", async () => {
const capturedOptions: Array<{
permissionMode?: string;
allowDangerouslySkipPermissions?: boolean;
effort?: string;
}> = [];
sdkQueryFactory.mockImplementation(
({
options,
}: {
options: {
permissionMode?: string;
allowDangerouslySkipPermissions?: boolean;
effort?: string;
};
}) => {
capturedOptions.push({
permissionMode: options.permissionMode,
allowDangerouslySkipPermissions: options.allowDangerouslySkipPermissions,
effort: options.effort,
});
return createBaseQueryMock(
vi.fn(async () => ({ done: true, value: undefined })),
);
},
);
const session = await createSession();
try {
await session.setMode("bypassPermissions");
await session.setMode("acceptEdits");
await session.setThinkingOption("high");
await session.setMode("bypassPermissions");
expect(capturedOptions).toHaveLength(2);
expect(capturedOptions[0]).toMatchObject({
permissionMode: "default",
allowDangerouslySkipPermissions: true,
});
expect(capturedOptions[1]).toMatchObject({
permissionMode: "acceptEdits",
allowDangerouslySkipPermissions: true,
effort: "high",
});
} finally {
await session.close();
}
});
test("reuses one autonomous run for unbound stream_event bursts with no foreground run", async () => {
const session = await createSession();
const internal = session as unknown as {
@@ -1889,6 +1889,10 @@ class ClaudeAgentSession implements AgentSession {
cwd: this.config.cwd,
includePartialMessages: true,
permissionMode: this.currentMode,
// Dynamic mode switching can recreate the underlying Claude query. Keep the
// bypass launch capability available so later setPermissionMode("bypassPermissions")
// calls do not fail after a model/thinking/rewind-driven restart.
allowDangerouslySkipPermissions: true,
agents: this.defaults?.agents,
canUseTool: this.handlePermissionRequest,
...(claudeBinary ? { pathToClaudeCodeExecutable: claudeBinary } : {}),