feat(agent): unify MCP tools and adopt Responses delivery

Move project and host queries into native MCP with host-owned OAuth/context,
while retaining memory, skills, actions and publication plugins. Add nearby-model
queries and explicit chat/task/learning model defaults.

Adopt Responses HTTP/SSE and native steer/queue inbox delivery, preserving scoped
session ownership, pending input edits and investigation communication.

Disable local-provider discovery: Server /health allowed native vLLM to probe
/v1/models on port 8000. A native before/after regression prevents recurrence.

Validation: 170 focused Bun tests; service/plugin typechecks; native discovery,
provider-discovery and input-inbox smoke checks; no paid model inference.
This commit is contained in:
2026-10-19 18:46:58 +08:00
parent f5c3cde2c2
commit 6a49d2209e
164 changed files with 12286 additions and 2368 deletions
+22
View File
@@ -0,0 +1,22 @@
import type { CallToolResult } from "@modelcontextprotocol/client";
import { queryMcpToolId } from "../runtime/product-mcp-tools.js";
// The local server exposes tools only. Retain the saved Server evidence, but
// replace its upstream-only resource link with this server's paging tool.
export function localEvidenceResult(result: CallToolResult): CallToolResult {
if (result.isError || !result.content.some((item) => item.type === "resource_link" && item.uri.startsWith("tjwater://"))) return result;
const raw = result.structuredContent;
const output = raw && typeof raw === "object" && !Array.isArray(raw) ? raw as Record<string, unknown> : undefined;
const evidenceId = output?.evidence_id;
if (!output || typeof evidenceId !== "string" || !evidenceId || evidenceId.length > 160) throw new Error("Saved evidence response has no identifier");
const originalData = output.data && typeof output.data === "object" && !Array.isArray(output.data) ? output.data as Record<string, unknown> : {};
const { resource_uri: _uri, ...data } = originalData;
const next = { ...output,
data: { ...data, evidence_read: { tool: queryMcpToolId("get_task_evidence"), arguments: { evidence_id: evidenceId, limit: 20, offset: 0 } } },
data_gaps: [...(Array.isArray(output.data_gaps) ? output.data_gaps.filter((gap) => gap !== "Inline result abbreviated; read the saved evidence resource") : []),
"Inline result abbreviated; use evidence_read with a small page and select deeper data_path values when needed"],
};
return { ...result, structuredContent: next,
content: [{ type: "text", text: JSON.stringify(next) }, ...result.content.filter((item) => item.type !== "text" && item.type !== "resource_link")],
};
}