refactor: consolidate chat state and task bridges

Centralize session scope, chat projections and typed task bridges.
Keep historical interaction replies authoritative and publish terminal state to subscribers. Validate Server contracts before replacing generated artifacts.
This commit is contained in:
2026-11-09 17:55:00 +08:00
parent addc81e106
commit 6279a4b555
31 changed files with 849 additions and 522 deletions
+7 -8
View File
@@ -4,7 +4,7 @@ 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";
import { readTaskBridgeContext, replyTaskBridgeError } from "./task-bridge-context.js";
const artifactsInputSchema = taskArtifactBridgeSchema.and(z.object({ session_id: z.string().trim().min(1).max(128) }));
@@ -19,12 +19,12 @@ export function registerTaskPublicationBridge(app: Express, options: {
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) {
const bridge = readTaskBridgeContext(req, options.internalToken);
if (!bridge) {
res.status(403).json({ message: "operational task context unavailable" });
return;
}
const { context, runtimeSessionId: sessionId, taskId } = bridge;
if ((kind === "presentation" || req.body?.progress !== undefined) && context.purpose !== "task_execution") {
res.status(403).json({ message: "task execution context required" });
return;
@@ -36,7 +36,7 @@ export function registerTaskPublicationBridge(app: Express, options: {
res.status(400).json({ message: "invalid task presentation", detail: parsed.error.flatten() });
return;
}
res.json(await client.publishPresentation(sessionId, context.taskId, {
res.json(await client.publishPresentation(sessionId, taskId, {
requestId: parsed.data.request_id,
sourceSessionId: context.clientSessionId,
command: parsed.data.command,
@@ -47,7 +47,7 @@ export function registerTaskPublicationBridge(app: Express, options: {
res.status(400).json({ message: "invalid task artifacts", detail: parsed.error.flatten() });
return;
}
res.json(await client.publishArtifacts(sessionId, context.taskId, {
res.json(await client.publishArtifacts(sessionId, taskId, {
requestId: parsed.data.request_id,
sourceSessionId: context.clientSessionId,
evidence: parsed.data.evidence,
@@ -57,8 +57,7 @@ export function registerTaskPublicationBridge(app: Express, options: {
}));
}
} 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` });
replyTaskBridgeError(res, error, `task ${kind} publish failed`);
}
});
}