

























@@ -79,6 +79,14 @@ function outputItem(payload: unknown, index = 0) {
7979return requireRecord(output[index], `response output ${index}`);
8080}
818182+function outputToolArgs(payload: unknown, index = 0) {
83+const item = outputItem(payload, index);
84+if (typeof item.arguments !== "string") {
85+throw new Error("Expected response output arguments");
86+}
87+return requireRecord(JSON.parse(item.arguments) as unknown, "response output arguments");
88+}
89+8290function outputContentItem(payload: unknown, outputIndex = 0, contentIndex = 0) {
8391const content = requireArray(outputItem(payload, outputIndex).content, "response output content");
8492return requireRecord(content[contentIndex], `response content ${contentIndex}`);
@@ -3017,7 +3025,7 @@ describe("qa mock openai server", () => {
30173025| { name: string; input: Record<string, unknown> }
30183026| undefined;
30193027expect(toolUseBlock?.name).toBe("read");
3020-expect(toolUseBlock?.input).toEqual({ path: "repo/qa/scenarios/index.md" });
3028+expect(toolUseBlock?.input).toEqual({ path: "repo/docs/help/testing.md" });
3021302930223030const debugResponse = await fetch(`${server.baseUrl}/debug/last-request`);
30233031expect(debugResponse.status).toBe(200);
@@ -3275,7 +3283,7 @@ describe("qa mock openai server", () => {
32753283expect(body).toContain("event: content_block_start");
32763284expect(body).toContain('"type":"tool_use"');
32773285expect(body).toContain('"name":"read"');
3278-expect(body).toContain("repo/qa/scenarios/index.md");
3286+expect(body).toContain("repo/docs/help/testing.md");
32793287expect(body).toContain("event: message_delta");
32803288expect(body).toContain("event: message_stop");
32813289});
@@ -3739,6 +3747,77 @@ describe("resolveProviderVariant", () => {
37393747});
3740374837413749describe("qa mock openai server provider variant tagging", () => {
3750+it("pins provider-specific plans for parity scenarios", async () => {
3751+const sourcePrompt =
3752+"Read the seeded docs and source plan, then report grouped into Worked, Failed, Blocked, and Follow-up.";
3753+const handoffPrompt =
3754+"Delegate one bounded QA task to a subagent. Wait for the subagent to finish.";
3755+const fanoutPrompt =
3756+"Subagent fanout synthesis check: delegate two bounded subagents sequentially, then report both results together.";
3757+3758+const openaiSourceServer = await startMockServer();
3759+const openaiSource = await expectResponsesJson(openaiSourceServer, {
3760+model: "openai/gpt-5.5",
3761+stream: false,
3762+input: [makeUserInput(sourcePrompt)],
3763+});
3764+expect(outputToolArgs(openaiSource)).toEqual({ path: "repo/qa/scenarios/index.md" });
3765+3766+const anthropicSourceServer = await startMockServer();
3767+const anthropicSource = await expectResponsesJson(anthropicSourceServer, {
3768+model: "anthropic/claude-opus-4-7",
3769+stream: false,
3770+input: [makeUserInput(sourcePrompt)],
3771+});
3772+expect(outputToolArgs(anthropicSource)).toEqual({ path: "repo/docs/help/testing.md" });
3773+3774+const openaiHandoffServer = await startMockServer();
3775+const openaiHandoff = await expectResponsesJson(openaiHandoffServer, {
3776+model: "gpt-5.5",
3777+stream: false,
3778+input: [makeUserInput(handoffPrompt)],
3779+});
3780+expect(outputToolArgs(openaiHandoff)).toMatchObject({
3781+label: "qa-sidecar",
3782+task: "Inspect the QA workspace and return one concise protocol note.",
3783+});
3784+3785+const anthropicHandoffServer = await startMockServer();
3786+const anthropicHandoff = await expectResponsesJson(anthropicHandoffServer, {
3787+model: "claude-opus-4-7",
3788+stream: false,
3789+input: [makeUserInput(handoffPrompt)],
3790+});
3791+expect(outputToolArgs(anthropicHandoff)).toMatchObject({
3792+label: "qa-sidecar",
3793+task: "Inspect the QA docs fixture and return one concise protocol note.",
3794+});
3795+3796+const openaiFanoutServer = await startMockServer();
3797+const openaiFanout = await expectResponsesJson(openaiFanoutServer, {
3798+model: "openai/gpt-5.5",
3799+stream: false,
3800+tools: [SESSIONS_SPAWN_TOOL],
3801+input: [makeUserInput(fanoutPrompt)],
3802+});
3803+expect(outputToolArgs(openaiFanout)).toMatchObject({
3804+label: "qa-fanout-alpha",
3805+task: "Fanout worker alpha: inspect the QA workspace and finish with exactly ALPHA-OK.",
3806+});
3807+3808+const anthropicFanoutServer = await startMockServer();
3809+const anthropicFanout = await expectResponsesJson(anthropicFanoutServer, {
3810+model: "anthropic/claude-opus-4-7",
3811+stream: false,
3812+tools: [SESSIONS_SPAWN_TOOL],
3813+input: [makeUserInput(fanoutPrompt)],
3814+});
3815+expect(outputToolArgs(anthropicFanout)).toMatchObject({
3816+label: "qa-fanout-alpha",
3817+task: "Fanout worker alpha: inspect the QA docs fixture and finish with exactly ALPHA-OK.",
3818+});
3819+});
3820+37423821it("records providerVariant on /debug/last-request for openai requests", async () => {
37433822const server = await startQaMockOpenAiServer({
37443823host: "127.0.0.1",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。