fix(agent): stabilize sandboxed streaming workflows
This commit is contained in:
@@ -90,6 +90,136 @@ describe("OpencodeRuntimeAdapter.ensureClient", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("OpencodeRuntimeAdapter.subscribeEvents", () => {
|
||||
it("subscribes to the conversation workspace directory", async () => {
|
||||
const calls: Array<Record<string, unknown> | undefined> = [];
|
||||
const stream = (async function* () {
|
||||
return;
|
||||
})();
|
||||
const client = {
|
||||
event: {
|
||||
subscribe: async (input?: Record<string, unknown>) => {
|
||||
calls.push(input);
|
||||
return { stream };
|
||||
},
|
||||
},
|
||||
} as unknown as OpencodeClient;
|
||||
const runtime = Object.assign(Object.create(OpencodeRuntimeAdapter.prototype), {
|
||||
ensureClient: async () => client,
|
||||
}) as OpencodeRuntimeAdapter;
|
||||
|
||||
await expect(
|
||||
runtime.subscribeEvents("/tmp/conversation-workspace-1"),
|
||||
).resolves.toBe(stream);
|
||||
expect(calls).toEqual([
|
||||
{ directory: "/tmp/conversation-workspace-1" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("OpencodeRuntimeAdapter.prompt", () => {
|
||||
it("forwards the final answer schema", async () => {
|
||||
const calls: unknown[] = [];
|
||||
const client = {
|
||||
session: {
|
||||
prompt: async (input: unknown) => {
|
||||
calls.push(input);
|
||||
return { data: {} };
|
||||
},
|
||||
},
|
||||
} as unknown as OpencodeClient;
|
||||
const runtime = Object.assign(Object.create(OpencodeRuntimeAdapter.prototype), {
|
||||
ensureClient: async () => client,
|
||||
}) as OpencodeRuntimeAdapter;
|
||||
|
||||
await runtime.prompt(
|
||||
"session-1",
|
||||
"分析供水分区",
|
||||
{ providerID: "deepseek", modelID: "deepseek-v4-flash" },
|
||||
{
|
||||
format: {
|
||||
type: "json_schema",
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: { answer: { type: "string" } },
|
||||
required: ["answer"],
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(calls).toEqual([
|
||||
{
|
||||
sessionID: "session-1",
|
||||
model: {
|
||||
providerID: "deepseek",
|
||||
modelID: "deepseek-v4-flash",
|
||||
},
|
||||
format: {
|
||||
type: "json_schema",
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: { answer: { type: "string" } },
|
||||
required: ["answer"],
|
||||
},
|
||||
},
|
||||
parts: [{ type: "text", text: "分析供水分区" }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("OpencodeRuntimeAdapter interaction replies", () => {
|
||||
it("replies to permissions in the conversation workspace directory", async () => {
|
||||
const calls: unknown[] = [];
|
||||
const client = {
|
||||
permission: {
|
||||
reply: async (input: unknown) => {
|
||||
calls.push(input);
|
||||
return { data: true };
|
||||
},
|
||||
},
|
||||
} as unknown as OpencodeClient;
|
||||
const runtime = Object.assign(Object.create(OpencodeRuntimeAdapter.prototype), {
|
||||
ensureClient: async () => client,
|
||||
}) as OpencodeRuntimeAdapter;
|
||||
|
||||
await runtime.replyPermission({
|
||||
requestId: "permission-1",
|
||||
sessionId: "session-1",
|
||||
directory: "/tmp/conversation-workspace-1",
|
||||
reply: "once",
|
||||
});
|
||||
|
||||
expect(calls).toEqual([
|
||||
{
|
||||
requestID: "permission-1",
|
||||
directory: "/tmp/conversation-workspace-1",
|
||||
reply: "once",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("fails when OpenCode returns no permission reply data", async () => {
|
||||
const client = {
|
||||
permission: {
|
||||
reply: async () => ({ data: undefined }),
|
||||
},
|
||||
} as unknown as OpencodeClient;
|
||||
const runtime = Object.assign(Object.create(OpencodeRuntimeAdapter.prototype), {
|
||||
ensureClient: async () => client,
|
||||
}) as OpencodeRuntimeAdapter;
|
||||
|
||||
await expect(
|
||||
runtime.replyPermission({
|
||||
requestId: "permission-1",
|
||||
directory: "/tmp/conversation-workspace-1",
|
||||
reply: "once",
|
||||
}),
|
||||
).rejects.toThrow("permission.reply returned no data");
|
||||
});
|
||||
});
|
||||
|
||||
describe("OpencodeRuntimeAdapter.createSession", () => {
|
||||
it("creates a real chat session inside a dedicated conversation workspace", async () => {
|
||||
const workspaceRoot = await mkdtemp(join(tmpdir(), "tjwater-conversations-"));
|
||||
@@ -225,11 +355,16 @@ describe("OpencodeRuntimeAdapter.warmup", () => {
|
||||
await runtime.replyQuestion({
|
||||
requestId: "question-1",
|
||||
sessionId: "session-1",
|
||||
directory: "/tmp/conversation-workspace-1",
|
||||
answers: [["继续"]],
|
||||
});
|
||||
|
||||
expect(calls).toEqual([
|
||||
{ requestID: "question-1", answers: [["继续"]] },
|
||||
{
|
||||
requestID: "question-1",
|
||||
directory: "/tmp/conversation-workspace-1",
|
||||
answers: [["继续"]],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user