feat(agent): improve investigation contracts and runtime readiness
Generic Container CI/CD / test-build-publish (push) Successful in 1m53s
Agent CI/CD / build-test-publish-and-deploy (push) Successful in 1m53s

This commit is contained in:
2026-11-07 19:43:57 +08:00
parent c7b750b099
commit b8f7edb3ee
29 changed files with 1465 additions and 119 deletions
+19 -1
View File
@@ -1,6 +1,6 @@
import { describe, expect, it } from "bun:test";
import { streamPromptResponse } from "../../src/routes/chatStream.js";
import type { OpencodeRuntimeAdapter } from "../../src/runtime/opencode.js";
import { McpPreparationError, type OpencodeRuntimeAdapter } from "../../src/runtime/opencode.js";
type Output = { event: string; data: Record<string, unknown> };
const textStart = { type: "message.part.updated", properties: { sessionID: "s", part: { id: "text", type: "text", text: "" } } };
@@ -143,3 +143,21 @@ describe("stream stage boundaries", () => {
expect(output.some((item) => item.event === "progress" && item.data.id === "query")).toBe(false);
});
});
it("propagates MCP_NOT_READY without completing an artifact-free investigation", async () => {
const output: Output[] = [];
const failure = new McpPreparationError("等待业务工具目录就绪超时");
let completionChecks = 0;
const runtime = createRuntime({ [Symbol.asyncIterator]: () => ({
next: () => new Promise<IteratorResult<unknown>>(() => {}),
return: async () => ({ done: true as const, value: undefined }),
}) }, { prompt: async () => { throw failure; } });
let caught: unknown;
try { await run(runtime, output, { beforeIdle: async () => { completionChecks++; return true; } }); }
catch (error) { caught = error; }
expect(caught).toBe(failure);
expect(caught).toMatchObject({ code: "MCP_NOT_READY" });
expect(completionChecks).toBe(0);
expect(output.some((item) => ["tool_call", "final_answer", "done"].includes(item.event))).toBe(false);
});