agentfootprint 6.13.0 → 6.14.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.
- package/CLAUDE.md +10 -0
- package/dist/core/RunnerBase.js +47 -2
- package/dist/core/RunnerBase.js.map +1 -1
- package/dist/esm/core/RunnerBase.js +47 -2
- package/dist/esm/core/RunnerBase.js.map +1 -1
- package/dist/esm/events/dispatcher.js +123 -17
- package/dist/esm/events/dispatcher.js.map +1 -1
- package/dist/events/dispatcher.js +123 -17
- package/dist/events/dispatcher.js.map +1 -1
- package/dist/types/core/RunnerBase.d.ts +43 -2
- package/dist/types/core/RunnerBase.d.ts.map +1 -1
- package/dist/types/core/runner.d.ts +31 -4
- package/dist/types/core/runner.d.ts.map +1 -1
- package/dist/types/events/dispatcher.d.ts +56 -3
- package/dist/types/events/dispatcher.d.ts.map +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -506,6 +506,16 @@ agent.on('agentfootprint.agent.turn_end', (e) =>
|
|
|
506
506
|
|
|
507
507
|
Wildcards: `.on('*', ...)` for every event, or `.on('agentfootprint.<domain>.*', ...)` per-domain (`agent`, `stream`, `context`, `tools`, `memory`, `cost`, `error`, …). `'agentfootprint.*'` is NOT a valid pattern — the dispatcher accepts `'*'` or `'agentfootprint.<DOMAIN>.*'` only. All events typed via `AgentfootprintEventMap`.
|
|
508
508
|
|
|
509
|
+
**Listener lifecycle (long-lived runners / servers):** subscriptions and attached recorders live for the RUNNER's lifetime — NOTHING auto-expires per-run; the caller owns cleanup. Three release paths for listeners:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
const unsub = agent.on('agentfootprint.agent.turn_end', fn); // 1. keep + call the Unsubscribe
|
|
513
|
+
agent.on('*', fn, { signal: requestController.signal }); // 2. AbortSignal — auto-unsubscribes on abort (also on .once())
|
|
514
|
+
agent.removeAllListeners(); // 3. bulk escape hatch (listeners ONLY — attach()ed recorders untouched)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
`agent.listenerCount()` is the leak diagnostic — no-arg = total retained; `listenerCount(key)` = that exact subscription bucket (wildcards not folded in; "would anything fire" is the dispatcher's `hasListenersFor`). Bounded-leak guarantee: every removal path (unsubscribe, `off()`, signal abort, once-fire, `removeAllListeners()`) prunes emptied buckets AND detaches the abort handler from the consumer's signal, so dispatcher storage is bounded by LIVE subscriptions — never subscription history. Per-run pattern on a reused server agent: subscribe with a per-request `AbortSignal`, abort after the run. Recorders via `attach()` follow rule 1 only — keep the returned Unsubscribe (`removeAllListeners()` does not detach them; `enable.*` strategy listeners DO get dropped by it, so re-enable afterwards if needed).
|
|
518
|
+
|
|
509
519
|
**"What the model saw" (debugging tool/skill selection):**
|
|
510
520
|
- `stream.llm_start.tools` — the tool CATALOG (`{ name, description }[]`) the model saw
|
|
511
521
|
for the call (its menu); `toolsCount` reflects the dynamic set actually sent.
|
package/dist/core/RunnerBase.js
CHANGED
|
@@ -290,10 +290,55 @@ class RunnerBase {
|
|
|
290
290
|
off(type, listener) {
|
|
291
291
|
this.dispatcher.off(type, listener);
|
|
292
292
|
}
|
|
293
|
-
once(type, listener) {
|
|
294
|
-
return this.dispatcher.once(type, listener);
|
|
293
|
+
once(type, listener, options) {
|
|
294
|
+
return this.dispatcher.once(type, listener, options);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Lifecycle escape hatch — drop EVERY event listener on this runner in
|
|
298
|
+
* one call (typed, domain-wildcard, and `'*'`). Delegates to
|
|
299
|
+
* `EventDispatcher.removeAllListeners()`.
|
|
300
|
+
*
|
|
301
|
+
* For long-lived runners on servers: when you can't thread an
|
|
302
|
+
* AbortSignal or keep every Unsubscribe handle, call this between
|
|
303
|
+
* requests to guarantee zero residual subscriptions. Note it also
|
|
304
|
+
* removes listeners wired by `enable.*` strategies — re-enable after
|
|
305
|
+
* calling if you still want them. Does NOT touch attached recorders
|
|
306
|
+
* (see `attach()` — recorders have their own Unsubscribe).
|
|
307
|
+
*/
|
|
308
|
+
removeAllListeners() {
|
|
309
|
+
this.dispatcher.removeAllListeners();
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Diagnostic — how many event listeners this runner currently retains.
|
|
313
|
+
* No argument = total across all buckets (the leak-detection number);
|
|
314
|
+
* with a subscription key = that bucket only. Delegates to
|
|
315
|
+
* `EventDispatcher.listenerCount()`.
|
|
316
|
+
*/
|
|
317
|
+
listenerCount(type) {
|
|
318
|
+
return this.dispatcher.listenerCount(type);
|
|
295
319
|
}
|
|
296
320
|
// ─── Recorder attach ───────────────────────────────────────────
|
|
321
|
+
/**
|
|
322
|
+
* Attach a footprintjs CombinedRecorder to observe every subsequent run.
|
|
323
|
+
*
|
|
324
|
+
* LIFECYCLE CONTRACT (who owns cleanup):
|
|
325
|
+
* - Attached recorders live for the RUNNER's lifetime, not a run's.
|
|
326
|
+
* NOTHING auto-expires per-run — a recorder attached once observes
|
|
327
|
+
* every later `run()` until you call the returned Unsubscribe.
|
|
328
|
+
* - The CALLER owns cleanup. Keep the Unsubscribe and call it when the
|
|
329
|
+
* observer's life ends (request scope, UI unmount, test teardown).
|
|
330
|
+
* - Event listeners (`on()` / `once()`) follow the same rule, with two
|
|
331
|
+
* extra outs: pass `{ signal }` for AbortSignal auto-cleanup, or call
|
|
332
|
+
* `removeAllListeners()` to bulk-drop listeners (listeners ONLY —
|
|
333
|
+
* recorders are not affected).
|
|
334
|
+
* - `once()` listeners are the only self-expiring subscription.
|
|
335
|
+
*
|
|
336
|
+
* attach() is NOT idempotent: every call pushes another entry. (At run
|
|
337
|
+
* time footprintjs's executor dedupes recorders by ID, so same-ID
|
|
338
|
+
* duplicates won't double-fire — but the runner-side array still
|
|
339
|
+
* grows.) Attaching in a per-run loop without detaching is the classic
|
|
340
|
+
* server leak; attach once, or detach per-run.
|
|
341
|
+
*/
|
|
297
342
|
attach(recorder) {
|
|
298
343
|
this.attachedRecorders.push(recorder);
|
|
299
344
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunnerBase.js","sourceRoot":"","sources":["../../src/core/RunnerBase.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AASH,2DAA0D;AAe1D,uDAIiC;AACjC,0FAIyD;AAGzD,IAAI,SAAS,GAAG,CAAC,CAAC;AAElB;;GAEG;AACH,SAAgB,SAAS;IACvB,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC5C,CAAC;AAFD,8BAEC;AAED,MAAsB,UAAU;IACX,UAAU,GAAG,IAAI,+BAAe,EAAE,CAAC;IACnC,iBAAiB,GAAuB,EAAE,CAAC;IAE9D;;;;;OAKG;IACO,YAAY,CAAgC;IAEtD;;;;;;;;;;;;;;;;;;;;OAoBG;IACK,KAAK,CAAwB;IAErC;;;;;;;;;;;;;OAaG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC1C,CAAC;IAED;;;;;;;;;;OAUG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC;IAChC,CAAC;IAED,kEAAkE;IAElE;;;;;;;;;;;;;;OAcG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,uJAAuJ,CAChL,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;;;;;;OAUG;IACK,YAAY,CAA0C;IAE9D;;;;;;;;;;;;;OAaG;IACH,UAAU;QACR,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,YAAY,CAAC,KAAsB,CAAC;QAClD,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC7C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YACzC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YACzC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,8DAA8D;QAC9D,kEAAkE;QAClE,qEAAqE;QACrE,qEAAqE;QACrE,6DAA6D;QAC7D,kEAAkE;QAClE,mEAAmE;QACnE,+CAA+C;QAC/C,IAAI,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAY,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,CAAC;QAC9B,OAAO,KAAU,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACO,kBAAkB;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAc,QAAmD;QAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC7C,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC7C,OAAO,QAAQ,CAAC,QAAQ,CAAM,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACO,oBAAoB;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACO,SAAS,CAAC,OAAwB;QAC1C,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,wFAAwF,CACjH,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC;IACzB,CAAC;IAoBD,mEAAmE;IAEnE;;;;;;;;OAQG;IACO,WAAW,CACnB,QAA2B,EAC3B,MAAe;QAEf,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAAE,OAAO,SAAS,CAAC;QAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC5C,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAE/C,MAAM,SAAS,GACb,UAAU,CAAC,SAAS,KAAK,SAAS;YAChC,CAAC,CAAC,UAAU,CAAC,SAAS;YACtB,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,QAAQ,IAAI,MAAM;gBACrE,CAAC,CAAE,MAAkC,CAAC,SAAS;gBAC/C,CAAC,CAAC,SAAS,CAAC;QAEhB,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAE7C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IACjD,CAAC;IAED;;;OAGG;IACK,gBAAgB,CAAC,UAA+B,EAAE,SAAkB;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,cAAc,GAClB,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI,IAAI,QAAQ,IAAI,SAAS;YAC1E,CAAC,CAAC,MAAM,CAAE,SAAiC,CAAC,MAAM,CAAC;YACnD,CAAC,CAAC,uBAAuB,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YACvB,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE;gBACP,MAAM,EAAE,cAAc;gBACtB,eAAe,EACb,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI;oBACjD,CAAC,CAAE,SAA+C;oBAClD,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;aAC1B;YACD,IAAI,EAAE;gBACJ,GAAG,IAAI;gBACP,cAAc,EAAE,GAAG,UAAU,CAAC,aAAa,SAAS;gBACpD,WAAW,EAAE,UAAU,CAAC,WAAW;aACpC;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACO,eAAe,CAAC,UAA+B,EAAE,KAAc;QACvE,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC;QAC1D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YACvB,IAAI,EAAE,6BAA6B;YACnC,OAAO,EAAE;gBACP,WAAW,EACT,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;oBACzC,CAAC,CAAE,KAA2C;oBAC9C,CAAC,CAAC,EAAE,KAAK,EAAE;gBACf,gBAAgB;aACjB;YACD,IAAI,EAAE;gBACJ,GAAG,IAAI;gBACP,cAAc,EAAE,GAAG,UAAU,CAAC,aAAa,UAAU;gBACrD,WAAW,EAAE,UAAU,CAAC,WAAW;aACpC;SACF,CAAC,CAAC;IACL,CAAC;IAUD,EAAE,CACA,IAAY,EACZ,QAA8C,EAC9C,OAAuB;QAEvB,sEAAsE;QACtE,kEAAkE;QAClE,qEAAqE;QACrE,OACE,IAAI,CAAC,UAAU,CAAC,EAKjB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7B,CAAC;IAID,GAAG,CAAC,IAAY,EAAE,QAA8C;QAE5D,IAAI,CAAC,UAAU,CAAC,GAIjB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"RunnerBase.js","sourceRoot":"","sources":["../../src/core/RunnerBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -286,10 +286,55 @@ export class RunnerBase {
|
|
|
286
286
|
off(type, listener) {
|
|
287
287
|
this.dispatcher.off(type, listener);
|
|
288
288
|
}
|
|
289
|
-
once(type, listener) {
|
|
290
|
-
return this.dispatcher.once(type, listener);
|
|
289
|
+
once(type, listener, options) {
|
|
290
|
+
return this.dispatcher.once(type, listener, options);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Lifecycle escape hatch — drop EVERY event listener on this runner in
|
|
294
|
+
* one call (typed, domain-wildcard, and `'*'`). Delegates to
|
|
295
|
+
* `EventDispatcher.removeAllListeners()`.
|
|
296
|
+
*
|
|
297
|
+
* For long-lived runners on servers: when you can't thread an
|
|
298
|
+
* AbortSignal or keep every Unsubscribe handle, call this between
|
|
299
|
+
* requests to guarantee zero residual subscriptions. Note it also
|
|
300
|
+
* removes listeners wired by `enable.*` strategies — re-enable after
|
|
301
|
+
* calling if you still want them. Does NOT touch attached recorders
|
|
302
|
+
* (see `attach()` — recorders have their own Unsubscribe).
|
|
303
|
+
*/
|
|
304
|
+
removeAllListeners() {
|
|
305
|
+
this.dispatcher.removeAllListeners();
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Diagnostic — how many event listeners this runner currently retains.
|
|
309
|
+
* No argument = total across all buckets (the leak-detection number);
|
|
310
|
+
* with a subscription key = that bucket only. Delegates to
|
|
311
|
+
* `EventDispatcher.listenerCount()`.
|
|
312
|
+
*/
|
|
313
|
+
listenerCount(type) {
|
|
314
|
+
return this.dispatcher.listenerCount(type);
|
|
291
315
|
}
|
|
292
316
|
// ─── Recorder attach ───────────────────────────────────────────
|
|
317
|
+
/**
|
|
318
|
+
* Attach a footprintjs CombinedRecorder to observe every subsequent run.
|
|
319
|
+
*
|
|
320
|
+
* LIFECYCLE CONTRACT (who owns cleanup):
|
|
321
|
+
* - Attached recorders live for the RUNNER's lifetime, not a run's.
|
|
322
|
+
* NOTHING auto-expires per-run — a recorder attached once observes
|
|
323
|
+
* every later `run()` until you call the returned Unsubscribe.
|
|
324
|
+
* - The CALLER owns cleanup. Keep the Unsubscribe and call it when the
|
|
325
|
+
* observer's life ends (request scope, UI unmount, test teardown).
|
|
326
|
+
* - Event listeners (`on()` / `once()`) follow the same rule, with two
|
|
327
|
+
* extra outs: pass `{ signal }` for AbortSignal auto-cleanup, or call
|
|
328
|
+
* `removeAllListeners()` to bulk-drop listeners (listeners ONLY —
|
|
329
|
+
* recorders are not affected).
|
|
330
|
+
* - `once()` listeners are the only self-expiring subscription.
|
|
331
|
+
*
|
|
332
|
+
* attach() is NOT idempotent: every call pushes another entry. (At run
|
|
333
|
+
* time footprintjs's executor dedupes recorders by ID, so same-ID
|
|
334
|
+
* duplicates won't double-fire — but the runner-side array still
|
|
335
|
+
* grows.) Attaching in a per-run loop without detaching is the classic
|
|
336
|
+
* server leak; attach once, or detach per-run.
|
|
337
|
+
*/
|
|
293
338
|
attach(recorder) {
|
|
294
339
|
this.attachedRecorders.push(recorder);
|
|
295
340
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunnerBase.js","sourceRoot":"","sources":["../../../src/core/RunnerBase.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"RunnerBase.js","sourceRoot":"","sources":["../../../src/core/RunnerBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,11 +15,26 @@
|
|
|
15
15
|
* - Dispatch is O(1) hash lookup by event type.
|
|
16
16
|
* - Zero allocation when no listener for an event type AND no wildcard.
|
|
17
17
|
* - Dev-mode wraps listeners to warn on async listener Promise return.
|
|
18
|
+
* - Lifecycle: subscriptions release via the returned Unsubscribe or an
|
|
19
|
+
* AbortSignal (`{ signal }`); `removeAllListeners()` is the bulk
|
|
20
|
+
* escape hatch for long-lived server consumers; `listenerCount()` is
|
|
21
|
+
* the leak diagnostic. Every removal path prunes emptied buckets and
|
|
22
|
+
* detaches abort handlers, so listener storage is bounded by LIVE
|
|
23
|
+
* subscriptions — never by subscription history.
|
|
18
24
|
*/
|
|
19
25
|
import { isDevMode } from 'footprintjs';
|
|
20
26
|
/** Shared no-op returned when subscribing to an already-aborted signal —
|
|
21
27
|
* the listener was never registered, so unsubscribe has nothing to do. */
|
|
22
28
|
const noopUnsubscribe = () => undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Empty a bucket, detaching each subscription's abort handler from its
|
|
31
|
+
* AbortSignal first. Used by removeAllListeners().
|
|
32
|
+
*/
|
|
33
|
+
function drainBucket(bucket) {
|
|
34
|
+
for (const stored of bucket)
|
|
35
|
+
stored.cleanup?.();
|
|
36
|
+
bucket.clear();
|
|
37
|
+
}
|
|
23
38
|
// ─── Dispatcher ──────────────────────────────────────────────────────
|
|
24
39
|
/**
|
|
25
40
|
* Central event bus. One per executable runner.
|
|
@@ -47,7 +62,19 @@ export class EventDispatcher {
|
|
|
47
62
|
return domain ? domain.size > 0 : false;
|
|
48
63
|
}
|
|
49
64
|
on(type, listener, options) {
|
|
50
|
-
|
|
65
|
+
return this.subscribe(type, listener, options);
|
|
66
|
+
}
|
|
67
|
+
once(type, listener, options) {
|
|
68
|
+
return this.subscribe(type, listener, { ...options, once: true });
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Shared subscribe path for on()/once(). The public overloads constrain
|
|
72
|
+
* `type` to either typed keys or wildcards; internally the dispatcher's
|
|
73
|
+
* bucket logic accepts any string and classifies by shape.
|
|
74
|
+
*/
|
|
75
|
+
subscribe(type, listener, options) {
|
|
76
|
+
const signal = options?.signal;
|
|
77
|
+
if (signal?.aborted) {
|
|
51
78
|
// Already aborted; register nothing — return a no-op unsubscribe.
|
|
52
79
|
return noopUnsubscribe;
|
|
53
80
|
}
|
|
@@ -55,18 +82,24 @@ export class EventDispatcher {
|
|
|
55
82
|
fn: wrapForDev(listener, type),
|
|
56
83
|
once: options?.once === true,
|
|
57
84
|
};
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
85
|
+
const remove = this.addListener(type, wrapped);
|
|
86
|
+
if (!signal)
|
|
87
|
+
return remove;
|
|
88
|
+
// DOM-parity AbortSignal wiring: abort → unsubscribe, AND every other
|
|
89
|
+
// removal path (manual unsubscribe, off(), once-auto-removal,
|
|
90
|
+
// removeAllListeners()) → detach the abort handler from the signal,
|
|
91
|
+
// so a long-lived, never-aborted signal doesn't accumulate handlers.
|
|
92
|
+
const onAbort = () => {
|
|
93
|
+
remove();
|
|
94
|
+
};
|
|
95
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
96
|
+
wrapped.cleanup = () => {
|
|
97
|
+
signal.removeEventListener('abort', onAbort);
|
|
98
|
+
};
|
|
99
|
+
return () => {
|
|
100
|
+
wrapped.cleanup?.();
|
|
101
|
+
remove();
|
|
102
|
+
};
|
|
70
103
|
}
|
|
71
104
|
off(type, listener) {
|
|
72
105
|
const bucket = this.bucketFor(type);
|
|
@@ -77,10 +110,48 @@ export class EventDispatcher {
|
|
|
77
110
|
const storedOriginal = originalsMap.get(stored.fn) ?? stored.fn;
|
|
78
111
|
if (storedOriginal === originalFn) {
|
|
79
112
|
bucket.delete(stored);
|
|
113
|
+
stored.cleanup?.();
|
|
114
|
+
this.pruneBucket(type, bucket);
|
|
80
115
|
return;
|
|
81
116
|
}
|
|
82
117
|
}
|
|
83
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Lifecycle escape hatch — drop EVERY listener (typed, domain-wildcard,
|
|
121
|
+
* and `'*'`) in one call. For long-lived server consumers that reuse one
|
|
122
|
+
* runner across many requests: when you can't thread an AbortSignal or
|
|
123
|
+
* keep every Unsubscribe handle, call this between requests to guarantee
|
|
124
|
+
* the dispatcher holds zero subscriptions.
|
|
125
|
+
*
|
|
126
|
+
* Safe to call mid-dispatch: the bucket currently being iterated
|
|
127
|
+
* finishes its already-taken snapshot (same semantics as `off()` during
|
|
128
|
+
* dispatch), buckets the in-flight dispatch has NOT yet reached deliver
|
|
129
|
+
* nothing (DOM-like "stop now"), and every SUBSEQUENT event sees no
|
|
130
|
+
* listeners. Abort handlers registered on consumer AbortSignals via
|
|
131
|
+
* `{ signal }` are detached too. Previously returned Unsubscribe
|
|
132
|
+
* handles become harmless no-ops.
|
|
133
|
+
*/
|
|
134
|
+
removeAllListeners() {
|
|
135
|
+
for (const bucket of this.byType.values())
|
|
136
|
+
drainBucket(bucket);
|
|
137
|
+
this.byType.clear();
|
|
138
|
+
for (const bucket of this.domainWildcards.values())
|
|
139
|
+
drainBucket(bucket);
|
|
140
|
+
this.domainWildcards.clear();
|
|
141
|
+
drainBucket(this.allWildcards);
|
|
142
|
+
}
|
|
143
|
+
listenerCount(type) {
|
|
144
|
+
if (type !== undefined) {
|
|
145
|
+
const bucket = this.bucketFor(type);
|
|
146
|
+
return bucket ? bucket.size : 0;
|
|
147
|
+
}
|
|
148
|
+
let total = this.allWildcards.size;
|
|
149
|
+
for (const bucket of this.byType.values())
|
|
150
|
+
total += bucket.size;
|
|
151
|
+
for (const bucket of this.domainWildcards.values())
|
|
152
|
+
total += bucket.size;
|
|
153
|
+
return total;
|
|
154
|
+
}
|
|
84
155
|
// ─── Dispatch ─────────────────────────────────────────────────────
|
|
85
156
|
/**
|
|
86
157
|
* Route an event to all matching listeners (typed + domain-wildcard + all).
|
|
@@ -90,8 +161,17 @@ export class EventDispatcher {
|
|
|
90
161
|
* The run continues regardless.
|
|
91
162
|
*/
|
|
92
163
|
dispatch(event) {
|
|
93
|
-
this.
|
|
94
|
-
this.
|
|
164
|
+
const typed = this.byType.get(event.type);
|
|
165
|
+
const domainKey = this.domainKey(event.type);
|
|
166
|
+
const domain = this.domainWildcards.get(domainKey);
|
|
167
|
+
this.fireBucket(typed, event);
|
|
168
|
+
// Prune only when once-listeners actually emptied the bucket — keeps the
|
|
169
|
+
// hot path free of per-event work (incl. the `${domainKey}.*` string build).
|
|
170
|
+
if (typed && typed.size === 0)
|
|
171
|
+
this.pruneBucket(event.type, typed);
|
|
172
|
+
this.fireBucket(domain, event);
|
|
173
|
+
if (domain && domain.size === 0)
|
|
174
|
+
this.pruneBucket(`${domainKey}.*`, domain);
|
|
95
175
|
this.fireBucket(this.allWildcards, event);
|
|
96
176
|
}
|
|
97
177
|
// ─── Internals ────────────────────────────────────────────────────
|
|
@@ -100,8 +180,30 @@ export class EventDispatcher {
|
|
|
100
180
|
bucket.add(stored);
|
|
101
181
|
return () => {
|
|
102
182
|
bucket.delete(stored);
|
|
183
|
+
this.pruneBucket(type, bucket);
|
|
103
184
|
};
|
|
104
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Bounded-leak guarantee: a bucket emptied by ANY removal path is
|
|
188
|
+
* deleted from its Map so `byType` / `domainWildcards` never retain
|
|
189
|
+
* empty Sets for event types subscribed once and released. The
|
|
190
|
+
* identity check (`get(...) === bucket`) guards stale Unsubscribe
|
|
191
|
+
* closures — they must never delete a NEWER bucket re-created under
|
|
192
|
+
* the same key after this one was pruned. (`allWildcards` is a stable
|
|
193
|
+
* field, not a Map entry — nothing to prune.)
|
|
194
|
+
*/
|
|
195
|
+
pruneBucket(type, bucket) {
|
|
196
|
+
if (bucket.size > 0 || type === '*')
|
|
197
|
+
return;
|
|
198
|
+
if (type.endsWith('.*')) {
|
|
199
|
+
const key = type.slice(0, -2);
|
|
200
|
+
if (this.domainWildcards.get(key) === bucket)
|
|
201
|
+
this.domainWildcards.delete(key);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (this.byType.get(type) === bucket)
|
|
205
|
+
this.byType.delete(type);
|
|
206
|
+
}
|
|
105
207
|
ensureBucket(type) {
|
|
106
208
|
if (type === '*')
|
|
107
209
|
return this.allWildcards;
|
|
@@ -131,11 +233,15 @@ export class EventDispatcher {
|
|
|
131
233
|
fireBucket(bucket, event) {
|
|
132
234
|
if (!bucket || bucket.size === 0)
|
|
133
235
|
return;
|
|
134
|
-
// Snapshot to allow
|
|
236
|
+
// Snapshot to allow removal during iteration (once-listeners, off(),
|
|
237
|
+
// removeAllListeners()). Removal mid-dispatch takes effect for
|
|
238
|
+
// SUBSEQUENT events; the in-flight snapshot completes delivery.
|
|
135
239
|
const snapshot = [...bucket];
|
|
136
240
|
for (const stored of snapshot) {
|
|
137
|
-
if (stored.once)
|
|
241
|
+
if (stored.once) {
|
|
138
242
|
bucket.delete(stored);
|
|
243
|
+
stored.cleanup?.(); // detach abort handler from the consumer's signal
|
|
244
|
+
}
|
|
139
245
|
try {
|
|
140
246
|
stored.fn(event);
|
|
141
247
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../../src/events/dispatcher.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../../src/events/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* - Dispatch is O(1) hash lookup by event type.
|
|
17
17
|
* - Zero allocation when no listener for an event type AND no wildcard.
|
|
18
18
|
* - Dev-mode wraps listeners to warn on async listener Promise return.
|
|
19
|
+
* - Lifecycle: subscriptions release via the returned Unsubscribe or an
|
|
20
|
+
* AbortSignal (`{ signal }`); `removeAllListeners()` is the bulk
|
|
21
|
+
* escape hatch for long-lived server consumers; `listenerCount()` is
|
|
22
|
+
* the leak diagnostic. Every removal path prunes emptied buckets and
|
|
23
|
+
* detaches abort handlers, so listener storage is bounded by LIVE
|
|
24
|
+
* subscriptions — never by subscription history.
|
|
19
25
|
*/
|
|
20
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
27
|
exports.EventDispatcher = void 0;
|
|
@@ -23,6 +29,15 @@ const footprintjs_1 = require("footprintjs");
|
|
|
23
29
|
/** Shared no-op returned when subscribing to an already-aborted signal —
|
|
24
30
|
* the listener was never registered, so unsubscribe has nothing to do. */
|
|
25
31
|
const noopUnsubscribe = () => undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Empty a bucket, detaching each subscription's abort handler from its
|
|
34
|
+
* AbortSignal first. Used by removeAllListeners().
|
|
35
|
+
*/
|
|
36
|
+
function drainBucket(bucket) {
|
|
37
|
+
for (const stored of bucket)
|
|
38
|
+
stored.cleanup?.();
|
|
39
|
+
bucket.clear();
|
|
40
|
+
}
|
|
26
41
|
// ─── Dispatcher ──────────────────────────────────────────────────────
|
|
27
42
|
/**
|
|
28
43
|
* Central event bus. One per executable runner.
|
|
@@ -50,7 +65,19 @@ class EventDispatcher {
|
|
|
50
65
|
return domain ? domain.size > 0 : false;
|
|
51
66
|
}
|
|
52
67
|
on(type, listener, options) {
|
|
53
|
-
|
|
68
|
+
return this.subscribe(type, listener, options);
|
|
69
|
+
}
|
|
70
|
+
once(type, listener, options) {
|
|
71
|
+
return this.subscribe(type, listener, { ...options, once: true });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Shared subscribe path for on()/once(). The public overloads constrain
|
|
75
|
+
* `type` to either typed keys or wildcards; internally the dispatcher's
|
|
76
|
+
* bucket logic accepts any string and classifies by shape.
|
|
77
|
+
*/
|
|
78
|
+
subscribe(type, listener, options) {
|
|
79
|
+
const signal = options?.signal;
|
|
80
|
+
if (signal?.aborted) {
|
|
54
81
|
// Already aborted; register nothing — return a no-op unsubscribe.
|
|
55
82
|
return noopUnsubscribe;
|
|
56
83
|
}
|
|
@@ -58,18 +85,24 @@ class EventDispatcher {
|
|
|
58
85
|
fn: wrapForDev(listener, type),
|
|
59
86
|
once: options?.once === true,
|
|
60
87
|
};
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
const remove = this.addListener(type, wrapped);
|
|
89
|
+
if (!signal)
|
|
90
|
+
return remove;
|
|
91
|
+
// DOM-parity AbortSignal wiring: abort → unsubscribe, AND every other
|
|
92
|
+
// removal path (manual unsubscribe, off(), once-auto-removal,
|
|
93
|
+
// removeAllListeners()) → detach the abort handler from the signal,
|
|
94
|
+
// so a long-lived, never-aborted signal doesn't accumulate handlers.
|
|
95
|
+
const onAbort = () => {
|
|
96
|
+
remove();
|
|
97
|
+
};
|
|
98
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
99
|
+
wrapped.cleanup = () => {
|
|
100
|
+
signal.removeEventListener('abort', onAbort);
|
|
101
|
+
};
|
|
102
|
+
return () => {
|
|
103
|
+
wrapped.cleanup?.();
|
|
104
|
+
remove();
|
|
105
|
+
};
|
|
73
106
|
}
|
|
74
107
|
off(type, listener) {
|
|
75
108
|
const bucket = this.bucketFor(type);
|
|
@@ -80,10 +113,48 @@ class EventDispatcher {
|
|
|
80
113
|
const storedOriginal = originalsMap.get(stored.fn) ?? stored.fn;
|
|
81
114
|
if (storedOriginal === originalFn) {
|
|
82
115
|
bucket.delete(stored);
|
|
116
|
+
stored.cleanup?.();
|
|
117
|
+
this.pruneBucket(type, bucket);
|
|
83
118
|
return;
|
|
84
119
|
}
|
|
85
120
|
}
|
|
86
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Lifecycle escape hatch — drop EVERY listener (typed, domain-wildcard,
|
|
124
|
+
* and `'*'`) in one call. For long-lived server consumers that reuse one
|
|
125
|
+
* runner across many requests: when you can't thread an AbortSignal or
|
|
126
|
+
* keep every Unsubscribe handle, call this between requests to guarantee
|
|
127
|
+
* the dispatcher holds zero subscriptions.
|
|
128
|
+
*
|
|
129
|
+
* Safe to call mid-dispatch: the bucket currently being iterated
|
|
130
|
+
* finishes its already-taken snapshot (same semantics as `off()` during
|
|
131
|
+
* dispatch), buckets the in-flight dispatch has NOT yet reached deliver
|
|
132
|
+
* nothing (DOM-like "stop now"), and every SUBSEQUENT event sees no
|
|
133
|
+
* listeners. Abort handlers registered on consumer AbortSignals via
|
|
134
|
+
* `{ signal }` are detached too. Previously returned Unsubscribe
|
|
135
|
+
* handles become harmless no-ops.
|
|
136
|
+
*/
|
|
137
|
+
removeAllListeners() {
|
|
138
|
+
for (const bucket of this.byType.values())
|
|
139
|
+
drainBucket(bucket);
|
|
140
|
+
this.byType.clear();
|
|
141
|
+
for (const bucket of this.domainWildcards.values())
|
|
142
|
+
drainBucket(bucket);
|
|
143
|
+
this.domainWildcards.clear();
|
|
144
|
+
drainBucket(this.allWildcards);
|
|
145
|
+
}
|
|
146
|
+
listenerCount(type) {
|
|
147
|
+
if (type !== undefined) {
|
|
148
|
+
const bucket = this.bucketFor(type);
|
|
149
|
+
return bucket ? bucket.size : 0;
|
|
150
|
+
}
|
|
151
|
+
let total = this.allWildcards.size;
|
|
152
|
+
for (const bucket of this.byType.values())
|
|
153
|
+
total += bucket.size;
|
|
154
|
+
for (const bucket of this.domainWildcards.values())
|
|
155
|
+
total += bucket.size;
|
|
156
|
+
return total;
|
|
157
|
+
}
|
|
87
158
|
// ─── Dispatch ─────────────────────────────────────────────────────
|
|
88
159
|
/**
|
|
89
160
|
* Route an event to all matching listeners (typed + domain-wildcard + all).
|
|
@@ -93,8 +164,17 @@ class EventDispatcher {
|
|
|
93
164
|
* The run continues regardless.
|
|
94
165
|
*/
|
|
95
166
|
dispatch(event) {
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
167
|
+
const typed = this.byType.get(event.type);
|
|
168
|
+
const domainKey = this.domainKey(event.type);
|
|
169
|
+
const domain = this.domainWildcards.get(domainKey);
|
|
170
|
+
this.fireBucket(typed, event);
|
|
171
|
+
// Prune only when once-listeners actually emptied the bucket — keeps the
|
|
172
|
+
// hot path free of per-event work (incl. the `${domainKey}.*` string build).
|
|
173
|
+
if (typed && typed.size === 0)
|
|
174
|
+
this.pruneBucket(event.type, typed);
|
|
175
|
+
this.fireBucket(domain, event);
|
|
176
|
+
if (domain && domain.size === 0)
|
|
177
|
+
this.pruneBucket(`${domainKey}.*`, domain);
|
|
98
178
|
this.fireBucket(this.allWildcards, event);
|
|
99
179
|
}
|
|
100
180
|
// ─── Internals ────────────────────────────────────────────────────
|
|
@@ -103,8 +183,30 @@ class EventDispatcher {
|
|
|
103
183
|
bucket.add(stored);
|
|
104
184
|
return () => {
|
|
105
185
|
bucket.delete(stored);
|
|
186
|
+
this.pruneBucket(type, bucket);
|
|
106
187
|
};
|
|
107
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Bounded-leak guarantee: a bucket emptied by ANY removal path is
|
|
191
|
+
* deleted from its Map so `byType` / `domainWildcards` never retain
|
|
192
|
+
* empty Sets for event types subscribed once and released. The
|
|
193
|
+
* identity check (`get(...) === bucket`) guards stale Unsubscribe
|
|
194
|
+
* closures — they must never delete a NEWER bucket re-created under
|
|
195
|
+
* the same key after this one was pruned. (`allWildcards` is a stable
|
|
196
|
+
* field, not a Map entry — nothing to prune.)
|
|
197
|
+
*/
|
|
198
|
+
pruneBucket(type, bucket) {
|
|
199
|
+
if (bucket.size > 0 || type === '*')
|
|
200
|
+
return;
|
|
201
|
+
if (type.endsWith('.*')) {
|
|
202
|
+
const key = type.slice(0, -2);
|
|
203
|
+
if (this.domainWildcards.get(key) === bucket)
|
|
204
|
+
this.domainWildcards.delete(key);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (this.byType.get(type) === bucket)
|
|
208
|
+
this.byType.delete(type);
|
|
209
|
+
}
|
|
108
210
|
ensureBucket(type) {
|
|
109
211
|
if (type === '*')
|
|
110
212
|
return this.allWildcards;
|
|
@@ -134,11 +236,15 @@ class EventDispatcher {
|
|
|
134
236
|
fireBucket(bucket, event) {
|
|
135
237
|
if (!bucket || bucket.size === 0)
|
|
136
238
|
return;
|
|
137
|
-
// Snapshot to allow
|
|
239
|
+
// Snapshot to allow removal during iteration (once-listeners, off(),
|
|
240
|
+
// removeAllListeners()). Removal mid-dispatch takes effect for
|
|
241
|
+
// SUBSEQUENT events; the in-flight snapshot completes delivery.
|
|
138
242
|
const snapshot = [...bucket];
|
|
139
243
|
for (const stored of snapshot) {
|
|
140
|
-
if (stored.once)
|
|
244
|
+
if (stored.once) {
|
|
141
245
|
bucket.delete(stored);
|
|
246
|
+
stored.cleanup?.(); // detach abort handler from the consumer's signal
|
|
247
|
+
}
|
|
142
248
|
try {
|
|
143
249
|
stored.fn(event);
|
|
144
250
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/events/dispatcher.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/events/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -194,8 +194,49 @@ export declare abstract class RunnerBase<TIn = unknown, TOut = unknown> implemen
|
|
|
194
194
|
on(type: WildcardSubscription, listener: WildcardListener, options?: ListenOptions): Unsubscribe;
|
|
195
195
|
off<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>): void;
|
|
196
196
|
off(type: WildcardSubscription, listener: WildcardListener): void;
|
|
197
|
-
once<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>): Unsubscribe;
|
|
198
|
-
once(type: WildcardSubscription, listener: WildcardListener): Unsubscribe;
|
|
197
|
+
once<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>, options?: Omit<ListenOptions, 'once'>): Unsubscribe;
|
|
198
|
+
once(type: WildcardSubscription, listener: WildcardListener, options?: Omit<ListenOptions, 'once'>): Unsubscribe;
|
|
199
|
+
/**
|
|
200
|
+
* Lifecycle escape hatch — drop EVERY event listener on this runner in
|
|
201
|
+
* one call (typed, domain-wildcard, and `'*'`). Delegates to
|
|
202
|
+
* `EventDispatcher.removeAllListeners()`.
|
|
203
|
+
*
|
|
204
|
+
* For long-lived runners on servers: when you can't thread an
|
|
205
|
+
* AbortSignal or keep every Unsubscribe handle, call this between
|
|
206
|
+
* requests to guarantee zero residual subscriptions. Note it also
|
|
207
|
+
* removes listeners wired by `enable.*` strategies — re-enable after
|
|
208
|
+
* calling if you still want them. Does NOT touch attached recorders
|
|
209
|
+
* (see `attach()` — recorders have their own Unsubscribe).
|
|
210
|
+
*/
|
|
211
|
+
removeAllListeners(): void;
|
|
212
|
+
/**
|
|
213
|
+
* Diagnostic — how many event listeners this runner currently retains.
|
|
214
|
+
* No argument = total across all buckets (the leak-detection number);
|
|
215
|
+
* with a subscription key = that bucket only. Delegates to
|
|
216
|
+
* `EventDispatcher.listenerCount()`.
|
|
217
|
+
*/
|
|
218
|
+
listenerCount(type?: AgentfootprintEventType | WildcardSubscription): number;
|
|
219
|
+
/**
|
|
220
|
+
* Attach a footprintjs CombinedRecorder to observe every subsequent run.
|
|
221
|
+
*
|
|
222
|
+
* LIFECYCLE CONTRACT (who owns cleanup):
|
|
223
|
+
* - Attached recorders live for the RUNNER's lifetime, not a run's.
|
|
224
|
+
* NOTHING auto-expires per-run — a recorder attached once observes
|
|
225
|
+
* every later `run()` until you call the returned Unsubscribe.
|
|
226
|
+
* - The CALLER owns cleanup. Keep the Unsubscribe and call it when the
|
|
227
|
+
* observer's life ends (request scope, UI unmount, test teardown).
|
|
228
|
+
* - Event listeners (`on()` / `once()`) follow the same rule, with two
|
|
229
|
+
* extra outs: pass `{ signal }` for AbortSignal auto-cleanup, or call
|
|
230
|
+
* `removeAllListeners()` to bulk-drop listeners (listeners ONLY —
|
|
231
|
+
* recorders are not affected).
|
|
232
|
+
* - `once()` listeners are the only self-expiring subscription.
|
|
233
|
+
*
|
|
234
|
+
* attach() is NOT idempotent: every call pushes another entry. (At run
|
|
235
|
+
* time footprintjs's executor dedupes recorders by ID, so same-ID
|
|
236
|
+
* duplicates won't double-fire — but the runner-side array still
|
|
237
|
+
* grows.) Attaching in a per-run loop without detaching is the classic
|
|
238
|
+
* server leak; attach once, or detach per-run.
|
|
239
|
+
*/
|
|
199
240
|
attach(recorder: CombinedRecorder): Unsubscribe;
|
|
200
241
|
readonly enable: EnableNamespace;
|
|
201
242
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunnerBase.d.ts","sourceRoot":"","sources":["../../../src/core/RunnerBase.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"RunnerBase.d.ts","sourceRoot":"","sources":["../../../src/core/RunnerBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -121,20 +121,47 @@ export interface Runner<TIn = unknown, TOut = unknown> {
|
|
|
121
121
|
* pauses again (e.g., a multi-step approval flow).
|
|
122
122
|
*/
|
|
123
123
|
resume(checkpoint: FlowchartCheckpoint, input?: unknown, options?: RunOptions): Promise<TOut | RunnerPauseOutcome>;
|
|
124
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* Subscribe a typed listener. Returns unsubscribe.
|
|
126
|
+
*
|
|
127
|
+
* Lifecycle: the subscription lives until you call the returned
|
|
128
|
+
* Unsubscribe, the `{ signal }` you passed aborts, or
|
|
129
|
+
* `removeAllListeners()` runs. Nothing auto-expires per-run — pass a
|
|
130
|
+
* per-run AbortSignal for request-scoped listeners on long-lived
|
|
131
|
+
* runners (servers).
|
|
132
|
+
*/
|
|
125
133
|
on<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>, options?: ListenOptions): Unsubscribe;
|
|
126
134
|
/** Subscribe to a domain wildcard (e.g. 'agentfootprint.context.*') or '*'. */
|
|
127
135
|
on(type: WildcardSubscription, listener: WildcardListener, options?: ListenOptions): Unsubscribe;
|
|
128
136
|
/** Unsubscribe a previously-registered listener. */
|
|
129
137
|
off<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>): void;
|
|
130
138
|
off(type: WildcardSubscription, listener: WildcardListener): void;
|
|
131
|
-
/** Subscribe a one-shot listener (fires once then auto-removes). */
|
|
132
|
-
once<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>): Unsubscribe;
|
|
133
|
-
once(type: WildcardSubscription, listener: WildcardListener): Unsubscribe;
|
|
139
|
+
/** Subscribe a one-shot listener (fires once then auto-removes). Accepts `{ signal }`. */
|
|
140
|
+
once<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>, options?: Omit<ListenOptions, 'once'>): Unsubscribe;
|
|
141
|
+
once(type: WildcardSubscription, listener: WildcardListener, options?: Omit<ListenOptions, 'once'>): Unsubscribe;
|
|
142
|
+
/**
|
|
143
|
+
* Drop every event listener on this runner in one call (typed,
|
|
144
|
+
* domain-wildcard, and `'*'`). Lifecycle escape hatch for server
|
|
145
|
+
* consumers that can't keep Unsubscribe handles. Also removes
|
|
146
|
+
* listeners wired by `enable.*` strategies; does NOT detach recorders
|
|
147
|
+
* added via `attach()`.
|
|
148
|
+
*/
|
|
149
|
+
removeAllListeners(): void;
|
|
150
|
+
/**
|
|
151
|
+
* Diagnostic — listeners currently retained. No argument = total
|
|
152
|
+
* (the leak-detection number); with a subscription key = that exact
|
|
153
|
+
* bucket only (wildcards not folded in — use the dispatcher's
|
|
154
|
+
* `hasListenersFor` semantics for "would anything fire").
|
|
155
|
+
*/
|
|
156
|
+
listenerCount(type?: AgentfootprintEventType | WildcardSubscription): number;
|
|
134
157
|
/**
|
|
135
158
|
* Attach a footprintjs CombinedRecorder to observe the execution.
|
|
136
159
|
* Returns an unsubscribe function — call it to detach the recorder
|
|
137
160
|
* from future runs. (Already-running executions continue using it.)
|
|
161
|
+
*
|
|
162
|
+
* Recorders live for the RUNNER's lifetime: nothing auto-expires
|
|
163
|
+
* per-run, and `removeAllListeners()` does not touch them. The caller
|
|
164
|
+
* owns cleanup via the returned Unsubscribe.
|
|
138
165
|
*/
|
|
139
166
|
attach(recorder: CombinedRecorder): Unsubscribe;
|
|
140
167
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/core/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,iDAAiD,CAAC;AACzD,OAAO,KAAK,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,EACxB,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,SAAS,CAAC,IAAI,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAAC;IACpD;;;;;OAKG;IACH,aAAa,CAAC,IAAI,CAAC,EAAE,0BAA0B,GAAG,WAAW,CAAC;IAC9D;;;;OAIG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAAC;IAC5C;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,uBAAuB,GAAG,WAAW,CAAC;CACxD;AAED;;;;;GAKG;AACH,MAAM,WAAW,MAAM,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,GAAG,OAAO;IACnD;;;;;;;;;;;OAWG;IACH,OAAO,IAAI,SAAS,CAAC;IAErB;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,SAAS,CAAC;IAEzC;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,iBAAiB,EAAE,eAAe,GAAG,CAAC,GAAG,SAAS,CAAC;IAEhG;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,GAAG,kBAAkB,CAAC,CAAC;IAE1E;;;;;OAKG;IACH,MAAM,CACJ,UAAU,EAAE,mBAAmB,EAC/B,KAAK,CAAC,EAAE,OAAO,EACf,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,GAAG,kBAAkB,CAAC,CAAC;IAEtC
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/core/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
* - Dispatch is O(1) hash lookup by event type.
|
|
16
16
|
* - Zero allocation when no listener for an event type AND no wildcard.
|
|
17
17
|
* - Dev-mode wraps listeners to warn on async listener Promise return.
|
|
18
|
+
* - Lifecycle: subscriptions release via the returned Unsubscribe or an
|
|
19
|
+
* AbortSignal (`{ signal }`); `removeAllListeners()` is the bulk
|
|
20
|
+
* escape hatch for long-lived server consumers; `listenerCount()` is
|
|
21
|
+
* the leak diagnostic. Every removal path prunes emptied buckets and
|
|
22
|
+
* detaches abort handlers, so listener storage is bounded by LIVE
|
|
23
|
+
* subscriptions — never by subscription history.
|
|
18
24
|
*/
|
|
19
25
|
import type { AgentfootprintEvent, AgentfootprintEventMap, AgentfootprintEventType } from './registry.js';
|
|
20
26
|
export type EventListener<K extends AgentfootprintEventType> = (event: AgentfootprintEventMap[K]) => void;
|
|
@@ -53,10 +59,17 @@ export declare class EventDispatcher {
|
|
|
53
59
|
on(type: WildcardSubscription, listener: WildcardListener, options?: ListenOptions): Unsubscribe;
|
|
54
60
|
/**
|
|
55
61
|
* Subscribe a one-shot listener. Fires at most once and then auto-removes.
|
|
56
|
-
* Equivalent to `on(type, listener, { once: true })`.
|
|
62
|
+
* Equivalent to `on(type, listener, { once: true })`. Accepts `{ signal }`
|
|
63
|
+
* for AbortSignal auto-cleanup, same as `on()`.
|
|
57
64
|
*/
|
|
58
|
-
once<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>): Unsubscribe;
|
|
59
|
-
once(type: WildcardSubscription, listener: WildcardListener): Unsubscribe;
|
|
65
|
+
once<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>, options?: Omit<ListenOptions, 'once'>): Unsubscribe;
|
|
66
|
+
once(type: WildcardSubscription, listener: WildcardListener, options?: Omit<ListenOptions, 'once'>): Unsubscribe;
|
|
67
|
+
/**
|
|
68
|
+
* Shared subscribe path for on()/once(). The public overloads constrain
|
|
69
|
+
* `type` to either typed keys or wildcards; internally the dispatcher's
|
|
70
|
+
* bucket logic accepts any string and classifies by shape.
|
|
71
|
+
*/
|
|
72
|
+
private subscribe;
|
|
60
73
|
/**
|
|
61
74
|
* Remove a specific listener for a type. Prefer AbortSignal for auto-cleanup.
|
|
62
75
|
*
|
|
@@ -65,6 +78,36 @@ export declare class EventDispatcher {
|
|
|
65
78
|
*/
|
|
66
79
|
off<K extends AgentfootprintEventType>(type: K, listener: EventListener<K>): void;
|
|
67
80
|
off(type: WildcardSubscription, listener: WildcardListener): void;
|
|
81
|
+
/**
|
|
82
|
+
* Lifecycle escape hatch — drop EVERY listener (typed, domain-wildcard,
|
|
83
|
+
* and `'*'`) in one call. For long-lived server consumers that reuse one
|
|
84
|
+
* runner across many requests: when you can't thread an AbortSignal or
|
|
85
|
+
* keep every Unsubscribe handle, call this between requests to guarantee
|
|
86
|
+
* the dispatcher holds zero subscriptions.
|
|
87
|
+
*
|
|
88
|
+
* Safe to call mid-dispatch: the bucket currently being iterated
|
|
89
|
+
* finishes its already-taken snapshot (same semantics as `off()` during
|
|
90
|
+
* dispatch), buckets the in-flight dispatch has NOT yet reached deliver
|
|
91
|
+
* nothing (DOM-like "stop now"), and every SUBSEQUENT event sees no
|
|
92
|
+
* listeners. Abort handlers registered on consumer AbortSignals via
|
|
93
|
+
* `{ signal }` are detached too. Previously returned Unsubscribe
|
|
94
|
+
* handles become harmless no-ops.
|
|
95
|
+
*/
|
|
96
|
+
removeAllListeners(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Diagnostic — how many listeners the dispatcher currently retains.
|
|
99
|
+
*
|
|
100
|
+
* - `listenerCount()` — TOTAL across every bucket (typed + domain
|
|
101
|
+
* wildcards + `'*'`). The number long-lived consumers watch to verify
|
|
102
|
+
* per-run subscriptions are being released (leak detection).
|
|
103
|
+
* - `listenerCount(type)` — listeners registered under that exact
|
|
104
|
+
* subscription key (`'agentfootprint.agent.turn_start'`,
|
|
105
|
+
* `'agentfootprint.context.*'`, or `'*'`). NOTE: counts the bucket
|
|
106
|
+
* only — a typed count does NOT include wildcard listeners that would
|
|
107
|
+
* also fire for that type. "Would anything fire?" is
|
|
108
|
+
* `hasListenersFor()`.
|
|
109
|
+
*/
|
|
110
|
+
listenerCount(type?: AgentfootprintEventType | WildcardSubscription): number;
|
|
68
111
|
/**
|
|
69
112
|
* Route an event to all matching listeners (typed + domain-wildcard + all).
|
|
70
113
|
*
|
|
@@ -74,6 +117,16 @@ export declare class EventDispatcher {
|
|
|
74
117
|
*/
|
|
75
118
|
dispatch(event: AgentfootprintEvent): void;
|
|
76
119
|
private addListener;
|
|
120
|
+
/**
|
|
121
|
+
* Bounded-leak guarantee: a bucket emptied by ANY removal path is
|
|
122
|
+
* deleted from its Map so `byType` / `domainWildcards` never retain
|
|
123
|
+
* empty Sets for event types subscribed once and released. The
|
|
124
|
+
* identity check (`get(...) === bucket`) guards stale Unsubscribe
|
|
125
|
+
* closures — they must never delete a NEWER bucket re-created under
|
|
126
|
+
* the same key after this one was pruned. (`allWildcards` is a stable
|
|
127
|
+
* field, not a Map entry — nothing to prune.)
|
|
128
|
+
*/
|
|
129
|
+
private pruneBucket;
|
|
77
130
|
private ensureBucket;
|
|
78
131
|
private bucketFor;
|
|
79
132
|
private fireBucket;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../../src/events/dispatcher.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../../src/events/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,eAAe,CAAC;AAQvB,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,uBAAuB,IAAI,CAC7D,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAC7B,IAAI,CAAC;AAEV,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAiBrC,MAAM,MAAM,cAAc,GACtB,8BAA8B,GAC9B,wBAAwB,GACxB,yBAAyB,GACzB,0BAA0B,GAC1B,yBAAyB,GACzB,wBAAwB,GACxB,wBAAwB,GACxB,6BAA6B,GAC7B,uBAAuB,GACvB,2BAA2B,GAC3B,uBAAuB,GACvB,uBAAuB,GACvB,wBAAwB,GACxB,wBAAwB,GACxB,4BAA4B,CAAC;AAEjC,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC;AAE9B,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,WAAW,CAAC;AA6BhE;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0C;IAC1E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAI1D;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO;IAWvD;;;;;OAKG;IACH,EAAE,CAAC,CAAC,SAAS,uBAAuB,EAClC,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,OAAO,CAAC,EAAE,aAAa,GACtB,WAAW;IACd,0EAA0E;IAC1E,EAAE,CAAC,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,WAAW;IAShG;;;;OAIG;IACH,IAAI,CAAC,CAAC,SAAS,uBAAuB,EACpC,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GACpC,WAAW;IACd,IAAI,CACF,IAAI,EAAE,oBAAoB,EAC1B,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GACpC,WAAW;IASd;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAsCjB;;;;;OAKG;IACH,GAAG,CAAC,CAAC,SAAS,uBAAuB,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IACjF,GAAG,CAAC,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAgBjE;;;;;;;;;;;;;;OAcG;IACH,kBAAkB,IAAI,IAAI;IAQ1B;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,IAAI,CAAC,EAAE,uBAAuB,GAAG,oBAAoB,GAAG,MAAM;IAc5E;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAe1C,OAAO,CAAC,WAAW;IASnB;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAyBlB,OAAO,CAAC,SAAS;CAKlB"}
|
package/package.json
CHANGED