feat(tasks): enforce dynamic execution plans
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { tool } from "@opencode-ai/plugin";
|
||||
import { getInternalBridgeConfig } from "../internalBridge.js";
|
||||
import { executionPlanSchema } from "../../src/routes/executionPlan.js";
|
||||
import { newExecutionPlanSchema } from "../../src/routes/executionPlan.js";
|
||||
|
||||
export default tool({
|
||||
description: "Publish the current full execution plan and progress to TJWater Server. Plans may be updated multiple times during investigation; a plan-only publish is intermediate and does not finish the task unless it explicitly records Agent failure. Publish the relevant plan node before proposing an action, then republish the plan with the returned action_id before the final report. Preserve stable node IDs and completed evidence. A running or completed node may only depend on completed or skipped predecessors. Edges are dependencies or labeled conditional branches, never guessed from list order. Human actions stay waiting until externally confirmed. Evidence must identify synthetic inputs, tool results or human confirmation accurately. This records a plan, it does not execute actions.",
|
||||
args: {
|
||||
request_id: tool.schema.string().describe("Stable UUID idempotency key for this plan revision"),
|
||||
schema: tool.schema.enum(["execution-plan@2"]),
|
||||
title: tool.schema.string(),
|
||||
reason: tool.schema.string().describe("Why the plan or node status changed"),
|
||||
nodes: tool.schema.array(tool.schema.object({
|
||||
@@ -14,12 +15,16 @@ export default tool({
|
||||
owner: tool.schema.enum(["agent", "human"]),
|
||||
detail: tool.schema.string(), evidence: tool.schema.array(tool.schema.string()),
|
||||
action_refs: tool.schema.array(tool.schema.string()).optional(),
|
||||
kind: tool.schema.enum(["activity", "decision", "parallel_split", "parallel_join", "gate"]).optional(),
|
||||
selected_edge_id: tool.schema.string().nullable().optional(),
|
||||
gate_ref: tool.schema.string().nullable().optional(),
|
||||
revisits_node_id: tool.schema.string().nullable().optional(),
|
||||
})),
|
||||
edges: tool.schema.array(tool.schema.object({ from: tool.schema.string(), to: tool.schema.string(), label: tool.schema.string() })),
|
||||
edges: tool.schema.array(tool.schema.object({ id: tool.schema.string().optional(), from: tool.schema.string(), to: tool.schema.string(), label: tool.schema.string() })),
|
||||
},
|
||||
async execute(args, context) {
|
||||
const { request_id, ...input } = args;
|
||||
const plan = executionPlanSchema.parse(input);
|
||||
const plan = newExecutionPlanSchema.parse(input);
|
||||
const { baseUrl, internalToken } = getInternalBridgeConfig();
|
||||
const response = await fetch(`${baseUrl}/internal/operational-task/artifacts`, {
|
||||
method: "POST",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { tool } from "@opencode-ai/plugin";
|
||||
import { getInternalBridgeConfig } from "../internalBridge.js";
|
||||
|
||||
export default tool({
|
||||
description: "Request task-scoped access to one or more finite investigation data sources. This only creates a pending human review record. Do not query the requested sources until the approved scope appears in task context; after denial, mark the evidence gap and continue with available facts.",
|
||||
args: {
|
||||
request_id: tool.schema.string().uuid(),
|
||||
node_id: tool.schema.string().min(1),
|
||||
scopes: tool.schema.array(tool.schema.enum([
|
||||
"workbench_runtime", "scada_devices", "scada_readings", "peripheral_points",
|
||||
"peripheral_work_orders", "peripheral_observations", "peripheral_test_data",
|
||||
])).min(1),
|
||||
reason: tool.schema.string().min(1),
|
||||
},
|
||||
async execute(args, context) {
|
||||
const { baseUrl, internalToken } = getInternalBridgeConfig();
|
||||
const response = await fetch(`${baseUrl}/internal/operational-task/access-requests`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", "x-agent-internal-token": internalToken },
|
||||
body: JSON.stringify({ session_id: context.sessionID, request: {
|
||||
requestId: args.request_id, nodeId: args.node_id, scopes: args.scopes, reason: args.reason,
|
||||
} }),
|
||||
});
|
||||
const text = await response.text();
|
||||
if (!response.ok) throw new Error(`task data access request failed (${response.status}): ${text}`);
|
||||
return text;
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user