Files
next-tjwater-agent/src/routes/response-input-routes.ts
T
jiang 7d47a2df86
Generic Container CI/CD / test-build-publish (push) Failing after 8m25s
Agent CI/CD / build-test-publish-and-deploy (push) Failing after 8m25s
feat: add scoped history and artifacts
2026-10-22 18:40:20 +08:00

44 lines
2.4 KiB
TypeScript

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", "delete"] 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);
if (method === "delete") {
const input = await options.runtime.cancelPendingUserInput(sessionId, inputId);
options.runState.activeRuns.get(sessionId)?.inputs?.observe("session.inbox.cancelled", { inboxID: inputId });
res.json(input);
return;
}
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" });
}
});
}
}