@caupulican/pi-adaptative 0.90.6 → 0.90.11

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 (219) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/bundled-resources/skills/tool-call-repair/SKILL.md +5 -4
  3. package/dist/bundled-resources/skills/tool-call-repair/references/failure-grammar.md +6 -3
  4. package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +1 -0
  5. package/dist/core/agent-session-contracts.d.ts +4 -0
  6. package/dist/core/agent-session-contracts.d.ts.map +1 -1
  7. package/dist/core/agent-session-contracts.js.map +1 -1
  8. package/dist/core/agent-session.d.ts +13 -17
  9. package/dist/core/agent-session.d.ts.map +1 -1
  10. package/dist/core/agent-session.js +112 -205
  11. package/dist/core/agent-session.js.map +1 -1
  12. package/dist/core/autonomy/bounded-completion.d.ts +7 -1
  13. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  14. package/dist/core/autonomy/bounded-completion.js +8 -2
  15. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  16. package/dist/core/autonomy/contracts.d.ts +1 -1
  17. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  18. package/dist/core/autonomy/contracts.js.map +1 -1
  19. package/dist/core/background-lane-controller.d.ts +14 -0
  20. package/dist/core/background-lane-controller.d.ts.map +1 -1
  21. package/dist/core/background-lane-controller.js +32 -0
  22. package/dist/core/background-lane-controller.js.map +1 -1
  23. package/dist/core/billing-failover-controller.js +1 -1
  24. package/dist/core/billing-failover-controller.js.map +1 -1
  25. package/dist/core/context/current-work-memory.d.ts +1 -1
  26. package/dist/core/context/current-work-memory.d.ts.map +1 -1
  27. package/dist/core/context/current-work-memory.js +2 -1
  28. package/dist/core/context/current-work-memory.js.map +1 -1
  29. package/dist/core/context/long-term-memory-trigger.d.ts +1 -1
  30. package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
  31. package/dist/core/context/long-term-memory-trigger.js +2 -1
  32. package/dist/core/context/long-term-memory-trigger.js.map +1 -1
  33. package/dist/core/delegation/managed-lane-controller.js +2 -2
  34. package/dist/core/delegation/managed-lane-controller.js.map +1 -1
  35. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +13 -0
  36. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  37. package/dist/core/delegation/worker-agent-control-coordinator.js +71 -8
  38. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  39. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
  40. package/dist/core/delegation/worker-attempt-executor.js +13 -8
  41. package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
  42. package/dist/core/delegation/worker-claim.d.ts.map +1 -1
  43. package/dist/core/delegation/worker-claim.js +14 -1
  44. package/dist/core/delegation/worker-claim.js.map +1 -1
  45. package/dist/core/delegation/worker-delegation-controller.d.ts +6 -9
  46. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  47. package/dist/core/delegation/worker-delegation-controller.js +95 -42
  48. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  49. package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
  50. package/dist/core/delegation/worker-fleet-limits.js +5 -1
  51. package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
  52. package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -1
  53. package/dist/core/delegation/worker-lane-projection.js +7 -4
  54. package/dist/core/delegation/worker-lane-projection.js.map +1 -1
  55. package/dist/core/delegation/worker-lifecycle.d.ts +8 -0
  56. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  57. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  58. package/dist/core/delegation/worker-notification-coordinator.d.ts +23 -0
  59. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
  60. package/dist/core/delegation/worker-notification-coordinator.js +69 -17
  61. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
  62. package/dist/core/delegation/worker-runner.d.ts +7 -0
  63. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  64. package/dist/core/delegation/worker-runner.js +24 -7
  65. package/dist/core/delegation/worker-runner.js.map +1 -1
  66. package/dist/core/delegation/worker-system-prompt.d.ts +54 -0
  67. package/dist/core/delegation/worker-system-prompt.d.ts.map +1 -0
  68. package/dist/core/delegation/worker-system-prompt.js +85 -0
  69. package/dist/core/delegation/worker-system-prompt.js.map +1 -0
  70. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -1
  71. package/dist/core/delegation/worker-tree-budget-coordinator.js +4 -0
  72. package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -1
  73. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +4 -0
  74. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
  75. package/dist/core/delegation/worker-write-reservation-coordinator.js +28 -1
  76. package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
  77. package/dist/core/durable-custom-message-turn-controller.d.ts +24 -0
  78. package/dist/core/durable-custom-message-turn-controller.d.ts.map +1 -0
  79. package/dist/core/durable-custom-message-turn-controller.js +71 -0
  80. package/dist/core/durable-custom-message-turn-controller.js.map +1 -0
  81. package/dist/core/extension-binding-controller.d.ts +107 -0
  82. package/dist/core/extension-binding-controller.d.ts.map +1 -0
  83. package/dist/core/extension-binding-controller.js +224 -0
  84. package/dist/core/extension-binding-controller.js.map +1 -0
  85. package/dist/core/extensions/types.d.ts +2 -0
  86. package/dist/core/extensions/types.d.ts.map +1 -1
  87. package/dist/core/extensions/types.js.map +1 -1
  88. package/dist/core/foreground-terminal-handoff-controller.d.ts +22 -7
  89. package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
  90. package/dist/core/foreground-terminal-handoff-controller.js +76 -12
  91. package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
  92. package/dist/core/goal-loop-controller.d.ts +5 -9
  93. package/dist/core/goal-loop-controller.d.ts.map +1 -1
  94. package/dist/core/goal-loop-controller.js +19 -7
  95. package/dist/core/goal-loop-controller.js.map +1 -1
  96. package/dist/core/goals/compact-goal-context.d.ts +1 -1
  97. package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
  98. package/dist/core/goals/compact-goal-context.js +2 -1
  99. package/dist/core/goals/compact-goal-context.js.map +1 -1
  100. package/dist/core/goals/goal-execution-errors.d.ts +18 -0
  101. package/dist/core/goals/goal-execution-errors.d.ts.map +1 -0
  102. package/dist/core/goals/goal-execution-errors.js +21 -0
  103. package/dist/core/goals/goal-execution-errors.js.map +1 -0
  104. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
  105. package/dist/core/goals/goal-lifecycle.js +3 -3
  106. package/dist/core/goals/goal-lifecycle.js.map +1 -1
  107. package/dist/core/goals/goal-session-controller.d.ts +41 -1
  108. package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
  109. package/dist/core/goals/goal-session-controller.js +217 -20
  110. package/dist/core/goals/goal-session-controller.js.map +1 -1
  111. package/dist/core/goals/goal-state.d.ts +6 -7
  112. package/dist/core/goals/goal-state.d.ts.map +1 -1
  113. package/dist/core/goals/goal-state.js +1 -1
  114. package/dist/core/goals/goal-state.js.map +1 -1
  115. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  116. package/dist/core/goals/goal-tool-core.js +2 -2
  117. package/dist/core/goals/goal-tool-core.js.map +1 -1
  118. package/dist/core/goals/natural-language-goal.d.ts +24 -0
  119. package/dist/core/goals/natural-language-goal.d.ts.map +1 -1
  120. package/dist/core/goals/natural-language-goal.js +121 -3
  121. package/dist/core/goals/natural-language-goal.js.map +1 -1
  122. package/dist/core/model-registry.d.ts +5 -0
  123. package/dist/core/model-registry.d.ts.map +1 -1
  124. package/dist/core/model-registry.js +10 -0
  125. package/dist/core/model-registry.js.map +1 -1
  126. package/dist/core/model-resolver.d.ts.map +1 -1
  127. package/dist/core/model-resolver.js +3 -1
  128. package/dist/core/model-resolver.js.map +1 -1
  129. package/dist/core/orchestration/capability-gateway.d.ts +1 -1
  130. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  131. package/dist/core/orchestration/capability-gateway.js +4 -4
  132. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  133. package/dist/core/orchestration/event-store.d.ts +8 -0
  134. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  135. package/dist/core/orchestration/event-store.js +9 -7
  136. package/dist/core/orchestration/event-store.js.map +1 -1
  137. package/dist/core/orchestration/task-runtime-reducer.js +1 -1
  138. package/dist/core/orchestration/task-runtime-reducer.js.map +1 -1
  139. package/dist/core/orchestration/worker-model-pins.d.ts +7 -0
  140. package/dist/core/orchestration/worker-model-pins.d.ts.map +1 -1
  141. package/dist/core/orchestration/worker-model-pins.js +17 -1
  142. package/dist/core/orchestration/worker-model-pins.js.map +1 -1
  143. package/dist/core/provider-request-runtime-controller.d.ts +10 -0
  144. package/dist/core/provider-request-runtime-controller.d.ts.map +1 -1
  145. package/dist/core/provider-request-runtime-controller.js +24 -2
  146. package/dist/core/provider-request-runtime-controller.js.map +1 -1
  147. package/dist/core/provider-tool-text.d.ts +15 -1
  148. package/dist/core/provider-tool-text.d.ts.map +1 -1
  149. package/dist/core/provider-tool-text.js +42 -10
  150. package/dist/core/provider-tool-text.js.map +1 -1
  151. package/dist/core/research/research-lane-controller.d.ts +1 -1
  152. package/dist/core/research/research-lane-controller.d.ts.map +1 -1
  153. package/dist/core/research/research-lane-controller.js +2 -1
  154. package/dist/core/research/research-lane-controller.js.map +1 -1
  155. package/dist/core/resource-loader.d.ts +3 -0
  156. package/dist/core/resource-loader.d.ts.map +1 -1
  157. package/dist/core/resource-loader.js +8 -0
  158. package/dist/core/resource-loader.js.map +1 -1
  159. package/dist/core/runtime-builder.d.ts +11 -0
  160. package/dist/core/runtime-builder.d.ts.map +1 -1
  161. package/dist/core/runtime-builder.js +9 -0
  162. package/dist/core/runtime-builder.js.map +1 -1
  163. package/dist/core/session-supervision-runtime.d.ts.map +1 -1
  164. package/dist/core/session-supervision-runtime.js +2 -1
  165. package/dist/core/session-supervision-runtime.js.map +1 -1
  166. package/dist/core/settings-manager.d.ts +2 -2
  167. package/dist/core/settings-manager.d.ts.map +1 -1
  168. package/dist/core/settings-manager.js +7 -2
  169. package/dist/core/settings-manager.js.map +1 -1
  170. package/dist/core/tool-recovery-logger.d.ts +2 -0
  171. package/dist/core/tool-recovery-logger.d.ts.map +1 -1
  172. package/dist/core/tool-recovery-logger.js +11 -0
  173. package/dist/core/tool-recovery-logger.js.map +1 -1
  174. package/dist/core/tools/delegate.d.ts +13 -0
  175. package/dist/core/tools/delegate.d.ts.map +1 -1
  176. package/dist/core/tools/delegate.js +20 -18
  177. package/dist/core/tools/delegate.js.map +1 -1
  178. package/dist/core/tools/goal.d.ts +2 -0
  179. package/dist/core/tools/goal.d.ts.map +1 -1
  180. package/dist/core/tools/goal.js +9 -0
  181. package/dist/core/tools/goal.js.map +1 -1
  182. package/dist/core/util/atomic-file.d.ts +7 -0
  183. package/dist/core/util/atomic-file.d.ts.map +1 -1
  184. package/dist/core/util/atomic-file.js +8 -6
  185. package/dist/core/util/atomic-file.js.map +1 -1
  186. package/dist/core/util/faultable-fs.d.ts +30 -0
  187. package/dist/core/util/faultable-fs.d.ts.map +1 -0
  188. package/dist/core/util/faultable-fs.js +30 -0
  189. package/dist/core/util/faultable-fs.js.map +1 -0
  190. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  191. package/dist/modes/interactive/auth-dialogs-controller.js +1 -0
  192. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  193. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
  194. package/dist/modes/interactive/components/activity-lane.js +4 -3
  195. package/dist/modes/interactive/components/activity-lane.js.map +1 -1
  196. package/dist/modes/interactive/components/footer.js +1 -1
  197. package/dist/modes/interactive/components/footer.js.map +1 -1
  198. package/dist/modes/interactive/components/oauth-selector.d.ts +2 -0
  199. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  200. package/dist/modes/interactive/components/oauth-selector.js +3 -2
  201. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  202. package/dist/modes/interactive/report-commands.js +1 -1
  203. package/dist/modes/interactive/report-commands.js.map +1 -1
  204. package/dist/modes/interactive/session-flow-commands.d.ts +1 -1
  205. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  206. package/dist/modes/interactive/session-flow-commands.js +3 -2
  207. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  208. package/docs/providers.md +3 -0
  209. package/docs/settings.md +4 -2
  210. package/docs/tool-repair.md +1 -0
  211. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  212. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  213. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  214. package/examples/extensions/sandbox/package-lock.json +2 -2
  215. package/examples/extensions/sandbox/package.json +1 -1
  216. package/examples/extensions/with-deps/package-lock.json +2 -2
  217. package/examples/extensions/with-deps/package.json +1 -1
  218. package/npm-shrinkwrap.json +12 -12
  219. package/package.json +9 -4
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { basename, dirname } from "node:path";
3
- import { projectToolsForProvider } from "@caupulican/pi-agent-core";
2
+ import { basename } from "node:path";
3
+ import { NATIVE_TOOL_PROTOCOL_RESIDUE_ERROR, projectToolsForProvider } from "@caupulican/pi-agent-core";
4
4
  import { AgentBusyError } from "@caupulican/pi-agent-core/agent";
