@caupulican/pi-adaptative 0.80.70 → 0.80.72

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 (36) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/core/agent-session.d.ts +11 -1
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +38 -5
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/catalog-manager.d.ts +1 -1
  7. package/dist/core/catalog-manager.d.ts.map +1 -1
  8. package/dist/core/catalog-manager.js +0 -0
  9. package/dist/core/catalog-manager.js.map +1 -1
  10. package/dist/core/gateways/channel-provider.d.ts.map +1 -1
  11. package/dist/core/gateways/channel-provider.js +7 -0
  12. package/dist/core/gateways/channel-provider.js.map +1 -1
  13. package/dist/core/memory/effectiveness-tracker.d.ts.map +1 -1
  14. package/dist/core/memory/effectiveness-tracker.js +11 -2
  15. package/dist/core/memory/effectiveness-tracker.js.map +1 -1
  16. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  17. package/dist/core/memory/providers/file-store.js +4 -0
  18. package/dist/core/memory/providers/file-store.js.map +1 -1
  19. package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
  20. package/dist/core/memory/providers/transcript-recall.js +12 -2
  21. package/dist/core/memory/providers/transcript-recall.js.map +1 -1
  22. package/dist/core/security/untrusted-boundary.d.ts.map +1 -1
  23. package/dist/core/security/untrusted-boundary.js +5 -3
  24. package/dist/core/security/untrusted-boundary.js.map +1 -1
  25. package/dist/core/settings-manager.d.ts.map +1 -1
  26. package/dist/core/settings-manager.js +4 -3
  27. package/dist/core/settings-manager.js.map +1 -1
  28. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  29. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  30. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  31. package/examples/extensions/sandbox/package-lock.json +2 -2
  32. package/examples/extensions/sandbox/package.json +1 -1
  33. package/examples/extensions/with-deps/package-lock.json +2 -2
  34. package/examples/extensions/with-deps/package.json +1 -1
  35. package/npm-shrinkwrap.json +12 -12
  36. package/package.json +4 -4
@@ -127,6 +127,12 @@ export class AgentSession {
127
127
  _effectivenessTracker = new EffectivenessTracker();
128
128
  /** R8: registry for deployment-supplied gateway channels + schedulers (lifecycle driven by the host runner). */
129
129
  _gatewayRegistry = new GatewayRegistry();
130
+ /** Cache for getSpawnedUsage(), keyed by session entry count (Bug #22 — avoid O(N) per render frame). */
131
+ _spawnedUsageCache;
132
+ /** Set on dispose so in-flight background reflection bails instead of writing to a dead session (Bug #21). */
133
+ _disposed = false;
134
+ /** Aborts in-flight background reflection completions on dispose (Bug #21). */
135
+ _reflectionAbort = new AbortController();
130
136
  _isChildSession;
131
137
  /** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */
132
138
  _pendingMemoryProviders = [];
@@ -676,6 +682,15 @@ export class AgentSession {
676
682
  this.agent.abort();
677
683
  // R8: stop any deployment-registered gateway channels / schedulers.
678
684
  void this._gatewayRegistry.stop().catch(() => { });
685
+ // Bug #21: abort any in-flight background reflection so it cannot keep spending tokens or
686
+ // write memory/skills against this now-disposed session.
687
+ this._disposed = true;
688
+ this._reflectionAbort.abort();
689
+ // Bug #20: clear the hooks this session installed on the shared agent so their closures stop
690
+ // pinning this (deactivated) session — and all its history/maps — in memory if the agent
691
+ // instance outlives the session.
692
+ this.agent.afterToolCall = undefined;
693
+ this.agent.transformContext = undefined;
679
694
  }
680
695
  catch {
681
696
  // Dispose must succeed even if an abort hook throws.
@@ -3296,8 +3311,15 @@ export class AgentSession {
3296
3311
  };
3297
3312
  return this.sessionManager.appendCustomEntry(SPAWNED_USAGE_CUSTOM_TYPE, report);
3298
3313
  }
3299
- /** Aggregate all recorded spawned-usage reports (see {@link addSpawnedUsage}). */
3314
+ /**
3315
+ * Aggregate all recorded spawned-usage reports (see {@link addSpawnedUsage}). Cached by the session
3316
+ * entry count so the interactive footer (which calls this every render frame) is O(1) between turns
3317
+ * instead of an O(N) scan on every keystroke (Bug #22). Recomputes only when entries change.
3318
+ */
3300
3319
  getSpawnedUsage() {
3320
+ const entryCount = this.sessionManager.getEntryCount?.() ?? this.sessionManager.getEntries().length;
3321
+ if (this._spawnedUsageCache?.entryCount === entryCount)
3322
+ return this._spawnedUsageCache.totals;
3301
3323
  let cost = 0;
3302
3324
  let reports = 0;
3303
3325
  for (const entry of this.sessionManager.getEntries()) {
@@ -3309,7 +3331,9 @@ export class AgentSession {
3309
3331
  cost += data.usage.cost.total;
3310
3332
  reports += 1;
3311
3333
  }
3312
- return { cost, reports };
3334
+ const totals = { cost, reports };
3335
+ this._spawnedUsageCache = { entryCount, totals };
3336
+ return totals;
3313
3337
  }
3314
3338
  /**
3315
3339
  * Run a one-shot LLM completion fully ISOLATED from the main session — the load-bearing
@@ -3383,18 +3407,23 @@ export class AgentSession {
3383
3407
  * is best-effort: a model/parse error yields no writes, never throws into the caller.
3384
3408
  */
3385
3409
  async runReflectionPass(input) {
3386
- if (this._isChildSession)
3410
+ if (this._isChildSession || this._disposed)
3387
3411
  return null;
3388
3412
  const plan = decideDemand(input.signals);
3389
3413
  if (plan.act === "skip")
3390
3414
  return null;
3415
+ // Bug #21: tie this background pass to the session lifetime. Disposing the session aborts the
3416
+ // in-flight completion (input.signal can add a more specific abort).
3417
+ const signal = input.signal
3418
+ ? AbortSignal.any([input.signal, this._reflectionAbort.signal])
3419
+ : this._reflectionAbort.signal;
3391
3420
  const complete = (systemPrompt, userPrompt) => this.runIsolatedCompletion({
3392
3421
  systemPrompt,
3393
3422
  messages: [{ role: "user", content: [{ type: "text", text: userPrompt }], timestamp: Date.now() }],
3394
3423
  model: input.model,
3395
3424
  thinkingLevel: input.thinkingLevel ?? "low",
3396
3425
  maxTokens: plan.tokenBudget,
3397
- signal: input.signal,
3426
+ signal,
3398
3427
  });
3399
3428
  const result = await new ReflectionEngine().reflect({
3400
3429
  recentTurnText: input.recentTurnText,
@@ -3404,8 +3433,12 @@ export class AgentSession {
3404
3433
  plan,
3405
3434
  complete,
3406
3435
  });
3436
+ // Bug #21: if the session was disposed while the completion was in flight, do NOT write memory
3437
+ // or skills against the dead session.
3438
+ if (this._disposed)
3439
+ return result;
3407
3440
  for (const write of result.writes) {
3408
- await this._applyReflectionWrite(write, input.signal);
3441
+ await this._applyReflectionWrite(write, signal);
3409
3442
  }
3410
3443
  // Account the reflection's spend so it surfaces in the footer roll-up (net-token visibility).
3411
3444
  // Idempotent on reportId so a retried/duplicated pass cannot double-count.