@trevonistrevon/pi-loop 0.4.9 → 0.4.10

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/dist/index.js CHANGED
@@ -571,11 +571,24 @@ Skip this tool when the task is a one-off check (just do it directly) or when th
571
571
  },
572
572
  });
573
573
  function handleMonitorDoneLoop(doneLoop, monitorId) {
574
- triggerSystem.add(doneLoop);
574
+ const deliver = () => {
575
+ const current = store.get(doneLoop.id);
576
+ if (!current)
577
+ return;
578
+ debug(`onDone loop #${doneLoop.id} — monitor #${monitorId} completed, delivering directly`);
579
+ onLoopFire(current);
580
+ store.delete(doneLoop.id);
581
+ };
582
+ const registered = monitorManager.onComplete(monitorId, deliver);
583
+ if (registered)
584
+ return;
575
585
  const monitor = monitorManager.get(monitorId);
576
586
  if (monitor && monitor.status !== "running") {
587
+ if (monitor.status === "completed") {
588
+ deliver();
589
+ return;
590
+ }
577
591
  debug(`onDone loop #${doneLoop.id} — monitor #${monitorId} already ${monitor.status}, expiring`);
578
- triggerSystem.remove(doneLoop.id);
579
592
  store.delete(doneLoop.id);
580
593
  }
581
594
  }
@@ -9,5 +9,6 @@ export declare class MonitorManager {
9
9
  get(id: string): MonitorEntry | undefined;
10
10
  list(): MonitorEntry[];
11
11
  stop(id: string): Promise<boolean>;
12
+ onComplete(id: string, callback: () => void): boolean;
12
13
  getProcess(id: string): MonitorProcess | undefined;
13
14
  }
@@ -30,6 +30,7 @@ export class MonitorManager {
30
30
  proc: child,
31
31
  abortController,
32
32
  waiters: [],
33
+ completionCallbacks: [],
33
34
  };
34
35
  child.stdout?.on("data", (data) => {
35
36
  const lines = data.toString().split("\n");
@@ -70,6 +71,11 @@ export class MonitorManager {
70
71
  exitCode: code,
71
72
  outputLines: entry.outputLines,
72
73
  });
74
+ if (status === "completed") {
75
+ for (const callback of bp.completionCallbacks)
76
+ callback();
77
+ }
78
+ bp.completionCallbacks = [];
73
79
  for (const resolve of bp.waiters)
74
80
  resolve();
75
81
  bp.waiters = [];
@@ -90,6 +96,7 @@ export class MonitorManager {
90
96
  monitorId: id,
91
97
  error: err.message,
92
98
  });
99
+ bp.completionCallbacks = [];
93
100
  for (const resolve of bp.waiters)
94
101
  resolve();
95
102
  bp.waiters = [];
@@ -134,11 +141,25 @@ export class MonitorManager {
134
141
  });
135
142
  });
136
143
  bp.entry.completedAt = Date.now();
144
+ bp.completionCallbacks = [];
137
145
  for (const resolve of bp.waiters)
138
146
  resolve();
139
147
  bp.waiters = [];
140
148
  return true;
141
149
  }
150
+ onComplete(id, callback) {
151
+ const bp = this.processes.get(id);
152
+ if (!bp)
153
+ return false;
154
+ if (bp.entry.status === "completed") {
155
+ callback();
156
+ return true;
157
+ }
158
+ if (bp.entry.status !== "running")
159
+ return false;
160
+ bp.completionCallbacks.push(callback);
161
+ return true;
162
+ }
142
163
  getProcess(id) {
143
164
  return this.processes.get(id);
144
165
  }
package/dist/types.d.ts CHANGED
@@ -55,4 +55,5 @@ export interface MonitorProcess {
55
55
  proc: import("node:child_process").ChildProcess;
56
56
  abortController: AbortController;
57
57
  waiters: Array<() => void>;
58
+ completionCallbacks: Array<() => void>;
58
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trevonistrevon/pi-loop",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "description": "A pi extension for cron/event-based agent re-wake loops and background process monitoring.",
5
5
  "author": "trevonistrevon",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -621,11 +621,24 @@ Skip this tool when the task is a one-off check (just do it directly) or when th
621
621
  });
622
622
 
623
623
  function handleMonitorDoneLoop(doneLoop: LoopEntry, monitorId: string): void {
624
- triggerSystem.add(doneLoop);
624
+ const deliver = () => {
625
+ const current = store.get(doneLoop.id);
626
+ if (!current) return;
627
+ debug(`onDone loop #${doneLoop.id} — monitor #${monitorId} completed, delivering directly`);
628
+ onLoopFire(current);
629
+ store.delete(doneLoop.id);
630
+ };
631
+
632
+ const registered = monitorManager.onComplete(monitorId, deliver);
633
+ if (registered) return;
634
+
625
635
  const monitor = monitorManager.get(monitorId);
626
636
  if (monitor && monitor.status !== "running") {
637
+ if (monitor.status === "completed") {
638
+ deliver();
639
+ return;
640
+ }
627
641
  debug(`onDone loop #${doneLoop.id} — monitor #${monitorId} already ${monitor.status}, expiring`);
628
- triggerSystem.remove(doneLoop.id);
629
642
  store.delete(doneLoop.id);
630
643
  }
631
644
  }
@@ -35,6 +35,7 @@ export class MonitorManager {
35
35
  proc: child,
36
36
  abortController,
37
37
  waiters: [],
38
+ completionCallbacks: [],
38
39
  };
39
40
 
40
41
  child.stdout?.on("data", (data: Buffer) => {
@@ -74,6 +75,10 @@ export class MonitorManager {
74
75
  exitCode: code,
75
76
  outputLines: entry.outputLines,
76
77
  });
78
+ if (status === "completed") {
79
+ for (const callback of bp.completionCallbacks) callback();
80
+ }
81
+ bp.completionCallbacks = [];
77
82
  for (const resolve of bp.waiters) resolve();
78
83
  bp.waiters = [];
79
84
  // Remove completed/errored monitors after a brief delay so tool
@@ -95,6 +100,7 @@ export class MonitorManager {
95
100
  monitorId: id,
96
101
  error: err.message,
97
102
  });
103
+ bp.completionCallbacks = [];
98
104
  for (const resolve of bp.waiters) resolve();
99
105
  bp.waiters = [];
100
106
  }
@@ -143,11 +149,24 @@ export class MonitorManager {
143
149
  });
144
150
 
145
151
  bp.entry.completedAt = Date.now();
152
+ bp.completionCallbacks = [];
146
153
  for (const resolve of bp.waiters) resolve();
147
154
  bp.waiters = [];
148
155
  return true;
149
156
  }
150
157
 
158
+ onComplete(id: string, callback: () => void): boolean {
159
+ const bp = this.processes.get(id);
160
+ if (!bp) return false;
161
+ if (bp.entry.status === "completed") {
162
+ callback();
163
+ return true;
164
+ }
165
+ if (bp.entry.status !== "running") return false;
166
+ bp.completionCallbacks.push(callback);
167
+ return true;
168
+ }
169
+
151
170
  getProcess(id: string): MonitorProcess | undefined {
152
171
  return this.processes.get(id);
153
172
  }
package/src/types.ts CHANGED
@@ -60,4 +60,5 @@ export interface MonitorProcess {
60
60
  proc: import("node:child_process").ChildProcess;
61
61
  abortController: AbortController;
62
62
  waiters: Array<() => void>;
63
+ completionCallbacks: Array<() => void>;
63
64
  }