feat: upgrade investigation and presentation runtime
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { afterEach, expect, it, mock } from "bun:test";
|
||||
import { afterEach, expect, it, mock, spyOn } from "bun:test";
|
||||
import { Client, StreamableHTTPClientTransport, type Tool } from "@modelcontextprotocol/client";
|
||||
import { startQueryMcpServer } from "../../src/mcp/query-server.js";
|
||||
import { createLocalQueryExecutor } from "../../src/mcp/local-query-tools.js";
|
||||
@@ -17,17 +17,17 @@ afterEach(async () => {
|
||||
});
|
||||
const productTool: Tool = { name: "get_task_context", description: "Bound task", inputSchema: { type: "object", properties: { report_revision: { type: "integer", minimum: 1 } }, additionalProperties: false } };
|
||||
|
||||
it("advertises simulation budgets and derives the native connection ceiling from the catalog", async () => {
|
||||
it("hides HTTP budgets from models and fixes the native connection ceiling", async () => {
|
||||
const simulation: Tool = { name: "run_simulation", inputSchema: { type: "object", properties: {
|
||||
timeout_seconds: { type: "integer", minimum: 1, maximum: 3600, default: 120 },
|
||||
timeout_seconds: { type: "integer", minimum: 1, maximum: 240, default: 120 },
|
||||
}, additionalProperties: false } };
|
||||
const { server, client, call, query } = await setup({ productTools: [simulation] });
|
||||
setRuntimeSessionContext(owner);
|
||||
expect(server.executionTimeoutMs).toBe(35_000);
|
||||
expect((await client.listTools()).tools[0].inputSchema.properties?.timeout_seconds).toMatchObject({ maximum: 3600 });
|
||||
expect((await call("run_simulation", { timeout_seconds: 900 })).isError).not.toBeTrue();
|
||||
expect((query.mock.calls[0] as unknown as unknown[])[3]).toEqual({ timeout_seconds: 900 });
|
||||
try { await call("run_simulation", { timeout_seconds: 3601 }); } catch { /* SDK schema rejection */ }
|
||||
expect(server.executionTimeoutMs).toBe(300_000);
|
||||
expect((await client.listTools()).tools[0].inputSchema.properties).not.toHaveProperty("timeout_seconds");
|
||||
expect((await call("run_simulation", {})).isError).not.toBeTrue();
|
||||
expect((query.mock.calls[0] as unknown as unknown[])[3]).toEqual({});
|
||||
try { await call("run_simulation", { timeout_seconds: 241 }); } catch { /* SDK schema rejection */ }
|
||||
expect(query).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it("discovers calculations natively but denies verified readers before upstream dispatch", async () => {
|
||||
@@ -183,3 +183,23 @@ it("distinguishes safe network and timeout failures without upstream text", asyn
|
||||
expect(JSON.stringify(result)).not.toContain("SECRET");
|
||||
}
|
||||
});
|
||||
|
||||
for (const stage of ["reader", "identity", "artifact"] as const) {
|
||||
it(`bounds a hanging ${stage} operation within the host deadline`, async () => {
|
||||
const never = () => new Promise<never>(() => {});
|
||||
const name = stage === "artifact" ? "export_project_model" : "get_task_context";
|
||||
const { call } = await setup({ productTools: [{ ...productTool, name }],
|
||||
...(stage === "reader" ? { resolveReader: never } : {}),
|
||||
...(stage === "identity" ? { resolveNativeCall: never } : {}),
|
||||
...(stage === "artifact" ? { artifactWorkspace: never } : {}),
|
||||
});
|
||||
if (stage !== "reader") setRuntimeSessionContext(owner);
|
||||
const original = AbortSignal.timeout.bind(AbortSignal);
|
||||
const timeout = spyOn(AbortSignal, "timeout").mockImplementation((ms) => original(ms === 180_000 ? 20 : ms));
|
||||
try {
|
||||
const result = await call(name);
|
||||
expect(result.isError).toBeTrue();
|
||||
expect(JSON.stringify(result)).toContain("Query timed out");
|
||||
} finally { timeout.mockRestore(); }
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user