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
+6 -4
View File
@@ -12,7 +12,8 @@ import { SessionMetadataStore } from "../../src/sessions/metadataStore.js";
describe("MCP routes", () => {
it("protects the internal policy bridge against browser and context injection", async () => {
const app = express(); app.use(express.json());
registerMcpPolicyBridge(app, { internalToken: "MCP_TEST_ONLY", runtime: { mcpReadonlyTools: () => ["mcp_fixture_read"] } });
let builds = 0;
registerMcpPolicyBridge(app, { internalToken: "MCP_TEST_ONLY", runtime: { mcpReadonlyTools: () => { builds++; return ["mcp_fixture_read"]; } } });
const server = app.listen(0, "127.0.0.1");
await new Promise<void>((resolve) => server.once("listening", resolve));
const url = `http://127.0.0.1:${(server.address() as { port: number }).port}/internal/mcp/session-policy`;
@@ -25,7 +26,8 @@ describe("MCP routes", () => {
expect((await post({ session_id: sessionID }, { "Sec-Fetch-Site": "same-origin" })).status).toBe(403);
expect((await post({ session_id: sessionID, project_id: "other" })).status).toBe(400);
expect((await post({ session_id: "missing" })).status).toBe(404);
expect(await (await post({ session_id: sessionID })).json()).toEqual({ mode: "readonly", readonly_tools: ["mcp_fixture_read"] });
expect(await (await post({ session_id: sessionID })).json()).toEqual({ mode: "readonly", readonly_tools: ["mcp_fixture_read"], query_tools: [] });
expect(builds).toBe(1);
} finally {
removeRuntimeSessionContext(sessionID);
await new Promise<void>((resolve) => server.close(() => resolve()));
@@ -61,10 +63,10 @@ describe("MCP routes", () => {
if (failed) throw new Error("SECRET_URL_AND_TOKEN");
return { configuration_errors: [], servers: [{ name: "mcp_fixture", type: "remote", status: "needs_auth", configured_protocol: "auto", tools: [] }] };
} } });
app.use("/api/v1/agent/chat", router);
app.use("/api/v1", router);
const server = app.listen(0, "127.0.0.1");
await new Promise<void>((resolve) => server.once("listening", resolve));
const url = `http://127.0.0.1:${(server.address() as { port: number }).port}/api/v1/agent/chat/session/private-session/mcp`;
const url = `http://127.0.0.1:${(server.address() as { port: number }).port}/api/v1/session/private-session/mcp`;
try {
expect((await originalFetch(url)).status).toBe(401);
const headers = { Authorization: "Bearer OWNER", "X-Project-Id": "project" };