@trevonistrevon/pi-loop 0.5.8 → 0.6.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.
Files changed (127) hide show
  1. package/.release-please-manifest.json +3 -0
  2. package/AGENTS.md +52 -12
  3. package/CHANGELOG.md +59 -0
  4. package/CONTRIBUTING.md +13 -3
  5. package/Dockerfile +17 -0
  6. package/README.md +47 -0
  7. package/coverage/coverage-final.json +35 -31
  8. package/coverage/index.html +64 -49
  9. package/coverage/src/api.ts.html +193 -0
  10. package/coverage/src/commands/index.html +32 -32
  11. package/coverage/src/commands/loop-command.ts.html +170 -170
  12. package/coverage/src/commands/tasks-command.ts.html +135 -135
  13. package/coverage/src/coordinator.ts.html +26 -26
  14. package/coverage/src/index.html +61 -106
  15. package/coverage/src/index.ts.html +280 -94
  16. package/coverage/src/loop-parse.ts.html +90 -57
  17. package/coverage/src/loop-reducer.ts.html +25 -25
  18. package/coverage/src/monitor-completion-coordinator.ts.html +1 -1
  19. package/coverage/src/monitor-manager.ts.html +95 -71
  20. package/coverage/src/monitor-reducer.ts.html +15 -15
  21. package/coverage/src/notification-reducer.ts.html +7 -7
  22. package/coverage/src/reducer-backed-store.ts.html +57 -57
  23. package/coverage/src/rpc/channels.ts.html +376 -0
  24. package/coverage/src/rpc/cross-extension-rpc.ts.html +541 -0
  25. package/coverage/src/rpc/index.html +131 -0
  26. package/coverage/src/runtime/index.html +89 -29
  27. package/coverage/src/{goal-coordinator.ts.html → runtime/loop-events.ts.html} +79 -73
  28. package/coverage/src/runtime/monitor-ondone-runtime.ts.html +5 -5
  29. package/coverage/src/runtime/native-task-rpc.ts.html +502 -0
  30. package/coverage/src/runtime/notification-runtime.ts.html +14 -14
  31. package/coverage/src/runtime/scope.ts.html +17 -17
  32. package/coverage/src/runtime/session-runtime.ts.html +40 -40
  33. package/coverage/src/runtime/task-backlog-runtime.ts.html +66 -24
  34. package/coverage/src/runtime/task-events.ts.html +208 -0
  35. package/coverage/src/runtime/task-mutations.ts.html +394 -0
  36. package/coverage/src/runtime/task-rpc.ts.html +106 -118
  37. package/coverage/src/scheduler.ts.html +12 -12
  38. package/coverage/src/store.ts.html +20 -20
  39. package/coverage/src/task-backlog-coordinator.ts.html +8 -8
  40. package/coverage/src/task-reducer.ts.html +42 -42
  41. package/coverage/src/task-store.ts.html +49 -49
  42. package/coverage/src/tools/index.html +39 -24
  43. package/coverage/src/tools/loop-tools.ts.html +12 -21
  44. package/coverage/src/tools/monitor-tools.ts.html +12 -21
  45. package/coverage/src/tools/native-task-tools.ts.html +52 -94
  46. package/coverage/src/tools/tool-result.ts.html +97 -0
  47. package/coverage/src/trigger-system.ts.html +12 -12
  48. package/coverage/src/ui/index.html +1 -1
  49. package/coverage/src/ui/widget.ts.html +23 -23
  50. package/dist/api.d.ts +11 -0
  51. package/dist/api.js +10 -0
  52. package/dist/commands/loop-command.js +2 -2
  53. package/dist/commands/tasks-command.js +3 -3
  54. package/dist/coordinator.d.ts +1 -1
  55. package/dist/index.js +80 -20
  56. package/dist/loop-parse.js +14 -5
  57. package/dist/monitor-manager.d.ts +4 -1
  58. package/dist/monitor-manager.js +5 -3
  59. package/dist/reducer-backed-store.d.ts +1 -1
  60. package/dist/reducer-backed-store.js +1 -1
  61. package/dist/rpc/channels.d.ts +73 -0
  62. package/dist/rpc/channels.js +30 -0
  63. package/dist/rpc/cross-extension-rpc.d.ts +59 -0
  64. package/dist/rpc/cross-extension-rpc.js +117 -0
  65. package/dist/runtime/loop-events.d.ts +26 -0
  66. package/dist/runtime/loop-events.js +26 -0
  67. package/dist/runtime/native-task-rpc.d.ts +22 -0
  68. package/dist/runtime/native-task-rpc.js +50 -0
  69. package/dist/runtime/task-backlog-runtime.d.ts +3 -0
  70. package/dist/runtime/task-backlog-runtime.js +4 -1
  71. package/dist/runtime/task-mutations.d.ts +39 -0
  72. package/dist/runtime/task-mutations.js +68 -0
  73. package/dist/runtime/task-rpc.d.ts +4 -0
  74. package/dist/runtime/task-rpc.js +40 -58
  75. package/dist/scheduler.js +1 -1
  76. package/dist/tools/loop-tools.js +1 -3
  77. package/dist/tools/monitor-tools.js +1 -3
  78. package/dist/tools/native-task-tools.d.ts +2 -6
  79. package/dist/tools/native-task-tools.js +25 -55
  80. package/dist/tools/tool-result.d.ts +8 -0
  81. package/dist/tools/tool-result.js +4 -0
  82. package/docker-compose.yml +12 -0
  83. package/docs/architecture/state-machine-migration.md +0 -44
  84. package/docs/architecture/state-machine-reducer-event-model.md +2 -3
  85. package/package.json +6 -1
  86. package/release-please-config.json +9 -0
  87. package/src/api.ts +36 -0
  88. package/src/commands/loop-command.ts +2 -2
  89. package/src/commands/tasks-command.ts +3 -3
  90. package/src/coordinator.ts +1 -1
  91. package/src/index.ts +84 -22
  92. package/src/loop-parse.ts +18 -7
  93. package/src/monitor-manager.ts +11 -3
  94. package/src/reducer-backed-store.ts +3 -3
  95. package/src/rpc/channels.ts +97 -0
  96. package/src/rpc/cross-extension-rpc.ts +152 -0
  97. package/src/runtime/loop-events.ts +60 -0
  98. package/src/runtime/native-task-rpc.ts +139 -0
  99. package/src/runtime/task-backlog-runtime.ts +14 -0
  100. package/src/runtime/task-mutations.ts +103 -0
  101. package/src/runtime/task-rpc.ts +48 -54
  102. package/src/scheduler.ts +1 -1
  103. package/src/tools/loop-tools.ts +1 -4
  104. package/src/tools/monitor-tools.ts +1 -4
  105. package/src/tools/native-task-tools.ts +31 -52
  106. package/src/tools/tool-result.ts +4 -0
  107. package/src/trigger-system.ts +4 -4
  108. package/vitest.config.ts +11 -7
  109. package/coverage/src/goal-reducer.ts.html +0 -982
  110. package/coverage/src/goal-store.ts.html +0 -742
  111. package/coverage/src/goal-verifier.ts.html +0 -808
  112. package/dist/goal-coordinator.d.ts +0 -22
  113. package/dist/goal-coordinator.js +0 -28
  114. package/dist/goal-reducer.d.ts +0 -98
  115. package/dist/goal-reducer.js +0 -190
  116. package/dist/goal-store.d.ts +0 -22
  117. package/dist/goal-store.js +0 -188
  118. package/dist/goal-types.d.ts +0 -82
  119. package/dist/goal-types.js +0 -1
  120. package/dist/goal-verifier.d.ts +0 -20
  121. package/dist/goal-verifier.js +0 -198
  122. package/docs/architecture/goal-state-schema.md +0 -505
  123. package/src/goal-coordinator.ts +0 -58
  124. package/src/goal-reducer.ts +0 -299
  125. package/src/goal-store.ts +0 -219
  126. package/src/goal-types.ts +0 -104
  127. package/src/goal-verifier.ts +0 -241
