mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-02 06:33:05 +00:00
fix(server): a rejected OpenCode auto_accept leaves the session asking for permission
applyOptions committed the new flag before approving pending requests, so a failed reply left the session auto-approving while the stored option stayed off. The flag is restored when the apply throws.
This commit is contained in:
@@ -50,6 +50,44 @@ describe("OpenCode v2 session lifecycle", () => {
|
||||
await session.close();
|
||||
});
|
||||
|
||||
test("a rejected auto_accept leaves the running session asking for permission", async () => {
|
||||
const harness = new V2Harness();
|
||||
const permissions = [
|
||||
{ id: "approval", sessionID: "session", action: "shell", resources: ["pwd"] },
|
||||
];
|
||||
harness.api.permission.list = async () => permissions;
|
||||
const replies: string[] = [];
|
||||
harness.api.permission.reply = async (input) => {
|
||||
replies.push(input.requestID);
|
||||
throw new Error("upstream refused");
|
||||
};
|
||||
const client = new OpenCodeV2AgentClient({
|
||||
logger: createTestLogger(),
|
||||
runtime: harness.runtime,
|
||||
});
|
||||
const session = await client.createSession({ provider: "opencode", cwd: "/tmp/project" });
|
||||
try {
|
||||
await expect(session.applyOptions?.({ auto_accept: true })).rejects.toThrow(
|
||||
"upstream refused",
|
||||
);
|
||||
|
||||
const next = {
|
||||
id: "next",
|
||||
sessionID: "session",
|
||||
action: "shell",
|
||||
resources: ["ls"],
|
||||
};
|
||||
permissions.push(next);
|
||||
harness.push({ id: "asked", created: 2, type: "permission.asked", data: next });
|
||||
|
||||
const pendingIds = () => session.getPendingPermissions().map(({ id }) => id);
|
||||
await expect.poll(pendingIds).toContain("next");
|
||||
expect(replies).not.toContain("next");
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects a live permission change the running session cannot apply", async () => {
|
||||
const harness = new V2Harness();
|
||||
const client = new OpenCodeV2AgentClient({
|
||||
|
||||
@@ -376,11 +376,18 @@ export class OpenCodeV2Session implements AgentSession {
|
||||
);
|
||||
if (!("auto_accept" in options)) return;
|
||||
const value = next?.auto_accept === true;
|
||||
this.config.providerOptions = { ...this.config.providerOptions, auto_accept: value };
|
||||
if (value && !this.config.toolPolicy)
|
||||
for (const request of this.permissions.list())
|
||||
if (request.kind !== "question")
|
||||
await this.respondToPermission(request.id, { behavior: "allow" });
|
||||
const previous = this.config.providerOptions;
|
||||
this.config.providerOptions = { ...previous, auto_accept: value };
|
||||
try {
|
||||
if (value && !this.config.toolPolicy)
|
||||
for (const request of this.permissions.list())
|
||||
if (request.kind !== "question")
|
||||
await this.respondToPermission(request.id, { behavior: "allow" });
|
||||
} catch (error) {
|
||||
// A rejected apply stores nothing, so the running session keeps asking as it did.
|
||||
this.config.providerOptions = previous;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async listCommands() {
|
||||
await this.reconnectIfExited();
|
||||
|
||||
Reference in New Issue
Block a user