pi-cohort 7.2.0 → 7.2.1
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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/extension/index.ts +2 -39
- package/src/runs/background/notify.ts +2 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [7.2.1] - 2026-10-16
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- A second pi-cohort instance loaded into the same Node process no longer stops the first instance's result watcher or drops its event subscriptions. The extension factory and `registerSubagentNotify` used to call cleanup callbacks a previous instance stored on `globalThis` (`__piSubagentRuntimeCleanup`, `__piSubagentEventUnsubscribes`, `__pi_subagents_notify_unsubscribe__`), which also retired a live session in another SDK runtime; those hooks are gone and each instance now tears down only itself in its own `session_shutdown` handler, which pi emits on reload, new, resume, fork, and quit. (#20)
|
|
8
|
+
|
|
3
9
|
## [7.2.0] - 2026-10-11
|
|
4
10
|
|
|
5
11
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cohort",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.1",
|
|
4
4
|
"description": "Delegate Pi work to focused child agents: code review, scouting, implementation, parallel audits, saved chains, and background jobs.",
|
|
5
5
|
"author": "Jacek Juraszek",
|
|
6
6
|
"license": "MIT",
|
package/src/extension/index.ts
CHANGED
|
@@ -246,15 +246,6 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
248
|
const globalStore = globalThis as Record<string, unknown>;
|
|
249
|
-
const runtimeCleanupStoreKey = "__piSubagentRuntimeCleanup";
|
|
250
|
-
const previousRuntimeCleanup = globalStore[runtimeCleanupStoreKey];
|
|
251
|
-
if (typeof previousRuntimeCleanup === "function") {
|
|
252
|
-
try {
|
|
253
|
-
previousRuntimeCleanup();
|
|
254
|
-
} catch {
|
|
255
|
-
// Best effort cleanup for stale timers from an older reload.
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
249
|
|
|
259
250
|
ensureAccessibleDir(RUN_STATE_ROOT_DIR, true);
|
|
260
251
|
ensureAccessibleDir(RESULTS_DIR);
|
|
@@ -296,16 +287,6 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
296
287
|
startResultWatcher();
|
|
297
288
|
primeExistingResults();
|
|
298
289
|
|
|
299
|
-
const runtimeCleanup = () => {
|
|
300
|
-
stopResultWatcher();
|
|
301
|
-
clearPendingForegroundControlNotices(state);
|
|
302
|
-
if (state.poller) {
|
|
303
|
-
clearInterval(state.poller);
|
|
304
|
-
state.poller = null;
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
globalStore[runtimeCleanupStoreKey] = runtimeCleanup;
|
|
308
|
-
|
|
309
290
|
const { ensurePoller, handleStarted, handleComplete, resetJobs } = createAsyncJobTracker(pi, state, ASYNC_DIR);
|
|
310
291
|
const executor = createSubagentExecutor({
|
|
311
292
|
pi,
|
|
@@ -491,20 +472,8 @@ DIAGNOSTICS:
|
|
|
491
472
|
pi.registerTool(tool);
|
|
492
473
|
registerSlashCommands(pi, state);
|
|
493
474
|
|
|
494
|
-
const eventUnsubscribeStoreKey = "__piSubagentEventUnsubscribes";
|
|
495
475
|
const controlNoticeSeenStoreKey = "__piSubagentVisibleControlNotices";
|
|
496
|
-
const
|
|
497
|
-
if (Array.isArray(previousEventUnsubscribes)) {
|
|
498
|
-
for (const unsubscribe of previousEventUnsubscribes) {
|
|
499
|
-
if (typeof unsubscribe !== "function") continue;
|
|
500
|
-
try {
|
|
501
|
-
unsubscribe();
|
|
502
|
-
} catch {
|
|
503
|
-
// Best effort cleanup for stale handlers from an older reload.
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
registerSubagentNotify(pi);
|
|
476
|
+
const unsubscribeNotify = registerSubagentNotify(pi);
|
|
508
477
|
|
|
509
478
|
const existingVisibleControlNotices = globalStore[controlNoticeSeenStoreKey];
|
|
510
479
|
const visibleControlNotices = existingVisibleControlNotices instanceof Set ? existingVisibleControlNotices as Set<string> : new Set<string>();
|
|
@@ -518,6 +487,7 @@ DIAGNOSTICS:
|
|
|
518
487
|
});
|
|
519
488
|
};
|
|
520
489
|
const eventUnsubscribes = [
|
|
490
|
+
unsubscribeNotify,
|
|
521
491
|
pi.events.on(SUBAGENT_ASYNC_STARTED_EVENT, handleStarted),
|
|
522
492
|
pi.events.on(SUBAGENT_ASYNC_COMPLETE_EVENT, handleComplete),
|
|
523
493
|
pi.events.on(SUBAGENT_CONTROL_EVENT, controlEventHandler),
|
|
@@ -527,7 +497,6 @@ DIAGNOSTICS:
|
|
|
527
497
|
}
|
|
528
498
|
}),
|
|
529
499
|
];
|
|
530
|
-
globalStore[eventUnsubscribeStoreKey] = eventUnsubscribes;
|
|
531
500
|
|
|
532
501
|
pi.on("message_end", (event, ctx) => {
|
|
533
502
|
if (event.message.role !== "assistant") return;
|
|
@@ -591,9 +560,6 @@ DIAGNOSTICS:
|
|
|
591
560
|
// Best effort cleanup during shutdown.
|
|
592
561
|
}
|
|
593
562
|
}
|
|
594
|
-
if (globalStore[eventUnsubscribeStoreKey] === eventUnsubscribes) {
|
|
595
|
-
delete globalStore[eventUnsubscribeStoreKey];
|
|
596
|
-
}
|
|
597
563
|
stopResultWatcher();
|
|
598
564
|
if (state.poller) clearInterval(state.poller);
|
|
599
565
|
state.poller = null;
|
|
@@ -608,9 +574,6 @@ DIAGNOSTICS:
|
|
|
608
574
|
slashBridge.dispose();
|
|
609
575
|
promptTemplateBridge.cancelAll();
|
|
610
576
|
promptTemplateBridge.dispose();
|
|
611
|
-
if (globalStore[runtimeCleanupStoreKey] === runtimeCleanup) {
|
|
612
|
-
delete globalStore[runtimeCleanupStoreKey];
|
|
613
|
-
}
|
|
614
577
|
try {
|
|
615
578
|
if (state.lastUiContext?.hasUI) {
|
|
616
579
|
state.lastUiContext.ui.setWidget(WIDGET_KEY, undefined);
|
|
@@ -40,18 +40,7 @@ interface SubagentResult {
|
|
|
40
40
|
totalTasks?: number;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export default function registerSubagentNotify(pi: ExtensionAPI): void {
|
|
44
|
-
const unsubscribeStoreKey = "__pi_subagents_notify_unsubscribe__";
|
|
45
|
-
const globalStore = globalThis as Record<string, unknown>;
|
|
46
|
-
const previousUnsubscribe = globalStore[unsubscribeStoreKey];
|
|
47
|
-
if (typeof previousUnsubscribe === "function") {
|
|
48
|
-
try {
|
|
49
|
-
previousUnsubscribe();
|
|
50
|
-
} catch {
|
|
51
|
-
// Best effort cleanup for stale handlers from an older reload.
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
43
|
+
export default function registerSubagentNotify(pi: ExtensionAPI): () => void {
|
|
55
44
|
const seen = getGlobalSeenMap("__pi_subagents_notify_seen__");
|
|
56
45
|
const ttlMs = 10 * 60 * 1000;
|
|
57
46
|
|
|
@@ -104,5 +93,5 @@ export default function registerSubagentNotify(pi: ExtensionAPI): void {
|
|
|
104
93
|
);
|
|
105
94
|
};
|
|
106
95
|
|
|
107
|
-
|
|
96
|
+
return pi.events.on(SUBAGENT_ASYNC_COMPLETE_EVENT, handleComplete);
|
|
108
97
|
}
|