feat: add scoped history and artifacts
Generic Container CI/CD / test-build-publish (push) Failing after 8m25s
Agent CI/CD / build-test-publish-and-deploy (push) Failing after 8m25s

This commit is contained in:
2026-10-22 18:40:20 +08:00
parent bc4e9834e5
commit 7d47a2df86
48 changed files with 2632 additions and 78 deletions
+8 -1
View File
@@ -8,6 +8,7 @@ import { localQueryDescriptions, localQueryInputs } from "./local-query-tools.js
import { allowedQueryTools } from "../runtime/query-mcp-policy.js";
import { localEvidenceResult } from "./evidence-result.js";
import { nativeQueryTimeout, queryTimeouts } from "./query-timeouts.js";
import { saveMcpArtifact } from "./artifact-files.js";
export type LocalQueryName = typeof LOCAL_QUERY_TOOLS[number];
const productNames = new Set<string>(PRODUCT_MCP_TOOLS);
@@ -16,6 +17,7 @@ export function createQueryMcpHandler(options: {
internalToken: string; productClient: Pick<McpQueryClient, "query"> | null; productTools: Tool[];
resolveReader: (id: string) => Promise<QueryOwner | null>;
executeLocal: (name: LocalQueryName, args: Record<string, unknown>, context: RuntimeSessionContext, signal: AbortSignal) => Promise<unknown>;
artifactWorkspace?: (context: RuntimeSessionContext) => Promise<string>;
}) {
const definitions: Tool[] = [...options.productTools, ...LOCAL_QUERY_TOOLS.map((name) => ({ name, description: localQueryDescriptions[name],
inputSchema: z.toJSONSchema(localQueryInputs[name], { io: "input" }) as Tool["inputSchema"], annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: name === "geocode" } }))];
@@ -38,7 +40,12 @@ export function createQueryMcpHandler(options: {
// JSON-RPC IDs may restart on a native MCP reconnect. Use a host
// request key, stable across this client's auth/transport retries,
// so a later query cannot collide with a saved evidence receipt.
return localEvidenceResult(await options.productClient.query(id, owner, definition.name, query, randomUUID(), signal));
const result = await options.productClient.query(id, owner, definition.name, query, randomUUID(), signal);
if (["export_project_model", "export_sensor_placement"].includes(definition.name) && !result.isError) {
if (!options.artifactWorkspace) return rejected("Export workspace unavailable");
return await saveMcpArtifact(result, owner.context, await options.artifactWorkspace(owner.context));
}
return localEvidenceResult(result);
}
const value = await options.executeLocal(definition.name as LocalQueryName, args, owner.context, signal);
signal.throwIfAborted();