5
5
  import { compactToolResultDetailsForRetention } from "@caupulican/pi-agent-core/message-retention";
6
6
  import { createCustomMessage } from "@caupulican/pi-agent-core/messages";
@@ -22,12 +22,15 @@ import { CompactionSupport } from "./compaction-support.js";
22
22
  import { buildContextCompositionReport, formatContextCompositionDashboard, } from "./context/context-composition.js";
23
23
  import { ContextPipeline } from "./context-pipeline.js";
24
24
  import { downgradeReasoning, estimateTurnCostUsd, evaluateCostGuard } from "./cost-guard.js";
25
- import { appendWorkerClaimSnapshot, getWorkerClaimSnapshots } from "./delegation/session-worker-claim.js";
25
+ import { appendWorkerClaimSnapshot, getLatestWorkerClaimSnapshot, getWorkerClaimSnapshots, } from "./delegation/session-worker-claim.js";
26
+ import { DurableCustomMessageTurnController } from "./durable-custom-message-turn-controller.js";
27
+ import { ExtensionBindingController } from "./extension-binding-controller.js";
26
28
  import { FailureCorpusRecorder } from "./failure-corpus.js";
27
29
  import { ForegroundRecoveryController } from "./foreground-recovery-controller.js";
28
30
  import { ForegroundTerminalHandoffController } from "./foreground-terminal-handoff-controller.js";
