@dougbots/avenor-pi 0.11.0 → 0.12.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/dist/index.d.ts +3 -1
- package/dist/index.js +111 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InspectResult, StatusResult, Supervisor, answerPermissionTool, brokerReceiveTool, brokerReplyTool, dial, eventsTool, followUpTool, inspectTool, observeRun, resultTool, shutdownTool, spawnTool, statusTool, workflowCompleteTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowStatusTool, workflowWaitTool } from "@dougbots/avenor-core";
|
|
1
|
+
import { InspectResult, StatusResult, Supervisor, answerPermissionTool, brokerReceiveTool, brokerReplyTool, dial, eventsTool, followUpTool, inspectTool, observeRun, resultTool, shutdownTool, spawnTool, statusTool, workflowCompleteTool, workflowControllerStatusTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowReadyTool, workflowStatusTool, workflowWaitTool } from "@dougbots/avenor-core";
|
|
2
2
|
import { EventBus, ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
|
|
4
4
|
//#region src/subagent-broker.d.ts
|
|
@@ -134,6 +134,8 @@ interface ExtensionDeps {
|
|
|
134
134
|
workflowEventsTool: typeof workflowEventsTool;
|
|
135
135
|
workflowCompleteTool: typeof workflowCompleteTool;
|
|
136
136
|
workflowGateTool: typeof workflowGateTool;
|
|
137
|
+
workflowControllerStatusTool: typeof workflowControllerStatusTool;
|
|
138
|
+
workflowReadyTool: typeof workflowReadyTool;
|
|
137
139
|
observeRun: typeof observeRun;
|
|
138
140
|
dial: typeof dial;
|
|
139
141
|
Supervisor: typeof Supervisor;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Input, Key, Text, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
|
-
import { Supervisor, THINKING_LEVELS, answerPermissionTool, askTool, brokerReceiveTool, brokerReplyTool, cancelTool, dial, eventsTool, extractEventText, followUpTool, inspectTool, observeRun, peersTool, resultTool, shutdownTool, socketsRoot, spawnTool, statusTool, validateSpawnSelection, workflowCompleteTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowStatusTool, workflowWaitTool } from "@dougbots/avenor-core";
|
|
4
|
+
import { Supervisor, THINKING_LEVELS, answerPermissionTool, askTool, brokerReceiveTool, brokerReplyTool, cancelTool, dial, eventsTool, extractEventText, followUpTool, inspectTool, observeRun, peersTool, resultTool, shutdownTool, socketsRoot, spawnTool, statusTool, validateSpawnSelection, workflowCompleteTool, workflowControllerStatusTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowReadyTool, workflowStatusTool, workflowWaitTool } from "@dougbots/avenor-core";
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
//#region src/subagent-broker.ts
|
|
@@ -1230,6 +1230,66 @@ function shutdownLines(details, args, expanded) {
|
|
|
1230
1230
|
...paths.length > CLEANUP_ITEMS ? [itemMarker(paths.length - CLEANUP_ITEMS)] : []
|
|
1231
1231
|
];
|
|
1232
1232
|
}
|
|
1233
|
+
function controllerLeaderLine(leader) {
|
|
1234
|
+
if (!leader) return "Leader: none";
|
|
1235
|
+
const owner = leader.is_this_process === true ? "this process" : `other owner (${scalar(leader.owner_id)})`;
|
|
1236
|
+
const expires = optionalScalar(leader.expires_at);
|
|
1237
|
+
return `Leader: ${owner}${expires ? ` — lease expires ${expires}` : ""}`;
|
|
1238
|
+
}
|
|
1239
|
+
function controllerStatusLines(details, args, expanded) {
|
|
1240
|
+
const status = asRecord(details);
|
|
1241
|
+
if (!status || !stringValue(status.controller_id) || !stringValue(status.desired_state)) return void 0;
|
|
1242
|
+
const controllerId = selected(status, "controller_id", args.controller_id);
|
|
1243
|
+
const desiredState = selected(status, "desired_state");
|
|
1244
|
+
const inflight = numberValue(status.inflight) ?? 0;
|
|
1245
|
+
const maxInflight = numberValue(status.max_inflight);
|
|
1246
|
+
const blocked = asRecord(status.capacity_blocked);
|
|
1247
|
+
const blockedDetail = blocked ? optionalScalar(blocked.detail) : void 0;
|
|
1248
|
+
const lines = [`Controller: ${controllerId} — ${desiredState}`, controllerLeaderLine(asRecord(status.leader))];
|
|
1249
|
+
const candidates = numberValue(status.candidate_count);
|
|
1250
|
+
if (candidates !== void 0) lines.push(`Candidates: ${candidates} (advisory)`);
|
|
1251
|
+
lines.push(`In-flight: ${inflight}${maxInflight !== void 0 ? ` of ${maxInflight}` : ""}`);
|
|
1252
|
+
const lastReconcile = optionalScalar(status.last_reconcile);
|
|
1253
|
+
if (lastReconcile) lines.push(`Last reconcile: ${lastReconcile}`);
|
|
1254
|
+
if (blocked) lines.push(`Capacity blocked: ${selected(blocked, "source")}${blockedDetail ? ` — ${blockedDetail}` : ""}`);
|
|
1255
|
+
const nextPoll = optionalScalar(status.next_poll_at);
|
|
1256
|
+
if (nextPoll) lines.push(`Next external poll: ${nextPoll}`);
|
|
1257
|
+
lines.push(desiredState === "disabled" ? `Guidance: Run \`avenor workflow controller enable ${controllerId}\` to start dispatch and polling.` : `Guidance: Call avenor_workflow_controller_status without controller_id to review all controllers.`);
|
|
1258
|
+
if (!expanded) return lines;
|
|
1259
|
+
const supervisor = stringValue(args.supervisor_id) ? scalar(args.supervisor_id) : "singleton";
|
|
1260
|
+
return [
|
|
1261
|
+
...lines,
|
|
1262
|
+
`Supervisor: ${supervisor}`,
|
|
1263
|
+
...maxInflight !== void 0 ? [`Max in-flight: ${maxInflight}`] : [],
|
|
1264
|
+
...optionalNumber(status.revision) !== void 0 ? [`Revision: ${optionalNumber(status.revision)}`] : [],
|
|
1265
|
+
...optionalNumber(status.owner_epoch) !== void 0 ? [`Owner epoch: ${optionalNumber(status.owner_epoch)}`] : []
|
|
1266
|
+
];
|
|
1267
|
+
}
|
|
1268
|
+
function controllerListLines(details, args, expanded) {
|
|
1269
|
+
const result = asRecord(details);
|
|
1270
|
+
if (!result || !Array.isArray(result.controllers) || result.controllers.some((controller) => !asRecord(controller))) return void 0;
|
|
1271
|
+
const controllers = result.controllers.map((controller) => controller);
|
|
1272
|
+
stringValue(args.supervisor_id) && scalar(args.supervisor_id);
|
|
1273
|
+
if (controllers.length === 0) return ["No workflow controllers configured."];
|
|
1274
|
+
const displayed = controllers.slice(0, STATUS_ROWS);
|
|
1275
|
+
const lines = [
|
|
1276
|
+
`Workflow controllers — ${controllers.length}`,
|
|
1277
|
+
...displayed.map(controllerListRow),
|
|
1278
|
+
...controllers.length > displayed.length ? [itemMarker(controllers.length - displayed.length)] : []
|
|
1279
|
+
];
|
|
1280
|
+
if (!expanded) return lines;
|
|
1281
|
+
for (const controller of displayed) {
|
|
1282
|
+
const leader = asRecord(controller.leader);
|
|
1283
|
+
const ownerEpoch = leader ? numberValue(leader.owner_epoch) : void 0;
|
|
1284
|
+
lines.push(`${selected(controller, "controller_id")}:`, controllerLeaderLine(leader), ...ownerEpoch !== void 0 ? [`Owner epoch: ${ownerEpoch}`] : []);
|
|
1285
|
+
}
|
|
1286
|
+
return lines;
|
|
1287
|
+
}
|
|
1288
|
+
function controllerListRow(controller) {
|
|
1289
|
+
const leader = asRecord(controller.leader);
|
|
1290
|
+
const owner = leader ? leader.is_this_process === true ? "this process" : `other owner (${scalar(leader.owner_id)})` : "none";
|
|
1291
|
+
return `${selected(controller, "controller_id")} — ${selected(controller, "desired_state")} — leader: ${owner}`;
|
|
1292
|
+
}
|
|
1233
1293
|
function render(tool, result, options, theme, build) {
|
|
1234
1294
|
try {
|
|
1235
1295
|
return linesText(options.isPartial ? partial(result) : build() ?? fallback(tool), theme);
|
|
@@ -1322,6 +1382,15 @@ function renderEventsResult(result, options, theme, args) {
|
|
|
1322
1382
|
function renderShutdownResult(result, options, theme, args) {
|
|
1323
1383
|
return render("shutdown", result, options, theme, () => shutdownLines(result.details, args, options.expanded));
|
|
1324
1384
|
}
|
|
1385
|
+
function renderWorkflowControllerStatusCall(args, theme) {
|
|
1386
|
+
const pieces = stringValue(args.controller_id) ? [`avenor_workflow_controller_status controller_id ${quoted(args.controller_id)}`] : ["avenor_workflow_controller_status (all controllers)"];
|
|
1387
|
+
const supervisor = optionalQuoted(args.supervisor_id);
|
|
1388
|
+
if (supervisor) pieces.push(`supervisor_id ${supervisor}`);
|
|
1389
|
+
return linesText([pieces.join(" ")], theme);
|
|
1390
|
+
}
|
|
1391
|
+
function renderWorkflowControllerStatusResult(result, options, theme, args) {
|
|
1392
|
+
return render("workflow controller status", result, options, theme, () => controllerStatusLines(result.details, args, options.expanded) ?? controllerListLines(result.details, args, options.expanded));
|
|
1393
|
+
}
|
|
1325
1394
|
//#endregion
|
|
1326
1395
|
//#region src/index.ts
|
|
1327
1396
|
const POLL_INTERVAL_MS = 3e3;
|
|
@@ -1349,6 +1418,8 @@ const defaultDeps = {
|
|
|
1349
1418
|
workflowEventsTool,
|
|
1350
1419
|
workflowCompleteTool,
|
|
1351
1420
|
workflowGateTool,
|
|
1421
|
+
workflowControllerStatusTool,
|
|
1422
|
+
workflowReadyTool,
|
|
1352
1423
|
observeRun,
|
|
1353
1424
|
dial,
|
|
1354
1425
|
Supervisor
|
|
@@ -2885,6 +2956,45 @@ function createExtension(deps = defaultDeps, options = {}) {
|
|
|
2885
2956
|
};
|
|
2886
2957
|
}
|
|
2887
2958
|
});
|
|
2959
|
+
pi.registerTool({
|
|
2960
|
+
name: "avenor_workflow_controller_status",
|
|
2961
|
+
label: "Avenor Workflow Controller Status",
|
|
2962
|
+
description: "Show workflow controller status. With controller_id, returns that controller's full status; without it, lists all controllers with summary state. Create, enable, and disable are CLI-only (avenor workflow controller ...).",
|
|
2963
|
+
parameters: Type.Object({
|
|
2964
|
+
controller_id: Type.Optional(Type.String({ description: "Controller ID; omit to list all controllers" })),
|
|
2965
|
+
supervisor_id: Type.Optional(Type.String({ description: "Supervisor ID for multi-supervisor mode" }))
|
|
2966
|
+
}),
|
|
2967
|
+
async execute(_toolCallId, params) {
|
|
2968
|
+
const result = await deps.workflowControllerStatusTool({
|
|
2969
|
+
controllerId: params.controller_id,
|
|
2970
|
+
supervisorId: params.supervisor_id
|
|
2971
|
+
});
|
|
2972
|
+
const details = { ...result };
|
|
2973
|
+
if (params.controller_id) try {
|
|
2974
|
+
const ready = await deps.workflowReadyTool({
|
|
2975
|
+
controllerId: params.controller_id,
|
|
2976
|
+
supervisorId: params.supervisor_id
|
|
2977
|
+
});
|
|
2978
|
+
if (Array.isArray(ready.candidates)) details.candidate_count = ready.candidates.length;
|
|
2979
|
+
} catch {}
|
|
2980
|
+
return {
|
|
2981
|
+
content: [{
|
|
2982
|
+
type: "text",
|
|
2983
|
+
text: JSON.stringify(result, null, 2)
|
|
2984
|
+
}],
|
|
2985
|
+
details
|
|
2986
|
+
};
|
|
2987
|
+
},
|
|
2988
|
+
renderCall(args, theme, context) {
|
|
2989
|
+
return renderWorkflowControllerStatusCall(context.args, theme);
|
|
2990
|
+
},
|
|
2991
|
+
renderResult(result, { expanded, isPartial }, theme, context) {
|
|
2992
|
+
return renderWorkflowControllerStatusResult(result, {
|
|
2993
|
+
expanded,
|
|
2994
|
+
isPartial
|
|
2995
|
+
}, theme, context.args);
|
|
2996
|
+
}
|
|
2997
|
+
});
|
|
2888
2998
|
pi.registerCommand("avenor-status", {
|
|
2889
2999
|
description: "Show status of all avenor runs",
|
|
2890
3000
|
handler: async (_args, ctx) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dougbots/avenor-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dev": "tsdown --watch"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@dougbots/avenor-core": "^0.
|
|
38
|
+
"@dougbots/avenor-core": "^0.12.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@earendil-works/pi-coding-agent": ">=0.74.0",
|