← Files LuciaARCHIVED FILE
modules/deep-research-validator/scripts/review_mcp_server.cjs
79.3 KB · Oct 2, 2026 · 00:30 UTC
"use strict";
const crypto = require("node:crypto");
const fs = require("node:fs");
const path = require("node:path");
const readline = require("node:readline");
const { spawnSync } = require("node:child_process");
const SERVER_NAME = "deep-research-validator-widgets";
const PLUGIN_ROOT = path.resolve(__dirname, "..");
const PLUGIN_MANIFEST = JSON.parse(
fs.readFileSync(path.join(PLUGIN_ROOT, ".codex-plugin", "plugin.json"), "utf8"),
);
const SERVER_VERSION = PLUGIN_MANIFEST.version || "0.1.0";
const WIDGET_URI = "ui://widget/deep-research-review.html";
const WIDGET_MIME_TYPE = "text/html;profile=mcp-app";
const MAX_ITEMS = 2500;
const MAX_PAYLOAD_BYTES = 2_000_000;
const MAX_PERSISTENCE_CONTEXTS = 128;
const PERSISTENCE_CONTEXT_TTL_MS = 4 * 60 * 60 * 1000;
const PERSISTENCE_TOKEN_RE = /^[A-Za-z0-9_-]{43}$/;
const LOWERCASE_SHA256_RE = /^[a-f0-9]{64}$/;
const PERSISTENCE_CONTEXTS = new Map();
const TOOL_NAMES = {
validateReview: "validate_deep_research_review",
renderReview: "render_deep_research_review",
saveDecisions: "save_deep_research_decisions",
applyDecisions: "apply_deep_research_decisions",
};
const ALLOWED_ACTIONS = new Set([
"accept",
"reject",
"edit",
"mark_unclear",
"request_more_documents",
"skip",
]);
const ACTION_STATUSES = {
accept: "accepted",
reject: "rejected",
edit: "edited",
mark_unclear: "needs_evidence",
request_more_documents: "needs_evidence",
skip: "skipped",
};
const MAX_DECISION_TEXT_LENGTH = 10_000;
const ITEM_TYPES = new Set([
"supported_claim",
"partially_supported_claim",
"unsupported_claim",
"contradicted_claim",
"uncertain_claim",
"claim_review",
"answer_contract_review",
"coverage_review",
"source_limit",
"audit_check",
"validation_artifact",
]);
const RUNTIME_COPY = {
en: {
handoffTitle: "Review Handoff",
reviewPayload: "Review payload",
runIntake: "Run intake",
pendingDecisions: "Pending decisions",
appliedDecisions: "Applied decisions",
finalArtifacts: "Final artifacts",
reviewInCodex: "Review In Codex",
validationMessage:
"Answer-validation review is valid. Call render_deep_research_review with the returned short-lived reference.",
saved: (count) => `Saved ${count} answer-validation decisions.`,
saveNotWritten:
"Validated decisions. No run_intake.output_dir was provided, so nothing was written.",
applied: (count) => `Applied ${count} answer-validation decisions.`,
applyNotWritten:
"Validated applied decisions. No run_intake.output_dir was provided, so nothing was written.",
blockers: "Resolve blocked review decisions before treating final artifacts as ready.",
regenerate: "Regenerate native DOCX/XLSX/PDF outputs before final handoff.",
ready: "Use final_artifacts.json as the reviewed artifact gallery for handoff.",
partial: "Complete remaining review decisions before final handoff.",
instructions:
"Use validate_deep_research_review with the hash-bound local review reference before render_deep_research_review, then reuse the returned short-lived token. Prefer the MCP widget for answer-validation review handoff; use save_deep_research_decisions to persist reviewer actions to ui_decisions.json and apply_deep_research_decisions to write applied_decisions.json plus final_artifacts.json status when decisions are collected; fall back to Markdown/static review only when MCP is unavailable.",
},
es: {
handoffTitle: "Entrega para revisión",
reviewPayload: "Datos de revisión",
runIntake: "Datos de ejecución",
pendingDecisions: "Decisiones pendientes",
appliedDecisions: "Decisiones aplicadas",
finalArtifacts: "Artefactos finales",
reviewInCodex: "Revisión en Codex",
validationMessage:
"La revisión de validación de respuestas es válida. Ejecute render_deep_research_review con la referencia temporal devuelta.",
saved: (count) =>
`Se ${count === 1 ? "ha" : "han"} guardado ${count} ${count === 1 ? "decisión" : "decisiones"} de validación de respuestas.`,
saveNotWritten:
"Las decisiones son válidas. No se ha proporcionado run_intake.output_dir, por lo que no se ha escrito ningún archivo.",
applied: (count) =>
`Se ${count === 1 ? "ha" : "han"} aplicado ${count} ${count === 1 ? "decisión" : "decisiones"} de validación de respuestas.`,
applyNotWritten:
"Las decisiones aplicadas son válidas. No se ha proporcionado run_intake.output_dir, por lo que no se ha escrito ningún archivo.",
blockers: "Resuelva las decisiones bloqueadas antes de considerar listos los artefactos finales.",
regenerate: "Vuelva a generar las salidas DOCX/XLSX/PDF antes de la entrega final.",
ready: "Utilice final_artifacts.json como galería revisada de artefactos para la entrega.",
partial: "Complete las decisiones de revisión pendientes antes de la entrega final.",
instructions:
"Ejecute validate_deep_research_review con la referencia local vinculada por hash antes de render_deep_research_review y reutilice después el token temporal devuelto. Utilice preferentemente el widget MCP para la entrega de la validación de respuestas; guarde las decisiones con save_deep_research_decisions y aplíquelas con apply_deep_research_decisions para generar applied_decisions.json y actualizar el estado de final_artifacts.json. Utilice la revisión Markdown o estática solo cuando MCP no esté disponible.",
},
};
function isPlainObject(value) {
return value != null && typeof value === "object" && !Array.isArray(value);
}
function normalizeLanguage(value) {
const code = String(value || "en")
.trim()
.toLowerCase()
.replaceAll("_", "-")
.split("-", 1)[0];
return code === "es" ? "es" : "en";
}
function runtimeLanguage(inputArgs) {
const reviewPayload = isPlainObject(inputArgs?.review_payload) ? inputArgs.review_payload : {};
const runIntake = isPlainObject(inputArgs?.run_intake) ? inputArgs.run_intake : {};
const summary = isPlainObject(reviewPayload.summary) ? reviewPayload.summary : {};
const meta = isPlainObject(inputArgs?._meta)
? inputArgs._meta
: isPlainObject(inputArgs?.meta)
? inputArgs.meta
: {};
return normalizeLanguage(
reviewPayload.language ||
summary.language ||
runIntake.language ||
inputArgs?.language ||
inputArgs?.locale ||
meta.language ||
meta.locale,
);
}
function runtimeCopy(inputArgs) {
return RUNTIME_COPY[runtimeLanguage(inputArgs)];
}
function localizeErrorMessage(message, inputArgs) {
const original = String(message || "");
if (runtimeLanguage(inputArgs) !== "es") return original;
const replacements = [
["tool arguments must be an object", "los argumentos de la herramienta deben ser un objeto"],
["review_payload must be an object", "review_payload debe ser un objeto"],
["must be a non-empty string", "debe ser una cadena no vacía"],
["must be a string when provided", "debe ser una cadena cuando se proporciona"],
["must be an object", "debe ser un objeto"],
["must be an array", "debe ser una lista"],
["must be a non-empty array", "debe ser una lista no vacía"],
["is not supported", "no es compatible"],
["contains unsupported action", "contiene una acción no compatible"],
["must equal", "debe coincidir con"],
["items exceeds", "supera el límite de elementos:"],
["characters", "caracteres"],
["is required when action is edit", "es obligatorio cuando la acción es edit"],
["is not allowed for item", "no está permitida para el elemento"],
["is not in review_payload.items", "no figura en review_payload.items"],
["contains duplicate item_id", "contiene un item_id duplicado"],
["decisions cannot exceed review_payload.items.length", "decisions no puede superar review_payload.items.length"],
["run_intake.run_id must match review_payload.run_id", "run_intake.run_id debe coincidir con review_payload.run_id"],
["widget payload exceeds", "los datos del widget superan"],
];
let localized = original;
for (const [source, target] of replacements) localized = localized.replaceAll(source, target);
return localized === original ? `La solicitud no es válida: ${original}` : localized;
}
function objectSchema(properties, required = [], additionalProperties = true) {
return { type: "object", properties, required, additionalProperties };
}
function toolUiMeta(resourceUri, toolName = null) {
const meta = {
ui: { resourceUri, visibility: ["model"] },
"ui/resourceUri": resourceUri,
"openai/outputTemplate": resourceUri,
"openai/widgetAccessible": true,
};
if (toolName === TOOL_NAMES.renderReview) {
meta["openai/toolInvocation/invoking"] = "Rendering answer-validation review";
meta["openai/toolInvocation/invoked"] = "Rendered answer-validation review";
}
return meta;
}
function widgetResourceMeta(uri) {
return {
ui: { resourceUri: uri },
"openai/widgetDescription":
"Interactive answer-validation surface separating source support, reasoning, professional judgment, source limits, audit checks, and package artifacts.",
"openai/widgetPrefersBorder": false,
"openai/widgetCSP": { connect_domains: [], resource_domains: [] },
"openai/widgetDomain": "https://chatgpt.com",
};
}
function toolDefinitions() {
const reviewPayload = objectSchema(
{
schema_version: { type: "string" },
plugin: { type: "string" },
workflow: { type: "string" },
run_id: { type: "string" },
review_type: { type: "string" },
items: { type: "array", items: { type: "object" } },
item_count: { type: "number" },
status: { type: "string" },
},
["schema_version", "plugin", "workflow", "run_id", "items", "item_count"],
);
const reviewReference = objectSchema(
{
path: { type: "string", enum: ["review_payload.json"] },
run_id: { type: "string" },
review_payload_sha256: { type: "string", pattern: "^[a-f0-9]{64}$" },
},
["path", "run_id", "review_payload_sha256"],
false,
);
const inputSchema = objectSchema(
{
run_intake: { type: "object", description: "Optional run_intake.json object." },
client_engagement: {
type: "string",
description: "Current absolute path to the managed run context.json.",
},
review_payload: reviewPayload,
review_reference: reviewReference,
persistence_token: {
type: "string",
description: "Opaque short-lived token returned by validation or rendering.",
},
ui_decisions: { type: "object", description: "Optional ui_decisions.json object." },
final_artifacts: { type: "object", description: "Optional final_artifacts.json object." },
},
[],
);
const decisionSchema = objectSchema(
{
item_id: { type: "string", description: "Review item id from review_payload.items[].id." },
action: { type: "string", enum: Array.from(ALLOWED_ACTIONS) },
reviewer_note: { type: "string", description: "Optional reviewer note." },
edit_value: { type: "string", description: "Required replacement text or value when action is edit." },
requested_documents: {
type: "array",
items: { type: "string" },
description: "Optional document requests when action is request_more_documents.",
},
},
["item_id", "action"],
);
const decisionInputSchema = objectSchema(
{
run_intake: { type: "object", description: "Optional run_intake.json object with output_dir for persistence." },
client_engagement: {
type: "string",
description: "Current absolute path to the managed run context.json.",
},
review_payload: reviewPayload,
review_reference: reviewReference,
persistence_token: {
type: "string",
description: "Opaque short-lived token returned by validation or rendering.",
},
ui_decisions: { type: "object", description: "Optional current ui_decisions.json object." },
decisions: { type: "array", items: decisionSchema },
decision_source: { type: "string", description: "Decision source label. Defaults to mcp_widget." },
reviewer: { type: "string", description: "Optional reviewer name or role." },
},
["decisions"],
);
return [
{
name: TOOL_NAMES.validateReview,
title: "Validate answer-review payload",
description:
"Validate a hash-bound local answer-review reference (or a legacy inline payload) before rendering. Call this first, then render_deep_research_review with the returned short-lived token.",
inputSchema,
annotations: {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: false,
},
},
{
name: TOOL_NAMES.renderReview,
title: "Render answer-validation review",
description:
"Render a validated answer review through its short-lived token as an MCP HTML widget for source support, reasoning, professional judgment, source limits, audit checks, and artifacts.",
inputSchema,
_meta: toolUiMeta(WIDGET_URI, TOOL_NAMES.renderReview),
annotations: {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: false,
},
},
{
name: TOOL_NAMES.saveDecisions,
title: "Save answer-validation decisions",
description:
"Validate answer-review decisions and persist them to ui_decisions.json when run_intake.output_dir is available.",
inputSchema: decisionInputSchema,
annotations: {
readOnlyHint: false,
destructiveHint: true,
idempotentHint: true,
openWorldHint: false,
},
},
{
name: TOOL_NAMES.applyDecisions,
title: "Apply answer-validation decisions",
description:
"Validate answer-review decisions, write applied_decisions.json, and update final_artifacts.json status when run_intake.output_dir is available.",
inputSchema: decisionInputSchema,
annotations: {
readOnlyHint: false,
destructiveHint: true,
idempotentHint: true,
openWorldHint: false,
},
},
];
}
function resources() {
return [
{
uri: WIDGET_URI,
name: "deep_research_review_widget",
title: "Answer-validation review widget",
description:
"Renders answer-validation review-session payloads with searchable claims, separate reasoning and judgment findings, source limits, audit checks, and artifacts.",
mimeType: WIDGET_MIME_TYPE,
_meta: widgetResourceMeta(WIDGET_URI),
},
];
}
function resourceText(uri) {
if (uri !== WIDGET_URI) {
throw new Error(`unknown answer-validation widget resource: ${uri}`);
}
return fs.readFileSync(
path.join(PLUGIN_ROOT, "assets", "deep-research-review-widget.html"),
"utf8",
);
}
function payloadBytes(payload) {
return Buffer.byteLength(JSON.stringify(payload), "utf8");
}
function requireString(value, fieldPath) {
if (typeof value !== "string" || value.trim() === "") {
throw new Error(`${fieldPath} must be a non-empty string`);
}
}
function boundedOptionalString(value, fieldPath) {
if (value == null) return "";
if (typeof value !== "string") {
throw new Error(`${fieldPath} must be a string when provided`);
}
if (value.length > MAX_DECISION_TEXT_LENGTH) {
throw new Error(`${fieldPath} exceeds ${MAX_DECISION_TEXT_LENGTH} characters`);
}
return value.trim();
}
function validateItem(item, index) {
if (!isPlainObject(item)) {
throw new Error(`review_payload.items[${index}] must be an object`);
}
requireString(item.id, `review_payload.items[${index}].id`);
requireString(item.item_type, `review_payload.items[${index}].item_type`);
requireString(item.title, `review_payload.items[${index}].title`);
if (!ITEM_TYPES.has(item.item_type)) {
throw new Error(
`review_payload.items[${index}].item_type is not supported: ${item.item_type}`,
);
}
if (!Array.isArray(item.allowed_actions) || item.allowed_actions.length === 0) {
throw new Error(
`review_payload.items[${index}].allowed_actions must be a non-empty array`,
);
}
for (const action of item.allowed_actions) {
if (!ALLOWED_ACTIONS.has(action)) {
throw new Error(
`review_payload.items[${index}].allowed_actions contains unsupported action: ${action}`,
);
}
}
if (item.recommended_action != null && !ALLOWED_ACTIONS.has(item.recommended_action)) {
throw new Error(
`review_payload.items[${index}].recommended_action is not supported`,
);
}
}
function validateReviewPayload(inputArgs) {
if (!isPlainObject(inputArgs)) throw new Error("tool arguments must be an object");
const reviewPayload = inputArgs.review_payload;
if (!isPlainObject(reviewPayload)) throw new Error("review_payload must be an object");
requireString(reviewPayload.schema_version, "review_payload.schema_version");
if (reviewPayload.plugin !== "deep-research-validator") {
throw new Error('review_payload.plugin must be "deep-research-validator"');
}
requireString(reviewPayload.workflow, "review_payload.workflow");
requireString(reviewPayload.run_id, "review_payload.run_id");
if (!Array.isArray(reviewPayload.items)) {
throw new Error("review_payload.items must be an array");
}
if (reviewPayload.items.length > MAX_ITEMS) {
throw new Error(`review_payload.items exceeds ${MAX_ITEMS} items`);
}
if (reviewPayload.item_count !== reviewPayload.items.length) {
throw new Error("review_payload.item_count must equal review_payload.items.length");
}
reviewPayload.items.forEach((item, index) => validateItem(item, index));
const payload = {
widget_type: "deep_research_review",
run_intake: isPlainObject(inputArgs.run_intake) ? inputArgs.run_intake : null,
review_payload: reviewPayload,
ui_decisions: isPlainObject(inputArgs.ui_decisions) ? inputArgs.ui_decisions : null,
final_artifacts: isPlainObject(inputArgs.final_artifacts) ? inputArgs.final_artifacts : null,
decision_policy: {
save_tool: TOOL_NAMES.saveDecisions,
apply_tool: TOOL_NAMES.applyDecisions,
can_persist: Boolean(resolveDecisionOutputPath(inputArgs)),
fallback: "copy_json",
},
};
if (payloadBytes(payload) > MAX_PAYLOAD_BYTES) {
throw new Error(`Answer-validation widget payload exceeds ${MAX_PAYLOAD_BYTES} bytes`);
}
return payload;
}
function canonicalValue(value) {
if (Array.isArray(value)) return value.map(canonicalValue);
if (!isPlainObject(value)) return value;
return Object.fromEntries(
Object.keys(value)
.sort()
.map((key) => [key, canonicalValue(value[key])]),
);
}
function canonicalJson(value) {
return JSON.stringify(canonicalValue(value));
}
function sha256Bytes(value) {
return crypto.createHash("sha256").update(value).digest("hex");
}
function readRegularJson(filePath, label) {
const stat = fs.lstatSync(filePath);
if (!stat.isFile() || stat.isSymbolicLink()) {
throw new Error(`${label} must be a regular file`);
}
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}
function prunePersistenceContexts(now = Date.now()) {
for (const [token, context] of PERSISTENCE_CONTEXTS.entries()) {
if (context.expires_at <= now) PERSISTENCE_CONTEXTS.delete(token);
}
while (PERSISTENCE_CONTEXTS.size >= MAX_PERSISTENCE_CONTEXTS) {
const oldest = PERSISTENCE_CONTEXTS.keys().next().value;
if (oldest == null) break;
PERSISTENCE_CONTEXTS.delete(oldest);
}
}
function storedReviewContext(inputArgs, expectedReview = null) {
const outputDir = resolveRunOutputDir(inputArgs);
if (!outputDir) return null;
const reference = isPlainObject(inputArgs.review_reference)
? inputArgs.review_reference
: null;
if (reference?.path != null && reference.path !== "review_payload.json") {
throw new Error("review_reference.path must be review_payload.json");
}
const expectedRunId =
(typeof reference?.run_id === "string" && reference.run_id.trim()) ||
(typeof expectedReview?.run_id === "string" && expectedReview.run_id.trim()) ||
(typeof inputArgs.run_intake?.run_id === "string" && inputArgs.run_intake.run_id.trim());
if (!expectedRunId) throw new Error("review reference requires a run_id");
preflightClientRun(outputDir, expectedRunId);
const reviewPath = path.join(outputDir, "review_payload.json");
const review = readRegularJson(reviewPath, "review_payload.json");
const reviewBytes = fs.readFileSync(reviewPath);
const reviewHash = sha256Bytes(reviewBytes);
if (review.run_id !== expectedRunId) {
throw new Error("stored review_payload.json does not match the referenced run");
}
if (expectedReview && canonicalJson(expectedReview) !== canonicalJson(review)) {
throw new Error("tool review_payload does not match stored review_payload.json");
}
const referenceHash =
typeof reference?.review_payload_sha256 === "string"
? reference.review_payload_sha256.trim()
: "";
if (referenceHash && (!LOWERCASE_SHA256_RE.test(referenceHash) || referenceHash !== reviewHash)) {
throw new Error("review_reference hash does not match stored review_payload.json");
}
const finalPath = path.join(outputDir, "final_artifacts.json");
const finalArtifacts = readRegularJson(finalPath, "final_artifacts.json");
if (
finalArtifacts.plugin !== "deep-research-validator" ||
finalArtifacts.workflow !== "deep-research-validator" ||
finalArtifacts.run_id !== expectedRunId ||
finalArtifacts.review_payload_sha256 !== reviewHash
) {
throw new Error("final_artifacts.json does not bind the stored review payload");
}
return {
outputDir,
review,
reviewHash,
runIntake: readRegularJson(path.join(outputDir, "run_intake.json"), "run_intake.json"),
uiDecisions: fs.existsSync(path.join(outputDir, "ui_decisions.json"))
? readRegularJson(path.join(outputDir, "ui_decisions.json"), "ui_decisions.json")
: null,
finalArtifacts,
};
}
function issuePersistenceToken(inputArgs, review) {
const context = storedReviewContext(inputArgs, review);
if (!context) return null;
prunePersistenceContexts();
const token = crypto.randomBytes(32).toString("base64url");
PERSISTENCE_CONTEXTS.set(token, {
...context,
client_engagement: inputArgs.client_engagement,
expires_at: Date.now() + PERSISTENCE_CONTEXT_TTL_MS,
});
return token;
}
function issuePersistenceTokenWhenBound(inputArgs, review) {
try {
return issuePersistenceToken(inputArgs, review);
} catch (error) {
if (isPlainObject(inputArgs?.review_reference)) throw error;
return null;
}
}
function inputWithReviewReference(inputArgs) {
if (isPlainObject(inputArgs?.review_payload)) return inputArgs;
const token = typeof inputArgs?.persistence_token === "string"
? inputArgs.persistence_token.trim()
: "";
if (token) {
if (!PERSISTENCE_TOKEN_RE.test(token)) {
throw new Error("persistence_token has an invalid format");
}
prunePersistenceContexts();
const context = PERSISTENCE_CONTEXTS.get(token);
if (!context || context.expires_at <= Date.now()) {
throw new Error("persistence_token is unknown or expired; validate the review again");
}
const reviewPath = path.join(context.outputDir, "review_payload.json");
readRegularJson(reviewPath, "review_payload.json");
const currentHash = sha256Bytes(fs.readFileSync(reviewPath));
if (currentHash !== context.reviewHash) {
throw new Error("persistence_token review binding no longer matches the stored package");
}
return {
...inputArgs,
client_engagement: context.client_engagement,
review_payload: context.review,
review_reference: {
path: "review_payload.json",
run_id: context.review.run_id,
review_payload_sha256: context.reviewHash,
},
run_intake: context.runIntake,
ui_decisions: context.uiDecisions,
final_artifacts: context.finalArtifacts,
};
}
if (isPlainObject(inputArgs?.review_reference)) {
const context = storedReviewContext(inputArgs);
return {
...inputArgs,
review_payload: context.review,
review_reference: {
path: "review_payload.json",
run_id: context.review.run_id,
review_payload_sha256: context.reviewHash,
},
run_intake: context.runIntake,
ui_decisions: context.uiDecisions,
final_artifacts: context.finalArtifacts,
};
}
throw new Error("review_payload, review_reference, or persistence_token is required");
}
function publicReviewReference(token) {
if (!token) return null;
const context = PERSISTENCE_CONTEXTS.get(token);
return context
? {
persistence_token: token,
path: "review_payload.json",
run_id: context.review.run_id,
review_payload_sha256: context.reviewHash,
expires_in_seconds: Math.floor(PERSISTENCE_CONTEXT_TTL_MS / 1000),
}
: null;
}
function resolveDecisionOutputPath(inputArgs) {
const outputDir = resolveRunOutputDir(inputArgs);
if (!outputDir) return null;
return path.join(outputDir, "ui_decisions.json");
}
function normalizeRequestedDocuments(value, fieldPath) {
if (value == null) return [];
if (!Array.isArray(value)) throw new Error(`${fieldPath} must be an array when provided`);
return value.map((entry, index) => {
const documentName = boundedOptionalString(entry, `${fieldPath}[${index}]`);
if (!documentName) throw new Error(`${fieldPath}[${index}] must be a non-empty string`);
return documentName;
});
}
function normalizeDecision(decision, itemById, seenIds, decidedAt, index) {
// Decision persistence is an audit contract: ids, actions, and edit payloads are mechanically verifiable.
if (!isPlainObject(decision)) throw new Error(`decisions[${index}] must be an object`);
const itemId = boundedOptionalString(decision.item_id ?? decision.id, `decisions[${index}].item_id`);
if (!itemId) throw new Error(`decisions[${index}].item_id must be a non-empty string`);
if (seenIds.has(itemId)) throw new Error(`decisions contains duplicate item_id: ${itemId}`);
seenIds.add(itemId);
const item = itemById.get(itemId);
if (!item) throw new Error(`decisions[${index}].item_id is not in review_payload.items: ${itemId}`);
const action = boundedOptionalString(decision.action, `decisions[${index}].action`);
if (!ALLOWED_ACTIONS.has(action)) throw new Error(`decisions[${index}].action is not supported: ${action}`);
if (!item.allowed_actions.includes(action)) {
throw new Error(`decisions[${index}].action is not allowed for item ${itemId}: ${action}`);
}
const reviewerNote = boundedOptionalString(
decision.reviewer_note ?? decision.note,
`decisions[${index}].reviewer_note`,
);
const editValue = boundedOptionalString(
decision.edit_value ?? decision.user_text,
`decisions[${index}].edit_value`,
);
if (action === "edit" && !editValue) {
throw new Error(`decisions[${index}].edit_value is required when action is edit`);
}
const explicitRequestedDocuments = normalizeRequestedDocuments(
decision.requested_documents,
`decisions[${index}].requested_documents`,
);
// Missing-document requests copy only explicit review metadata; no semantic evidence inference happens here.
const requestedDocuments = requestedDocumentsFromReviewContext(
{ action, requested_documents: explicitRequestedDocuments },
item,
isPlainObject(item.data) ? item.data : {},
);
// Follow-up context copies only explicit item/evidence metadata to make blocker queues actionable.
const followupContext = followupContextFromReviewContext(
{ action },
item,
isPlainObject(item.data) ? item.data : {},
);
const normalized = {
item_id: itemId,
item_type: item.item_type,
title: item.title,
action,
status: ACTION_STATUSES[action],
decided_at: decidedAt,
};
if (reviewerNote) normalized.reviewer_note = reviewerNote;
if (editValue) normalized.edit_value = editValue;
if (requestedDocuments.length) normalized.requested_documents = requestedDocuments;
if (Object.keys(followupContext).length) normalized.followup_context = followupContext;
return normalized;
}
function buildUiDecisions(inputArgs) {
const payload = validateReviewPayload(inputArgs);
const reviewPayload = payload.review_payload;
const runIntake = payload.run_intake;
if (runIntake?.run_id != null && runIntake.run_id !== reviewPayload.run_id) {
throw new Error("run_intake.run_id must match review_payload.run_id");
}
if (!Array.isArray(inputArgs.decisions)) throw new Error("decisions must be an array");
if (inputArgs.decisions.length > reviewPayload.items.length) {
throw new Error("decisions cannot exceed review_payload.items.length");
}
const decidedAt = new Date().toISOString();
const itemById = new Map(reviewPayload.items.map((item) => [item.id, item]));
const seenIds = new Set();
const decisions = inputArgs.decisions.map((decision, index) =>
normalizeDecision(decision, itemById, seenIds, decidedAt, index),
);
const decisionSource =
boundedOptionalString(inputArgs.decision_source, "decision_source") || "mcp_widget";
const reviewer = boundedOptionalString(inputArgs.reviewer, "reviewer");
const currentUiDecisions = isPlainObject(inputArgs.ui_decisions) ? inputArgs.ui_decisions : null;
const reviewPayloadPath =
typeof currentUiDecisions?.review_payload_path === "string"
? path.basename(currentUiDecisions.review_payload_path)
: "review_payload.json";
const status =
decisions.length === 0
? "pending_review"
: decisions.length === reviewPayload.items.length
? "reviewed"
: "partial_review";
const uiDecisions = {
schema_version: reviewPayload.schema_version,
plugin: reviewPayload.plugin,
workflow: reviewPayload.workflow,
run_id: reviewPayload.run_id,
decided_at: decisions.length ? decidedAt : null,
decision_source: decisionSource,
review_payload_path: reviewPayloadPath,
decisions,
decision_count: decisions.length,
item_count: reviewPayload.items.length,
status,
};
const reviewPayloadSha256 =
(isPlainObject(inputArgs.review_reference)
? boundedOptionalString(
inputArgs.review_reference.review_payload_sha256,
"review_reference.review_payload_sha256",
)
: "") ||
boundedOptionalString(
currentUiDecisions?.review_payload_sha256,
"ui_decisions.review_payload_sha256",
);
if (reviewPayloadSha256) uiDecisions.review_payload_sha256 = reviewPayloadSha256;
if (reviewer) uiDecisions.reviewer = reviewer;
return {
uiDecisions,
decisionOutputPath: resolveDecisionOutputPath(inputArgs),
};
}
function saveDecisionPayload(inputArgs) {
const { uiDecisions, decisionOutputPath } = buildUiDecisions(inputArgs);
let persisted = false;
if (decisionOutputPath) {
preflightClientRun(resolveRunOutputDir(inputArgs), uiDecisions.run_id);
fs.mkdirSync(path.dirname(decisionOutputPath), { recursive: true });
fs.writeFileSync(decisionOutputPath, `${JSON.stringify(uiDecisions, null, 2)}\n`, "utf8");
persisted = true;
}
return {
ok: true,
validation_type: "deep_research_decisions",
run_id: uiDecisions.run_id,
decision_count: uiDecisions.decision_count,
item_count: uiDecisions.item_count,
status: uiDecisions.status,
persisted,
ui_decisions_path: persisted ? decisionOutputPath : null,
message: persisted
? runtimeCopy(inputArgs).saved(uiDecisions.decision_count)
: runtimeCopy(inputArgs).saveNotWritten,
ui_decisions: uiDecisions,
};
}
function resolveRunOutputDir(inputArgs) {
const runIntake = isPlainObject(inputArgs.run_intake) ? inputArgs.run_intake : null;
const outputRef = typeof runIntake?.output_dir === "string" ? runIntake.output_dir.trim() : "";
if (!outputRef) return null;
const contextRef =
typeof inputArgs.client_engagement === "string"
? inputArgs.client_engagement.trim()
: "";
if (runIntake?.path_reference !== "run_root_relative") {
if (contextRef) {
throw new Error(
"run_intake.output_dir must be a portable managed-run reference",
);
}
return null;
}
if (!contextRef) {
throw new Error(
"Answer Validator persistence requires the current client_engagement context",
);
}
if (
!path.isAbsolute(contextRef) ||
path.normalize(contextRef) !== contextRef ||
path.basename(contextRef) !== "context.json"
) {
throw new Error("client_engagement must be the current absolute context.json path");
}
if (outputRef.includes("\\")) {
throw new Error("run_intake.output_dir must use a canonical relative path");
}
const parts = outputRef.split("/");
if (
parts[0] !== "outputs" ||
parts.some((part) => !part || part === "." || part === "..") ||
parts.join("/") !== outputRef
) {
throw new Error("run_intake.output_dir must stay inside the managed run outputs");
}
const runRoot = path.dirname(contextRef);
const outputRoot = path.join(runRoot, "outputs");
const resolved = path.join(runRoot, ...parts);
if (resolved !== outputRoot && !resolved.startsWith(`${outputRoot}${path.sep}`)) {
throw new Error("run_intake.output_dir escapes the managed run outputs");
}
return resolved;
}
function resolveAppliedDecisionOutputPath(inputArgs) {
const outputDir = resolveRunOutputDir(inputArgs);
return outputDir ? path.join(outputDir, "applied_decisions.json") : null;
}
function resolveFinalArtifactsOutputPath(inputArgs) {
const outputDir = resolveRunOutputDir(inputArgs);
return outputDir ? path.join(outputDir, "final_artifacts.json") : null;
}
function shortString(value) {
return typeof value === "string" ? value.trim() : "";
}
const REVISION_TEXT_EXTENSIONS = new Set([
".htm",
".html",
".md",
".sql",
".txt",
".xml",
".yaml",
".yml",
]);
const DIRECT_TEXT_UPDATE_EXTENSIONS = new Set([
".htm",
".html",
".md",
".sql",
".txt",
".xml",
".yaml",
".yml",
]);
const STRUCTURED_UPDATE_EXTENSIONS = new Set([".csv", ".json", ".jsonl"]);
const NATIVE_REGENERATION_EXTENSIONS = new Set([
".docx",
".pdf",
".pptx",
".xls",
".xlsm",
".xlsx",
]);
const DERIVED_NATIVE_REGENERATION_TARGETS = new Map([
["check_results.csv", ["check_results.xlsx"]],
["codex_run_review.md", ["concordato_review_summary.docx"]],
["reconciliation_matches.csv", ["journal_bank_reconciliation.xlsx"]],
]);
function safePathSegment(value, fallback) {
const cleaned = shortString(value)
.replace(/[^a-zA-Z0-9._-]+/g, "-")
.replace(/^-+|-+$/g, "")
.slice(0, 80);
return cleaned || fallback;
}
function revisionExtension(targetArtifact) {
const extension = path.extname(shortString(targetArtifact)).toLowerCase();
return REVISION_TEXT_EXTENSIONS.has(extension) ? extension : ".txt";
}
function revisionRelativePath(effect) {
const extension = revisionExtension(effect.target_artifact);
const targetArtifact = shortString(effect.target_artifact);
const targetExtension = path.extname(targetArtifact) || extension;
const sourceBase = path.basename(targetArtifact || "review-item", targetExtension);
const base = safePathSegment(sourceBase, "review-item");
const itemId = safePathSegment(effect.item_id, "item");
return path.join("revisions", `${base}__${itemId}${extension}`).split(path.sep).join("/");
}
function normalizeRelativePath(filePath) {
return filePath.split(path.sep).join("/");
}
function artifactPathKey(value) {
return normalizeRelativePath(shortString(value)).replace(/\\/g, "/").replace(/^\.\//, "");
}
function resolveSafeRunOutputPath(outputDir, value) {
const rawPath = shortString(value);
if (!outputDir || !rawPath) return null;
const absolutePath = path.resolve(outputDir, rawPath);
const relativePath = path.relative(outputDir, absolutePath);
if (!relativePath || relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
return null;
}
return {
absolutePath,
relativePath: normalizeRelativePath(relativePath),
};
}
function canDirectlyUpdateTextArtifact(targetArtifact) {
const extension = path.extname(shortString(targetArtifact)).toLowerCase();
return DIRECT_TEXT_UPDATE_EXTENSIONS.has(extension);
}
function canUpdateStructuredArtifact(targetArtifact) {
const extension = path.extname(shortString(targetArtifact)).toLowerCase();
return STRUCTURED_UPDATE_EXTENSIONS.has(extension);
}
function needsNativeRegeneration(targetArtifact) {
const extension = path.extname(shortString(targetArtifact)).toLowerCase();
return NATIVE_REGENERATION_EXTENSIONS.has(extension);
}
function currentFinalArtifactsForApplication(inputArgs, finalArtifactsPath) {
return (
(isPlainObject(inputArgs.final_artifacts) ? inputArgs.final_artifacts : null) ||
readJsonFileIfPresent(finalArtifactsPath) ||
{}
);
}
function finalArtifactsOutputPaths(currentFinalArtifacts) {
const outputs = Array.isArray(currentFinalArtifacts?.outputs)
? currentFinalArtifacts.outputs
: [];
return new Set(
outputs
.map((output) => artifactPathKey(output?.path))
.filter(Boolean),
);
}
function existingDerivedNativeTargets(outputDir, currentFinalArtifacts, sourceArtifact) {
const sourceKey = artifactPathKey(sourceArtifact);
const candidates = DERIVED_NATIVE_REGENERATION_TARGETS.get(sourceKey) || [];
if (!candidates.length) return [];
const declaredOutputPaths = finalArtifactsOutputPaths(currentFinalArtifacts);
return candidates.filter((candidate) => {
const candidateKey = artifactPathKey(candidate);
if (declaredOutputPaths.has(candidateKey)) return true;
const target = resolveSafeRunOutputPath(outputDir, candidateKey);
return Boolean(target && fs.existsSync(target.absolutePath));
});
}
function csvEscape(value) {
const text = String(value ?? "");
if (!/[",\r\n]/.test(text)) return text;
return `"${text.replace(/"/g, '""')}"`;
}
function parseCsv(text) {
const rows = [];
let row = [];
let field = "";
let inQuotes = false;
for (let index = 0; index < text.length; index += 1) {
const char = text[index];
if (inQuotes) {
if (char === '"' && text[index + 1] === '"') {
field += '"';
index += 1;
} else if (char === '"') {
inQuotes = false;
} else {
field += char;
}
continue;
}
if (char === '"') {
inQuotes = true;
} else if (char === ",") {
row.push(field);
field = "";
} else if (char === "\n") {
row.push(field);
rows.push(row);
row = [];
field = "";
} else if (char === "\r") {
if (text[index + 1] === "\n") index += 1;
row.push(field);
rows.push(row);
row = [];
field = "";
} else {
field += char;
}
}
if (inQuotes) throw new Error("CSV parse failed: unclosed quoted field");
if (field !== "" || row.length || !text.endsWith("\n")) {
row.push(field);
rows.push(row);
}
return rows;
}
function serializeCsv(rows) {
return `${rows.map((row) => row.map(csvEscape).join(",")).join("\n")}\n`;
}
function structuredUpdateSpec(effect) {
// Native table/object edits are deterministic only when the review payload names the exact row and field.
if (!effect.target_artifact || !effect.target_id_field || !effect.target_record_id || !effect.target_field) {
return null;
}
return {
idField: effect.target_id_field,
recordId: effect.target_record_id,
targetField: effect.target_field,
recordsKey: effect.target_records_key || null,
};
}
function updateMatchingRecord(records, spec, editValue) {
if (!Array.isArray(records)) throw new Error("structured artifact records must be an array");
let updated = 0;
for (const record of records) {
if (!isPlainObject(record)) continue;
if (String(record[spec.idField] ?? "") !== spec.recordId) continue;
record[spec.targetField] = editValue;
updated += 1;
}
if (updated !== 1) {
throw new Error(
`structured edit expected exactly one record for ${spec.idField}=${spec.recordId}, found ${updated}`,
);
}
return updated;
}
function updateCsvArtifact(filePath, effect, spec) {
const rows = parseCsv(fs.readFileSync(filePath, "utf8"));
if (!rows.length) throw new Error("CSV structured edit requires a header row");
const header = rows[0];
const idIndex = header.indexOf(spec.idField);
const fieldIndex = header.indexOf(spec.targetField);
if (idIndex < 0) throw new Error(`CSV structured edit missing id column ${spec.idField}`);
if (fieldIndex < 0) throw new Error(`CSV structured edit missing target column ${spec.targetField}`);
let updated = 0;
for (const row of rows.slice(1)) {
if (String(row[idIndex] ?? "") !== spec.recordId) continue;
while (row.length < header.length) row.push("");
row[fieldIndex] = effect.edit_value;
updated += 1;
}
if (updated !== 1) {
throw new Error(
`CSV structured edit expected exactly one row for ${spec.idField}=${spec.recordId}, found ${updated}`,
);
}
fs.writeFileSync(filePath, serializeCsv(rows), "utf8");
return { updatedRows: updated, rowCount: Math.max(rows.length - 1, 0) };
}
function updateJsonArtifact(filePath, effect, spec) {
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
if (Array.isArray(parsed)) {
const updatedRows = updateMatchingRecord(parsed, spec, effect.edit_value);
fs.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
return { updatedRows, rowCount: parsed.length };
}
if (isPlainObject(parsed) && spec.recordsKey && Array.isArray(parsed[spec.recordsKey])) {
const records = parsed[spec.recordsKey];
const updatedRows = updateMatchingRecord(records, spec, effect.edit_value);
fs.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
return { updatedRows, rowCount: records.length };
}
if (isPlainObject(parsed) && String(parsed[spec.idField] ?? "") === spec.recordId) {
parsed[spec.targetField] = effect.edit_value;
fs.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
return { updatedRows: 1, rowCount: 1 };
}
throw new Error("JSON structured edit requires an object, array, or explicit records_key array");
}
function updateJsonlArtifact(filePath, effect, spec) {
const text = fs.readFileSync(filePath, "utf8");
const records = text
.split(/\r?\n/)
.filter((line) => line.trim())
.map((line) => JSON.parse(line));
const updatedRows = updateMatchingRecord(records, spec, effect.edit_value);
fs.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}\n`, "utf8");
return { updatedRows, rowCount: records.length };
}
function originalBackupRelativePath(effect, targetRelativePath) {
const extension = path.extname(targetRelativePath).toLowerCase() || ".txt";
const sourceBase = path.basename(targetRelativePath, extension);
const base = safePathSegment(sourceBase, "artifact");
const itemId = safePathSegment(effect.item_id, "item");
return normalizeRelativePath(path.join("revisions", "originals", `${base}__${itemId}${extension}`));
}
function readJsonFileIfPresent(filePath) {
if (!filePath || !fs.existsSync(filePath)) return null;
try {
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
return isPlainObject(parsed) ? parsed : null;
} catch {
return null;
}
}
function uniqueStrings(values) {
return Array.from(
new Set(
values
.map((value) => shortString(value))
.filter(Boolean),
),
);
}
function collectReviewApplicationPaths(appliedDecisions, finalArtifacts) {
const paths = ["ui_decisions.json", "applied_decisions.json", "final_artifacts.json"];
const finalOutputs = Array.isArray(finalArtifacts?.outputs) ? finalArtifacts.outputs : [];
if (
finalOutputs.some(
(output) => isPlainObject(output) && output.path === "review_handoff.md",
)
) {
paths.push("review_handoff.md");
}
const reviewApplication = isPlainObject(finalArtifacts?.review_application)
? finalArtifacts.review_application
: {};
for (const fieldName of [
"applied_decisions_path",
"revision_paths",
"target_update_paths",
"structured_update_paths",
"native_regeneration_paths",
"native_regenerated_paths",
"downstream_regenerated_paths",
"original_backup_paths",
]) {
const value = reviewApplication[fieldName] ?? appliedDecisions?.[fieldName];
if (Array.isArray(value)) paths.push(...value);
else paths.push(value);
}
return uniqueStrings(paths);
}
function appendReviewApplicationExecutionTrace(
inputArgs,
outputDir,
appliedDecisions,
finalArtifacts,
) {
if (!outputDir) return null;
const runIntakePath = path.join(outputDir, "run_intake.json");
const current = readJsonFileIfPresent(runIntakePath) ||
(isPlainObject(inputArgs.run_intake) ? { ...inputArgs.run_intake } : null);
if (!current) return null;
const trace = Array.isArray(current.execution_trace) ? [...current.execution_trace] : [];
const appliedAt = shortString(appliedDecisions?.applied_at) || new Date().toISOString();
const stepIdSuffix = appliedAt.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
trace.push({
step_id: `${shortString(appliedDecisions?.workflow) || "deep_research"}_review_apply_${stepIdSuffix || Date.now()}`,
kind: "deterministic_review_apply",
status: "passed",
execution_location: "local_codex_workspace",
command: [SERVER_NAME, TOOL_NAMES.applyDecisions],
inputs: uniqueStrings([
appliedDecisions?.review_payload?.path || "review_payload.json",
"ui_decisions.json",
"final_artifacts.json",
]),
outputs: collectReviewApplicationPaths(appliedDecisions, finalArtifacts),
});
const updated = { ...current, execution_trace: trace };
fs.mkdirSync(path.dirname(runIntakePath), { recursive: true });
fs.writeFileSync(runIntakePath, `${JSON.stringify(updated, null, 2)}\n`, "utf8");
return runIntakePath;
}
function requestedDocumentsFromReviewContext(decision, item, data) {
if (Array.isArray(decision.requested_documents) && decision.requested_documents.length) {
return decision.requested_documents;
}
if (decision.action !== "request_more_documents") return [];
const candidates = [];
function add(value) {
if (Array.isArray(value)) {
for (const entry of value) add(entry);
return;
}
const text = shortString(value);
if (text) candidates.push(text);
}
for (const key of [
"requested_document",
"requested_documents",
"missing_document",
"missing_documents",
"required_document",
"required_documents",
"support_document",
"support_documents",
]) {
add(data[key]);
}
const evidence = Array.isArray(item.evidence) ? item.evidence : [];
for (const record of evidence) {
if (!isPlainObject(record)) continue;
for (const key of [
"requested_document",
"requested_documents",
"missing_document",
"missing_documents",
"required_document",
"required_documents",
"support_document",
"support_documents",
]) {
add(record[key]);
}
}
return Array.from(new Set(candidates));
}
function compactContextValue(value) {
if (value == null || value === "") return "";
if (typeof value === "string") return value.trim();
if (typeof value === "number" && Number.isFinite(value)) return String(value);
if (typeof value === "boolean") return String(value);
return "";
}
function followupContextFromReviewContext(decision, item, data) {
if (isPlainObject(decision.followup_context) && Object.keys(decision.followup_context).length) {
return decision.followup_context;
}
if (!["reject", "mark_unclear", "request_more_documents"].includes(decision.action)) return {};
const records = [
data,
...(Array.isArray(item.evidence) ? item.evidence.filter(isPlainObject) : []),
];
const fields = [
["owner", ["owner", "responsible_party", "assignee", "contact", "client_contact"]],
["source_system", ["source_system", "system", "source_system_name"]],
["source_file", ["source_file", "filename", "file_name", "source_workbook"]],
["source_table", ["source_table", "sheet", "worksheet", "table"]],
["due_date", ["due_date", "deadline", "response_due_date"]],
["period", ["period", "tax_period", "fiscal_year", "year"]],
["entity", ["entity", "client", "company", "account", "counterparty", "beneficiary"]],
["record_id", ["record_id", "source_row", "movement_number", "bank_transaction_id", "journal_entry_id", "claim_index"]],
["amount", ["amount", "amount_abs", "amount_value"]],
["reason", ["reason", "missing_reason", "blocking_reason", "mismatches"]],
["priority", ["priority", "severity"]],
];
const context = {};
for (const [targetKey, sourceKeys] of fields) {
for (const record of records) {
for (const sourceKey of sourceKeys) {
const value = compactContextValue(record[sourceKey]);
if (!value) continue;
context[targetKey] = value;
break;
}
if (context[targetKey]) break;
}
}
return context;
}
function buildApplicationEffect(decision, item, appliedAt) {
const data = isPlainObject(item.data) ? item.data : {};
const targetArtifact =
shortString(data.target_artifact) ||
shortString(item.output_path) ||
shortString(data.path);
const targetPath =
shortString(data.target_path) ||
shortString(data.field_path) ||
shortString(data.field);
const targetIdField =
shortString(data.target_id_field) ||
shortString(data.record_id_field);
const targetRecordId =
shortString(data.target_record_id) ||
shortString(data.record_id);
const targetField =
shortString(data.target_field) ||
shortString(data.edit_field);
const targetRecordsKey =
shortString(data.target_records_key) ||
shortString(data.records_key);
const requiresFollowup = new Set(["reject", "mark_unclear", "request_more_documents"]).has(
decision.action,
);
const requestedDocuments = requestedDocumentsFromReviewContext(decision, item, data);
const followupContext = followupContextFromReviewContext(decision, item, data);
const effect = {
item_id: decision.item_id,
item_type: decision.item_type,
title: decision.title,
action: decision.action,
status: decision.status,
applied_at: appliedAt,
applied: true,
requires_followup: requiresFollowup,
target_artifact: targetArtifact || null,
target_path: targetPath || null,
target_id_field: targetIdField || null,
target_record_id: targetRecordId || null,
target_field: targetField || null,
target_records_key: targetRecordsKey || null,
source_path: shortString(item.source_path) || null,
artifact_update:
decision.action === "edit"
? "revision_artifact_pending"
: targetArtifact
? "decision_manifest_only"
: "review_record_only",
};
if (decision.reviewer_note) effect.reviewer_note = decision.reviewer_note;
if (decision.edit_value) effect.edit_value = decision.edit_value;
if (requestedDocuments.length) {
effect.requested_documents = requestedDocuments;
}
if (Object.keys(followupContext).length) {
effect.followup_context = followupContext;
}
return effect;
}
function writeRevisionArtifacts(outputDir, effects) {
if (!outputDir) return [];
const revisionOutputs = [];
for (const effect of effects) {
if (effect.action !== "edit" || !effect.edit_value) continue;
const relativePath = revisionRelativePath(effect);
const absolutePath = path.join(outputDir, relativePath);
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
fs.writeFileSync(absolutePath, effect.edit_value, "utf8");
effect.revision_artifact = relativePath;
effect.artifact_update = "revision_artifact_written";
revisionOutputs.push({
path: relativePath,
kind: revisionExtension(effect.target_artifact).replace(/^\./, "") || "txt",
status: "written_revision",
source_artifact: effect.target_artifact,
item_id: effect.item_id,
});
}
return revisionOutputs;
}
function writeDirectTextArtifactUpdates(outputDir, effects) {
if (!outputDir) return { targetOutputs: [], backupOutputs: [] };
const targetOutputs = [];
const backupOutputs = [];
for (const effect of effects) {
if (effect.action !== "edit" || !effect.edit_value) continue;
if (!canDirectlyUpdateTextArtifact(effect.target_artifact)) continue;
const target = resolveSafeRunOutputPath(outputDir, effect.target_artifact);
if (!target || !fs.existsSync(target.absolutePath)) continue;
const stat = fs.statSync(target.absolutePath);
if (!stat.isFile()) continue;
const backupRelativePath = originalBackupRelativePath(effect, target.relativePath);
const backupAbsolutePath = path.join(outputDir, backupRelativePath);
fs.mkdirSync(path.dirname(backupAbsolutePath), { recursive: true });
if (!fs.existsSync(backupAbsolutePath)) {
fs.writeFileSync(backupAbsolutePath, fs.readFileSync(target.absolutePath, "utf8"), "utf8");
}
fs.writeFileSync(target.absolutePath, effect.edit_value, "utf8");
effect.target_artifact = target.relativePath;
effect.original_artifact_backup = backupRelativePath;
effect.artifact_update = "target_artifact_updated";
targetOutputs.push({
path: target.relativePath,
kind: path.extname(target.relativePath).replace(/^\./, "") || "txt",
status: "updated_from_review",
item_id: effect.item_id,
});
backupOutputs.push({
path: backupRelativePath,
kind: path.extname(backupRelativePath).replace(/^\./, "") || "txt",
status: "backup_original",
source_artifact: target.relativePath,
item_id: effect.item_id,
});
}
return { targetOutputs, backupOutputs };
}
function writeStructuredArtifactUpdates(outputDir, effects) {
if (!outputDir) return { targetOutputs: [], backupOutputs: [] };
const targetOutputs = [];
const backupOutputs = [];
for (const effect of effects) {
if (effect.action !== "edit" || !effect.edit_value) continue;
const spec = structuredUpdateSpec(effect);
if (!spec) continue;
if (!canUpdateStructuredArtifact(effect.target_artifact)) continue;
const target = resolveSafeRunOutputPath(outputDir, effect.target_artifact);
if (!target || !fs.existsSync(target.absolutePath)) continue;
const stat = fs.statSync(target.absolutePath);
if (!stat.isFile()) continue;
const backupRelativePath = originalBackupRelativePath(effect, target.relativePath);
const backupAbsolutePath = path.join(outputDir, backupRelativePath);
fs.mkdirSync(path.dirname(backupAbsolutePath), { recursive: true });
if (!fs.existsSync(backupAbsolutePath)) {
fs.copyFileSync(target.absolutePath, backupAbsolutePath);
}
const extension = path.extname(target.relativePath).toLowerCase();
const result =
extension === ".csv"
? updateCsvArtifact(target.absolutePath, effect, spec)
: extension === ".jsonl"
? updateJsonlArtifact(target.absolutePath, effect, spec)
: updateJsonArtifact(target.absolutePath, effect, spec);
effect.target_artifact = target.relativePath;
effect.original_artifact_backup = backupRelativePath;
effect.artifact_update = "structured_artifact_updated";
effect.structured_update = {
id_field: spec.idField,
record_id: spec.recordId,
target_field: spec.targetField,
records_key: spec.recordsKey,
updated_rows: result.updatedRows,
};
targetOutputs.push({
path: target.relativePath,
kind: extension.replace(/^\./, "") || "file",
status: "updated_from_review",
item_id: effect.item_id,
row_count: result.rowCount,
required_columns: [spec.idField, spec.targetField],
});
backupOutputs.push({
path: backupRelativePath,
kind: path.extname(backupRelativePath).replace(/^\./, "") || "file",
status: "backup_original",
source_artifact: target.relativePath,
item_id: effect.item_id,
});
}
return { targetOutputs, backupOutputs };
}
function markNativeRegenerationPending(effects) {
const nativeOutputs = [];
for (const effect of effects) {
if (effect.action !== "edit" || !effect.edit_value) continue;
if (effect.artifact_update !== "revision_artifact_written") continue;
if (!needsNativeRegeneration(effect.target_artifact)) continue;
effect.requires_native_regeneration = true;
effect.native_regeneration_status = "pending";
effect.artifact_update = "native_regeneration_pending";
nativeOutputs.push({
path: effect.target_artifact,
kind: path.extname(effect.target_artifact || "").replace(/^\./, "") || "file",
status: "native_regeneration_pending",
item_id: effect.item_id,
revision_artifact: effect.revision_artifact || null,
});
}
return nativeOutputs;
}
function markDerivedNativeRegenerationPending(outputDir, effects, currentFinalArtifacts) {
const nativeOutputs = [];
for (const effect of effects) {
if (effect.action !== "edit" || !effect.edit_value) continue;
if (!["revision_artifact_written", "structured_artifact_updated"].includes(effect.artifact_update)) continue;
const derivedTargets = existingDerivedNativeTargets(
outputDir,
currentFinalArtifacts,
effect.target_artifact,
);
if (!derivedTargets.length) continue;
effect.requires_native_regeneration = true;
effect.native_regeneration_status = "pending";
effect.derived_native_regeneration_paths = derivedTargets;
for (const targetPath of derivedTargets) {
nativeOutputs.push({
path: targetPath,
kind: path.extname(targetPath).replace(/^\./, "") || "file",
status: "native_regeneration_pending",
item_id: effect.item_id,
source_artifact: effect.target_artifact,
});
}
}
return nativeOutputs;
}
function nativeRegenerationPathsForEffect(effect) {
const derivedPaths = Array.isArray(effect.derived_native_regeneration_paths)
? effect.derived_native_regeneration_paths
: [];
const paths = derivedPaths.length
? derivedPaths
: effect.requires_native_regeneration
? [effect.target_artifact]
: [];
return Array.from(new Set(paths.map(artifactPathKey).filter(Boolean)));
}
function statusFromEffects(effects, itemCount) {
if (!effects.length) return "pending_review";
if (effects.some((effect) => effect.requires_followup)) return "blocked";
if (effects.some((effect) => effect.requires_native_regeneration)) return "partial_review_applied";
if (effects.length < itemCount) return "partial_review_applied";
return "final_ready";
}
const REVIEW_HANDOFF_PLUGINS = new Set([
"check-entries",
"client-file-preparation",
"journal-sampling",
"journal-bank-reconciliation",
"deep-research-validator",
"prompt-optimizer",
"report-builder",
"concordato-plan-review",
]);
function reviewHandoffOutputRecord(inputArgs) {
const copy = runtimeCopy(inputArgs);
return {
path: "review_handoff.md",
kind: "md",
status: "written",
required_text: [
"Review Handoff",
...(runtimeLanguage(inputArgs) === "es" ? [copy.handoffTitle, copy.reviewInCodex] : []),
"review_payload.json",
"ui_decisions.json",
"applied_decisions.json",
"final_artifacts.json",
],
qa_checks: ["nonempty_text", "required_text"],
};
}
function ensureReviewHandoffCard(inputArgs, outputDir) {
const reviewPayload = isPlainObject(inputArgs.review_payload) ? inputArgs.review_payload : {};
const pluginName = shortString(reviewPayload.plugin);
if (!REVIEW_HANDOFF_PLUGINS.has(pluginName) || !outputDir) return null;
const handoffPath = path.join(outputDir, "review_handoff.md");
fs.mkdirSync(outputDir, { recursive: true });
if (!fs.existsSync(handoffPath)) {
const displayName = PLUGIN_MANIFEST.name || pluginName || "Review";
const copy = runtimeCopy(inputArgs);
const spanish = runtimeLanguage(inputArgs) === "es";
const text = [
spanish ? `# ${displayName} · ${copy.handoffTitle}` : `# ${displayName} Review Handoff`,
...(spanish ? ["<!-- review-contract: Review Handoff -->"] : []),
"",
`- ${copy.reviewPayload}: \`review_payload.json\``,
`- ${copy.runIntake}: \`run_intake.json\``,
`- ${copy.pendingDecisions}: \`ui_decisions.json\``,
`- ${copy.appliedDecisions}: \`applied_decisions.json\``,
`- ${copy.finalArtifacts}: \`final_artifacts.json\``,
"",
`## ${copy.reviewInCodex}`,
`1. ${spanish ? "Valide los datos con" : "Validate the payload with"} \`${TOOL_NAMES.validateReview}\`.`,
`2. ${spanish ? "Abra el área de revisión con" : "Render the review workbench with"} \`${TOOL_NAMES.renderReview}\`.`,
`3. ${spanish ? "Guarde las decisiones del revisor con" : "Save reviewer actions with"} \`${TOOL_NAMES.saveDecisions}\`.`,
`4. ${spanish ? "Aplique las decisiones del revisor con" : "Apply reviewer actions with"} \`${TOOL_NAMES.applyDecisions}\`.`,
].join("\n");
fs.writeFileSync(handoffPath, `${text}\n`, "utf8");
}
return reviewHandoffOutputRecord(inputArgs);
}
function finalArtifactsWithApplication(
inputArgs,
appliedDecisions,
finalArtifactsPath,
revisionOutputs = [],
targetOutputs = [],
backupOutputs = [],
nativeRegenerationOutputs = [],
) {
const reviewPayload = appliedDecisions.review_payload;
const current = currentFinalArtifactsForApplication(inputArgs, finalArtifactsPath);
const outputDir = resolveRunOutputDir(inputArgs);
const outputs = Array.isArray(current.outputs) ? [...current.outputs] : [];
function upsertOutput(record) {
const existingIndex = outputs.findIndex((output) => output?.path === record.path);
if (existingIndex >= 0) outputs[existingIndex] = { ...outputs[existingIndex], ...record };
else outputs.push(record);
}
const handoffOutput = ensureReviewHandoffCard(inputArgs, outputDir);
if (handoffOutput) upsertOutput(handoffOutput);
upsertOutput({ path: "ui_decisions.json", kind: "json", status: "written_reviewed" });
upsertOutput({
path: "applied_decisions.json",
kind: "json",
status: appliedDecisions.application_status,
});
for (const output of revisionOutputs) upsertOutput(output);
for (const output of targetOutputs) upsertOutput(output);
for (const output of backupOutputs) upsertOutput(output);
for (const output of nativeRegenerationOutputs) upsertOutput(output);
const blockers = effectsToBlockers(appliedDecisions.effects);
return {
schema_version: current.schema_version || reviewPayload.schema_version || "1.0",
plugin: current.plugin || reviewPayload.plugin,
workflow: current.workflow || reviewPayload.workflow,
run_id: current.run_id || reviewPayload.run_id,
outputs,
caveats: Array.isArray(current.caveats) ? current.caveats : [],
blockers,
next_actions: nextActionsWithReviewApplication(
current.next_actions,
appliedDecisions,
blockers,
inputArgs,
),
status: appliedDecisions.application_status,
review_status: appliedDecisions.application_status,
review_application: {
applied_at: appliedDecisions.applied_at,
application_status: appliedDecisions.application_status,
decision_count: appliedDecisions.decision_count,
item_count: appliedDecisions.item_count,
blocker_count: appliedDecisions.blocker_count,
revision_count: revisionOutputs.length,
revision_paths: revisionOutputs.map((output) => output.path),
target_update_count: targetOutputs.length,
target_update_paths: targetOutputs.map((output) => output.path),
structured_update_count: appliedDecisions.structured_update_count || 0,
structured_update_paths: appliedDecisions.structured_update_paths || [],
native_regeneration_count: appliedDecisions.native_regeneration_count || 0,
native_regeneration_paths: appliedDecisions.native_regeneration_paths || [],
original_backup_paths: backupOutputs.map((output) => output.path),
applied_decisions_path: "applied_decisions.json",
},
};
}
function effectsToBlockers(effects) {
return effects
.filter((effect) => effect.requires_followup)
.map((effect) => {
const blocker = {
item_id: effect.item_id,
item_type: effect.item_type,
title: effect.title,
action: effect.action,
status: effect.status,
reviewer_note: effect.reviewer_note || null,
requested_documents: Array.isArray(effect.requested_documents)
? effect.requested_documents
: [],
};
if (isPlainObject(effect.followup_context) && Object.keys(effect.followup_context).length) {
blocker.followup_context = effect.followup_context;
}
return blocker;
});
}
function nextActionsWithReviewApplication(currentNextActions, appliedDecisions, blockers, inputArgs) {
const nextActions = Array.isArray(currentNextActions) ? [...currentNextActions] : [];
const copy = runtimeCopy(inputArgs);
if (blockers.length) {
nextActions.push(copy.blockers);
} else if (appliedDecisions.native_regeneration_count) {
nextActions.push(copy.regenerate);
} else if (appliedDecisions.application_status === "final_ready") {
nextActions.push(copy.ready);
} else if (appliedDecisions.application_status === "partial_review_applied") {
nextActions.push(copy.partial);
}
return Array.from(new Set(nextActions));
}
function applyDecisionPayload(inputArgs) {
const { uiDecisions, decisionOutputPath } = buildUiDecisions(inputArgs);
const validationPayload = validateReviewPayload(inputArgs);
const reviewPayload = validationPayload.review_payload;
const itemById = new Map(reviewPayload.items.map((item) => [item.id, item]));
const appliedAt = new Date().toISOString();
const effects = uiDecisions.decisions.map((decision) =>
buildApplicationEffect(decision, itemById.get(decision.item_id), appliedAt),
);
const outputDir = resolveRunOutputDir(inputArgs);
if (outputDir) preflightClientRun(outputDir, uiDecisions.run_id);
const revisionOutputs = writeRevisionArtifacts(outputDir, effects);
const textUpdates = writeDirectTextArtifactUpdates(outputDir, effects);
const structuredUpdates = writeStructuredArtifactUpdates(outputDir, effects);
const appliedOutputPath = resolveAppliedDecisionOutputPath(inputArgs);
const finalArtifactsPath = resolveFinalArtifactsOutputPath(inputArgs);
const currentFinalArtifacts = currentFinalArtifactsForApplication(inputArgs, finalArtifactsPath);
const nativeRegenerationOutputs = [
...markNativeRegenerationPending(effects),
...markDerivedNativeRegenerationPending(outputDir, effects, currentFinalArtifacts),
];
const targetOutputs = [...textUpdates.targetOutputs, ...structuredUpdates.targetOutputs];
const backupOutputs = [...textUpdates.backupOutputs, ...structuredUpdates.backupOutputs];
const structuredUpdatePaths = effects
.filter((effect) => effect.artifact_update === "structured_artifact_updated")
.map((effect) => effect.target_artifact);
const nativeRegenerationPaths = Array.from(
new Set(effects.flatMap((effect) => nativeRegenerationPathsForEffect(effect))),
);
const blockerCount = effects.filter((effect) => effect.requires_followup).length;
const applicationStatus = statusFromEffects(effects, reviewPayload.items.length);
const appliedDecisions = {
schema_version: reviewPayload.schema_version,
plugin: reviewPayload.plugin,
workflow: reviewPayload.workflow,
run_id: reviewPayload.run_id,
applied_at: appliedAt,
decision_source: uiDecisions.decision_source || "mcp_widget",
review_payload: {
path: uiDecisions.review_payload_path || "review_payload.json",
item_count: reviewPayload.items.length,
review_type: reviewPayload.review_type || null,
},
decisions: uiDecisions.decisions,
effects,
decision_count: uiDecisions.decision_count,
item_count: reviewPayload.items.length,
blocker_count: blockerCount,
revision_count: revisionOutputs.length,
revision_paths: revisionOutputs.map((output) => output.path),
target_update_count: targetOutputs.length,
target_update_paths: targetOutputs.map((output) => output.path),
structured_update_count: structuredUpdatePaths.length,
structured_update_paths: structuredUpdatePaths,
native_regeneration_count: nativeRegenerationPaths.length,
native_regeneration_paths: nativeRegenerationPaths,
original_backup_paths: backupOutputs.map((output) => output.path),
application_status: applicationStatus,
};
if (uiDecisions.reviewer) appliedDecisions.reviewer = uiDecisions.reviewer;
const finalArtifacts = finalArtifactsWithApplication(
inputArgs,
appliedDecisions,
finalArtifactsPath,
revisionOutputs,
targetOutputs,
backupOutputs,
nativeRegenerationOutputs,
);
let persisted = false;
if (decisionOutputPath) {
fs.mkdirSync(path.dirname(decisionOutputPath), { recursive: true });
fs.writeFileSync(decisionOutputPath, `${JSON.stringify(uiDecisions, null, 2)}\n`, "utf8");
}
if (appliedOutputPath) {
fs.mkdirSync(path.dirname(appliedOutputPath), { recursive: true });
fs.writeFileSync(appliedOutputPath, `${JSON.stringify(appliedDecisions, null, 2)}\n`, "utf8");
persisted = true;
}
if (finalArtifactsPath) {
fs.mkdirSync(path.dirname(finalArtifactsPath), { recursive: true });
fs.writeFileSync(finalArtifactsPath, `${JSON.stringify(finalArtifacts, null, 2)}\n`, "utf8");
}
const workflowSpecificResult = applyWorkflowSpecificReviewApplication(
outputDir,
appliedOutputPath,
finalArtifactsPath,
);
const responseAppliedDecisions =
(isPlainObject(workflowSpecificResult?.applied_decisions)
? workflowSpecificResult.applied_decisions
: null) ||
readJsonFileIfPresent(appliedOutputPath) ||
appliedDecisions;
const responseFinalArtifacts =
(isPlainObject(workflowSpecificResult?.final_artifacts)
? workflowSpecificResult.final_artifacts
: null) ||
readJsonFileIfPresent(finalArtifactsPath) ||
finalArtifacts;
const runIntakePath = appendReviewApplicationExecutionTrace(
inputArgs,
outputDir,
responseAppliedDecisions,
responseFinalArtifacts,
);
return {
ok: true,
validation_type: "deep_research_application",
run_id: responseAppliedDecisions.run_id,
decision_count: responseAppliedDecisions.decision_count,
item_count: responseAppliedDecisions.item_count,
blocker_count: responseAppliedDecisions.blocker_count,
revision_count: responseAppliedDecisions.revision_count || revisionOutputs.length,
target_update_count: responseAppliedDecisions.target_update_count || targetOutputs.length,
structured_update_count: responseAppliedDecisions.structured_update_count || structuredUpdatePaths.length,
native_regeneration_count: responseAppliedDecisions.native_regeneration_count || 0,
native_regenerated_count: responseAppliedDecisions.native_regenerated_count || 0,
application_status: responseAppliedDecisions.application_status || applicationStatus,
persisted,
ui_decisions_path: decisionOutputPath,
applied_decisions_path: persisted ? appliedOutputPath : null,
final_artifacts_path: finalArtifactsPath,
run_intake_path: runIntakePath,
message: persisted
? runtimeCopy(inputArgs).applied(responseAppliedDecisions.decision_count)
: runtimeCopy(inputArgs).applyNotWritten,
applied_decisions: responseAppliedDecisions,
final_artifacts: responseFinalArtifacts,
};
}
function pythonExecutable() {
const candidates = [
process.env.PYTHON,
process.env.VIRTUAL_ENV ? path.join(process.env.VIRTUAL_ENV, "bin", "python") : "",
path.resolve(PLUGIN_ROOT, "..", "..", ".venv", "bin", "python"),
"python3",
"python",
].filter(Boolean);
for (const candidate of candidates) {
if (path.isAbsolute(candidate) && !fs.existsSync(candidate)) continue;
return candidate;
}
return "python3";
}
function preflightClientRun(outputDir, expectedRunId) {
if (!outputDir) return null;
const scriptPath = path.join(PLUGIN_ROOT, "scripts", "apply_review_edits.py");
const completed = spawnSync(
pythonExecutable(),
[
scriptPath,
"--output-dir",
outputDir,
"--client-run-preflight-only",
],
{ cwd: PLUGIN_ROOT, encoding: "utf8" },
);
if (completed.error) throw completed.error;
if (completed.status !== 0) {
throw new Error(
completed.stderr ||
completed.stdout ||
"Answer-validation customer-run preflight failed.",
);
}
const output = completed.stdout.trim().split(/\r?\n/).filter(Boolean).pop();
if (!output) throw new Error("Answer-validation customer-run preflight failed.");
const parsed = JSON.parse(output);
if (
!isPlainObject(parsed) ||
parsed.ok !== true ||
parsed.schema_version !== "vera.client_workflow_context.v2" ||
parsed.workflow_id !== "deep-research-validator" ||
typeof parsed.client_run_id !== "string" ||
!parsed.client_run_id.trim() ||
parsed.client_run_id !== expectedRunId
) {
throw new Error("Answer-validation customer-run preflight returned an invalid result.");
}
return parsed;
}
function applyWorkflowSpecificReviewApplication(outputDir, appliedOutputPath, finalArtifactsPath) {
if (!outputDir || !appliedOutputPath || !finalArtifactsPath) return null;
const currentApplied = readJsonFileIfPresent(appliedOutputPath);
if (!currentApplied || !currentApplied.structured_update_count) return null;
if (!hasDeepResearchClaimFixTarget(currentApplied)) return null;
const scriptPath = path.join(PLUGIN_ROOT, "scripts", "apply_review_edits.py");
const completed = spawnSync(
pythonExecutable(),
[
scriptPath,
"--output-dir",
outputDir,
"--applied-decisions",
appliedOutputPath,
"--final-artifacts",
finalArtifactsPath,
],
{ cwd: PLUGIN_ROOT, encoding: "utf8" },
);
if (completed.error) throw completed.error;
if (completed.status !== 0) {
throw new Error(
completed.stderr ||
completed.stdout ||
"Answer-validation downstream artifact refresh failed.",
);
}
const output = completed.stdout.trim().split(/\r?\n/).filter(Boolean).pop();
if (!output) return null;
const parsed = JSON.parse(output);
return isPlainObject(parsed) ? parsed : null;
}
function hasDeepResearchClaimFixTarget(appliedDecisions) {
if (!isPlainObject(appliedDecisions)) return false;
const effects = Array.isArray(appliedDecisions.effects) ? appliedDecisions.effects : [];
return effects.some((effect) => {
if (!isPlainObject(effect)) return false;
if (effect.action !== "edit") return false;
if (effect.artifact_update !== "structured_artifact_updated") return false;
if (shortString(effect.target_artifact) !== "claims_review.json") return false;
if (shortString(effect.target_field) !== "proposed_fix") return false;
return shortString(effect.edit_value) !== "";
});
}
function callTool(name, args = {}) {
if (name === TOOL_NAMES.validateReview) {
const resolvedArgs = inputWithReviewReference(args);
const payload = validateReviewPayload(resolvedArgs);
const persistenceToken = issuePersistenceTokenWhenBound(
resolvedArgs,
payload.review_payload,
);
return {
ok: true,
validation_type: "deep_research_review",
run_id: payload.review_payload.run_id,
item_count: payload.review_payload.item_count,
review_type: payload.review_payload.review_type || null,
message: runtimeCopy(args).validationMessage,
review_reference: publicReviewReference(persistenceToken),
};
}
if (name === TOOL_NAMES.renderReview) {
const resolvedArgs = inputWithReviewReference(args);
const payload = validateReviewPayload(resolvedArgs);
const persistenceToken = issuePersistenceTokenWhenBound(
resolvedArgs,
payload.review_payload,
);
return {
...payload,
persistence_token: persistenceToken,
review_reference: publicReviewReference(persistenceToken),
};
}
if (name === TOOL_NAMES.saveDecisions) {
return saveDecisionPayload(inputWithReviewReference(args));
}
if (name === TOOL_NAMES.applyDecisions) {
return applyDecisionPayload(inputWithReviewReference(args));
}
throw new Error(`unknown answer-validation widget tool: ${name}`);
}
function toolResult(payload, toolName) {
const summary = {
ok: payload?.ok !== false,
run_id: payload?.run_id || payload?.review_payload?.run_id || null,
item_count: payload?.item_count ?? payload?.review_payload?.item_count ?? null,
status:
payload?.status ||
payload?.application_status ||
payload?.review_payload?.status ||
null,
message: payload?.message || null,
review_reference: payload?.review_reference || null,
};
const result = {
content: [{ type: "text", text: JSON.stringify(summary) }],
structuredContent: payload,
isError: false,
};
if (toolName === TOOL_NAMES.renderReview) {
result._meta = toolUiMeta(WIDGET_URI, toolName);
}
return result;
}
function toolError(message) {
const payload = { ok: false, error: message };
return {
content: [{ type: "text", text: JSON.stringify(payload) }],
structuredContent: payload,
isError: true,
};
}
function rpcResponse(id, result) {
return { jsonrpc: "2.0", id, result };
}
function rpcError(id, code, message) {
return { jsonrpc: "2.0", id, error: { code, message } };
}
function handleRpc(message) {
const messageId = message.id ?? null;
const method = message.method;
const params = isPlainObject(message.params) ? message.params : {};
try {
if (method === "initialize") {
return rpcResponse(messageId, {
protocolVersion: params.protocolVersion || "2024-11-05",
serverInfo: { name: SERVER_NAME, version: SERVER_VERSION },
capabilities: {
tools: {},
resources: {},
prompts: {},
},
instructions: runtimeCopy(params).instructions,
});
}
if (method === "notifications/initialized") return null;
if (method === "tools/list") return rpcResponse(messageId, { tools: toolDefinitions() });
if (method === "tools/call") {
const { name, arguments: args } = params;
if (typeof name !== "string") {
return rpcError(messageId, -32602, "tools/call requires a tool name");
}
if (!isPlainObject(args)) {
return rpcError(messageId, -32602, "tools/call arguments must be an object");
}
try {
return rpcResponse(messageId, toolResult(callTool(name, args), name));
} catch (error) {
return rpcResponse(
messageId,
toolError(
localizeErrorMessage(
error instanceof Error ? error.message : String(error),
args,
),
),
);
}
}
if (method === "resources/list") return rpcResponse(messageId, { resources: resources() });
if (method === "resources/read") {
const { uri } = params;
if (typeof uri !== "string") {
return rpcError(messageId, -32602, "resources/read requires a resource uri");
}
const text = resourceText(uri);
return rpcResponse(messageId, {
contents: [
{
uri,
mimeType: WIDGET_MIME_TYPE,
text,
_meta: widgetResourceMeta(uri),
},
],
});
}
if (method === "resources/templates/list") {
return rpcResponse(messageId, { resourceTemplates: [] });
}
if (method === "prompts/list") return rpcResponse(messageId, { prompts: [] });
return rpcError(messageId, -32601, `method not found: ${method}`);
} catch (error) {
return rpcError(
messageId,
-32000,
error instanceof Error ? error.message : String(error),
);
}
}
function send(payload) {
process.stdout.write(`${JSON.stringify(payload)}\n`);
}
function main() {
const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });
rl.on("line", (line) => {
if (!line.trim()) return;
let message;
try {
message = JSON.parse(line);
} catch (error) {
send(rpcError(null, -32700, "parse error"));
return;
}
const response = handleRpc(message);
if (response != null && message.id != null) send(response);
});
}
main();
SHA-256: f38dedf59432050b70138e2d576dd3a86fdbca01d3b0612c37c14f28bc525ca2