@@ -23,9 +23,9 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">93.18% </span>
26
+ <span class="strong">93.02% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>41/44</span>
28
+ <span class='fraction'>40/43</span>
29
29
  </div>
30
30
 
31
31
 
@@ -39,14 +39,14 @@
39
39
  <div class='fl pad1y space-right2'>
40
40
  <span class="strong">100% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>7/7</span>
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">94.73% </span>
47
+ <span class="strong">94.59% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>36/38</span>
49
+ <span class='fraction'>35/37</span>
50
50
  </div>
51
51
 
52
52
 
@@ -214,10 +214,7 @@
214
214
  <a name='L149'></a><a href='#L149'>149</a>
215
215
  <a name='L150'></a><a href='#L150'>150</a>
216
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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
217
+ <a name='L152'></a><a href='#L152'>152</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
221
218
  <span class="cline-any cline-neutral">&nbsp;</span>
222
219
  <span class="cline-any cline-neutral">&nbsp;</span>
223
220
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -246,9 +243,6 @@
246
243
  <span class="cline-any cline-neutral">&nbsp;</span>
247
244
  <span class="cline-any cline-neutral">&nbsp;</span>
248
245
  <span class="cline-any cline-neutral">&nbsp;</span>
249
- <span class="cline-any cline-yes">25x</span>
250
- <span class="cline-any cline-neutral">&nbsp;</span>
251
- <span class="cline-any cline-neutral">&nbsp;</span>
252
246
  <span class="cline-any cline-neutral">&nbsp;</span>
