pi-harness-runtime 1.1.235 → 1.1.237
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/index.ts +80 -0
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/dist/continuation-controller.d.ts +4 -0
- package/packages/jev-judge/dist/continuation-controller.d.ts.map +1 -1
- package/packages/jev-judge/dist/continuation-controller.js +65 -19
- package/packages/jev-judge/dist/continuation-controller.js.map +1 -1
- package/packages/jev-judge/dist/index.d.ts +5 -3
- package/packages/jev-judge/dist/index.d.ts.map +1 -1
- package/packages/jev-judge/dist/index.js +3 -1
- package/packages/jev-judge/dist/index.js.map +1 -1
- package/packages/jev-judge/dist/task-intake.d.ts +71 -0
- package/packages/jev-judge/dist/task-intake.d.ts.map +1 -0
- package/packages/jev-judge/dist/task-intake.js +217 -0
- package/packages/jev-judge/dist/task-intake.js.map +1 -0
- package/packages/jev-judge/package.json +1 -1
- package/packages/jev-judge/src/continuation-controller.ts +73 -22
- package/packages/jev-judge/src/index.ts +7 -4
- package/packages/jev-judge/src/task-intake.ts +281 -0
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
package/index.ts
CHANGED
|
@@ -282,6 +282,17 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
282
282
|
return null;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
// Detect routine continuation questions ("Should I continue?")
|
|
286
|
+
// These should NOT block immediate continuation - let Jev/todo controller decide
|
|
287
|
+
// Detect routine continuation questions ("Should I continue?")
|
|
288
|
+
// These should NOT block immediate continuation - let Jev/todo controller decide
|
|
289
|
+
function isRoutineContinuation(question: string): boolean {
|
|
290
|
+
const lower = question.toLowerCase();
|
|
291
|
+
// Match patterns like "should i continue?", "should we continue?", etc.
|
|
292
|
+
return (/\b(should i|should we|should the|can i continue|can we continue)\b/.test(lower)
|
|
293
|
+
&& /\b(continue|proceed|with the next|to the next|move on)\b/.test(lower));
|
|
294
|
+
}
|
|
295
|
+
|
|
285
296
|
// Detect when agent asks for continuation
|
|
286
297
|
pi.on("message_end", async (event) => {
|
|
287
298
|
const msg = event.message as { role?: string; content?: string | Array<{ type?: string; text?: string }> } | undefined;
|
|
@@ -291,7 +302,13 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
291
302
|
const detectedQuestion = detectConfirmationRequest(content);
|
|
292
303
|
|
|
293
304
|
// Only trigger if: we found a question AND it's different from last notification
|
|
305
|
+
// Skip routine continuation questions - let Jev/todo controller decide
|
|
294
306
|
if (detectedQuestion && detectedQuestion !== _lastNotifiedQuestion && !waitingForUserSince) {
|
|
307
|
+
// Skip routine continuation - don't block automatic continuation
|
|
308
|
+
if (isRoutineContinuation(detectedQuestion)) {
|
|
309
|
+
logToFile("[auto-continue]", "Routine continuation detected, not blocking");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
295
312
|
_lastNotifiedQuestion = detectedQuestion;
|
|
296
313
|
waitingForUserSince = new Date();
|
|
297
314
|
|
|
@@ -467,6 +484,69 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
467
484
|
todoContinuationController = null;
|
|
468
485
|
});
|
|
469
486
|
|
|
487
|
+
// --- task-intake: Automatic todo capture from user requests -----------
|
|
488
|
+
let taskIntakeController: import("./packages/jev-judge/dist/task-intake.js").TaskIntakeController | null = null;
|
|
489
|
+
|
|
490
|
+
// Create task intake controller if Jev API key is available
|
|
491
|
+
if (resolvedApiKey) {
|
|
492
|
+
try {
|
|
493
|
+
const { TaskIntakeController } = await import("./packages/jev-judge/dist/task-intake.js");
|
|
494
|
+
taskIntakeController = new TaskIntakeController({
|
|
495
|
+
apiKey: resolvedApiKey,
|
|
496
|
+
dispatch: async (content: string) => {
|
|
497
|
+
await pi.sendUserMessage(content, { deliverAs: "steer" });
|
|
498
|
+
},
|
|
499
|
+
});
|
|
500
|
+
logToFile("[auto-continue]", "Task intake controller initialized");
|
|
501
|
+
} catch (err) {
|
|
502
|
+
logToFile("[auto-continue]", "Failed to create task intake controller:", String(err));
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Clean up task intake on session shutdown
|
|
507
|
+
pi.on("session_shutdown", () => {
|
|
508
|
+
taskIntakeController = null;
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
// Wire user messages to task intake
|
|
512
|
+
pi.on("message_start", (event) => {
|
|
513
|
+
const msg = (event as { message?: { role?: string; content?: string } }).message;
|
|
514
|
+
if (msg?.role === "user" && taskIntakeController) {
|
|
515
|
+
// Pause continuation when user sends message
|
|
516
|
+
if (todoContinuationController) {
|
|
517
|
+
todoContinuationController.pause();
|
|
518
|
+
logToFile("[auto-continue]", "User input received, pausing continuation");
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Extract user message content
|
|
522
|
+
const content = msg.content;
|
|
523
|
+
let userMessage = "";
|
|
524
|
+
if (typeof content === "string") {
|
|
525
|
+
userMessage = content;
|
|
526
|
+
} else if (Array.isArray(content)) {
|
|
527
|
+
const textBlocks = (content as Array<{ type?: string; text?: string }>)
|
|
528
|
+
.filter((c): c is { type: "text"; text: string } =>
|
|
529
|
+
c.type === "text" && typeof c.text === "string"
|
|
530
|
+
);
|
|
531
|
+
userMessage = textBlocks.map((c) => c.text).join("\n");
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Evaluate with task intake controller (non-blocking)
|
|
535
|
+
if (userMessage.trim().length > 10 && taskIntakeController) {
|
|
536
|
+
const intake = taskIntakeController;
|
|
537
|
+
intake.evaluate(userMessage).then(async (result) => {
|
|
538
|
+
if (result.actionable && result.action !== "skip") {
|
|
539
|
+
logToFile("[auto-continue]", "Task intake result:", JSON.stringify(result));
|
|
540
|
+
// Request capture if actionable
|
|
541
|
+
await intake.requestCapture(userMessage);
|
|
542
|
+
}
|
|
543
|
+
}).catch((err) => {
|
|
544
|
+
logToFile("[auto-continue]", "Task intake error:", String(err));
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
470
550
|
// --- agent_settled: Check todos and continue work ---------------
|
|
471
551
|
pi.on("agent_settled", async (_event, ctx) => {
|
|
472
552
|
// Don't continue if user is waiting for response
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.237",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -65,6 +65,10 @@ export declare class TodoContinuationController {
|
|
|
65
65
|
* Continue a specific todo item
|
|
66
66
|
*/
|
|
67
67
|
continueItem(item: TodoItem): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Guarded dispatch - checks all conditions before sending
|
|
70
|
+
*/
|
|
71
|
+
private guardedDispatch;
|
|
68
72
|
/**
|
|
69
73
|
* Steer to continue a todo item
|
|
70
74
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"continuation-controller.d.ts","sourceRoot":"","sources":["../src/continuation-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAmBhE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,iEAAiE;IACjE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,4CAA4C;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,2BAA2B,EAAE,MAAM,CAAC;IACpC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,0BAA0B;IACtC,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,YAAY,CAAwC;IAE5D,OAAO,CAAC,KAAK,CAaX;IAEF,YAAY,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,kBAAkB,EAUxD;IAED;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"continuation-controller.d.ts","sourceRoot":"","sources":["../src/continuation-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAmBhE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,iEAAiE;IACjE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,4CAA4C;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,2BAA2B,EAAE,MAAM,CAAC;IACpC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,0BAA0B;IACtC,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,YAAY,CAAwC;IAE5D,OAAO,CAAC,KAAK,CAaX;IAEF,YAAY,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,kBAAkB,EAUxD;IAED;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAmF1C;IAED;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BhD;IAED;;OAEG;YACW,eAAe;IA+C7B;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBnD;IAED;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjD;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAIZ;IAED;;OAEG;IACH,MAAM,IAAI,IAAI,CAeb;IAED;;OAEG;IACH,QAAQ,IAAI,IAAI,CAIf;IAED;;OAEG;IACH,QAAQ,IAAI;QAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAM7E;CACD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,GAAG,EAAE,WAAW,EAChB,MAAM,CAAC,EAAE,kBAAkB,GACzB,0BAA0B,CAE5B"}
|
|
@@ -87,19 +87,29 @@ export class TodoContinuationController {
|
|
|
87
87
|
let inProgress;
|
|
88
88
|
let ready;
|
|
89
89
|
let blocked;
|
|
90
|
+
let allItems;
|
|
90
91
|
try {
|
|
91
92
|
inProgress = await this.todoProvider.getInProgress();
|
|
92
93
|
ready = await this.todoProvider.getReady();
|
|
93
94
|
blocked = await this.todoProvider.getBlocked();
|
|
95
|
+
const snapshot = await this.todoProvider.getSnapshot();
|
|
96
|
+
allItems = snapshot.items;
|
|
94
97
|
}
|
|
95
98
|
catch (err) {
|
|
96
99
|
const msg = err instanceof Error ? err.message : String(err);
|
|
97
100
|
debugLog("TodoContinuation", "Failed to read todos:", msg);
|
|
98
101
|
return { action: "stop", reason: `todo read failed: ${msg}` };
|
|
99
102
|
}
|
|
100
|
-
// 4.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
// 4. Filter in-progress for items without unfinished blockers
|
|
104
|
+
const unblockedInProgress = inProgress.filter((item) => {
|
|
105
|
+
if (!item.blockedBy?.length)
|
|
106
|
+
return true;
|
|
107
|
+
const blockerIds = new Set(item.blockedBy);
|
|
108
|
+
return !allItems.some((i) => blockerIds.has(i.id) && i.status !== "completed" && i.id !== item.id);
|
|
109
|
+
});
|
|
110
|
+
// 5. Continue unblocked in-progress work first
|
|
111
|
+
if (unblockedInProgress.length > 0) {
|
|
112
|
+
const item = unblockedInProgress[0];
|
|
103
113
|
// Reset counter if switching to a different task
|
|
104
114
|
if (this.state.lastItemContinued !== item.id) {
|
|
105
115
|
this.state.steerAttemptsForCurrentItem = 0;
|
|
@@ -163,6 +173,52 @@ export class TodoContinuationController {
|
|
|
163
173
|
this.state.continuationQueued = false;
|
|
164
174
|
}
|
|
165
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Guarded dispatch - checks all conditions before sending
|
|
178
|
+
*/
|
|
179
|
+
async guardedDispatch(itemId, message) {
|
|
180
|
+
// 1. Check if paused by user
|
|
181
|
+
if (this.state.userPaused) {
|
|
182
|
+
debugLog("TodoContinuation", "Guarded dispatch: user paused, skipping");
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
// 2. Check if session is still idle
|
|
186
|
+
if (this.ctx.isIdle?.() === false) {
|
|
187
|
+
debugLog("TodoContinuation", "Guarded dispatch: session not idle, skipping");
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
// 3. Check if continuation already queued (prevent duplicates)
|
|
191
|
+
if (this.state.continuationQueued) {
|
|
192
|
+
debugLog("TodoContinuation", "Guarded dispatch: already queued, skipping");
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
// 4. Verify item still needs work (not completed)
|
|
196
|
+
try {
|
|
197
|
+
const snapshot = await this.todoProvider.getSnapshot();
|
|
198
|
+
const item = snapshot.items.find((i) => i.id === itemId);
|
|
199
|
+
if (item?.status === "completed") {
|
|
200
|
+
debugLog("TodoContinuation", "Guarded dispatch: item completed, skipping");
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// If we can't read todos, skip dispatch
|
|
206
|
+
debugLog("TodoContinuation", "Guarded dispatch: failed to read todos, skipping");
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
// All checks passed - dispatch
|
|
210
|
+
this.state.continuationQueued = true;
|
|
211
|
+
this.state.lastSteerMessage = message;
|
|
212
|
+
try {
|
|
213
|
+
await this.config.dispatch(message);
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
debugLog("TodoContinuation", "Guarded dispatch failed:", String(err));
|
|
218
|
+
this.state.continuationQueued = false;
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
166
222
|
/**
|
|
167
223
|
* Steer to continue a todo item
|
|
168
224
|
*/
|
|
@@ -177,22 +233,12 @@ export class TodoContinuationController {
|
|
|
177
233
|
return;
|
|
178
234
|
}
|
|
179
235
|
this.state.steerAttemptsForCurrentItem++;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this.state.lastSteerMessage = message;
|
|
187
|
-
this.state.todoRevision = snapshot.revision;
|
|
188
|
-
debugLog("TodoContinuation", "Steering to continue item", itemId);
|
|
189
|
-
// Send continuation message via dispatch callback
|
|
190
|
-
try {
|
|
191
|
-
await this.config.dispatch(message);
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
debugLog("TodoContinuation", "Failed to send steer:", String(err));
|
|
195
|
-
this.state.continuationQueued = false;
|
|
236
|
+
const message = `Continue todo item ID ${itemId}.`;
|
|
237
|
+
debugLog("TodoContinuation", "Attempting steer to continue item", itemId);
|
|
238
|
+
// Use guarded dispatch to verify all conditions
|
|
239
|
+
const sent = await this.guardedDispatch(itemId, message);
|
|
240
|
+
if (!sent) {
|
|
241
|
+
debugLog("TodoContinuation", "Steer blocked by guard conditions");
|
|
196
242
|
}
|
|
197
243
|
}
|
|
198
244
|
/**
|