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
+65
View File
@@ -0,0 +1,65 @@
import { type Express } from "express";
import { z } from "zod";
import { isTrustedInternalBridgeRequest } from "../product/internal-bridge-auth.js";
import { operationalTaskClient, type OperationalTaskClient, taskArtifactBridgeSchema } from "../product/operational-task-client.js";
import { taskPresentationBridgeSchema } from "../product/task-presentation.js";
import { getRuntimeSessionContext } from "../runtime/sessionContext.js";
const artifactsInputSchema = taskArtifactBridgeSchema.and(z.object({ session_id: z.string().trim().min(1).max(128) }));
export function registerTaskPublicationBridge(app: Express, options: {
internalToken: string;
client?: Pick<OperationalTaskClient, "publishArtifacts" | "publishPresentation">;
}) {
const client = options.client ?? operationalTaskClient;
for (const kind of ["artifacts", "presentation"] as const) {
app.post(`/internal/operational-task/${kind}`, async (req, res) => {
if (!isTrustedInternalBridgeRequest(req, options.internalToken)) {
res.status(403).json({ message: "forbidden" });
return;
}
const sessionId = typeof req.body?.session_id === "string" ? req.body.session_id.trim() : "";
const context = sessionId ? getRuntimeSessionContext(sessionId) : null;
if (!context?.taskId) {
res.status(403).json({ message: "operational task context unavailable" });
return;
}
if ((kind === "presentation" || req.body?.progress !== undefined) && context.purpose !== "task_execution") {
res.status(403).json({ message: "task execution context required" });
return;
}
try {
if (kind === "presentation") {
const parsed = taskPresentationBridgeSchema.safeParse(req.body);
if (!parsed.success) {
res.status(400).json({ message: "invalid task presentation", detail: parsed.error.flatten() });
return;
}
res.json(await client.publishPresentation(sessionId, context.taskId, {
requestId: parsed.data.request_id,
sourceSessionId: context.clientSessionId,
command: parsed.data.command,
}));
} else {
const parsed = artifactsInputSchema.safeParse(req.body);
if (!parsed.success) {
res.status(400).json({ message: "invalid task artifacts", detail: parsed.error.flatten() });
return;
}
res.json(await client.publishArtifacts(sessionId, context.taskId, {
requestId: parsed.data.request_id,
sourceSessionId: context.clientSessionId,
evidence: parsed.data.evidence,
executionPlan: parsed.data.execution_plan,
report: parsed.data.report,
progress: parsed.data.progress,
}));
}
} catch (error) {
const status = error && typeof error === "object" && "status" in error && typeof error.status === "number" ? error.status : 502;
res.status(status).json({ message: error instanceof Error ? error.message : `task ${kind} publish failed` });
}
});
}
}