253
247
  <span class="cline-any cline-yes">4x</span>
254
248
  <span class="cline-any cline-no">&nbsp;</span>
@@ -256,9 +250,9 @@
256
250
  <span class="cline-any cline-neutral">&nbsp;</span>
257
251
  <span class="cline-any cline-neutral">&nbsp;</span>
258
252
  <span class="cline-any cline-neutral">&nbsp;</span>
259
- <span class="cline-any cline-yes">68x</span>
253
+ <span class="cline-any cline-yes">72x</span>
260
254
  <span class="cline-any cline-neutral">&nbsp;</span>
261
- <span class="cline-any cline-yes">68x</span>
255
+ <span class="cline-any cline-yes">72x</span>
262
256
  <span class="cline-any cline-neutral">&nbsp;</span>
263
257
  <span class="cline-any cline-neutral">&nbsp;</span>
264
258
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -324,7 +318,7 @@
324
318
  <span class="cline-any cline-neutral">&nbsp;</span>
325
319
  <span class="cline-any cline-neutral">&nbsp;</span>
326
320
  <span class="cline-any cline-neutral">&nbsp;</span>
327
- <span class="cline-any cline-yes">68x</span>
321
+ <span class="cline-any cline-yes">72x</span>
328
322
  <span class="cline-any cline-neutral">&nbsp;</span>
329
323
  <span class="cline-any cline-neutral">&nbsp;</span>
330
324
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -354,7 +348,7 @@
354
348
  <span class="cline-any cline-neutral">&nbsp;</span>
355
349
  <span class="cline-any cline-neutral">&nbsp;</span>
356
350
  <span class="cline-any cline-neutral">&nbsp;</span>
357
- <span class="cline-any cline-yes">68x</span>
351
+ <span class="cline-any cline-yes">72x</span>
358
352
  <span class="cline-any cline-neutral">&nbsp;</span>
359
353
  <span class="cline-any cline-neutral">&nbsp;</span>
360
354
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -374,6 +368,7 @@
374
368
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
375
369
  import { Type } from "typebox";
376
370
  import type { LoopEntry, MonitorEntry, Trigger } from "../types.js";
371
+ import { textResult } from "./tool-result.js";
377
372
  &nbsp;
