Publish graph deltas using the Server-owned cumulative graph contract. Validate historical comparison chart publications and consolidate Agent documentation.
92 lines
4.9 KiB
TypeScript
92 lines
4.9 KiB
TypeScript
import { tool } from "../tool.js";
|
|
import { investigationNodeAnnotations } from "../../src/product/investigation-node-state.js";
|
|
|
|
// OpenCode owns a separate Zod version. Native parameters are described here;
|
|
// product schemas revalidate progress and presentation at execution boundaries.
|
|
const text = tool.schema.string().trim().min(1);
|
|
const identifier = text.max(128);
|
|
const layer = tool.schema.enum(["junctions", "pipes", "valves", "pumps", "tanks", "reservoirs", "scada"]);
|
|
|
|
export const taskReportUiBlocksSchema = tool.schema.array(tool.schema.object({
|
|
version: tool.schema.literal("answer-ui@1").optional().describe("Legacy wrapper tag; normally omit. The host supplies the canonical block version."),
|
|
block: tool.schema.object({
|
|
version: tool.schema.literal("answer-ui@1").optional().describe("Fixed protocol version supplied by the host when omitted."),
|
|
block_id: tool.schema.string().regex(/^[a-zA-Z0-9_-]{1,80}$/),
|
|
phase: tool.schema.literal("final").optional(),
|
|
fallback_text: text.max(4000),
|
|
spec: tool.schema.object({
|
|
root: tool.schema.string(),
|
|
elements: tool.schema.record(tool.schema.string(), tool.schema.object({
|
|
type: tool.schema.string(),
|
|
props: tool.schema.record(tool.schema.string(), tool.schema.unknown()),
|
|
children: tool.schema.array(tool.schema.string()).max(48),
|
|
}).strict()),
|
|
}).strict(),
|
|
}).strict(),
|
|
evidence_refs: tool.schema.array(identifier).min(1).max(100),
|
|
}).strict()).max(8).optional();
|
|
|
|
const gapFields = {
|
|
gap_id: text,
|
|
node_id: text.nullish(),
|
|
missing_data: text,
|
|
scope: text,
|
|
impact: text,
|
|
required_data: text,
|
|
evidence_refs: tool.schema.array(text).min(1),
|
|
};
|
|
|
|
const reportFields = {
|
|
title: text,
|
|
current_conclusion: text,
|
|
conclusion_boundary: text,
|
|
evidence_refs: tool.schema.array(text).default([]),
|
|
ui_blocks: taskReportUiBlocksSchema,
|
|
};
|
|
|
|
export const taskPublicationReportSchema = tool.schema.discriminatedUnion("outcome", [
|
|
tool.schema.object({
|
|
...reportFields,
|
|
outcome: tool.schema.literal("concluded"),
|
|
stage: tool.schema.enum(["interim", "final"]),
|
|
stop_reason: tool.schema.null().optional().describe("Omit for concluded reports; the host supplies null. Put external follow-up in pending_items."),
|
|
recommendations: tool.schema.array(text).default([]),
|
|
pending_items: tool.schema.array(text).default([]),
|
|
data_gaps: tool.schema.array(tool.schema.object({ ...gapFields, blocking: tool.schema.literal(false) }).strict()),
|
|
}).strict(),
|
|
tool.schema.object({
|
|
...reportFields,
|
|
outcome: tool.schema.literal("insufficient_data"),
|
|
stage: tool.schema.literal("final"),
|
|
stop_reason: text.describe("Why verified missing data prevents a necessary judgment or concrete recommendation."),
|
|
recommendations: tool.schema.array(text).max(0).default([]),
|
|
pending_items: tool.schema.array(text).max(0).default([]),
|
|
data_gaps: tool.schema.array(tool.schema.object({ ...gapFields, blocking: tool.schema.boolean() }).strict()).min(1)
|
|
.refine((gaps) => gaps.some((gap) => gap.blocking), "insufficient_data requires at least one evidence-backed blocking gap"),
|
|
}).strict(),
|
|
]);
|
|
|
|
export const taskPublicationGraphProgressSchema = tool.schema.object({
|
|
summary: text.max(20000),
|
|
graph_update: tool.schema.object({
|
|
title: text.max(200).nullish(),
|
|
nodes: tool.schema.array(tool.schema.object({
|
|
node_id: tool.schema.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,79}$/).describe("Stable task-wide id. Keep this id when updating a step; use a new id for a retry of a failed attempt."),
|
|
label: text,
|
|
detail: text.max(2000).nullish().describe("Actual result or failure reason; preserve the failed attempt."),
|
|
status: tool.schema.enum(investigationNodeAnnotations).nullish().describe("Optional saved reference annotation. recorded means a finding exists, not business completion; reference is neutral. No running state or live task synchronization."),
|
|
evidence_refs: tool.schema.array(text).default([]),
|
|
action_refs: tool.schema.array(tool.schema.string().uuid()).default([]),
|
|
map_targets: tool.schema.array(tool.schema.object({ source_id: layer, feature_id: identifier }).strict()).max(100).default([]),
|
|
}).strict()).max(100).default([]),
|
|
edges: tool.schema.array(tool.schema.object({
|
|
source: tool.schema.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,79}$/),
|
|
target: tool.schema.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,79}$/),
|
|
label: text.max(200).nullish(),
|
|
}).strict()).max(200).default([]),
|
|
}).strict().optional().describe("Incremental nodes and explicit relationships. The Server retains prior paths and generates Mermaid; omit for a text-only update."),
|
|
}).strict();
|
|
|
|
import { createViewSchemas } from "../../src/frontendAction/command.js";
|
|
export const taskPublicationCommandSchema = createViewSchemas(tool.schema as unknown as Parameters<typeof createViewSchemas>[0], true).command as unknown as ReturnType<typeof tool.schema.object>;
|