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:
@@ -0,0 +1,37 @@
|
||||
import type { Router } from "express";
|
||||
import { z } from "zod";
|
||||
import { getLocalAgentContext } from "../context/localContext.js";
|
||||
import type { OpencodeRuntimeAdapter } from "../runtime/opencode.js";
|
||||
import { readPurpose, type SessionMetadataStore } from "../sessions/metadataStore.js";
|
||||
import type { ChatRunState } from "./chatRunState.js";
|
||||
|
||||
const id = z.string().regex(/^msg_[a-f0-9]{32}$/);
|
||||
const update = z.object({ delivery: z.enum(["steer", "queue"]) }).strict();
|
||||
|
||||
export function registerResponseInputRoutes(router: Router, options: {
|
||||
runtime: OpencodeRuntimeAdapter; sessionMetadataStore: SessionMetadataStore; runState: ChatRunState;
|
||||
}) {
|
||||
for (const method of ["get", "patch"] as const) {
|
||||
router[method](method === "get" ? "/session/:session_id/inputs" : "/session/:session_id/inputs/:input_id", async (req, res) => {
|
||||
const sessionId = String(req.params.session_id);
|
||||
try {
|
||||
const record = await options.sessionMetadataStore.get(getLocalAgentContext(req), sessionId);
|
||||
if (!record || readPurpose(record) === "task_execution") { res.status(404).json({ message: "session not found" }); return; }
|
||||
if (method === "get") {
|
||||
res.json({ items: await options.runtime.listPendingUserInputs(sessionId) });
|
||||
return;
|
||||
}
|
||||
const inputId = id.parse((req.params as Record<string, string>).input_id);
|
||||
const { delivery } = update.parse(req.body);
|
||||
const input = await options.runtime.updatePendingUserInput(sessionId, inputId, delivery);
|
||||
options.runState.activeRuns.get(sessionId)?.inputs?.observe("session.inbox.delivery.changed", { inboxID: inputId, delivery });
|
||||
res.json(input);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) { res.status(400).json({ message: "invalid input delivery" }); return; }
|
||||
const status = error && typeof error === "object" && "status" in error ? error.status : undefined;
|
||||
res.status(status === 404 || status === 409 ? 409 : 503).json({ message: status === 404 || status === 409
|
||||
? "Message has already been consumed or is unavailable" : "Input inbox is unavailable" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user