378
373
  interface MonitorManagerLike {
379
374
  list(): MonitorEntry[];
@@ -399,10 +394,6 @@ export interface MonitorToolsOptions {
399
394
  handleMonitorDoneLoop: (doneLoop: LoopEntry, monitorId: string) =&gt; void;
400
395
  }
401
396
  &nbsp;
402
- function textResult(msg: string) {
403
- return { content: [{ type: "text" as const, text: msg }], details: undefined as any };
404
- }
405
- &nbsp;
406
397
  function formatRemaining(ms: number): string {
407
398
  <span class="missing-if-branch" title="else path not taken" >E</span>if (ms &lt; 60000) return `${Math.round(ms / 1000)}s`;
408
399
  <span class="cstat-no" title="statement not covered" > if (ms &lt; 3600000) <span class="cstat-no" title="statement not covered" >return `${Math.round(ms / 60000)}m`;</span></span>
@@ -532,7 +523,7 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
532
523
  <div class='footer quiet pad2 space-top1 center small'>
533
524
  Code coverage generated by
534
525
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
535
- at 2026-06-19T00:56:38.236Z
526
+ at 2026-07-02T19:31:50.067Z
536
527
  </div>
537
528
  <script src="../../prettify.js"></script>
538
529
  <script>
@@ -25,14 +25,14 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">100% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>50/50</span>
28
+ <span class='fraction'>30/30</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">94.11% </span>
33
+ <span class="strong">100% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>32/34</span>
35
+ <span class='fraction'>16/16</span>
36
36
  </div>
37
37
 
38
38
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">100% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>43/43</span>
49
+ <span class='fraction'>27/27</span>
50
50
  </div>
51
51
 
52
52
 
@@ -199,21 +199,9 @@
199
199
  <a name='L134'></a><a href='#L134'>134</a>
200
200
  <a name='L135'></a><a href='#L135'>135</a>
201
201
  <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
202
+ <a name='L137'></a><a href='#L137'>137</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
203
+ <span class="cline-any cline-neutral">&nbsp;</span>
204
+ <span class="cline-any cline-neutral">&nbsp;</span>
217
205
  <span class="cline-any cline-neutral">&nbsp;</span>
218
206
  <span class="cline-any cline-neutral">&nbsp;</span>
219
207
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -230,19 +218,20 @@
230
218
  <span class="cline-any cline-neutral">&nbsp;</span>
231
219
  <span class="cline-any cline-neutral">&nbsp;</span>
232
220
  <span class="cline-any cline-neutral">&nbsp;</span>
233
- <span class="cline-any cline-yes">82x</span>
234
221
  <span class="cline-any cline-neutral">&nbsp;</span>
235
222
  <span class="cline-any cline-neutral">&nbsp;</span>
236
223
  <span class="cline-any cline-neutral">&nbsp;</span>
237
- <span class="cline-any cline-yes">55x</span>
238
224
  <span class="cline-any cline-neutral">&nbsp;</span>
239
- <span class="cline-any cline-yes">55x</span>
225
+ <span class="cline-any cline-yes">74x</span>
240
226
  <span class="cline-any cline-neutral">&nbsp;</span>
241
227
  <span class="cline-any cline-neutral">&nbsp;</span>
242
228
  <span class="cline-any cline-neutral">&nbsp;</span>
243
229
  <span class="cline-any cline-neutral">&nbsp;</span>
244
230
  <span class="cline-any cline-neutral">&nbsp;</span>
231
+ <span class="cline-any cline-yes">57x</span>
232
+ <span class="cline-any cline-yes">57x</span>
245
233
  <span class="cline-any cline-neutral">&nbsp;</span>
234
+ <span class="cline-any cline-yes">57x</span>
246
235
  <span class="cline-any cline-neutral">&nbsp;</span>
247
236
  <span class="cline-any cline-neutral">&nbsp;</span>
248
237
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -261,24 +250,21 @@
261
250
  <span class="cline-any cline-neutral">&nbsp;</span>
262
251
  <span class="cline-any cline-neutral">&nbsp;</span>
263
252
  <span class="cline-any cline-neutral">&nbsp;</span>
264
- <span class="cline-any cline-yes">42x</span>
265
- <span class="cline-any cline-yes">42x</span>
266
253
  <span class="cline-any cline-neutral">&nbsp;</span>
267
254
  <span class="cline-any cline-neutral">&nbsp;</span>
268
255
  <span class="cline-any cline-neutral">&nbsp;</span>
269
256
  <span class="cline-any cline-neutral">&nbsp;</span>
270
257
  <span class="cline-any cline-neutral">&nbsp;</span>
271
- <span class="cline-any cline-yes">42x</span>
272
- <span class="cline-any cline-yes">42x</span>
273
258
  <span class="cline-any cline-neutral">&nbsp;</span>
274
- <span class="cline-any cline-yes">42x</span>
259
+ <span class="cline-any cline-yes">43x</span>
275
260
  <span class="cline-any cline-neutral">&nbsp;</span>
276
261
  <span class="cline-any cline-neutral">&nbsp;</span>
277
- <span class="cline-any cline-yes">42x</span>
278
262
  <span class="cline-any cline-neutral">&nbsp;</span>
263
+ <span class="cline-any cline-yes">43x</span>
279
264
  <span class="cline-any cline-neutral">&nbsp;</span>
280
265
  <span class="cline-any cline-neutral">&nbsp;</span>
281
- <span class="cline-any cline-yes">55x</span>
266
+ <span class="cline-any cline-neutral">&nbsp;</span>
267
+ <span class="cline-any cline-yes">57x</span>
282
268
  <span class="cline-any cline-neutral">&nbsp;</span>
283
269
  <span class="cline-any cline-neutral">&nbsp;</span>
284
270
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -303,7 +289,7 @@
303
289
  <span class="cline-any cline-neutral">&nbsp;</span>
304
290
  <span class="cline-any cline-neutral">&nbsp;</span>
305
291
  <span class="cline-any cline-neutral">&nbsp;</span>
306
- <span class="cline-any cline-yes">55x</span>
292
+ <span class="cline-any cline-yes">57x</span>
307
293
  <span class="cline-any cline-neutral">&nbsp;</span>
308
294
  <span class="cline-any cline-neutral">&nbsp;</span>
309
295
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -322,30 +308,20 @@
322
308
  <span class="cline-any cline-neutral">&nbsp;</span>
323
309
  <span class="cline-any cline-neutral">&nbsp;</span>
324
310
  <span class="cline-any cline-neutral">&nbsp;</span>
325
- <span class="cline-any cline-yes">31x</span>
326
- <span class="cline-any cline-yes">31x</span>
327
- <span class="cline-any cline-yes">31x</span>
311
+ <span class="cline-any cline-yes">32x</span>
312
+ <span class="cline-any cline-yes">32x</span>
328
313
  <span class="cline-any cline-neutral">&nbsp;</span>
329
- <span class="cline-any cline-yes">30x</span>
330
- <span class="cline-any cline-yes">27x</span>
331
- <span class="cline-any cline-yes">8x</span>
332
314
  <span class="cline-any cline-neutral">&nbsp;</span>
333
- <span class="cline-any cline-yes">30x</span>
334
- <span class="cline-any cline-yes">30x</span>
335
- <span class="cline-any cline-yes">1x</span>
336
315
  <span class="cline-any cline-neutral">&nbsp;</span>
337
- <span class="cline-any cline-yes">30x</span>
338
- <span class="cline-any cline-yes">30x</span>
339
- <span class="cline-any cline-yes">30x</span>
340
- <span class="cline-any cline-yes">30x</span>
341
- <span class="cline-any cline-yes">31x</span>
342
316
  <span class="cline-any cline-neutral">&nbsp;</span>
343
317
  <span class="cline-any cline-neutral">&nbsp;</span>
318
+ <span class="cline-any cline-yes">32x</span>
344
319
  <span class="cline-any cline-yes">31x</span>
320
+ <span class="cline-any cline-yes">32x</span>
345
321
  <span class="cline-any cline-neutral">&nbsp;</span>
346
322
  <span class="cline-any cline-neutral">&nbsp;</span>
347
323
  <span class="cline-any cline-neutral">&nbsp;</span>
348
- <span class="cline-any cline-yes">55x</span>
324
+ <span class="cline-any cline-yes">57x</span>
349
325
  <span class="cline-any cline-neutral">&nbsp;</span>
350
326
  <span class="cline-any cline-neutral">&nbsp;</span>
351
327
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -355,22 +331,24 @@
355
331
  <span class="cline-any cline-neutral">&nbsp;</span>
356
332
  <span class="cline-any cline-yes">2x</span>
357
333
  <span class="cline-any cline-yes">2x</span>
358
- <span class="cline-any cline-yes">2x</span>
359
- <span class="cline-any cline-yes">1x</span>
360
- <span class="cline-any cline-yes">1x</span>
361
- <span class="cline-any cline-neutral">&nbsp;</span>
362
334
  <span class="cline-any cline-yes">1x</span>
363
335
  <span class="cline-any cline-neutral">&nbsp;</span>
364
336
  <span class="cline-any cline-neutral">&nbsp;</span>
365
337
  <span class="cline-any cline-neutral">&nbsp;</span>
366
338
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
367
339
  import { Type } from "typebox";
340
+ import {
341
+ createTask,
342
+ deleteTask,
343
+ type TaskBacklogResult,
344
+ type TaskMutationContext,
345
+ updateTask,
346
+ } from "../runtime/task-mutations.js";
368
347
  import { TaskStore } from "../task-store.js";
348
+ import type { TaskStatus } from "../task-types.js";
349
+ import { textResult } from "./tool-result.js";
369
350
  &nbsp;
370
- export interface TaskBacklogResult {
371
- created: boolean;
372
- entry?: { id: string };
373
- }
351
+ export type { TaskBacklogResult };
374
352
  &nbsp;
375
353
  export interface NativeTaskToolsOptions {
376
354
  pi: ExtensionAPI;
@@ -379,12 +357,15 @@ export interface NativeTaskToolsOptions {
379
357
  updateWidget: () =&gt; void;
380
358
  }
381
359
  &nbsp;
382
- function textResult(msg: string) {
383
- return { content: [{ type: "text" as const, text: msg }], details: undefined as any };
360
+ function backlogSuffix(backlog: TaskBacklogResult): string {
361
+ return backlog.created &amp;&amp; backlog.entry
362
+ ? `\nBacklog worker loop #${backlog.entry.id} created`
363
+ : "";
384
364
  }
385
365
  &nbsp;
386
366
  export function registerNativeTaskTools(options: NativeTaskToolsOptions): void {
387
367
  const { pi, taskStore, evaluateTaskBacklog, updateWidget } = options;
368
+ const mutationCtx: TaskMutationContext = { pi, taskStore, evaluateTaskBacklog, updateWidget };
388
369
  &nbsp;
389
370
  pi.registerTool({
390
371
  name: "TaskCreate",
@@ -411,20 +392,11 @@ Fields:
411
392
  description: Type.String({ description: "Detailed description of what needs to be done" }),
412
393
  }),
413
394
  async execute(_toolCallId, params) {
414
- const entry = taskStore.create(params.subject, params.description);
415
- pi.events.emit("tasks:created", {
416
- taskId: entry.id,
417
- subject: entry.subject,
418
- description: entry.description,
419
- status: entry.status,
395
+ const { entry, backlog } = await createTask(mutationCtx, {
396
+ subject: params.subject,
397
+ description: params.description,
420
398
  });
421
- const backlog = await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
422
- updateWidget();
423
- &nbsp;
424
- const autoLoopMsg = backlog.created &amp;&amp; backlog.entry
425
- ? `\nBacklog worker loop #${backlog.entry.id} created`
426
- : "";
427
- return Promise.resolve(textResult(`Task #${entry.id} created: ${entry.subject}${autoLoopMsg}`));
399
+ return textResult(`Task #${entry.id} created: ${entry.subject}${backlogSuffix(backlog)}`);
428
400
  },
429
401
  });
430
402
  &nbsp;
@@ -473,25 +445,15 @@ Parameters: id (required), status, subject, description`,
473
445
  }),
474
446
  async execute(_toolCallId, params) {
475
447
  const { id, status, subject, description } = params;
476
- let entry = taskStore.get(id);
477
- if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
478
- &nbsp;
479
- if (status === "in_progress") entry = taskStore.start(id);
480
- else if (status === "completed") entry = taskStore.complete(id);
481
- else if (status === "pending") entry = taskStore.reopen(id);
482
- &nbsp;
483
- <span class="missing-if-branch" title="if path not taken" >I</span>if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
484
- if (subject !== undefined || description !== undefined) {
485
- entry = taskStore.updateDetails(id, { subject, description });
486
- }
487
- <span class="missing-if-branch" title="if path not taken" >I</span>if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
488
- updateWidget();
489
- const backlog = await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
448
+ const result = await updateTask(mutationCtx, {
449
+ id,
450
+ status: status as TaskStatus | undefined,
451
+ subject,
452
+ description,
453
+ });
454
+ if (!result) return textResult(`Task #${id} not found`);
490
455
  const statusMsg = status ? ` → ${status}` : "";
491
- const autoLoopMsg = backlog.created &amp;&amp; backlog.entry
492
- ? `\nBacklog worker loop #${backlog.entry.id} created`
493
- : "";
494
- return Promise.resolve(textResult(`Task #${id} updated${statusMsg}${autoLoopMsg}`));
456
+ return textResult(`Task #${id} updated${statusMsg}${backlogSuffix(result.backlog)}`);
495
457
  },
496
458
  });
497
459
  &nbsp;
@@ -503,13 +465,9 @@ Parameters: id (required), status, subject, description`,
503
465
  id: Type.String({ description: "Task ID to delete" }),
504
466
  }),
505
467
  async execute(_toolCallId, params) {
506
- const deleted = taskStore.delete(params.id);
507
- updateWidget();
508
- if (deleted) {
509
- await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
510
- return Promise.resolve(textResult(`Task #${params.id} deleted`));
511
- }
512
- return Promise.resolve(textResult(`Task #${params.id} not found`));
468
+ const result = await deleteTask(mutationCtx, params.id);
469
+ if (!result) return textResult(`Task #${params.id} not found`);
470
+ return textResult(`Task #${params.id} deleted`);
513
471
  },
