@trevonistrevon/pi-loop 0.5.8 → 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 +25 -24
- package/coverage/index.html +42 -42
- 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 +3 -3
- 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 +18 -18
- package/coverage/src/index.ts.html +126 -78
- package/coverage/src/loop-parse.ts.html +38 -38
- package/coverage/src/loop-reducer.ts.html +17 -17
- package/coverage/src/monitor-completion-coordinator.ts.html +1 -1
- package/coverage/src/monitor-manager.ts.html +16 -16
- package/coverage/src/monitor-reducer.ts.html +10 -10
- package/coverage/src/notification-reducer.ts.html +11 -11
- package/coverage/src/reducer-backed-store.ts.html +49 -49
- package/coverage/src/runtime/index.html +35 -20
- package/coverage/src/runtime/monitor-ondone-runtime.ts.html +5 -5
- package/coverage/src/runtime/notification-runtime.ts.html +25 -25
- package/coverage/src/runtime/scope.ts.html +12 -12
- package/coverage/src/runtime/session-runtime.ts.html +23 -23
- package/coverage/src/runtime/task-backlog-runtime.ts.html +7 -7
- package/coverage/src/runtime/task-events.ts.html +208 -0
- package/coverage/src/runtime/task-rpc.ts.html +21 -15
- package/coverage/src/scheduler.ts.html +25 -25
- package/coverage/src/store.ts.html +12 -12
- package/coverage/src/task-backlog-coordinator.ts.html +1 -1
- package/coverage/src/task-reducer.ts.html +1 -1
- package/coverage/src/task-store.ts.html +5 -5
- package/coverage/src/tools/index.html +11 -11
- package/coverage/src/tools/loop-tools.ts.html +5 -5
- package/coverage/src/tools/monitor-tools.ts.html +5 -5
- package/coverage/src/tools/native-task-tools.ts.html +41 -20
- 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/index.js +34 -19
- package/dist/monitor-manager.d.ts +4 -1
- package/dist/monitor-manager.js +5 -3
- package/docker-compose.yml +12 -0
- package/package.json +1 -1
- package/release-please-config.json +9 -0
- package/src/index.ts +37 -21
- package/src/monitor-manager.ts +11 -3
- package/vitest.config.ts +4 -0
|
@@ -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>
|
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
|
|
@@ -76,7 +78,7 @@ export class MonitorManager {
|
|
|
76
78
|
const id = String(this.nextId - 1);
|
|
77
79
|
const entry = result.state.monitorsById[id];
|
|
78
80
|
const abortController = new AbortController();
|
|
79
|
-
const child =
|
|
81
|
+
const child = this.spawnFn("sh", ["-c", command], {
|
|
80
82
|
stdio: ["ignore", "pipe", "pipe"],
|
|
81
83
|
signal: abortController.signal,
|
|
82
84
|
env: { ...process.env },
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
services:
|
|
2
|
+
ci-node20:
|
|
3
|
+
build:
|
|
4
|
+
context: .
|
|
5
|
+
target: node20
|
|
6
|
+
command: sh -c "npm run typecheck && npm run lint && npm run test:coverage && npm run build"
|
|
7
|
+
|
|
8
|
+
ci-node22:
|
|
9
|
+
build:
|
|
10
|
+
context: .
|
|
11
|
+
target: node22
|
|
12
|
+
command: sh -c "npm run typecheck && npm run lint && npm run test:coverage && npm run build"
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -43,6 +43,10 @@ function debug(...args: unknown[]) {
|
|
|
43
43
|
if (DEBUG) console.error("[pi-loop]", ...args);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function isStaleExtensionContextError(error: unknown): boolean {
|
|
47
|
+
return error instanceof Error && error.message.includes("extension ctx is stale");
|
|
48
|
+
}
|
|
49
|
+
|
|
46
50
|
export default function (pi: ExtensionAPI) {
|
|
47
51
|
const piLoopEnv = process.env.PI_LOOP;
|
|
48
52
|
const piLoopScope = process.env.PI_LOOP_SCOPE as "memory" | "session" | "project" | undefined;
|
|
@@ -297,30 +301,42 @@ export default function (pi: ExtensionAPI) {
|
|
|
297
301
|
|
|
298
302
|
// ── Native task tools (only when pi-tasks is absent) ──
|
|
299
303
|
|
|
300
|
-
setTimeout(
|
|
304
|
+
const nativeTaskFallbackTimer = setTimeout(() => {
|
|
301
305
|
if (tasksAvailable || nativeTasksRegistered) return;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
});
|
|
306
|
+
const taskStore = new TaskStore(resolveTaskStorePath(getScopeOptions(), _sessionId));
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
registerTasksCommand({
|
|
310
|
+
pi,
|
|
311
|
+
getNativeTaskStore: () => nativeTaskStore,
|
|
312
|
+
evaluateTaskBacklog,
|
|
313
|
+
updateWidget: () => {
|
|
314
|
+
widget.update();
|
|
315
|
+
},
|
|
316
|
+
});
|
|
314
317
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
318
|
+
registerNativeTaskTools({
|
|
319
|
+
pi,
|
|
320
|
+
taskStore,
|
|
321
|
+
evaluateTaskBacklog,
|
|
322
|
+
updateWidget: () => {
|
|
323
|
+
widget.update();
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
} catch (error) {
|
|
327
|
+
if (isStaleExtensionContextError(error)) {
|
|
328
|
+
debug("native task fallback skipped: extension context went stale");
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
323
333
|
|
|
334
|
+
nativeTaskStore = taskStore;
|
|
335
|
+
nativeTasksRegistered = true;
|
|
324
336
|
debug("native task tools registered (pi-tasks not detected)");
|
|
325
337
|
}, 6000);
|
|
338
|
+
|
|
339
|
+
pi.on("session_shutdown", () => {
|
|
340
|
+
clearTimeout(nativeTaskFallbackTimer);
|
|
341
|
+
});
|
|
326
342
|
}
|
package/src/monitor-manager.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
2
|
+
import { type ChildProcess, spawn as nodeSpawn, type SpawnOptions } from "node:child_process";
|
|
3
3
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import {
|
|
5
5
|
type MonitorReducerEvent,
|
|
@@ -8,12 +8,20 @@ import {
|
|
|
8
8
|
} from "./monitor-reducer.js";
|
|
9
9
|
import type { MonitorEntry, MonitorProcess } from "./types.js";
|
|
10
10
|
|
|
11
|
+
export type SpawnFn = (command: string, args: string[], options: SpawnOptions) => ChildProcess;
|
|
12
|
+
|
|
11
13
|
export class MonitorManager {
|
|
12
14
|
private processes = new Map<string, MonitorProcess>();
|
|
13
15
|
private nextId = 1;
|
|
14
16
|
private onChange: (() => void) | undefined;
|
|
17
|
+
private spawnFn: SpawnFn;
|
|
15
18
|
|
|
16
|
-
constructor(
|
|
19
|
+
constructor(
|
|
20
|
+
private pi: ExtensionAPI,
|
|
21
|
+
spawnFn?: SpawnFn,
|
|
22
|
+
) {
|
|
23
|
+
this.spawnFn = spawnFn ?? ((cmd, args, opts) => nodeSpawn(cmd, args, opts));
|
|
24
|
+
}
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
27
|
* Register a callback fired when a monitor's status changes or it is pruned
|
|
@@ -90,7 +98,7 @@ export class MonitorManager {
|
|
|
90
98
|
const entry = result.state.monitorsById[id]!;
|
|
91
99
|
|
|
92
100
|
const abortController = new AbortController();
|
|
93
|
-
const child =
|
|
101
|
+
const child = this.spawnFn("sh", ["-c", command], {
|
|
94
102
|
stdio: ["ignore", "pipe", "pipe"],
|
|
95
103
|
signal: abortController.signal,
|
|
96
104
|
env: { ...process.env },
|
package/vitest.config.ts
CHANGED
|
@@ -5,6 +5,10 @@ export default defineConfig({
|
|
|
5
5
|
environment: "node",
|
|
6
6
|
include: ["test/**/*.test.ts"],
|
|
7
7
|
exclude: ["node_modules", "dist"],
|
|
8
|
+
// CI runners are slower than local; 15s gives real-child-process
|
|
9
|
+
// tests (monitor stop, lifecycle) enough headroom.
|
|
10
|
+
testTimeout: 15000,
|
|
11
|
+
hookTimeout: 15000,
|
|
8
12
|
coverage: {
|
|
9
13
|
provider: "v8",
|
|
10
14
|
reporter: ["text-summary", "html", "json"],
|