29
31
  import { GatewayRegistry } from "./gateways/channel-provider.js";
30
32
  import { GoalSessionController } from "./goals/goal-session-controller.js";
33
+ import { parseExplicitGoalStartAuthority } from "./goals/natural-language-goal.js";
31
34
  import { constrainStreamIdleToHttpTimeout } from "./http-dispatcher.js";
32
35
  import { HumanInputController } from "./human-input-controller.js";
33
36
  import { appendLearningDecisionSnapshot, getLearningDecisionSnapshots } from "./learning/session-learning-decision.js";
@@ -114,6 +117,8 @@ export class AgentSession {
114
117
  this._pendingNextTurnMessages = [];
115
118
  this._streamingPromptSubmissionTail = Promise.resolve();
116
119
  this._unboundToolGrantWarnings = [];
120
+ /** Delegate provider-prompt-guideline bounding diagnostics (root-session delegate tool only). */
121
+ this._delegatePromptGuidelineWarnings = [];
117
122
  this._branchSummaryAbortController = undefined;
118
123
  this._turnIndex = 0;
119
124
  /** Per-agent persistent shell session identity: stable across runtime reloads, disposed with the session. */
@@ -211,6 +216,7 @@ export class AgentSession {
211
216
  else if (event.message.role === "custom") {
212
217
  // Persist as CustomMessageEntry
213
218
  this.sessionManager.appendCustomMessageEntry(event.message.customType, event.message.content, event.message.display, event.message.details);
219
+ this._durableCustomMessageTurns.notePersisted(event.message);
214
220
  messagePersisted = true;
215
221
  }
216
222
  else if (event.message.role === "user" ||
@@ -224,9 +230,13 @@ export class AgentSession {
224
230
  // Track the response for ordered retry/failover/compaction handling after agent_end.
225
231
  if (event.message.role === "assistant") {
226
232
  const assistantMsg = event.message;
233
+ this._goals.recordExecutionUsage(assistantMsg);
227
234
  if (messagePersisted) {
228
235
  this._pipeline.observeProviderUsage(this.agent.state.messages, assistantMsg);
229
236
  }
237
+ if (assistantMsg.errorMessage?.startsWith(`${NATIVE_TOOL_PROTOCOL_RESIDUE_ERROR}:`)) {
238
+ this._goals.markProtocolFailureBlocked(assistantMsg.errorMessage);
239
+ }
230
240
  this._foregroundRecovery.observeAssistant(assistantMsg);
231
241
  }
232
242
  }
@@ -553,6 +563,8 @@ export class AgentSession {
553
563
  agent: this.agent,
554
564
  compaction: this._compaction,
555
565
  context: providerRequestContext,
566
+ admitGoalRequest: () => this._goals.admitProviderRequest(),
567
+ shouldStopGoalExecutionAfterTurn: () => this._goals.hasExecutionLeaseCrossedBudgetLimit(),
556
568
  });
557
569
  this._toolRecoveryLogger = new ToolRecoveryLogger({
558
570
  enabled: toolRepairSettings.logging,
@@ -578,11 +590,19 @@ export class AgentSession {
578
590
  await this._drainQueuedExtensionCommands();
579
591
  },
580
592
  });
593
+ this._durableCustomMessageTurns = new DurableCustomMessageTurnController({
594
+ foreground: this._foregroundRecovery,
595
+ goals: this._goals,
596
+ });
581
597
  this._terminalHandoffs = new ForegroundTerminalHandoffController({
582
598
  foreground: this._foregroundRecovery,
583
599
  isDisposed: () => this._disposed,
600
+ getGoalStateSnapshot: () => this.getGoalStateSnapshot(),
584
601
  workerInputsWillWakeParent: (workerRequestIds) => this._humanInput.workerInputsWillWakeParent(workerRequestIds),
602
+ getWorkerClaimSnapshot: (laneId) => getLatestWorkerClaimSnapshot(getActiveSessionBranchEntries(this.sessionManager), laneId),
603
+ startCustomMessageTurn: (message, lease, goalId) => this._durableCustomMessageTurns.start(message, lease, goalId),
585
604
  sendCustomMessage: (message, options, lease) => this._sendCustomMessage(message, options, lease),
605
+ warn: (message) => this._emit({ type: "warning", message }),
586
606
  });
587
607
  this._modelRouter = new ModelRouterController({
588
608
  getAgent: () => this.agent,
@@ -693,15 +713,18 @@ export class AgentSession {
693
713
  this._unboundToolGrantWarnings = warnings;
694
714
  },
695
715
  getUnboundToolGrantWarnings: () => this._unboundToolGrantWarnings,
716
+ setDelegatePromptGuidelineWarnings: (warnings) => {
717
+ this._delegatePromptGuidelineWarnings = warnings;
718
+ },
696
719
  createProfileFilterReloadSnapshot: () => this._profileFilter.createReloadSnapshot(),
697
720
  restoreProfileFilterReloadSnapshot: (snapshot) => this._profileFilter.restoreReloadSnapshot(snapshot),
698
721
  getActiveToolNames: () => this.getActiveToolNames(),
699
722
  setActiveToolsByName: (toolNames) => this.setActiveToolsByName(toolNames),
700
723
  normalizePromptSnippet: (text) => this._normalizePromptSnippet(text),
701
724
  normalizePromptGuidelines: (guidelines) => this._normalizePromptGuidelines(guidelines),
702
- bindExtensionCore: (runner) => this._bindExtensionCore(runner),
703
- applyExtensionBindings: (runner) => this._applyExtensionBindings(runner),
704
- extendResourcesFromExtensions: (reason) => this.extendResourcesFromExtensions(reason),
725
+ bindExtensionCore: (runner) => this._extensionBinding.bindExtensionCore(runner),
726
+ applyExtensionBindings: (runner) => this._extensionBinding.applyExtensionBindings(runner),
727
+ extendResourcesFromExtensions: (reason) => this._extensionBinding.extendResourcesFromExtensions(reason),
705
728
  reapplyActiveProfileModelSettings: () => this._profileFilter.reapplyActiveProfileModelSettings(),
706
729
  notifyExtensionsChanged: () => this._notifyExtensionsChanged(),
707
730
  getToolArtifactStore: () => this._getToolArtifactStore(),
@@ -715,6 +738,7 @@ export class AgentSession {
715
738
  initializeMemory: () => this._memory.initialize(),
716
739
  getGoalStateSnapshot: () => this.getGoalStateSnapshot(),
717
740
  saveGoalStateSnapshot: (state) => this.saveGoalStateSnapshot(state),
741
+ authorizeGoalStartFromTool: (input) => this._goals.authorizeStartFromTool(input),
718
742
  getTaskStepsStateSnapshot: () => this.getTaskStepsStateSnapshot(),
719
743
  saveTaskStepsStateSnapshot: (state) => this.saveTaskStepsStateSnapshot(state),
720
744
  getContextGcReport: (messages) => this.getContextGcReport(messages),
@@ -743,6 +767,67 @@ export class AgentSession {
743
767
  this._localRuntimeController.reconcile(this._collectEligibleLocalModelsForReconcile());
744
768
  },
745
769
  });
770
+ this._extensionBinding = new ExtensionBindingController({
771
+ getAgent: () => this.agent,
772
+ getExtensionRunner: () => this._extensionRunner,
773
+ getSessionStartEvent: () => this._sessionStartEvent,
774
+ getCwd: () => this._cwd,
775
+ getResourceLoader: () => this._resourceLoader,
776
+ getSessionManager: () => this.sessionManager,
777
+ getSettingsManager: () => this.settingsManager,
778
+ getModelRegistry: () => this._modelRegistry,
779
+ getModel: () => this.model,
780
+ getActiveToolNames: () => this.getActiveToolNames(),
781
+ getAllTools: () => this.getAllTools(),
782
+ setActiveToolsByName: (toolNames) => this.setActiveToolsByName(toolNames),
783
+ refreshToolRegistry: () => this._refreshToolRegistry(),
784
+ rebuildSystemPrompt: (toolNames) => this._rebuildSystemPrompt(toolNames),
785
+ setBaseSystemPrompt: (prompt) => {
786
+ this._baseSystemPrompt = prompt;
787
+ },
788
+ getPromptTemplates: () => this.promptTemplates,
789
+ getThinkingLevel: () => this.thinkingLevel,
790
+ setThinkingLevel: (level) => this.setThinkingLevel(level),
791
+ setModel: (model) => this.setModel(model),
792
+ sendCustomMessage: (message, options) => this.sendCustomMessage(message, options),
793
+ sendUserMessage: (content, options) => this.sendUserMessage(content, options),
794
+ setSessionName: (name) => this.setSessionName(name),
795
+ registerMemoryProvider: (provider) => this.registerMemoryProvider(provider),
796
+ registerContextMemoryProvider: (provider) => this.registerContextMemoryProvider(provider),
797
+ addSpawnedUsage: (usage, opts) => this.addSpawnedUsage(usage, opts),
798
+ recordManagedLane: (event) => this._backgroundLanes.recordManagedLane(event),
799
+ isForegroundBusy: () => this._foregroundRecovery.isBusy,
800
+ getPendingMessageCount: () => this.pendingMessageCount,
801
+ isStreaming: () => this.isStreaming,
802
+ isCompacting: () => this.isCompacting,
803
+ getContextUsage: () => this.getContextUsage(),
804
+ compactForExtension: (options) => this.compactForExtension(options),
805
+ reload: () => this.reload(),
806
+ abort: () => this.abort(),
807
+ getSystemPrompt: () => this.systemPrompt,
808
+ getExtensionCommandContextActions: () => this._extensionCommandContextActions,
809
+ refreshCurrentModelFromRegistry: () => this._refreshCurrentModelFromRegistry(),
810
+ initializeMemory: () => this._memory.initialize(),
811
+ getExtensionUIContext: () => this._extensionUIContext,
812
+ setExtensionUIContext: (uiContext) => {
813
+ this._extensionUIContext = uiContext;
814
+ },
815
+ getExtensionMode: () => this._extensionMode,
816
+ setExtensionMode: (mode) => {
817
+ this._extensionMode = mode;
818
+ },
819
+ setExtensionCommandContextActions: (actions) => {
820
+ this._extensionCommandContextActions = actions;
821
+ },
822
+ getExtensionShutdownHandler: () => this._extensionShutdownHandler,
823
+ setExtensionShutdownHandler: (handler) => {
824
+ this._extensionShutdownHandler = handler;
825
+ },
826
+ getExtensionErrorListener: () => this._extensionErrorListener,
827
+ setExtensionErrorListener: (listener) => {
828
+ this._extensionErrorListener = listener;
829
+ },
830
+ });
746
831
  this._analytics = new SessionAnalytics({
747
832
  getState: () => this.state,
748
833
  getMessages: () => this.messages,
@@ -1260,6 +1345,7 @@ export class AgentSession {
1260
1345
  ...this._profileFilter.profileDeniedResourceObservations(),
1261
1346
  ...this._profileFilter.getInertExtensionWarnings(),
1262
1347
  ...this._unboundToolGrantWarnings,
1348
+ ...this._delegatePromptGuidelineWarnings,
1263
1349
  // Auto-built per-turn foreground envelope (observe-only; not enforced). Falls back to a
1264
1350
  // live preview when no turn has run yet so /context always shows the current scope.
1265
1351
  formatForegroundEnvelopeObservation(this._currentForegroundEnvelope ?? this._buildForegroundEnvelopeFromState()),
@@ -1281,8 +1367,8 @@ export class AgentSession {
1281
1367
  this._toolSelection.formatTimingReport(),
1282
1368
  ].join("\n\n");
1283
1369
  }
1284
- async flushToolRecoveryLogsForTests(timeoutMs = 1000) {
1285
- await this._toolRecoveryLogger.flush(timeoutMs);
1370
+ async flushToolRecoveryLogsForTests() {
1371
+ await this._toolRecoveryLogger.drain();
1286
1372
  }
1287
1373
  removeToolRepairRule(model, mode) {
1288
1374
  return this._toolProtocol.removeRepairRule(model, mode);
@@ -1668,6 +1754,7 @@ export class AgentSession {
1668
1754
  this.agent.subscribeToolCallHandoffRequest = undefined;
1669
1755
  });
1670
1756
  safely(() => this._extensionRunner.invalidate());
1757
+ track(() => this._resourceLoader.dispose?.() ?? Promise.resolve());
1671
1758
  safely(() => this._disconnectFromAgent());
1672
1759
  this._eventListeners = [];
1673
1760
  // Let an aborted in-flight reflection reach its terminal state, then flush session-owned write
@@ -2009,6 +2096,8 @@ export class AgentSession {
2009
2096
  // response, whether the agent actually used the recalled context.
2010
2097
  let injectedRecall = "";
2011
2098
  let recallQuery = "";
2099
+ let admittedGoalId = options?.goalExecutionId;
2100
+ let goalToolStartAuthority;
2012
2101
  try {
2013
2102
  // Handle extension commands first. Programmatic extension messages may opt
2014
2103
  // into command handling; if the agent is currently streaming, queue the
@@ -2050,7 +2139,10 @@ export class AgentSession {
2050
2139
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
2051
2140
  }
2052
2141
  if (!options?.internalContextType) {
2142
+ goalToolStartAuthority = parseExplicitGoalStartAuthority(expandedText);
2053
2143
  const admission = this._goals.admitExplicitChatGoal(expandedText);
2144
+ if (admission.status === "started")
2145
+ admittedGoalId = admission.state.goalId;
2054
2146
  if (admission.status === "unfinished_goal_exists") {
2055
2147
  this._emit({
2056
2148
  type: "warning",
@@ -2240,12 +2332,19 @@ export class AgentSession {
2240
2332
  return;
2241
2333
  }
2242
2334
  preflightResult?.(true);
2335
+ const goalExecutionLease = this._goals.beginExecution(admittedGoalId, {
2336
+ adoptNewGoal: goalToolStartAuthority !== undefined,
2337
+ provisionalTokenBudget: goalToolStartAuthority?.tokenBudget,
2338
+ });
2339
+ this._goals.setStartAuthority(goalToolStartAuthority);
2243
2340
  try {
2244
2341
  this._toolProtocol.resetTurnState();
2245
2342
  await this._modelRouter.runRoutedTurn(messages, routedTurnModel, routedTurnRouteDecision);
2246
2343
  this._toolProtocol.recordParseOutcomeFromLastAssistant();
2247
2344
  }
2248
2345
  finally {
2346
+ this._goals.setStartAuthority(undefined);
2347
+ this._goals.endExecution(goalExecutionLease);
2249
2348
  // Normally consumed by the authoritative message_start. If execution failed before that
2250
2349
  // event, do not retain the early-painted message identity indefinitely.
2251
2350
  if (userMessage)
@@ -2684,79 +2783,9 @@ export class AgentSession {
2684
2783
  get autoCompactionEnabled() {
2685
2784
  return this.settingsManager.getCompactionEnabled();
2686
2785
  }
2786
+ /** Public entry point delegating to {@link ExtensionBindingController.bindExtensions}. */
2687
2787
  async bindExtensions(bindings) {
2688
- if (bindings.uiContext !== undefined) {
2689
- this._extensionUIContext = bindings.uiContext;
2690
- }
2691
- if (bindings.mode !== undefined) {
2692
- this._extensionMode = bindings.mode;
2693
- }
2694
- if (bindings.commandContextActions !== undefined) {
2695
- this._extensionCommandContextActions = bindings.commandContextActions;
2696
- }
2697
- if (bindings.abortHandler !== undefined) {
2698
- this._extensionAbortHandler = bindings.abortHandler;
2699
- }
2700
- if (bindings.shutdownHandler !== undefined) {
2701
- this._extensionShutdownHandler = bindings.shutdownHandler;
2702
- }
2703
- if (bindings.onError !== undefined) {
2704
- this._extensionErrorListener = bindings.onError;
2705
- }
2706
- this._applyExtensionBindings(this._extensionRunner);
2707
- await this._extensionRunner.emit(this._sessionStartEvent);
2708
- await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
2709
- // Initialize the memory subsystem after extensions have had a chance to register providers.
2710
- await this._memory.initialize();
2711
- }
2712
- async extendResourcesFromExtensions(reason) {
2713
- if (!this._extensionRunner.hasHandlers("resources_discover")) {
2714
- return;
2715
- }
2716
- const { skillPaths, promptPaths, themePaths } = await this._extensionRunner.emitResourcesDiscover(this._cwd, reason);
2717
- if (skillPaths.length === 0 && promptPaths.length === 0 && themePaths.length === 0) {
2718
- return;
2719
- }
2720
- const extensionPaths = {
2721
- skillPaths: this.buildExtensionResourcePaths(skillPaths),
2722
- promptPaths: this.buildExtensionResourcePaths(promptPaths),
2723
- themePaths: this.buildExtensionResourcePaths(themePaths),
2724
- };
2725
- this._resourceLoader.extendResources(extensionPaths);
2726
- this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
2727
- this.agent.state.systemPrompt = this._baseSystemPrompt;
2728
- }
2729
- buildExtensionResourcePaths(entries) {
2730
- return entries.map((entry) => {
2731
- const source = this.getExtensionSourceLabel(entry.extensionPath);
2732
- const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
2733
- return {
2734
- path: entry.path,
2735
- metadata: {
2736
- source,
2737
- scope: "temporary",
2738
- origin: "top-level",
2739
- baseDir,
2740
- },
2741
- };
2742
- });
2743
- }
2744
- getExtensionSourceLabel(extensionPath) {
2745
- if (extensionPath.startsWith("<")) {
2746
- return `extension:${extensionPath.replace(/[<>]/g, "")}`;
2747
- }
2748
- const base = basename(extensionPath);
2749
- const name = base.replace(/\.(ts|js)$/, "");
2750
- return `extension:${name}`;
2751
- }
2752
- _applyExtensionBindings(runner) {
2753
- runner.setUIContext(this._extensionUIContext);
2754
- runner.setMode(this._extensionMode);
2755
- runner.bindCommandContext(this._extensionCommandContextActions);
2756
- this._extensionErrorUnsubscriber?.();
2757
- this._extensionErrorUnsubscriber = this._extensionErrorListener
2758
- ? runner.onError(this._extensionErrorListener)
2759
- : undefined;
2788
+ return this._extensionBinding.bindExtensions(bindings);
2760
2789
  }
2761
2790
  _refreshCurrentModelFromRegistry() {
2762
2791
  const currentModel = this.model;
@@ -2769,123 +2798,6 @@ export class AgentSession {
2769
2798
  }
2770
2799
  this.agent.state.model = refreshedModel;
2771
2800
  }
2772
- _bindExtensionCore(runner) {
2773
- const getCommands = () => {
2774
- const extensionCommands = runner.getRegisteredCommands().map((command) => ({
2775
- name: command.invocationName,
2776
- description: command.description,
2777
- source: "extension",
2778
- sourceInfo: command.sourceInfo,
2779
- }));
2780
- const templates = this.promptTemplates.map((template) => ({
2781
- name: template.name,
2782
- description: template.description,
2783
- source: "prompt",
2784
- sourceInfo: template.sourceInfo,
2785
- }));
2786
- const skills = this._resourceLoader.getActiveSkills().map((skill) => ({
2787
- name: `skill:${skill.name}`,
2788
- description: skill.description,
2789
- source: "skill",
2790
- sourceInfo: skill.sourceInfo,
2791
- }));
2792
- return [...extensionCommands, ...templates, ...skills];
2793
- };
2794
- runner.bindCore({
2795
- sendMessage: (message, options) => {
2796
- this.sendCustomMessage(message, options).catch((err) => {
2797
- runner.emitError({
2798
- extensionPath: "<runtime>",
2799
- event: "send_message",
2800
- error: err instanceof Error ? err.message : String(err),
2801
- });
2802
- });
2803
- },
2804
- sendUserMessage: (content, options) => {
2805
- this.sendUserMessage(content, options).catch((err) => {
2806
- runner.emitError({
2807
- extensionPath: "<runtime>",
2808
- event: "send_user_message",
2809
- error: err instanceof Error ? err.message : String(err),
2810
- });
2811
- });
2812
- },
2813
- appendEntry: (customType, data) => {
2814
- this.sessionManager.appendCustomEntry(customType, data);
2815
- },
2816
- setSessionName: (name) => {
2817
- this.setSessionName(name);
2818
- },
2819
- getSessionName: () => {
2820
- return this.sessionManager.getSessionName();
2821
- },
2822
- setLabel: (entryId, label) => {
2823
- this.sessionManager.appendLabelChange(entryId, label);
2824
- },
2825
- getActiveTools: () => this.getActiveToolNames(),
2826
- getAllTools: () => this.getAllTools(),
2827
- setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
2828
- refreshTools: () => this._refreshToolRegistry(),
2829
- getCommands,
2830
- setModel: async (model) => {
2831
- if (!this.modelRegistry.hasConfiguredAuth(model))
2832
- return false;
2833
- await this.setModel(model);
2834
- return true;
2835
- },
2836
- getThinkingLevel: () => this.thinkingLevel,
2837
- setThinkingLevel: (level) => this.setThinkingLevel(level),
2838
- getExternalResourceRoots: () => this.settingsManager.getEffectiveExternalResourceRoots(),
2839
- registerMemoryProvider: (provider) => this.registerMemoryProvider(provider),
2840
- registerContextMemoryProvider: (provider) => this.registerContextMemoryProvider(provider),
2841
- reportSpawnedUsage: (usage, opts) => {
2842
- this.addSpawnedUsage(usage, opts);
2843
- },
2844
- reportManagedLane: (event) => {
2845
- this._backgroundLanes.recordManagedLane(event);
2846
- },
2847
- }, {
2848
- getModel: () => this.model,
2849
- isIdle: () => !this._foregroundRecovery.isBusy,
2850
- getSignal: () => this.agent.signal,
2851
- abort: () => {
2852
- if (this._extensionAbortHandler) {
2853
- this._extensionAbortHandler();
2854
- return;
2855
- }
2856
- void this.abort();
2857
- },
2858
- hasPendingMessages: () => this.pendingMessageCount > 0,
2859
- shutdown: () => {
2860
- this._extensionShutdownHandler?.();
2861
- },
2862
- getContextUsage: () => this.getContextUsage(),
2863
- compact: (options) => this.compactForExtension(options),
2864
- reload: () => {
2865
- if (this.isStreaming) {
2866
- return Promise.reject(new Error("ctx.reload() cannot run while the agent is streaming or a tool call is active. Wait for ctx.isIdle(), queue a follow-up /reload, or use an idle command/event handler so hot reload cannot destabilize the UI."));
2867
- }
2868
- if (this.isCompacting) {
2869
- return Promise.reject(new Error("ctx.reload() cannot run during context compaction or branch summarization. Let compaction finish before reloading so the session tree and UI remain stable."));
2870
- }
2871
- const actions = this._extensionCommandContextActions;
2872
- if (!actions) {
2873
- return this.reload();
2874
- }
2875
- return actions.reload();
2876
- },
2877
- getSystemPrompt: () => this.systemPrompt,
2878
- }, {
2879
- registerProvider: (name, config) => {
2880
- this._modelRegistry.registerProvider(name, config);
2881
- this._refreshCurrentModelFromRegistry();
2882
- },
2883
- unregisterProvider: (name) => {
2884
- this._modelRegistry.unregisterProvider(name);
2885
- this._refreshCurrentModelFromRegistry();
2886
- },
2887
- });
2888
- }
2889
2801
  /** Register a memory provider contributed by an extension; applied on the next memory (re)init. */
2890
2802
  registerMemoryProvider(provider) {
2891
2803
  this._memory.registerMemoryProvider(provider);
@@ -3042,14 +2954,9 @@ export class AgentSession {
3042
2954
  return this._goals.getState();
3043
2955
  }
3044
2956
  /**
3045
- * Persist one submitted continuation pass's exact turn/wall-clock/token/spend contribution onto the active
3046
- * goal's durable cumulative accounting (see `GoalState.continuationTurnsUsed` et al.). This is the
3047
- * "persistence dep" `GoalLoopController` calls once per pass actually submitted — it, not the
3048
- * loop controller, is where usage gets attributed: it scans only assistant messages appended on
3049
- * the active branch after the pass's captured cursor. Compaction cannot erase or reattribute that
3050
- * append-only interval, and unrelated foreground turns outside the interval are excluded.
3051
- * A no-op when no goal state exists (defensive — in practice this is only ever called right
3052
- * after a pass the loop already confirmed was submitted against an active goal).
2957
+ * Persist one submitted continuation pass's turn and active-wall-clock telemetry. Provider usage
2958
+ * is charged separately at every assistant-response boundary under an identity-bound goal lease.
2959
+ * A no-op when no goal state exists.
3053
2960
  */
3054
2961
  recordGoalContinuationPass(pass) {
3055
2962
  this._goals.recordContinuationPass(pass);