acpus 0.0.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -103
- package/dist/catalog.d.ts +27 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +186 -0
- package/dist/catalog.js.map +1 -0
- package/dist/follow.d.ts +23 -0
- package/dist/follow.d.ts.map +1 -0
- package/dist/follow.js +109 -0
- package/dist/follow.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +522 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +4 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +28 -0
- package/dist/io.js.map +1 -0
- package/dist/observations.d.ts +26 -0
- package/dist/observations.d.ts.map +1 -0
- package/dist/observations.js +60 -0
- package/dist/observations.js.map +1 -0
- package/dist/output.d.ts +9 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +51 -0
- package/dist/output.js.map +1 -0
- package/dist/runs-show.d.ts +5 -0
- package/dist/runs-show.d.ts.map +1 -0
- package/dist/runs-show.js +72 -0
- package/dist/runs-show.js.map +1 -0
- package/dist/supervisor-client.d.ts +9 -0
- package/dist/supervisor-client.d.ts.map +1 -0
- package/dist/supervisor-client.js +8 -0
- package/dist/supervisor-client.js.map +1 -0
- package/dist/supervisor.d.ts +18 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +24 -0
- package/dist/supervisor.js.map +1 -0
- package/package.json +30 -44
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +0 -4017
- package/dist/index.d.mts +0 -2194
- package/dist/index.mjs +0 -243
- package/dist/monitor-app-CPlEcyHR.mjs +0 -369
- package/dist/monitor-rendering-LGr9Ebd_.mjs +0 -78
- package/dist/run-picker-app-utJ2f5CU.mjs +0 -104
- package/dist/run-workflow-DdIAC8Zu.mjs +0 -12922
- package/schemas/workflow-spec.schema.json +0 -2649
package/dist/index.mjs
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { $ as ConditionSchema, B as retryCountByReason, C as RUN_MONITOR_VIEW_VERSION, Ct as TaskStageSchema, Dt as WorkflowLimitsSchema, E as buildTaskDetailView, Et as WorkflowInputSchema, F as parseWorkflowOutput, Ft as runDir, G as compileSchemaDsl, H as retryableOutputFailure, I as AGENT_TASK_RETRY_BUDGET, J as outputSchemaFooter, K as defaultAgentOutputZod, L as AGENT_TASK_RETRY_DELAY_MS, N as syncRun, Ot as WorkflowSpecSchema, P as collectWorkflowOutputCandidates, Q as AgentFaninSchema, R as agentTaskRetryDelayMs, S as resultFromIssues, St as TaskProgramStageSchema, T as buildRunMonitorView, Tt as VariableSchema, U as setAgentTaskRetryDelayForTests, V as retryExhaustedEnvelope, W as DEFAULT_AGENT_OUTPUT_SCHEMA, X as ActorModeSchema, Y as zodForCompiledSchema, Z as ActorSchema, _t as RouteStageSchema, a as renderStagePrompt, at as GateAgentStageSchema, b as OrchestratorError, bt as StageSchema, c as EXECUTION_PLAN_VERSION, ct as LimitBindingSchema, d as previewRunView, dt as LoopStageSchema, et as FaninSchema, f as runViewFromIndex, ft as PositiveIntegerLimitSchema, g as lintWorkflowSpec, gt as RouteRuleSchema, h as stringifyWorkflowSpec, ht as RouteProgramStageSchema, i as renderPromptMap, it as FanoutStageSchema, kt as RuntimeErrorCodes, l as estimateAgentCalls, lt as LimitValueSchema, m as loadWorkflowSpec, mt as RouteAgentStageSchema, n as startPreparedRun, nt as FanoutPolicySchema, o as stageActorLabel, ot as GateProgramStageSchema, p as isWorkflowYamlPath, pt as ProgramFaninSchema, q as formatSchema, r as compileExecutionPlan, rt as FanoutStageLimitsSchema, s as topologicalOrder, st as GateStageSchema, t as prepareRun, tt as FanoutLaneSchema, u as estimateFanoutWork, ut as LoopBodyStageSchema, vt as SCHEMA_VERSION, w as TASK_DETAIL_VIEW_VERSION, wt as TransformSchema, x as issue, xt as TaskAgentStageSchema, yt as StageLimitsSchema, z as formatContinuationPrompt } from "./run-workflow-DdIAC8Zu.mjs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
|
-
//#region src/projections/run-diagnostics.ts
|
|
5
|
-
const RUN_DIAGNOSTICS_VIEW_VERSION = "acpus.diagnostics/v1";
|
|
6
|
-
const RUN_LEVEL_RUNTIME_CODES = new Set([
|
|
7
|
-
RuntimeErrorCodes.EVENT_APPEND_LOCK_TIMEOUT,
|
|
8
|
-
RuntimeErrorCodes.RUN_INDEX_LOCK_TIMEOUT,
|
|
9
|
-
RuntimeErrorCodes.AGENT_TASK_RETRY_EXHAUSTED,
|
|
10
|
-
RuntimeErrorCodes.FANOUT_ITEM_UNSTARTED_TIMEOUT,
|
|
11
|
-
RuntimeErrorCodes.FANOUT_ITEM_BLOCKED,
|
|
12
|
-
RuntimeErrorCodes.FANOUT_ITEM_CASCADE_BLOCKED,
|
|
13
|
-
RuntimeErrorCodes.FANOUT_LANE_RESULT_MISMATCH,
|
|
14
|
-
RuntimeErrorCodes.NO_SELECTED_LANES,
|
|
15
|
-
RuntimeErrorCodes.MISSING_FANOUT_ITEM_OUTPUT,
|
|
16
|
-
RuntimeErrorCodes.FANOUT_STAGE_STUCK_PENDING_BATCH,
|
|
17
|
-
RuntimeErrorCodes.RUN_INDEX_OUTPUT_MISMATCH,
|
|
18
|
-
RuntimeErrorCodes.LOOP_EXHAUSTED,
|
|
19
|
-
RuntimeErrorCodes.LOOP_BODY_STAGE_BLOCKED,
|
|
20
|
-
RuntimeErrorCodes.LOOP_BODY_STAGE_FAILED,
|
|
21
|
-
RuntimeErrorCodes.LOOP_BODY_OUTPUT_MISSING,
|
|
22
|
-
RuntimeErrorCodes.VARIABLE_RESOLUTION_FAILED,
|
|
23
|
-
RuntimeErrorCodes.AGENT_RUNTIME_ERROR,
|
|
24
|
-
RuntimeErrorCodes.AGENT_TURN_FAILED,
|
|
25
|
-
RuntimeErrorCodes.AGENT_TURN_CANCELLED,
|
|
26
|
-
RuntimeErrorCodes.AGENT_STAGE_STALE_RECOVERY,
|
|
27
|
-
RuntimeErrorCodes.GATE_CONDITION_FAILED,
|
|
28
|
-
RuntimeErrorCodes.GATE_VERDICT_BLOCKED,
|
|
29
|
-
RuntimeErrorCodes.GATE_VERDICT_FAILED,
|
|
30
|
-
RuntimeErrorCodes.GATE_VERDICT_UNKNOWN
|
|
31
|
-
]);
|
|
32
|
-
const RunDiagnosticCodes = { SCHEDULER_RECOVERY_SUCCEEDED_WITH_BLOCKED_VERDICT: "SCHEDULER_RECOVERY_SUCCEEDED_WITH_BLOCKED_VERDICT" };
|
|
33
|
-
const DEFAULT_EVENT_TAIL_LIMIT = 50;
|
|
34
|
-
const DEFAULT_EVENT_TAIL_MAX_BYTES = 256 * 1024;
|
|
35
|
-
async function buildRunDiagnosticsView(cwd, index, options = {}) {
|
|
36
|
-
const dir = runDir(index.logicalRunId, cwd);
|
|
37
|
-
const eventTail = await readEventTail(path.join(dir, "events.ndjson"), {
|
|
38
|
-
limit: options.eventTailLimit ?? DEFAULT_EVENT_TAIL_LIMIT,
|
|
39
|
-
maxBytes: options.eventTailMaxBytes ?? DEFAULT_EVENT_TAIL_MAX_BYTES
|
|
40
|
-
});
|
|
41
|
-
const diagnostics = [...await buildRuntimeDiagnostics(dir, index), ...buildEventTailDiagnostics(path.join(dir, "events.ndjson"), eventTail)];
|
|
42
|
-
return {
|
|
43
|
-
version: RUN_DIAGNOSTICS_VIEW_VERSION,
|
|
44
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45
|
-
run: {
|
|
46
|
-
logicalRunId: index.logicalRunId,
|
|
47
|
-
workflowName: index.workflowName,
|
|
48
|
-
status: index.status,
|
|
49
|
-
blockedReason: index.blockedReason,
|
|
50
|
-
gateVerdict: index.gateVerdict,
|
|
51
|
-
runDir: dir
|
|
52
|
-
},
|
|
53
|
-
diagnostics,
|
|
54
|
-
eventTail
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
async function readNdjsonTail(filePath, maxLines, maxBytes = DEFAULT_EVENT_TAIL_MAX_BYTES) {
|
|
58
|
-
if (maxLines <= 0 || maxBytes <= 0) return [];
|
|
59
|
-
let handle;
|
|
60
|
-
try {
|
|
61
|
-
const stat = await fs.stat(filePath);
|
|
62
|
-
if (stat.size === 0) return [];
|
|
63
|
-
const bytesToRead = Math.min(stat.size, maxBytes);
|
|
64
|
-
const start = stat.size - bytesToRead;
|
|
65
|
-
const buffer = Buffer.alloc(bytesToRead);
|
|
66
|
-
handle = await fs.open(filePath, "r");
|
|
67
|
-
await handle.read(buffer, 0, bytesToRead, start);
|
|
68
|
-
let lines = buffer.toString("utf8").split("\n");
|
|
69
|
-
if (start > 0) lines = lines.slice(1);
|
|
70
|
-
return lines.filter((line) => line.trim().length > 0).slice(-maxLines);
|
|
71
|
-
} catch {
|
|
72
|
-
return [];
|
|
73
|
-
} finally {
|
|
74
|
-
await handle?.close().catch(() => void 0);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async function readEventTail(filePath, options) {
|
|
78
|
-
return (await readNdjsonTail(filePath, options.limit, options.maxBytes)).map(parseEventLine).filter((event) => event !== void 0);
|
|
79
|
-
}
|
|
80
|
-
async function buildRuntimeDiagnostics(dir, index) {
|
|
81
|
-
const diagnostics = [];
|
|
82
|
-
if (index.blockedReason && isRunLevelRuntimeCode(index.blockedReason)) diagnostics.push(runtimeDiagnostic({
|
|
83
|
-
code: index.blockedReason,
|
|
84
|
-
path: path.join(dir, "run.json"),
|
|
85
|
-
summary: runLevelBlockedSummary(index),
|
|
86
|
-
source: "run_index"
|
|
87
|
-
}));
|
|
88
|
-
for (const stage of Object.values(index.stages)) {
|
|
89
|
-
if (!stage.fanout && (stage.blockedReason === RuntimeErrorCodes.AGENT_RUNTIME_ERROR || stage.blockedReason === RuntimeErrorCodes.AGENT_STAGE_STALE_RECOVERY || stage.blockedReason === RuntimeErrorCodes.AGENT_TASK_RETRY_EXHAUSTED)) {
|
|
90
|
-
const outputPath = stage.outputPath ? path.join(dir, stage.outputPath) : path.join(dir, "outputs", `${stage.stageId}.json`);
|
|
91
|
-
const code = stage.blockedReason;
|
|
92
|
-
diagnostics.push(runtimeDiagnostic({
|
|
93
|
-
code,
|
|
94
|
-
stageId: stage.stageId,
|
|
95
|
-
path: outputPath,
|
|
96
|
-
summary: stageRetryDiagnosticSummary(code),
|
|
97
|
-
source: "run_index"
|
|
98
|
-
}));
|
|
99
|
-
}
|
|
100
|
-
if (!stage.fanout) continue;
|
|
101
|
-
const hasRunningItems = stage.fanout.items.some((item) => item.status === "running");
|
|
102
|
-
const queuedItems = stage.fanout.items.filter((item) => item.status === "pending" || item.status === "ready");
|
|
103
|
-
if (stage.status === "running" && !hasRunningItems && queuedItems.length > 0) diagnostics.push(runtimeDiagnostic({
|
|
104
|
-
code: RuntimeErrorCodes.FANOUT_STAGE_STUCK_PENDING_BATCH,
|
|
105
|
-
stageId: stage.stageId,
|
|
106
|
-
path: path.join(dir, "run.json"),
|
|
107
|
-
summary: `Fanout stage ${stage.stageId} is running with no running items and ${queuedItems.length} queued item(s).`,
|
|
108
|
-
source: "run_index"
|
|
109
|
-
}));
|
|
110
|
-
for (const item of stage.fanout.items) {
|
|
111
|
-
const outputPath = item.outputPath ? path.join(dir, item.outputPath) : path.join(dir, "outputs", stage.stageId, `${safeFileName(item.id)}.json`);
|
|
112
|
-
if (item.status === "running" && await fileExists(outputPath)) diagnostics.push(runtimeDiagnostic({
|
|
113
|
-
code: RuntimeErrorCodes.RUN_INDEX_OUTPUT_MISMATCH,
|
|
114
|
-
stageId: stage.stageId,
|
|
115
|
-
itemId: item.id,
|
|
116
|
-
path: outputPath,
|
|
117
|
-
summary: `Fanout item ${stage.stageId}/${item.id} is running in run.json but has an output file.`,
|
|
118
|
-
source: "stage_output"
|
|
119
|
-
}));
|
|
120
|
-
if (item.errorCode) diagnostics.push(runtimeDiagnostic({
|
|
121
|
-
code: item.errorCode,
|
|
122
|
-
stageId: stage.stageId,
|
|
123
|
-
itemId: item.id,
|
|
124
|
-
path: outputPath,
|
|
125
|
-
summary: item.errorMessage ?? item.blockedReason ?? item.errorCode,
|
|
126
|
-
source: "run_index"
|
|
127
|
-
}));
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const recoveryVerdictDiagnostic = buildRecoverySucceededWithBlockedVerdictDiagnostic(dir, index);
|
|
131
|
-
if (recoveryVerdictDiagnostic) diagnostics.push(recoveryVerdictDiagnostic);
|
|
132
|
-
return diagnostics;
|
|
133
|
-
}
|
|
134
|
-
function stageRetryDiagnosticSummary(code) {
|
|
135
|
-
if (code === RuntimeErrorCodes.AGENT_STAGE_STALE_RECOVERY) return "Agent task retry exhausted after scheduler stale recovery.";
|
|
136
|
-
if (code === RuntimeErrorCodes.AGENT_TASK_RETRY_EXHAUSTED) return "Agent task retry budget exhausted.";
|
|
137
|
-
return "Agent runtime failed after retry exhaustion.";
|
|
138
|
-
}
|
|
139
|
-
function buildEventTailDiagnostics(eventPath, eventTail) {
|
|
140
|
-
const diagnostics = [];
|
|
141
|
-
for (const event of eventTail) {
|
|
142
|
-
if (!(event.summary?.includes("Lock file is already being held") || event.errorCode === RuntimeErrorCodes.RUN_INDEX_LOCK_TIMEOUT || event.errorCode === RuntimeErrorCodes.EVENT_APPEND_LOCK_TIMEOUT)) continue;
|
|
143
|
-
diagnostics.push(runtimeDiagnostic({
|
|
144
|
-
code: event.errorCode ?? "LOCK_CONTENTION",
|
|
145
|
-
stageId: event.stageId,
|
|
146
|
-
itemId: event.itemId,
|
|
147
|
-
attemptId: event.attemptId,
|
|
148
|
-
path: eventPath,
|
|
149
|
-
summary: "Runtime lock contention was observed in recent events.",
|
|
150
|
-
source: "event_tail",
|
|
151
|
-
status: "blocked"
|
|
152
|
-
}));
|
|
153
|
-
}
|
|
154
|
-
return diagnostics;
|
|
155
|
-
}
|
|
156
|
-
function buildRecoverySucceededWithBlockedVerdictDiagnostic(dir, index) {
|
|
157
|
-
if (!isBlockedGateVerdictCode(index.blockedReason) || !index.gateVerdict) return void 0;
|
|
158
|
-
const recoveredFanoutStages = Object.values(index.stages).filter((stage) => {
|
|
159
|
-
if (!stage.fanout) return false;
|
|
160
|
-
if (stage.fanout.items.some((item) => item.status === "running" || item.status === "pending" || item.status === "ready")) return false;
|
|
161
|
-
return stage.fanout.items.some((item) => item.errorCode === RuntimeErrorCodes.AGENT_TASK_RETRY_EXHAUSTED || item.errorCode === RuntimeErrorCodes.FANOUT_ITEM_CASCADE_BLOCKED || item.errorCode === RuntimeErrorCodes.FANOUT_ITEM_UNSTARTED_TIMEOUT || item.errorCode === RuntimeErrorCodes.RUN_INDEX_OUTPUT_MISMATCH);
|
|
162
|
-
});
|
|
163
|
-
if (recoveredFanoutStages.length === 0) return void 0;
|
|
164
|
-
const stageIds = recoveredFanoutStages.map((stage) => stage.stageId);
|
|
165
|
-
return {
|
|
166
|
-
id: `runtime-${RunDiagnosticCodes.SCHEDULER_RECOVERY_SUCCEEDED_WITH_BLOCKED_VERDICT}-run-all`,
|
|
167
|
-
code: RunDiagnosticCodes.SCHEDULER_RECOVERY_SUCCEEDED_WITH_BLOCKED_VERDICT,
|
|
168
|
-
status: "completed",
|
|
169
|
-
summary: `Scheduler recovery completed for fanout stage(s) ${stageIds.join(", ")}, but workflow gate verdict remains ${index.gateVerdict}.`,
|
|
170
|
-
path: path.join(dir, "run.json"),
|
|
171
|
-
source: "run_index"
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
function runtimeDiagnostic(input) {
|
|
175
|
-
return {
|
|
176
|
-
id: `runtime-${input.code}-${input.stageId ?? "run"}-${input.itemId ?? input.attemptId ?? "all"}`,
|
|
177
|
-
code: input.code,
|
|
178
|
-
stageId: input.stageId,
|
|
179
|
-
itemId: input.itemId,
|
|
180
|
-
attemptId: input.attemptId,
|
|
181
|
-
status: input.status ?? "blocked",
|
|
182
|
-
summary: input.summary,
|
|
183
|
-
path: input.path,
|
|
184
|
-
source: input.source
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
function isRunLevelRuntimeCode(value) {
|
|
188
|
-
return RUN_LEVEL_RUNTIME_CODES.has(value);
|
|
189
|
-
}
|
|
190
|
-
function isBlockedGateVerdictCode(value) {
|
|
191
|
-
return value === RuntimeErrorCodes.GATE_VERDICT_BLOCKED || value === RuntimeErrorCodes.GATE_VERDICT_FAILED || value === RuntimeErrorCodes.GATE_VERDICT_UNKNOWN;
|
|
192
|
-
}
|
|
193
|
-
function runLevelBlockedSummary(index) {
|
|
194
|
-
if (index.blockedReason === RuntimeErrorCodes.AGENT_TASK_RETRY_EXHAUSTED) return "Agent Task Retry budget exhausted.";
|
|
195
|
-
if (index.blockedReason === RuntimeErrorCodes.AGENT_RUNTIME_ERROR) return "Agent runtime failed after Agent Task Retry budget exhaustion.";
|
|
196
|
-
if (index.blockedReason === RuntimeErrorCodes.AGENT_STAGE_STALE_RECOVERY) return "Agent stage stale recovery exhausted Agent Task Retry budget.";
|
|
197
|
-
if (index.blockedReason === RuntimeErrorCodes.FANOUT_ITEM_BLOCKED) return "Fanout stage blocked because one or more items did not complete.";
|
|
198
|
-
if (index.blockedReason === RuntimeErrorCodes.GATE_CONDITION_FAILED) return "Program gate condition failed.";
|
|
199
|
-
if (index.gateVerdict === "blocked") return "Gate returned verdict=blocked.";
|
|
200
|
-
if (index.gateVerdict === "failed") return "Gate returned verdict=failed.";
|
|
201
|
-
return "Gate returned verdict=unknown.";
|
|
202
|
-
}
|
|
203
|
-
function parseEventLine(line) {
|
|
204
|
-
const record = objectRecord(safeJson(line));
|
|
205
|
-
if (!record) return void 0;
|
|
206
|
-
const errorCode = stringField(record, "errorCode") ?? stringField(record, "code");
|
|
207
|
-
return {
|
|
208
|
-
at: stringField(record, "at"),
|
|
209
|
-
type: stringField(record, "type"),
|
|
210
|
-
stageId: stringField(record, "stageId"),
|
|
211
|
-
itemId: stringField(record, "itemId"),
|
|
212
|
-
attemptId: stringField(record, "attemptId"),
|
|
213
|
-
errorCode,
|
|
214
|
-
summary: stringField(record, "summary") ?? stringField(record, "error") ?? stringField(record, "errorMessage")
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
async function fileExists(filePath) {
|
|
218
|
-
try {
|
|
219
|
-
await fs.access(filePath);
|
|
220
|
-
return true;
|
|
221
|
-
} catch {
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
function safeJson(value) {
|
|
226
|
-
try {
|
|
227
|
-
return JSON.parse(value);
|
|
228
|
-
} catch {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function objectRecord(value) {
|
|
233
|
-
return value && typeof value === "object" ? value : void 0;
|
|
234
|
-
}
|
|
235
|
-
function stringField(value, key) {
|
|
236
|
-
const field = value?.[key];
|
|
237
|
-
return typeof field === "string" ? field : void 0;
|
|
238
|
-
}
|
|
239
|
-
function safeFileName(value) {
|
|
240
|
-
return String(value || "item").replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
241
|
-
}
|
|
242
|
-
//#endregion
|
|
243
|
-
export { AGENT_TASK_RETRY_BUDGET, AGENT_TASK_RETRY_DELAY_MS, ActorModeSchema, ActorSchema, AgentFaninSchema, ConditionSchema, DEFAULT_AGENT_OUTPUT_SCHEMA, EXECUTION_PLAN_VERSION, FaninSchema, FanoutLaneSchema, FanoutPolicySchema, FanoutStageLimitsSchema, FanoutStageSchema, GateAgentStageSchema, GateProgramStageSchema, GateStageSchema, LimitBindingSchema, LimitValueSchema, LoopBodyStageSchema, LoopStageSchema, OrchestratorError, PositiveIntegerLimitSchema, ProgramFaninSchema, RUN_DIAGNOSTICS_VIEW_VERSION, RUN_MONITOR_VIEW_VERSION, RouteAgentStageSchema, RouteProgramStageSchema, RouteRuleSchema, RouteStageSchema, RunDiagnosticCodes, SCHEMA_VERSION, StageLimitsSchema, StageSchema, TASK_DETAIL_VIEW_VERSION, TaskAgentStageSchema, TaskProgramStageSchema, TaskStageSchema, TransformSchema, VariableSchema, WorkflowInputSchema, WorkflowLimitsSchema, WorkflowSpecSchema, agentTaskRetryDelayMs, buildRunDiagnosticsView, buildRunMonitorView, buildTaskDetailView, collectWorkflowOutputCandidates, compileExecutionPlan, compileSchemaDsl, defaultAgentOutputZod, estimateAgentCalls, estimateFanoutWork, formatContinuationPrompt, formatSchema, isWorkflowYamlPath, issue, lintWorkflowSpec, loadWorkflowSpec, outputSchemaFooter, parseWorkflowOutput, prepareRun, previewRunView, readNdjsonTail, renderPromptMap, renderStagePrompt, resultFromIssues, retryCountByReason, retryExhaustedEnvelope, retryableOutputFailure, runViewFromIndex, setAgentTaskRetryDelayForTests, stageActorLabel, startPreparedRun, stringifyWorkflowSpec, syncRun, topologicalOrder, zodForCompiledSchema };
|
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import { E as buildTaskDetailView, Ft as runDir, N as syncRun, Ot as WorkflowSpecSchema, T as buildRunMonitorView } from "./run-workflow-DdIAC8Zu.mjs";
|
|
2
|
-
import { n as resolveRunLocator } from "./cli.mjs";
|
|
3
|
-
import { a as nextIndex, c as shorten, d as tasksForStage, i as formatDuration, l as stageProgressLabel, n as defaultStageIndex, o as runProgressLabel, r as detailSummary, s as runStatusLabel, t as clampIndex, u as statusMark } from "./monitor-rendering-LGr9Ebd_.mjs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import fs from "node:fs/promises";
|
|
6
|
-
import YAML from "yaml";
|
|
7
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
8
|
-
import { Box, Text, useApp, useInput, useStdout } from "ink";
|
|
9
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
//#region src/tui/monitor-data.ts
|
|
11
|
-
async function loadMonitorSnapshot(runArg) {
|
|
12
|
-
const locator = await resolveRunLocator(runArg);
|
|
13
|
-
const index = await syncRun(locator.cwd, locator.runId, { startPending: false });
|
|
14
|
-
const spec = WorkflowSpecSchema.parse(YAML.parse(await fs.readFile(path.join(runDir(locator.runId, locator.cwd), "workflow.spec.yaml"), "utf8")));
|
|
15
|
-
return {
|
|
16
|
-
locator,
|
|
17
|
-
view: await buildRunMonitorView(locator.cwd, spec, index)
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
async function loadTaskDetail(locator, taskId) {
|
|
21
|
-
const index = await syncRun(locator.cwd, locator.runId, { startPending: false });
|
|
22
|
-
const spec = WorkflowSpecSchema.parse(YAML.parse(await fs.readFile(path.join(runDir(locator.runId, locator.cwd), "workflow.spec.yaml"), "utf8")));
|
|
23
|
-
return buildTaskDetailView(locator.cwd, spec, index, taskId);
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/tui/monitor-app.tsx
|
|
27
|
-
function MonitorApp({ runArg, pollMs = 1e3, initialView, initialLocator, initialFocus = "stages", loadSnapshot = loadMonitorSnapshot, loadDetail = loadTaskDetail }) {
|
|
28
|
-
const { exit } = useApp();
|
|
29
|
-
const { stdout } = useStdout();
|
|
30
|
-
const [locator, setLocator] = useState(initialLocator);
|
|
31
|
-
const [view, setView] = useState(initialView);
|
|
32
|
-
const [error, setError] = useState();
|
|
33
|
-
const [focus, setFocus] = useState(initialFocus);
|
|
34
|
-
const [stageIndex, setStageIndex] = useState(() => initialView ? defaultStageIndex(initialView.stages) : 0);
|
|
35
|
-
const [taskIndex, setTaskIndex] = useState(void 0);
|
|
36
|
-
const [detailTaskId, setDetailTaskId] = useState();
|
|
37
|
-
const [detail, setDetail] = useState();
|
|
38
|
-
const refreshRequest = useRef(0);
|
|
39
|
-
const detailRequest = useRef(0);
|
|
40
|
-
const hasLoadedView = useRef(Boolean(initialView));
|
|
41
|
-
const userSelectedStage = useRef(false);
|
|
42
|
-
async function refresh() {
|
|
43
|
-
const requestId = ++refreshRequest.current;
|
|
44
|
-
try {
|
|
45
|
-
const snapshot = await loadSnapshot(runArg);
|
|
46
|
-
if (requestId !== refreshRequest.current) return;
|
|
47
|
-
const shouldSelectDefaultStage = !hasLoadedView.current && !userSelectedStage.current;
|
|
48
|
-
setLocator(snapshot.locator);
|
|
49
|
-
setView(snapshot.view);
|
|
50
|
-
setError(void 0);
|
|
51
|
-
setStageIndex((current) => {
|
|
52
|
-
if (shouldSelectDefaultStage) return defaultStageIndex(snapshot.view.stages);
|
|
53
|
-
return clampIndex(current, snapshot.view.stages.length);
|
|
54
|
-
});
|
|
55
|
-
hasLoadedView.current = true;
|
|
56
|
-
} catch (loadError) {
|
|
57
|
-
if (requestId !== refreshRequest.current) return;
|
|
58
|
-
setError(loadError instanceof Error ? loadError.message : String(loadError));
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
refresh();
|
|
63
|
-
const timer = setInterval(() => void refresh(), pollMs);
|
|
64
|
-
return () => clearInterval(timer);
|
|
65
|
-
}, [
|
|
66
|
-
runArg,
|
|
67
|
-
pollMs,
|
|
68
|
-
loadSnapshot
|
|
69
|
-
]);
|
|
70
|
-
const selectedStage = view?.stages[stageIndex];
|
|
71
|
-
const stageTasks = useMemo(() => tasksForStage(view, selectedStage?.id), [view, selectedStage?.id]);
|
|
72
|
-
const selectedTask = taskIndex === void 0 ? void 0 : stageTasks[taskIndex];
|
|
73
|
-
const panelWidths = useMemo(() => monitorPanelWidths(stdout.columns), [stdout.columns]);
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
setTaskIndex(void 0);
|
|
76
|
-
setDetailTaskId(void 0);
|
|
77
|
-
setDetail(void 0);
|
|
78
|
-
}, [selectedStage?.id]);
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
setTaskIndex((current) => current === void 0 ? void 0 : clampIndex(current, stageTasks.length));
|
|
81
|
-
}, [stageTasks.length]);
|
|
82
|
-
useEffect(() => {
|
|
83
|
-
setDetailTaskId(selectedTask?.id);
|
|
84
|
-
}, [selectedTask?.id]);
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
const requestId = ++detailRequest.current;
|
|
87
|
-
if (!locator || !detailTaskId) {
|
|
88
|
-
setDetail(void 0);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
setDetail(void 0);
|
|
92
|
-
loadDetail(locator, detailTaskId).then((nextDetail) => {
|
|
93
|
-
if (requestId !== detailRequest.current) return;
|
|
94
|
-
setDetail(nextDetail);
|
|
95
|
-
setError(void 0);
|
|
96
|
-
}).catch((detailError) => {
|
|
97
|
-
if (requestId !== detailRequest.current) return;
|
|
98
|
-
setDetail(void 0);
|
|
99
|
-
setError(detailError instanceof Error ? detailError.message : String(detailError));
|
|
100
|
-
});
|
|
101
|
-
}, [
|
|
102
|
-
locator?.runId,
|
|
103
|
-
detailTaskId,
|
|
104
|
-
loadDetail
|
|
105
|
-
]);
|
|
106
|
-
useInput((input, key) => {
|
|
107
|
-
if (input === "q" || key.ctrl && input === "c") exit();
|
|
108
|
-
if (input === "r") refresh();
|
|
109
|
-
if (key.escape && focus === "detail") {
|
|
110
|
-
setFocus("tasks");
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (key.leftArrow) {
|
|
114
|
-
if (focus === "detail") setFocus("tasks");
|
|
115
|
-
else if (focus === "tasks") setFocus("stages");
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (key.rightArrow) {
|
|
119
|
-
if (focus === "stages" && stageTasks.length > 0) {
|
|
120
|
-
setTaskIndex((current) => current ?? 0);
|
|
121
|
-
setFocus("tasks");
|
|
122
|
-
} else if (focus === "tasks" && selectedTask) setFocus("detail");
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (key.upArrow) {
|
|
126
|
-
if (focus === "tasks") setTaskIndex((current) => nextIndex(current ?? 0, -1, stageTasks.length));
|
|
127
|
-
else if (focus === "stages") {
|
|
128
|
-
userSelectedStage.current = true;
|
|
129
|
-
setStageIndex((current) => nextIndex(current, -1, view?.stages.length ?? 0));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (key.downArrow) {
|
|
133
|
-
if (focus === "tasks") setTaskIndex((current) => nextIndex(current ?? 0, 1, stageTasks.length));
|
|
134
|
-
else if (focus === "stages") {
|
|
135
|
-
userSelectedStage.current = true;
|
|
136
|
-
setStageIndex((current) => nextIndex(current, 1, view?.stages.length ?? 0));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (key.return && focus === "tasks" && selectedTask) setFocus("detail");
|
|
140
|
-
});
|
|
141
|
-
if (!view) return /* @__PURE__ */ jsx(Text, { children: error ? `Error: ${error}` : "Loading monitor..." });
|
|
142
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
143
|
-
flexDirection: "column",
|
|
144
|
-
children: [
|
|
145
|
-
/* @__PURE__ */ jsx(Header, { view }),
|
|
146
|
-
error ? /* @__PURE__ */ jsxs(Text, {
|
|
147
|
-
color: "red",
|
|
148
|
-
children: ["Error: ", error]
|
|
149
|
-
}) : null,
|
|
150
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
151
|
-
marginTop: 1,
|
|
152
|
-
children: [
|
|
153
|
-
/* @__PURE__ */ jsx(StageList, {
|
|
154
|
-
view,
|
|
155
|
-
selectedIndex: stageIndex,
|
|
156
|
-
focused: focus === "stages",
|
|
157
|
-
width: panelWidths.stages
|
|
158
|
-
}),
|
|
159
|
-
/* @__PURE__ */ jsx(StageTaskPanel, {
|
|
160
|
-
view,
|
|
161
|
-
stage: selectedStage,
|
|
162
|
-
tasks: stageTasks,
|
|
163
|
-
selectedIndex: taskIndex,
|
|
164
|
-
focused: focus === "tasks",
|
|
165
|
-
width: panelWidths.tasks
|
|
166
|
-
}),
|
|
167
|
-
/* @__PURE__ */ jsx(DetailPanel, {
|
|
168
|
-
detail,
|
|
169
|
-
focused: focus === "detail",
|
|
170
|
-
width: panelWidths.detail
|
|
171
|
-
})
|
|
172
|
-
]
|
|
173
|
-
}),
|
|
174
|
-
/* @__PURE__ */ jsx(Text, {
|
|
175
|
-
dimColor: true,
|
|
176
|
-
children: "up/down move - left/right panel - enter detail - esc back - r refresh - q quit"
|
|
177
|
-
})
|
|
178
|
-
]
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
function Header({ view }) {
|
|
182
|
-
const title = `${view.run.workflowName}`;
|
|
183
|
-
const worker = view.run.worker ? ` - worker ${view.run.worker.status}` : "";
|
|
184
|
-
const runTime = formatDuration(view.run.durationMs ?? view.run.elapsedMs);
|
|
185
|
-
const meta = `${runProgressLabel(view)} - ${runStatusLabel(view)}${runTime ? ` - ${runTime}` : ""}${worker}`;
|
|
186
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
187
|
-
flexDirection: "column",
|
|
188
|
-
children: [/* @__PURE__ */ jsx(Text, {
|
|
189
|
-
color: "blue",
|
|
190
|
-
bold: true,
|
|
191
|
-
children: title
|
|
192
|
-
}), /* @__PURE__ */ jsxs(Text, {
|
|
193
|
-
dimColor: true,
|
|
194
|
-
children: [
|
|
195
|
-
shorten(view.run.logicalRunId, 48),
|
|
196
|
-
" - ",
|
|
197
|
-
meta
|
|
198
|
-
]
|
|
199
|
-
})]
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
function StageList({ view, selectedIndex, focused, width }) {
|
|
203
|
-
const currentStage = view.stages.find((stage) => stage.status === "running") ?? view.stages.find((stage) => stage.status === "blocked" || stage.status === "failed") ?? view.stages[selectedIndex];
|
|
204
|
-
const finished = view.stages.filter((stage) => stage.status === "completed" || stage.status === "skipped").length;
|
|
205
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
206
|
-
flexDirection: "column",
|
|
207
|
-
width,
|
|
208
|
-
borderStyle: "single",
|
|
209
|
-
paddingX: 1,
|
|
210
|
-
children: [
|
|
211
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
212
|
-
bold: true,
|
|
213
|
-
children: [focused ? "🟢 " : " ", "Stage List"]
|
|
214
|
-
}),
|
|
215
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
216
|
-
dimColor: true,
|
|
217
|
-
children: ["Current: ", shorten(currentStage?.id ?? "-", Math.max(6, width - 13))]
|
|
218
|
-
}),
|
|
219
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
220
|
-
dimColor: true,
|
|
221
|
-
children: [
|
|
222
|
-
"Finished: ",
|
|
223
|
-
finished,
|
|
224
|
-
"/",
|
|
225
|
-
view.stages.length
|
|
226
|
-
]
|
|
227
|
-
}),
|
|
228
|
-
view.stages.map((stage, index) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
229
|
-
/* @__PURE__ */ jsxs(Text, { children: [focused && index === selectedIndex ? "▶" : " ", " "] }),
|
|
230
|
-
/* @__PURE__ */ jsx(StatusMark, { status: stage.status }),
|
|
231
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
232
|
-
" ",
|
|
233
|
-
shorten(stage.id, 22),
|
|
234
|
-
" ",
|
|
235
|
-
stageProgressLabel(stage)
|
|
236
|
-
] })
|
|
237
|
-
] }, stage.id))
|
|
238
|
-
]
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
function StageTaskPanel({ view, stage, tasks, selectedIndex, focused, width }) {
|
|
242
|
-
const counts = stage?.taskCounts;
|
|
243
|
-
const stageTime = formatDuration(stage?.durationMs ?? stage?.elapsedMs);
|
|
244
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
245
|
-
flexDirection: "column",
|
|
246
|
-
width,
|
|
247
|
-
borderStyle: "single",
|
|
248
|
-
paddingX: 1,
|
|
249
|
-
children: [
|
|
250
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
251
|
-
bold: true,
|
|
252
|
-
children: [focused ? "🟢 " : " ", "Stage Info"]
|
|
253
|
-
}),
|
|
254
|
-
stage ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
255
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
256
|
-
shorten(stage.id, 28),
|
|
257
|
-
" ",
|
|
258
|
-
/* @__PURE__ */ jsx(Text, {
|
|
259
|
-
dimColor: true,
|
|
260
|
-
children: stage.kind
|
|
261
|
-
})
|
|
262
|
-
] }),
|
|
263
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
264
|
-
"Status: ",
|
|
265
|
-
stage.status,
|
|
266
|
-
counts ? ` - ${counts.completed}/${counts.total} tasks` : "",
|
|
267
|
-
stageTime ? ` - ${stageTime}` : ""
|
|
268
|
-
] }),
|
|
269
|
-
stage.dependsOn.length > 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
270
|
-
dimColor: true,
|
|
271
|
-
children: ["Depends: ", shorten(stage.dependsOn.join(", "), 34)]
|
|
272
|
-
}) : null,
|
|
273
|
-
stage.blockedReason ? /* @__PURE__ */ jsxs(Text, {
|
|
274
|
-
color: "red",
|
|
275
|
-
children: ["Reason: ", shorten(stage.blockedReason, 34)]
|
|
276
|
-
}) : null,
|
|
277
|
-
stage.outputPath ? /* @__PURE__ */ jsxs(Text, {
|
|
278
|
-
dimColor: true,
|
|
279
|
-
children: ["Output: ", shorten(stage.outputPath, 34)]
|
|
280
|
-
}) : null,
|
|
281
|
-
stage.kind === "gate" && view.run.gateVerdict ? /* @__PURE__ */ jsxs(Text, {
|
|
282
|
-
dimColor: true,
|
|
283
|
-
children: ["Gate: ", view.run.gateVerdict]
|
|
284
|
-
}) : null
|
|
285
|
-
] }) : /* @__PURE__ */ jsx(Text, {
|
|
286
|
-
dimColor: true,
|
|
287
|
-
children: "No stage selected"
|
|
288
|
-
}),
|
|
289
|
-
/* @__PURE__ */ jsx(Text, {
|
|
290
|
-
bold: true,
|
|
291
|
-
children: "Tasks"
|
|
292
|
-
}),
|
|
293
|
-
tasks.length === 0 ? /* @__PURE__ */ jsx(Text, {
|
|
294
|
-
dimColor: true,
|
|
295
|
-
children: "No known Stage Tasks"
|
|
296
|
-
}) : null,
|
|
297
|
-
tasks.map((task, index) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
298
|
-
/* @__PURE__ */ jsxs(Text, { children: [focused && index === selectedIndex ? "▶" : " ", " "] }),
|
|
299
|
-
/* @__PURE__ */ jsx(StatusMark, { status: task.status }),
|
|
300
|
-
/* @__PURE__ */ jsxs(Text, { children: [" ", shorten(task.label, Math.max(16, width - 24))] }),
|
|
301
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
302
|
-
dimColor: true,
|
|
303
|
-
children: [
|
|
304
|
-
" ",
|
|
305
|
-
shorten(task.agent ?? task.execution, 10),
|
|
306
|
-
" ",
|
|
307
|
-
shorten(formatDuration(task.durationMs ?? task.elapsedMs), 7),
|
|
308
|
-
" ",
|
|
309
|
-
shorten(task.blockedReason ?? task.errorCode ?? "", 10)
|
|
310
|
-
]
|
|
311
|
-
})
|
|
312
|
-
] }, task.id))
|
|
313
|
-
]
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
function DetailPanel({ detail, focused, width }) {
|
|
317
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
318
|
-
flexDirection: "column",
|
|
319
|
-
width,
|
|
320
|
-
borderStyle: "single",
|
|
321
|
-
paddingX: 1,
|
|
322
|
-
children: [
|
|
323
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
324
|
-
bold: true,
|
|
325
|
-
children: [focused ? "🟢 " : " ", "Task Detail"]
|
|
326
|
-
}),
|
|
327
|
-
detail ? /* @__PURE__ */ jsx(Text, { children: shorten(detail.task.label, 60) }) : null,
|
|
328
|
-
detailSummary(detail).slice(0, 16).map((line, index) => /* @__PURE__ */ jsx(Text, {
|
|
329
|
-
dimColor: index > 0,
|
|
330
|
-
children: shorten(line, 100)
|
|
331
|
-
}, `${index}-${line}`))
|
|
332
|
-
]
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
function monitorPanelWidths(columns) {
|
|
336
|
-
const total = Math.max(80, columns ?? 120);
|
|
337
|
-
const stages = Math.max(16, Math.floor(total * .2));
|
|
338
|
-
const tasks = Math.max(40, Math.floor(total * .5));
|
|
339
|
-
return {
|
|
340
|
-
stages,
|
|
341
|
-
tasks,
|
|
342
|
-
detail: Math.max(32, total - stages - tasks)
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
function StatusMark({ status }) {
|
|
346
|
-
const mark = statusMark(status);
|
|
347
|
-
if (status === "completed") return /* @__PURE__ */ jsx(Text, {
|
|
348
|
-
color: "green",
|
|
349
|
-
children: mark
|
|
350
|
-
});
|
|
351
|
-
if (status === "running" || status === "raw_received" || status === "parsing") return /* @__PURE__ */ jsx(Text, {
|
|
352
|
-
color: "yellow",
|
|
353
|
-
children: mark
|
|
354
|
-
});
|
|
355
|
-
if (status === "blocked" || status === "failed" || status === "cancelled" || status === "timed_out") return /* @__PURE__ */ jsx(Text, {
|
|
356
|
-
color: "red",
|
|
357
|
-
children: mark
|
|
358
|
-
});
|
|
359
|
-
if (status === "skipped") return /* @__PURE__ */ jsx(Text, {
|
|
360
|
-
dimColor: true,
|
|
361
|
-
children: mark
|
|
362
|
-
});
|
|
363
|
-
return /* @__PURE__ */ jsx(Text, {
|
|
364
|
-
dimColor: true,
|
|
365
|
-
children: mark
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
//#endregion
|
|
369
|
-
export { MonitorApp };
|