514
472
  });
515
473
  }
@@ -520,7 +478,7 @@ Parameters: id (required), status, subject, description`,
520
478
  <div class='footer quiet pad2 space-top1 center small'>
521
479
  Code coverage generated by
522
480
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
523
- at 2026-06-19T00:56:38.236Z
481
+ at 2026-07-02T19:31:50.067Z
524
482
  </div>
525
483
  <script src="../../prettify.js"></script>
526
484
  <script>
@@ -0,0 +1,97 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/tools/tool-result.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../prettify.css" />
9
+ <link rel="stylesheet" href="../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../index.html">All files</a> / <a href="index.html">src/tools</a> tool-result.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">100% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>1/1</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">100% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>0/0</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>1/1</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">100% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>1/1</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
71
+ <span class="cline-any cline-neutral">&nbsp;</span>
72
+ <span class="cline-any cline-yes">164x</span>
73
+ <span class="cline-any cline-neutral">&nbsp;</span>
74
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/** Plain-text tool result in the shape pi's registerTool expects. */
75
+ export function textResult(msg: string) {
76
+ return { content: [{ type: "text" as const, text: msg }], details: undefined };
77
+ }
78
+ &nbsp;</pre></td></tr></table></pre>
79
+
80
+ <div class='push'></div><!-- for sticky footer -->
81
+ </div><!-- /wrapper -->
82
+ <div class='footer quiet pad2 space-top1 center small'>
83
+ Code coverage generated by
84
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
85
+ at 2026-07-02T19:31:50.067Z
86
+ </div>
87
+ <script src="../../prettify.js"></script>
88
+ <script>
89
+ window.onload = function () {
90
+ prettyPrint();
91
+ };
92
+ </script>
93
+ <script src="../../sorter.js"></script>
94
+ <script src="../../block-navigation.js"></script>
95
+ </body>
96
+ </html>
97
+
@@ -224,15 +224,15 @@
224
224
  <span class="cline-any cline-neutral">&nbsp;</span>
225
225
  <span class="cline-any cline-neutral">&nbsp;</span>
226
226
  <span class="cline-any cline-neutral">&nbsp;</span>
227
- <span class="cline-any cline-yes">121x</span>
228
- <span class="cline-any cline-yes">121x</span>
229
- <span class="cline-any cline-yes">121x</span>
227
+ <span class="cline-any cline-yes">126x</span>
228
+ <span class="cline-any cline-yes">126x</span>
229
+ <span class="cline-any cline-yes">126x</span>
230
230
  <span class="cline-any cline-neutral">&nbsp;</span>
231
231
  <span class="cline-any cline-neutral">&nbsp;</span>
232
- <span class="cline-any cline-yes">121x</span>
233
- <span class="cline-any cline-yes">121x</span>
234
- <span class="cline-any cline-yes">121x</span>
235
- <span class="cline-any cline-yes">121x</span>
232
+ <span class="cline-any cline-yes">126x</span>
233
+ <span class="cline-any cline-yes">126x</span>
234
+ <span class="cline-any cline-yes">126x</span>
235
+ <span class="cline-any cline-yes">126x</span>
236
236
  <span class="cline-any cline-neutral">&nbsp;</span>
237
237
  <span class="cline-any cline-neutral">&nbsp;</span>
238
238
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -431,7 +431,7 @@ export class TriggerSystem {
431
431
  }
432
432
  const subs = this.eventSubscriptions.get(source)!;
433
433
  &nbsp;
434
- const unsub = this.pi.events.on(source as any, (data: any) =&gt; {
434
+ const unsub = this.pi.events.on(source, (data: unknown) =&gt; {
435
435
  if (entry.trigger.type === "hybrid") {
436
436
  this.handleHybridFire(entry, data);
437
437
  } else {
@@ -444,7 +444,7 @@ export class TriggerSystem {
444
444
  subs.set(entry.id, unsub);
445
445
  }
446
446
  &nbsp;
447
- private handleHybridFire(entry: LoopEntry, _data: any): void {
447
+ private handleHybridFire(entry: LoopEntry, _data: unknown): void {
448
448
  const now = Date.now();
449
449
  const last = this.lastFireTime.get(entry.id) ?? 0;
450
450
  const debounceMs = entry.trigger.type === "hybrid" ? entry.trigger.debounceMs : <span class="branch-1 cbranch-no" title="branch not covered" >0;</span>
@@ -496,7 +496,7 @@ export class TriggerSystem {
496
496
  }
497
497
  }
498
498
  &nbsp;
499
- private matchesFilter(data: any, filter?: string): boolean {
499
+ private matchesFilter(data: unknown, filter?: string): boolean {
500
500
  if (!filter) return true;
501
501
  &nbsp;
502
502
  if (filter.startsWith("regex:")) {
@@ -511,7 +511,7 @@ export class TriggerSystem {
511
511
  try {
512
512
  const parsed = JSON.parse(filter);
513
513
  for (const [key, value] of Object.entries(parsed)) {
514
- const dataValue = <span class="cstat-no" title="statement not covered" >data?.[key];</span>
514
+ const dataValue = (<span class="cstat-no" title="statement not covered" >data as Record&lt;string, unknown&gt; | undefined)?.[key];</span>
515
515
  <span class="cstat-no" title="statement not covered" > if (dataValue === undefined) <span class="cstat-no" title="statement not covered" >return false;</span></span>
516
516
  <span class="cstat-no" title="statement not covered" > if (typeof value === "object" &amp;&amp; typeof dataValue === "object") {</span>
517
517
  <span class="cstat-no" title="statement not covered" > if (JSON.stringify(value) !== JSON.stringify(dataValue)) <span class="cstat-no" title="statement not covered" >return false;</span></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-19T00:56:38.236Z
535
+ at 2026-07-02T19:31:50.067Z
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-19T00:56:38.236Z
104
+ at 2026-07-02T19:31:50.067Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>