@trevonistrevon/pi-loop 0.5.7 → 0.5.9
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/.release-please-manifest.json +3 -0
- package/Dockerfile +17 -0
- package/coverage/coverage-final.json +28 -27
- package/coverage/index.html +47 -47
- package/coverage/src/commands/index.html +15 -15
- package/coverage/src/commands/loop-command.ts.html +3 -3
- package/coverage/src/commands/tasks-command.ts.html +23 -23
- package/coverage/src/coordinator.ts.html +20 -20
- package/coverage/src/goal-coordinator.ts.html +1 -1
- package/coverage/src/goal-reducer.ts.html +1 -1
- package/coverage/src/goal-store.ts.html +1 -1
- package/coverage/src/goal-verifier.ts.html +1 -1
- package/coverage/src/index.html +42 -42
- package/coverage/src/index.ts.html +122 -74
- package/coverage/src/loop-parse.ts.html +61 -61
- package/coverage/src/loop-reducer.ts.html +25 -25
- package/coverage/src/monitor-completion-coordinator.ts.html +3 -3
- package/coverage/src/monitor-manager.ts.html +73 -67
- package/coverage/src/monitor-reducer.ts.html +27 -27
- package/coverage/src/notification-reducer.ts.html +7 -7
- package/coverage/src/reducer-backed-store.ts.html +53 -53
- package/coverage/src/runtime/index.html +66 -51
- package/coverage/src/runtime/monitor-ondone-runtime.ts.html +39 -39
- package/coverage/src/runtime/notification-runtime.ts.html +14 -14
- package/coverage/src/runtime/scope.ts.html +34 -34
- package/coverage/src/runtime/session-runtime.ts.html +63 -57
- package/coverage/src/runtime/task-backlog-runtime.ts.html +48 -48
- package/coverage/src/runtime/task-events.ts.html +208 -0
- package/coverage/src/runtime/task-rpc.ts.html +88 -82
- package/coverage/src/scheduler.ts.html +34 -34
- package/coverage/src/store.ts.html +21 -21
- package/coverage/src/task-backlog-coordinator.ts.html +8 -8
- package/coverage/src/task-reducer.ts.html +39 -39
- package/coverage/src/task-store.ts.html +55 -55
- package/coverage/src/tools/index.html +43 -43
- package/coverage/src/tools/loop-tools.ts.html +94 -94
- package/coverage/src/tools/monitor-tools.ts.html +53 -53
- package/coverage/src/tools/native-task-tools.ts.html +99 -78
- package/coverage/src/trigger-system.ts.html +8 -8
- package/coverage/src/ui/index.html +1 -1
- package/coverage/src/ui/widget.ts.html +5 -5
- package/dist/commands/tasks-command.js +12 -9
- package/dist/index.js +34 -19
- package/dist/monitor-manager.d.ts +4 -1
- package/dist/monitor-manager.js +8 -4
- package/dist/runtime/session-runtime.js +3 -1
- package/dist/runtime/task-events.d.ts +15 -0
- package/dist/runtime/task-events.js +13 -0
- package/dist/runtime/task-rpc.js +2 -0
- package/dist/tools/native-task-tools.js +20 -9
- package/docker-compose.yml +12 -0
- package/package.json +1 -1
- package/release-please-config.json +9 -0
- package/src/commands/tasks-command.ts +9 -9
- package/src/index.ts +37 -21
- package/src/monitor-manager.ts +14 -4
- package/src/runtime/session-runtime.ts +3 -1
- package/src/runtime/task-events.ts +41 -0
- package/src/runtime/task-rpc.ts +2 -0
- package/src/tools/native-task-tools.ts +16 -9
- package/vitest.config.ts +11 -7
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">100% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>62/62</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">84.09% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>37/44</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">
|
|
40
|
+
<span class="strong">100% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>6/6</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">100% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>53/53</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
</div>
|
|
62
62
|
</template>
|
|
63
63
|
</div>
|
|
64
|
-
<div class='status-line
|
|
64
|
+
<div class='status-line high'></div>
|
|
65
65
|
<pre><table class="coverage">
|
|
66
66
|
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
67
|
<a name='L2'></a><a href='#L2'>2</a>
|
|
@@ -213,7 +213,14 @@
|
|
|
213
213
|
<a name='L148'></a><a href='#L148'>148</a>
|
|
214
214
|
<a name='L149'></a><a href='#L149'>149</a>
|
|
215
215
|
<a name='L150'></a><a href='#L150'>150</a>
|
|
216
|
-
<a name='L151'></a><a href='#L151'>151</a
|
|
216
|
+
<a name='L151'></a><a href='#L151'>151</a>
|
|
217
|
+
<a name='L152'></a><a href='#L152'>152</a>
|
|
218
|
+
<a name='L153'></a><a href='#L153'>153</a>
|
|
219
|
+
<a name='L154'></a><a href='#L154'>154</a>
|
|
220
|
+
<a name='L155'></a><a href='#L155'>155</a>
|
|
221
|
+
<a name='L156'></a><a href='#L156'>156</a>
|
|
222
|
+
<a name='L157'></a><a href='#L157'>157</a>
|
|
223
|
+
<a name='L158'></a><a href='#L158'>158</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
217
224
|
<span class="cline-any cline-neutral"> </span>
|
|
218
225
|
<span class="cline-any cline-neutral"> </span>
|
|
219
226
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -230,14 +237,14 @@
|
|
|
230
237
|
<span class="cline-any cline-neutral"> </span>
|
|
231
238
|
<span class="cline-any cline-neutral"> </span>
|
|
232
239
|
<span class="cline-any cline-neutral"> </span>
|
|
233
|
-
<span class="cline-any cline-yes">71x</span>
|
|
234
240
|
<span class="cline-any cline-neutral"> </span>
|
|
241
|
+
<span class="cline-any cline-yes">82x</span>
|
|
235
242
|
<span class="cline-any cline-neutral"> </span>
|
|
236
243
|
<span class="cline-any cline-neutral"> </span>
|
|
237
|
-
<span class="cline-any cline-yes">45x</span>
|
|
238
244
|
<span class="cline-any cline-neutral"> </span>
|
|
239
|
-
<span class="cline-any cline-yes">
|
|
245
|
+
<span class="cline-any cline-yes">55x</span>
|
|
240
246
|
<span class="cline-any cline-neutral"> </span>
|
|
247
|
+
<span class="cline-any cline-yes">55x</span>
|
|
241
248
|
<span class="cline-any cline-neutral"> </span>
|
|
242
249
|
<span class="cline-any cline-neutral"> </span>
|
|
243
250
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -261,49 +268,46 @@
|
|
|
261
268
|
<span class="cline-any cline-neutral"> </span>
|
|
262
269
|
<span class="cline-any cline-neutral"> </span>
|
|
263
270
|
<span class="cline-any cline-neutral"> </span>
|
|
264
|
-
<span class="cline-any cline-yes">40x</span>
|
|
265
|
-
<span class="cline-any cline-yes">40x</span>
|
|
266
271
|
<span class="cline-any cline-neutral"> </span>
|
|
272
|
+
<span class="cline-any cline-yes">42x</span>
|
|
273
|
+
<span class="cline-any cline-yes">42x</span>
|
|
274
|
+
<span class="cline-any cline-yes">42x</span>
|
|
275
|
+
<span class="cline-any cline-yes">42x</span>
|
|
267
276
|
<span class="cline-any cline-neutral"> </span>
|
|
277
|
+
<span class="cline-any cline-yes">42x</span>
|
|
268
278
|
<span class="cline-any cline-neutral"> </span>
|
|
269
279
|
<span class="cline-any cline-neutral"> </span>
|
|
280
|
+
<span class="cline-any cline-yes">42x</span>
|
|
270
281
|
<span class="cline-any cline-neutral"> </span>
|
|
271
|
-
<span class="cline-any cline-yes">40x</span>
|
|
272
|
-
<span class="cline-any cline-yes">40x</span>
|
|
273
282
|
<span class="cline-any cline-neutral"> </span>
|
|
274
|
-
<span class="cline-any cline-yes">40x</span>
|
|
275
283
|
<span class="cline-any cline-neutral"> </span>
|
|
284
|
+
<span class="cline-any cline-yes">55x</span>
|
|
276
285
|
<span class="cline-any cline-neutral"> </span>
|
|
277
|
-
<span class="cline-any cline-yes">40x</span>
|
|
278
286
|
<span class="cline-any cline-neutral"> </span>
|
|
279
287
|
<span class="cline-any cline-neutral"> </span>
|
|
280
288
|
<span class="cline-any cline-neutral"> </span>
|
|
281
|
-
<span class="cline-any cline-yes">45x</span>
|
|
282
289
|
<span class="cline-any cline-neutral"> </span>
|
|
290
|
+
<span class="cline-any cline-yes">7x</span>
|
|
291
|
+
<span class="cline-any cline-yes">7x</span>
|
|
283
292
|
<span class="cline-any cline-neutral"> </span>
|
|
284
|
-
<span class="cline-any cline-
|
|
285
|
-
<span class="cline-any cline-
|
|
286
|
-
<span class="cline-any cline-neutral"> </span>
|
|
287
|
-
<span class="cline-any cline-yes">5x</span>
|
|
288
|
-
<span class="cline-any cline-yes">5x</span>
|
|
289
|
-
<span class="cline-any cline-neutral"> </span>
|
|
290
|
-
<span class="cline-any cline-yes">5x</span>
|
|
291
|
-
<span class="cline-any cline-yes">5x</span>
|
|
293
|
+
<span class="cline-any cline-yes">6x</span>
|
|
294
|
+
<span class="cline-any cline-yes">6x</span>
|
|
292
295
|
<span class="cline-any cline-neutral"> </span>
|
|
293
296
|
<span class="cline-any cline-neutral"> </span>
|
|
294
297
|
<span class="cline-any cline-neutral"> </span>
|
|
295
298
|
<span class="cline-any cline-neutral"> </span>
|
|
296
|
-
<span class="cline-any cline-yes">5x</span>
|
|
297
299
|
<span class="cline-any cline-yes">6x</span>
|
|
300
|
+
<span class="cline-any cline-yes">8x</span>
|
|
301
|
+
<span class="cline-any cline-yes">8x</span>
|
|
302
|
+
<span class="cline-any cline-yes">8x</span>
|
|
303
|
+
<span class="cline-any cline-neutral"> </span>
|
|
298
304
|
<span class="cline-any cline-yes">6x</span>
|
|
299
305
|
<span class="cline-any cline-yes">6x</span>
|
|
300
306
|
<span class="cline-any cline-neutral"> </span>
|
|
301
|
-
<span class="cline-any cline-yes">5x</span>
|
|
302
|
-
<span class="cline-any cline-yes">5x</span>
|
|
303
307
|
<span class="cline-any cline-neutral"> </span>
|
|
304
308
|
<span class="cline-any cline-neutral"> </span>
|
|
309
|
+
<span class="cline-any cline-yes">55x</span>
|
|
305
310
|
<span class="cline-any cline-neutral"> </span>
|
|
306
|
-
<span class="cline-any cline-yes">45x</span>
|
|
307
311
|
<span class="cline-any cline-neutral"> </span>
|
|
308
312
|
<span class="cline-any cline-neutral"> </span>
|
|
309
313
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -321,31 +325,39 @@
|
|
|
321
325
|
<span class="cline-any cline-neutral"> </span>
|
|
322
326
|
<span class="cline-any cline-neutral"> </span>
|
|
323
327
|
<span class="cline-any cline-neutral"> </span>
|
|
328
|
+
<span class="cline-any cline-yes">31x</span>
|
|
329
|
+
<span class="cline-any cline-yes">31x</span>
|
|
330
|
+
<span class="cline-any cline-yes">31x</span>
|
|
324
331
|
<span class="cline-any cline-neutral"> </span>
|
|
325
|
-
<span class="cline-any cline-yes">
|
|
326
|
-
<span class="cline-any cline-yes">
|
|
327
|
-
<span class="cline-any cline-yes">
|
|
332
|
+
<span class="cline-any cline-yes">30x</span>
|
|
333
|
+
<span class="cline-any cline-yes">30x</span>
|
|
334
|
+
<span class="cline-any cline-yes">3x</span>
|
|
335
|
+
<span class="cline-any cline-yes">3x</span>
|
|
336
|
+
<span class="cline-any cline-yes">27x</span>
|
|
337
|
+
<span class="cline-any cline-yes">19x</span>
|
|
338
|
+
<span class="cline-any cline-yes">19x</span>
|
|
339
|
+
<span class="cline-any cline-yes">8x</span>
|
|
340
|
+
<span class="cline-any cline-yes">7x</span>
|
|
341
|
+
<span class="cline-any cline-yes">7x</span>
|
|
328
342
|
<span class="cline-any cline-neutral"> </span>
|
|
329
|
-
<span class="cline-any cline-yes">26x</span>
|
|
330
|
-
<span class="cline-any cline-yes">24x</span>
|
|
331
|
-
<span class="cline-any cline-yes">6x</span>
|
|
332
343
|
<span class="cline-any cline-neutral"> </span>
|
|
333
|
-
<span class="cline-any cline-yes">
|
|
334
|
-
<span class="cline-any cline-yes">
|
|
335
|
-
<span class="cline-any cline-
|
|
344
|
+
<span class="cline-any cline-yes">30x</span>
|
|
345
|
+
<span class="cline-any cline-yes">30x</span>
|
|
346
|
+
<span class="cline-any cline-yes">1x</span>
|
|
347
|
+
<span class="cline-any cline-yes">1x</span>
|
|
336
348
|
<span class="cline-any cline-neutral"> </span>
|
|
337
|
-
<span class="cline-any cline-yes">
|
|
338
|
-
<span class="cline-any cline-yes">
|
|
339
|
-
<span class="cline-any cline-yes">
|
|
340
|
-
<span class="cline-any cline-yes">
|
|
341
|
-
<span class="cline-any cline-yes">
|
|
349
|
+
<span class="cline-any cline-yes">30x</span>
|
|
350
|
+
<span class="cline-any cline-yes">30x</span>
|
|
351
|
+
<span class="cline-any cline-yes">30x</span>
|
|
352
|
+
<span class="cline-any cline-yes">30x</span>
|
|
353
|
+
<span class="cline-any cline-yes">31x</span>
|
|
342
354
|
<span class="cline-any cline-neutral"> </span>
|
|
343
355
|
<span class="cline-any cline-neutral"> </span>
|
|
344
|
-
<span class="cline-any cline-yes">
|
|
356
|
+
<span class="cline-any cline-yes">31x</span>
|
|
345
357
|
<span class="cline-any cline-neutral"> </span>
|
|
346
358
|
<span class="cline-any cline-neutral"> </span>
|
|
347
359
|
<span class="cline-any cline-neutral"> </span>
|
|
348
|
-
<span class="cline-any cline-yes">
|
|
360
|
+
<span class="cline-any cline-yes">55x</span>
|
|
349
361
|
<span class="cline-any cline-neutral"> </span>
|
|
350
362
|
<span class="cline-any cline-neutral"> </span>
|
|
351
363
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -353,18 +365,21 @@
|
|
|
353
365
|
<span class="cline-any cline-neutral"> </span>
|
|
354
366
|
<span class="cline-any cline-neutral"> </span>
|
|
355
367
|
<span class="cline-any cline-neutral"> </span>
|
|
356
|
-
<span class="cline-any cline-
|
|
357
|
-
<span class="cline-any cline-
|
|
358
|
-
<span class="cline-any cline-
|
|
359
|
-
<span class="cline-any cline-
|
|
360
|
-
<span class="cline-any cline-
|
|
368
|
+
<span class="cline-any cline-yes">2x</span>
|
|
369
|
+
<span class="cline-any cline-yes">2x</span>
|
|
370
|
+
<span class="cline-any cline-yes">2x</span>
|
|
371
|
+
<span class="cline-any cline-yes">2x</span>
|
|
372
|
+
<span class="cline-any cline-yes">1x</span>
|
|
373
|
+
<span class="cline-any cline-yes">1x</span>
|
|
374
|
+
<span class="cline-any cline-yes">1x</span>
|
|
361
375
|
<span class="cline-any cline-neutral"> </span>
|
|
362
|
-
<span class="cline-any cline-
|
|
376
|
+
<span class="cline-any cline-yes">1x</span>
|
|
363
377
|
<span class="cline-any cline-neutral"> </span>
|
|
364
378
|
<span class="cline-any cline-neutral"> </span>
|
|
365
379
|
<span class="cline-any cline-neutral"> </span>
|
|
366
380
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
367
381
|
import { Type } from "typebox";
|
|
382
|
+
import { emitNativeTaskEvent } from "../runtime/task-events.js";
|
|
368
383
|
import { TaskStore } from "../task-store.js";
|
|
369
384
|
|
|
370
385
|
export interface TaskBacklogResult {
|
|
@@ -412,12 +427,7 @@ Fields:
|
|
|
412
427
|
}),
|
|
413
428
|
async execute(_toolCallId, params) {
|
|
414
429
|
const entry = taskStore.create(params.subject, params.description);
|
|
415
|
-
pi
|
|
416
|
-
taskId: entry.id,
|
|
417
|
-
subject: entry.subject,
|
|
418
|
-
description: entry.description,
|
|
419
|
-
status: entry.status,
|
|
420
|
-
});
|
|
430
|
+
emitNativeTaskEvent(pi, "tasks:created", entry);
|
|
421
431
|
const backlog = await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
|
|
422
432
|
updateWidget();
|
|
423
433
|
|
|
@@ -435,7 +445,7 @@ Fields:
|
|
|
435
445
|
parameters: Type.Object({}),
|
|
436
446
|
execute() {
|
|
437
447
|
const tasks = taskStore.list();
|
|
438
|
-
|
|
448
|
+
if (tasks.length === 0) return Promise.resolve(textResult("No tasks."));
|
|
439
449
|
|
|
440
450
|
const lines: string[] = [];
|
|
441
451
|
const statuses: Record<"pending" | "in_progress" | "completed", number> = {
|
|
@@ -474,20 +484,29 @@ Parameters: id (required), status, subject, description`,
|
|
|
474
484
|
async execute(_toolCallId, params) {
|
|
475
485
|
const { id, status, subject, description } = params;
|
|
476
486
|
let entry = taskStore.get(id);
|
|
477
|
-
|
|
487
|
+
if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
|
|
478
488
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
489
|
+
const previousStatus = entry.status;
|
|
490
|
+
if (status === "in_progress") {
|
|
491
|
+
entry = taskStore.start(id);
|
|
492
|
+
<span class="missing-if-branch" title="else path not taken" >E</span>if (entry) emitNativeTaskEvent(pi, "tasks:started", entry, previousStatus);
|
|
493
|
+
} else if (status === "completed") {
|
|
494
|
+
entry = taskStore.complete(id);
|
|
495
|
+
<span class="missing-if-branch" title="else path not taken" >E</span>if (entry) emitNativeTaskEvent(pi, "tasks:completed", entry, previousStatus);
|
|
496
|
+
} else if (status === "pending") {
|
|
497
|
+
entry = taskStore.reopen(id);
|
|
498
|
+
<span class="missing-if-branch" title="else path not taken" >E</span>if (entry) emitNativeTaskEvent(pi, "tasks:reopened", entry, previousStatus);
|
|
499
|
+
}
|
|
482
500
|
|
|
483
|
-
<span class="missing-if-branch" title="if path not taken" >I</span>if (!entry)
|
|
484
|
-
|
|
485
|
-
|
|
501
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
|
|
502
|
+
if (subject !== undefined || description !== undefined) {
|
|
503
|
+
entry = taskStore.updateDetails(id, { subject, description });
|
|
504
|
+
<span class="missing-if-branch" title="else path not taken" >E</span>if (entry) emitNativeTaskEvent(pi, "tasks:updated", entry, previousStatus);
|
|
486
505
|
}
|
|
487
|
-
<span class="missing-if-branch" title="if path not taken" >I</span>if (!entry)
|
|
506
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
|
|
488
507
|
updateWidget();
|
|
489
508
|
const backlog = await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
|
|
490
|
-
const statusMsg = status ? ` → ${status}` :
|
|
509
|
+
const statusMsg = status ? ` → ${status}` : "";
|
|
491
510
|
const autoLoopMsg = backlog.created && backlog.entry
|
|
492
511
|
? `\nBacklog worker loop #${backlog.entry.id} created`
|
|
493
512
|
: "";
|
|
@@ -502,14 +521,16 @@ Parameters: id (required), status, subject, description`,
|
|
|
502
521
|
parameters: Type.Object({
|
|
503
522
|
id: Type.String({ description: "Task ID to delete" }),
|
|
504
523
|
}),
|
|
505
|
-
async
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
<span class="
|
|
524
|
+
async execute(_toolCallId, params) {
|
|
525
|
+
const existing = taskStore.get(params.id);
|
|
526
|
+
const deleted = taskStore.delete(params.id);
|
|
527
|
+
updateWidget();
|
|
528
|
+
if (deleted) {
|
|
529
|
+
<span class="missing-if-branch" title="else path not taken" >E</span>if (existing) emitNativeTaskEvent(pi, "tasks:deleted", existing, existing.status);
|
|
530
|
+
await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
|
|
531
|
+
return Promise.resolve(textResult(`Task #${params.id} deleted`));
|
|
511
532
|
}
|
|
512
|
-
|
|
533
|
+
return Promise.resolve(textResult(`Task #${params.id} not found`));
|
|
513
534
|
},
|
|
514
535
|
});
|
|
515
536
|
}
|
|
@@ -520,7 +541,7 @@ Parameters: id (required), status, subject, description`,
|
|
|
520
541
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
521
542
|
Code coverage generated by
|
|
522
543
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
523
|
-
at 2026-06-
|
|
544
|
+
at 2026-06-23T21:49:18.784Z
|
|
524
545
|
</div>
|
|
525
546
|
<script src="../../prettify.js"></script>
|
|
526
547
|
<script>
|
|
@@ -224,15 +224,15 @@
|
|
|
224
224
|
<span class="cline-any cline-neutral"> </span>
|
|
225
225
|
<span class="cline-any cline-neutral"> </span>
|
|
226
226
|
<span class="cline-any cline-neutral"> </span>
|
|
227
|
-
<span class="cline-any cline-yes">
|
|
228
|
-
<span class="cline-any cline-yes">
|
|
229
|
-
<span class="cline-any cline-yes">
|
|
227
|
+
<span class="cline-any cline-yes">123x</span>
|
|
228
|
+
<span class="cline-any cline-yes">123x</span>
|
|
229
|
+
<span class="cline-any cline-yes">123x</span>
|
|
230
230
|
<span class="cline-any cline-neutral"> </span>
|
|
231
231
|
<span class="cline-any cline-neutral"> </span>
|
|
232
|
-
<span class="cline-any cline-yes">
|
|
233
|
-
<span class="cline-any cline-yes">
|
|
234
|
-
<span class="cline-any cline-yes">
|
|
235
|
-
<span class="cline-any cline-yes">
|
|
232
|
+
<span class="cline-any cline-yes">123x</span>
|
|
233
|
+
<span class="cline-any cline-yes">123x</span>
|
|
234
|
+
<span class="cline-any cline-yes">123x</span>
|
|
235
|
+
<span class="cline-any cline-yes">123x</span>
|
|
236
236
|
<span class="cline-any cline-neutral"> </span>
|
|
237
237
|
<span class="cline-any cline-neutral"> </span>
|
|
238
238
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -532,7 +532,7 @@ export class TriggerSystem {
|
|
|
532
532
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
533
533
|
Code coverage generated by
|
|
534
534
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
535
|
-
at 2026-06-
|
|
535
|
+
at 2026-06-23T21:49:18.784Z
|
|
536
536
|
</div>
|
|
537
537
|
<script src="../prettify.js"></script>
|
|
538
538
|
<script>
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
102
102
|
Code coverage generated by
|
|
103
103
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
104
|
-
at 2026-06-
|
|
104
|
+
at 2026-06-23T21:49:18.784Z
|
|
105
105
|
</div>
|
|
106
106
|
<script src="../../prettify.js"></script>
|
|
107
107
|
<script>
|
|
@@ -147,8 +147,8 @@
|
|
|
147
147
|
<span class="cline-any cline-neutral"> </span>
|
|
148
148
|
<span class="cline-any cline-neutral"> </span>
|
|
149
149
|
<span class="cline-any cline-neutral"> </span>
|
|
150
|
-
<span class="cline-any cline-yes">
|
|
151
|
-
<span class="cline-any cline-yes">
|
|
150
|
+
<span class="cline-any cline-yes">70x</span>
|
|
151
|
+
<span class="cline-any cline-yes">70x</span>
|
|
152
152
|
<span class="cline-any cline-neutral"> </span>
|
|
153
153
|
<span class="cline-any cline-neutral"> </span>
|
|
154
154
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -160,11 +160,11 @@
|
|
|
160
160
|
<span class="cline-any cline-neutral"> </span>
|
|
161
161
|
<span class="cline-any cline-neutral"> </span>
|
|
162
162
|
<span class="cline-any cline-neutral"> </span>
|
|
163
|
-
<span class="cline-any cline-yes">
|
|
163
|
+
<span class="cline-any cline-yes">65x</span>
|
|
164
164
|
<span class="cline-any cline-neutral"> </span>
|
|
165
165
|
<span class="cline-any cline-neutral"> </span>
|
|
166
166
|
<span class="cline-any cline-neutral"> </span>
|
|
167
|
-
<span class="cline-any cline-yes">
|
|
167
|
+
<span class="cline-any cline-yes">189x</span>
|
|
168
168
|
<span class="cline-any cline-yes">164x</span>
|
|
169
169
|
<span class="cline-any cline-neutral"> </span>
|
|
170
170
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -277,7 +277,7 @@ function isStatusVisibleLoop(loop: LoopEntry): boolean {
|
|
|
277
277
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
278
278
|
Code coverage generated by
|
|
279
279
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
280
|
-
at 2026-06-
|
|
280
|
+
at 2026-06-23T21:49:18.784Z
|
|
281
281
|
</div>
|
|
282
282
|
<script src="../../prettify.js"></script>
|
|
283
283
|
<script>
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
import { emitNativeTaskEvent } from "../runtime/task-events.js";
|
|
1
2
|
export function registerTasksCommand(options) {
|
|
2
3
|
const { pi, getNativeTaskStore, evaluateTaskBacklog, updateWidget } = options;
|
|
3
4
|
async function emitCreated(entry) {
|
|
4
|
-
pi
|
|
5
|
-
taskId: entry.id,
|
|
6
|
-
subject: entry.subject,
|
|
7
|
-
description: entry.description,
|
|
8
|
-
status: entry.status,
|
|
9
|
-
});
|
|
5
|
+
emitNativeTaskEvent(pi, "tasks:created", entry);
|
|
10
6
|
const taskStore = getNativeTaskStore();
|
|
11
7
|
if (!taskStore)
|
|
12
8
|
return { created: false };
|
|
@@ -75,18 +71,25 @@ export function registerTasksCommand(options) {
|
|
|
75
71
|
return viewNativeTasks(ui);
|
|
76
72
|
if (action === "x Delete") {
|
|
77
73
|
taskStore.delete(task.id);
|
|
74
|
+
emitNativeTaskEvent(pi, "tasks:deleted", task, task.status);
|
|
78
75
|
ui.notify(`Task #${task.id} deleted`, "info");
|
|
79
76
|
}
|
|
80
77
|
else if (action === "> Start") {
|
|
81
|
-
taskStore.start(task.id);
|
|
78
|
+
const next = taskStore.start(task.id);
|
|
79
|
+
if (next)
|
|
80
|
+
emitNativeTaskEvent(pi, "tasks:started", next, task.status);
|
|
82
81
|
ui.notify(`Task #${task.id} started`, "info");
|
|
83
82
|
}
|
|
84
83
|
else if (action === "ok Complete") {
|
|
85
|
-
taskStore.complete(task.id);
|
|
84
|
+
const next = taskStore.complete(task.id);
|
|
85
|
+
if (next)
|
|
86
|
+
emitNativeTaskEvent(pi, "tasks:completed", next, task.status);
|
|
86
87
|
ui.notify(`Task #${task.id} completed`, "info");
|
|
87
88
|
}
|
|
88
89
|
else if (action === "* Return to pending" || action === "* Reopen") {
|
|
89
|
-
taskStore.reopen(task.id);
|
|
90
|
+
const next = taskStore.reopen(task.id);
|
|
91
|
+
if (next)
|
|
92
|
+
emitNativeTaskEvent(pi, "tasks:reopened", next, task.status);
|
|
90
93
|
ui.notify(`Task #${task.id} reopened`, "info");
|
|
91
94
|
}
|
|
92
95
|
updateWidget();
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,9 @@ function debug(...args) {
|
|
|
36
36
|
if (DEBUG)
|
|
37
37
|
console.error("[pi-loop]", ...args);
|
|
38
38
|
}
|
|
39
|
+
function isStaleExtensionContextError(error) {
|
|
40
|
+
return error instanceof Error && error.message.includes("extension ctx is stale");
|
|
41
|
+
}
|
|
39
42
|
export default function (pi) {
|
|
40
43
|
const piLoopEnv = process.env.PI_LOOP;
|
|
41
44
|
const piLoopScope = process.env.PI_LOOP_SCOPE;
|
|
@@ -263,28 +266,40 @@ export default function (pi) {
|
|
|
263
266
|
},
|
|
264
267
|
});
|
|
265
268
|
// ── Native task tools (only when pi-tasks is absent) ──
|
|
266
|
-
setTimeout(
|
|
269
|
+
const nativeTaskFallbackTimer = setTimeout(() => {
|
|
267
270
|
if (tasksAvailable || nativeTasksRegistered)
|
|
268
271
|
return;
|
|
269
|
-
|
|
272
|
+
const taskStore = new TaskStore(resolveTaskStorePath(getScopeOptions(), _sessionId));
|
|
273
|
+
try {
|
|
274
|
+
registerTasksCommand({
|
|
275
|
+
pi,
|
|
276
|
+
getNativeTaskStore: () => nativeTaskStore,
|
|
277
|
+
evaluateTaskBacklog,
|
|
278
|
+
updateWidget: () => {
|
|
279
|
+
widget.update();
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
registerNativeTaskTools({
|
|
283
|
+
pi,
|
|
284
|
+
taskStore,
|
|
285
|
+
evaluateTaskBacklog,
|
|
286
|
+
updateWidget: () => {
|
|
287
|
+
widget.update();
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
if (isStaleExtensionContextError(error)) {
|
|
293
|
+
debug("native task fallback skipped: extension context went stale");
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
nativeTaskStore = taskStore;
|
|
270
299
|
nativeTasksRegistered = true;
|
|
271
|
-
const taskStore = nativeTaskStore;
|
|
272
|
-
registerTasksCommand({
|
|
273
|
-
pi,
|
|
274
|
-
getNativeTaskStore: () => nativeTaskStore,
|
|
275
|
-
evaluateTaskBacklog,
|
|
276
|
-
updateWidget: () => {
|
|
277
|
-
widget.update();
|
|
278
|
-
},
|
|
279
|
-
});
|
|
280
|
-
registerNativeTaskTools({
|
|
281
|
-
pi,
|
|
282
|
-
taskStore,
|
|
283
|
-
evaluateTaskBacklog,
|
|
284
|
-
updateWidget: () => {
|
|
285
|
-
widget.update();
|
|
286
|
-
},
|
|
287
|
-
});
|
|
288
300
|
debug("native task tools registered (pi-tasks not detected)");
|
|
289
301
|
}, 6000);
|
|
302
|
+
pi.on("session_shutdown", () => {
|
|
303
|
+
clearTimeout(nativeTaskFallbackTimer);
|
|
304
|
+
});
|
|
290
305
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { type ChildProcess, type SpawnOptions } from "node:child_process";
|
|
1
2
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
3
|
import type { MonitorEntry, MonitorProcess } from "./types.js";
|
|
4
|
+
export type SpawnFn = (command: string, args: string[], options: SpawnOptions) => ChildProcess;
|
|
3
5
|
export declare class MonitorManager {
|
|
4
6
|
private pi;
|
|
5
7
|
private processes;
|
|
6
8
|
private nextId;
|
|
7
9
|
private onChange;
|
|
8
|
-
|
|
10
|
+
private spawnFn;
|
|
11
|
+
constructor(pi: ExtensionAPI, spawnFn?: SpawnFn);
|
|
9
12
|
/**
|
|
10
13
|
* Register a callback fired when a monitor's status changes or it is pruned
|
|
11
14
|
* (e.g. autonomous completion/error/stop/prune with no tool call). Used to
|
package/dist/monitor-manager.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
2
2
|
import { reduceMonitorState, } from "./monitor-reducer.js";
|
|
3
3
|
export class MonitorManager {
|
|
4
4
|
pi;
|
|
5
5
|
processes = new Map();
|
|
6
6
|
nextId = 1;
|
|
7
7
|
onChange;
|
|
8
|
-
|
|
8
|
+
spawnFn;
|
|
9
|
+
constructor(pi, spawnFn) {
|
|
9
10
|
this.pi = pi;
|
|
11
|
+
this.spawnFn = spawnFn ?? ((cmd, args, opts) => nodeSpawn(cmd, args, opts));
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Register a callback fired when a monitor's status changes or it is pruned
|
|
@@ -46,7 +48,8 @@ export class MonitorManager {
|
|
|
46
48
|
// finish() and stop() so every terminal status is pruned consistently — a
|
|
47
49
|
// stopped monitor that is never pruned lingers in list() and the widget count.
|
|
48
50
|
schedulePrune(id) {
|
|
49
|
-
|
|
51
|
+
// unref so a pending prune never keeps a one-shot (`pi -p`) process alive.
|
|
52
|
+
const timer = setTimeout(() => {
|
|
50
53
|
this.applyReducerEvent({
|
|
51
54
|
type: "MONITOR_PRUNED",
|
|
52
55
|
at: Date.now(),
|
|
@@ -56,6 +59,7 @@ export class MonitorManager {
|
|
|
56
59
|
payload: { id },
|
|
57
60
|
});
|
|
58
61
|
}, 30000);
|
|
62
|
+
timer.unref?.();
|
|
59
63
|
}
|
|
60
64
|
create(command, description, timeout = 300000) {
|
|
61
65
|
const now = Date.now();
|
|
@@ -74,7 +78,7 @@ export class MonitorManager {
|
|
|
74
78
|
const id = String(this.nextId - 1);
|
|
75
79
|
const entry = result.state.monitorsById[id];
|
|
76
80
|
const abortController = new AbortController();
|
|
77
|
-
const child =
|
|
81
|
+
const child = this.spawnFn("sh", ["-c", command], {
|
|
78
82
|
stdio: ["ignore", "pipe", "pipe"],
|
|
79
83
|
signal: abortController.signal,
|
|
80
84
|
env: { ...process.env },
|
|
@@ -14,7 +14,9 @@ export function registerSessionRuntimeHooks(options) {
|
|
|
14
14
|
if (heartbeatTimer)
|
|
15
15
|
return;
|
|
16
16
|
heartbeatTimer = setInterval(() => {
|
|
17
|
-
|
|
17
|
+
// Swallow pump failures so a transient error never surfaces as an
|
|
18
|
+
// unhandled rejection; the next tick retries.
|
|
19
|
+
void pumpLoops().catch(() => { });
|
|
18
20
|
}, HEARTBEAT_MS);
|
|
19
21
|
heartbeatTimer.unref?.();
|
|
20
22
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { TaskEntry, TaskStatus } from "../task-types.js";
|
|
3
|
+
export type NativeTaskEventName = "tasks:created" | "tasks:started" | "tasks:completed" | "tasks:reopened" | "tasks:updated" | "tasks:deleted";
|
|
4
|
+
export interface NativeTaskEventPayload {
|
|
5
|
+
taskId: string;
|
|
6
|
+
subject: string;
|
|
7
|
+
description: string;
|
|
8
|
+
status: TaskStatus;
|
|
9
|
+
previousStatus?: TaskStatus;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
updatedAt: number;
|
|
12
|
+
completedAt?: number;
|
|
13
|
+
metadata?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export declare function emitNativeTaskEvent(pi: ExtensionAPI, name: NativeTaskEventName, entry: TaskEntry, previousStatus?: TaskStatus): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function emitNativeTaskEvent(pi, name, entry, previousStatus) {
|
|
2
|
+
pi.events.emit(name, {
|
|
3
|
+
taskId: entry.id,
|
|
4
|
+
subject: entry.subject,
|
|
5
|
+
description: entry.description,
|
|
6
|
+
status: entry.status,
|
|
7
|
+
previousStatus,
|
|
8
|
+
createdAt: entry.createdAt,
|
|
9
|
+
updatedAt: entry.updatedAt,
|
|
10
|
+
completedAt: entry.completedAt,
|
|
11
|
+
metadata: entry.metadata,
|
|
12
|
+
});
|
|
13
|
+
}
|
package/dist/runtime/task-rpc.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { emitNativeTaskEvent } from "./task-events.js";
|
|
2
3
|
export function createTaskRuntimeBridge(options) {
|
|
3
4
|
const { pi, isTasksAvailable, setTasksAvailable, getNativeTaskStore, onNativeTaskCreated, onNativeTasksPruned, debug, } = options;
|
|
4
5
|
function checkTasksVersion() {
|
|
@@ -52,6 +53,7 @@ export function createTaskRuntimeBridge(options) {
|
|
|
52
53
|
if (!nativeTaskStore)
|
|
53
54
|
return undefined;
|
|
54
55
|
const task = nativeTaskStore.create(entry.prompt.slice(0, 80), `Auto-created from loop #${entry.id}`, { loopId: entry.id, trigger: entry.trigger });
|
|
56
|
+
emitNativeTaskEvent(pi, "tasks:created", task);
|
|
55
57
|
onNativeTaskCreated?.(nativeTaskStore);
|
|
56
58
|
return task.id;
|
|
57
59
|
}
|