@astralyn/pi 0.87.5 → 0.87.6

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 (173) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/bundle/chunks/{chunk-EWLAVDVN.js → chunk-4W4Q2H6W.js} +55 -54
  3. package/dist/bundle/chunks/{chunk-APQ4ACY3.js → chunk-IORR2FW4.js} +1 -1
  4. package/dist/bundle/chunks/{virtual-modules-W3OGMIX7.js → virtual-modules-KUEIEAZN.js} +1 -1
  5. package/dist/bundle/cli.js +1 -1
  6. package/dist/bundle/index.js +1 -1
  7. package/dist/bundle/rpc-entry.js +1 -1
  8. package/dist/core/agent-session.d.ts +8 -24
  9. package/dist/core/agent-session.d.ts.map +1 -1
  10. package/dist/core/agent-session.js +54 -109
  11. package/dist/core/agent-session.js.map +1 -1
  12. package/dist/core/background/session.d.ts +11 -7
  13. package/dist/core/background/session.d.ts.map +1 -1
  14. package/dist/core/background/session.js +42 -16
  15. package/dist/core/background/session.js.map +1 -1
  16. package/dist/core/context-snapshot.d.ts +17 -4
  17. package/dist/core/context-snapshot.d.ts.map +1 -1
  18. package/dist/core/context-snapshot.js +48 -50
  19. package/dist/core/context-snapshot.js.map +1 -1
  20. package/dist/core/extensions/distribution-api.d.ts +0 -7
  21. package/dist/core/extensions/distribution-api.d.ts.map +1 -1
  22. package/dist/core/extensions/distribution-api.js +6 -6
  23. package/dist/core/extensions/distribution-api.js.map +1 -1
  24. package/dist/core/extensions/index.d.ts +1 -1
  25. package/dist/core/extensions/index.d.ts.map +1 -1
  26. package/dist/core/extensions/index.js +1 -1
  27. package/dist/core/extensions/index.js.map +1 -1
  28. package/dist/core/extensions/loader.d.ts +1 -1
  29. package/dist/core/extensions/loader.d.ts.map +1 -1
  30. package/dist/core/extensions/loader.js +3 -2
  31. package/dist/core/extensions/loader.js.map +1 -1
  32. package/dist/core/extensions/types.d.ts +1 -5
  33. package/dist/core/extensions/types.d.ts.map +1 -1
  34. package/dist/core/extensions/types.js +1 -1
  35. package/dist/core/extensions/types.js.map +1 -1
  36. package/dist/core/keybindings.d.ts +10 -0
  37. package/dist/core/keybindings.d.ts.map +1 -1
  38. package/dist/core/keybindings.js +3 -0
  39. package/dist/core/keybindings.js.map +1 -1
  40. package/dist/core/sdk.d.ts.map +1 -1
  41. package/dist/core/sdk.js +59 -7
  42. package/dist/core/sdk.js.map +1 -1
  43. package/dist/core/tools/bash.d.ts +1 -3
  44. package/dist/core/tools/bash.d.ts.map +1 -1
  45. package/dist/core/tools/bash.js.map +1 -1
  46. package/dist/core/tools/find.d.ts.map +1 -1
  47. package/dist/core/tools/find.js +0 -1
  48. package/dist/core/tools/find.js.map +1 -1
  49. package/dist/core/tools/grep.d.ts.map +1 -1
  50. package/dist/core/tools/grep.js +0 -1
  51. package/dist/core/tools/grep.js.map +1 -1
  52. package/dist/core/tools/ls.d.ts.map +1 -1
  53. package/dist/core/tools/ls.js +0 -1
  54. package/dist/core/tools/ls.js.map +1 -1
  55. package/dist/core/tools/read.d.ts.map +1 -1
  56. package/dist/core/tools/read.js +0 -1
  57. package/dist/core/tools/read.js.map +1 -1
  58. package/dist/core/tools/render-utils.d.ts +0 -7
  59. package/dist/core/tools/render-utils.d.ts.map +1 -1
  60. package/dist/core/tools/render-utils.js +0 -11
  61. package/dist/core/tools/render-utils.js.map +1 -1
  62. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  63. package/dist/core/tools/renderers/bash.js +59 -5
  64. package/dist/core/tools/renderers/bash.js.map +1 -1
  65. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  66. package/dist/core/tools/renderers/edit.js +4 -22
  67. package/dist/core/tools/renderers/edit.js.map +1 -1
  68. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  69. package/dist/core/tools/renderers/find.js +7 -6
  70. package/dist/core/tools/renderers/find.js.map +1 -1
  71. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  72. package/dist/core/tools/renderers/grep.js +8 -7
  73. package/dist/core/tools/renderers/grep.js.map +1 -1
  74. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  75. package/dist/core/tools/renderers/ls.js +3 -2
  76. package/dist/core/tools/renderers/ls.js.map +1 -1
  77. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  78. package/dist/core/tools/renderers/read.js +7 -12
  79. package/dist/core/tools/renderers/read.js.map +1 -1
  80. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  81. package/dist/core/tools/renderers/write.js +3 -2
  82. package/dist/core/tools/renderers/write.js.map +1 -1
  83. package/dist/core/tools/tool-definition-wrapper.d.ts +2 -6
  84. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  85. package/dist/core/tools/tool-definition-wrapper.js +0 -2
  86. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  87. package/dist/extensions/background/completion-render.d.ts.map +1 -1
  88. package/dist/extensions/background/completion-render.js +3 -4
  89. package/dist/extensions/background/completion-render.js.map +1 -1
  90. package/dist/extensions/background/constants.d.ts +2 -0
  91. package/dist/extensions/background/constants.d.ts.map +1 -1
  92. package/dist/extensions/background/constants.js +2 -0
  93. package/dist/extensions/background/constants.js.map +1 -1
  94. package/dist/extensions/background/index.d.ts.map +1 -1
  95. package/dist/extensions/background/index.js +31 -5
  96. package/dist/extensions/background/index.js.map +1 -1
  97. package/dist/extensions/question/detail-pane.d.ts +12 -0
  98. package/dist/extensions/question/detail-pane.d.ts.map +1 -0
  99. package/dist/extensions/question/detail-pane.js +42 -0
  100. package/dist/extensions/question/detail-pane.js.map +1 -0
  101. package/dist/extensions/question/dialog.d.ts.map +1 -1
  102. package/dist/extensions/question/dialog.js +175 -105
  103. package/dist/extensions/question/dialog.js.map +1 -1
  104. package/dist/extensions/question/option-window.d.ts +26 -0
  105. package/dist/extensions/question/option-window.d.ts.map +1 -0
  106. package/dist/extensions/question/option-window.js +53 -0
  107. package/dist/extensions/question/option-window.js.map +1 -0
  108. package/dist/extensions/question/render-cache.d.ts +4 -4
  109. package/dist/extensions/question/render-cache.d.ts.map +1 -1
  110. package/dist/extensions/question/render-cache.js +10 -11
  111. package/dist/extensions/question/render-cache.js.map +1 -1
  112. package/dist/extensions/todo/index.d.ts.map +1 -1
  113. package/dist/extensions/todo/index.js +12 -8
  114. package/dist/extensions/todo/index.js.map +1 -1
  115. package/dist/extensions/todo/view.d.ts +3 -3
  116. package/dist/extensions/todo/view.d.ts.map +1 -1
  117. package/dist/extensions/todo/view.js +7 -6
  118. package/dist/extensions/todo/view.js.map +1 -1
  119. package/dist/modes/interactive/components/index.d.ts +1 -1
  120. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  121. package/dist/modes/interactive/components/index.js +1 -1
  122. package/dist/modes/interactive/components/index.js.map +1 -1
  123. package/dist/modes/interactive/components/status-marker.d.ts +2 -2
  124. package/dist/modes/interactive/components/status-marker.js +2 -2
  125. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  126. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  127. package/dist/modes/interactive/interactive-mode.js +7 -10
  128. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  129. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  130. package/dist/modes/interactive/theme/theme.js +2 -3
  131. package/dist/modes/interactive/theme/theme.js.map +1 -1
  132. package/dist/modes/interactive/tool-view/chat.d.ts +20 -0
  133. package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -0
  134. package/dist/modes/interactive/tool-view/chat.js +46 -0
  135. package/dist/modes/interactive/tool-view/chat.js.map +1 -0
  136. package/dist/modes/interactive/tool-view/fallback.d.ts +14 -0
  137. package/dist/modes/interactive/tool-view/fallback.d.ts.map +1 -0
  138. package/dist/modes/interactive/tool-view/fallback.js +52 -0
  139. package/dist/modes/interactive/tool-view/fallback.js.map +1 -0
  140. package/dist/modes/interactive/tool-view/style.d.ts +63 -0
  141. package/dist/modes/interactive/tool-view/style.d.ts.map +1 -0
  142. package/dist/modes/interactive/tool-view/style.js +83 -0
  143. package/dist/modes/interactive/tool-view/style.js.map +1 -0
  144. package/dist/modes/interactive/{components → tool-view}/tool-execution.d.ts +17 -24
  145. package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -0
  146. package/dist/modes/interactive/{components → tool-view}/tool-execution.js +42 -116
  147. package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -0
  148. package/docs/bundled/README.md +1 -1
  149. package/docs/bundled/extensions/background.md +1 -1
  150. package/docs/bundled/extensions/question.md +6 -5
  151. package/docs/bundled/tool-presentation.md +41 -31
  152. package/docs/extensions.md +1 -4
  153. package/docs/keybindings.md +11 -0
  154. package/npm-shrinkwrap.json +2 -2
  155. package/package.json +1 -1
  156. package/dist/core/model-stream-options.d.ts +0 -6
  157. package/dist/core/model-stream-options.d.ts.map +0 -1
  158. package/dist/core/model-stream-options.js +0 -20
  159. package/dist/core/model-stream-options.js.map +0 -1
  160. package/dist/modes/interactive/components/tool-chrome.d.ts +0 -28
  161. package/dist/modes/interactive/components/tool-chrome.d.ts.map +0 -1
  162. package/dist/modes/interactive/components/tool-chrome.js +0 -84
  163. package/dist/modes/interactive/components/tool-chrome.js.map +0 -1
  164. package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
  165. package/dist/modes/interactive/components/tool-execution.js.map +0 -1
  166. package/dist/modes/interactive/components/tool-group.d.ts +0 -17
  167. package/dist/modes/interactive/components/tool-group.d.ts.map +0 -1
  168. package/dist/modes/interactive/components/tool-group.js +0 -78
  169. package/dist/modes/interactive/components/tool-group.js.map +0 -1
  170. package/dist/modes/interactive/tool-chat.d.ts +0 -21
  171. package/dist/modes/interactive/tool-chat.d.ts.map +0 -1
  172. package/dist/modes/interactive/tool-chat.js +0 -58
  173. package/dist/modes/interactive/tool-chat.js.map +0 -1
@@ -10,11 +10,10 @@ interface BackgroundSessionOptions {
10
10
  /** The main session owns prompt queues, preflight and idle state. */
11
11
  canDeliver(): boolean;
12
12
  /**
13
- * Hand one completion to the host's prompt path. The promise must settle only after the
14
- * message is persisted, or after it can no longer be persisted: a claim is released for
15
- * a delivery attempt that ended without the transcript containing the message.
13
+ * Start a completion turn, or enqueue the message and return waitForPersistence().
14
+ * The host owns prompt routing; this adapter owns the queued delivery's lifetime.
16
15
  */
17
- deliver(message: CustomMessage): Promise<void>;
16
+ deliver(message: CustomMessage, waitForPersistence: () => Promise<void>): Promise<void>;
18
17
  onEntry(entry: SessionEntry): void;
19
18
  onError(event: string, message: string): void;
20
19
  }
@@ -53,10 +52,15 @@ export declare class BackgroundSession {
53
52
  private schedule;
54
53
  private canDeliver;
55
54
  private drain;
56
- /** Capture before message hooks, invoke only after the resulting message was persisted. */
57
- messageAcknowledgement(message: AgentMessage): (() => void) | undefined;
55
+ /** Record dequeueing before message hooks can fail or rewrite the notification. */
56
+ messageStarted(message: AgentMessage): void;
57
+ /** A queued message that was never emitted remains claimed for the next run. */
58
+ agentEnded(): void;
59
+ queueCleared(): void;
60
+ /** Acknowledge only successful appends, using identity even when metadata was rewritten. */
61
+ messagePersisted(message: AgentMessage): void;
58
62
  /** A wait result claims delivery only through its final, persisted marker. */
59
- acknowledgeWaitResult(details: unknown): void;
63
+ private acknowledgeWaitResult;
60
64
  dispose(): void;
61
65
  }
62
66
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/core/background/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,YAAY,CAAC;AAEvE,UAAU,wBAAwB;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC;IAC1B,qEAAqE;IACrE,UAAU,IAAI,OAAO,CAAC;IACtB;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,+BAA+B;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;CACd;AAQD,qGAAqG;AACrG,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAAC,CAAgC;IAC9C,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyC;gBAExD,OAAO,EAAE,wBAAwB;IAK7C,IAAI,OAAO,IAAI,iBAAiB,CAE/B;IAED,IAAI,sBAAsB,IAAI,SAAS,+BAA+B,EAAE,CAEvE;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKlC,2FAA2F;IAC3F,cAAc,IAAI,IAAI;IAMtB,OAAO,CAAC,aAAa;IA0BrB,cAAc,CAAC,OAAO,oBAAe,GAAG,IAAI;IAU5C,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,IAAI;IAQZ,sEAAsE;IACtE,KAAK,IAAI,MAAM,IAAI;IAanB,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,UAAU;YAMJ,KAAK;IAmCnB,2FAA2F;IAC3F,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS;IAYvE,8EAA8E;IAC9E,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAY7C,OAAO,IAAI,IAAI;CAMf"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/core/background/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,YAAY,CAAC;AAEvE,UAAU,wBAAwB;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC;IAC1B,qEAAqE;IACrE,UAAU,IAAI,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxF,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,+BAA+B;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;CACd;AAWD,qGAAqG;AACrG,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAAC,CAAgC;IAC9C,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyC;gBAExD,OAAO,EAAE,wBAAwB;IAK7C,IAAI,OAAO,IAAI,iBAAiB,CAE/B;IAED,IAAI,sBAAsB,IAAI,SAAS,+BAA+B,EAAE,CAEvE;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKlC,2FAA2F;IAC3F,cAAc,IAAI,IAAI;IAMtB,OAAO,CAAC,aAAa;IA0BrB,cAAc,CAAC,OAAO,oBAAe,GAAG,IAAI;IAU5C,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,IAAI;IAQZ,sEAAsE;IACtE,KAAK,IAAI,MAAM,IAAI;IAanB,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,UAAU;YAMJ,KAAK;IAiDnB,mFAAmF;IACnF,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAK3C,gFAAgF;IAChF,UAAU,IAAI,IAAI;IAOlB,YAAY,IAAI,IAAI;IAIpB,4FAA4F;IAC5F,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAU7C,8EAA8E;IAC9E,OAAO,CAAC,qBAAqB;IAY7B,OAAO,IAAI,IAAI;CAOf"}
@@ -158,21 +158,34 @@ export class BackgroundSession {
158
158
  this.failures.delete(id);
159
159
  }
160
160
  const task = service.pendingNotifications().find((task) => !this.failures.has(task.id));
161
- if (!task || !service.claimNotification(task.id))
161
+ if (!task)
162
+ return;
163
+ const message = backgroundCompletionMessage(task);
164
+ if (!service.claimNotification(task.id))
162
165
  return;
163
166
  // Exactly one completion may be in flight, whether queued for steering or running its
164
167
  // own turn; there is no separate claim registry.
165
- const delivery = { id: task.id, service, persisted: false };
168
+ const delivery = {
169
+ id: task.id,
170
+ service,
171
+ message,
172
+ phase: "pending",
173
+ };
166
174
  this.delivery = delivery;
167
175
  let deliveryError;
168
176
  try {
169
- await this.options.deliver(backgroundCompletionMessage(task));
177
+ await this.options.deliver(delivery.message, () => new Promise((resolve, reject) => {
178
+ if (delivery.phase === "persisted")
179
+ resolve();
180
+ else
181
+ delivery.queued = { resolve, reject };
182
+ }));
170
183
  }
171
184
  catch (error) {
172
185
  deliveryError = error;
173
186
  }
174
187
  finally {
175
- if (!delivery.persisted) {
188
+ if (delivery.phase !== "persisted") {
176
189
  service.releaseNotification(task.id);
177
190
  if (service === this.service)
178
191
  this.failures.add(task.id);
@@ -185,20 +198,32 @@ export class BackgroundSession {
185
198
  this.schedule();
186
199
  }
187
200
  }
188
- /** Capture before message hooks, invoke only after the resulting message was persisted. */
189
- messageAcknowledgement(message) {
190
- if (message.role !== "custom" || message.customType !== "background-completion")
191
- return;
192
- const details = message.details;
201
+ /** Record dequeueing before message hooks can fail or rewrite the notification. */
202
+ messageStarted(message) {
193
203
  const delivery = this.delivery;
194
- if (!delivery || details?.taskId !== delivery.id)
195
- return;
196
- return () => {
197
- if (delivery.persisted)
198
- return;
199
- delivery.persisted = true;
204
+ if (delivery?.message === message && delivery.phase === "pending")
205
+ delivery.phase = "started";
206
+ }
207
+ /** A queued message that was never emitted remains claimed for the next run. */
208
+ agentEnded() {
209
+ const delivery = this.delivery;
210
+ if (delivery?.phase === "started") {
211
+ delivery.queued?.reject(new Error("the completion message was not persisted"));
212
+ }
213
+ }
214
+ queueCleared() {
215
+ this.delivery?.queued?.reject(new Error("the completion message was dequeued before delivery"));
216
+ }
217
+ /** Acknowledge only successful appends, using identity even when metadata was rewritten. */
218
+ messagePersisted(message) {
219
+ const delivery = this.delivery;
220
+ if (delivery?.message === message && delivery.phase !== "persisted") {
221
+ delivery.phase = "persisted";
200
222
  delivery.service.markDelivered(delivery.id);
201
- };
223
+ delivery.queued?.resolve();
224
+ }
225
+ if (message.role === "toolResult")
226
+ this.acknowledgeWaitResult(message.details);
202
227
  }
203
228
  /** A wait result claims delivery only through its final, persisted marker. */
204
229
  acknowledgeWaitResult(details) {
@@ -214,6 +239,7 @@ export class BackgroundSession {
214
239
  dispose() {
215
240
  this.disposed = true;
216
241
  this.service.close();
242
+ this.delivery?.queued?.reject(new Error("the session was disposed"));
217
243
  if (this.timer)
218
244
  clearTimeout(this.timer);
219
245
  this.timer = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/core/background/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { CustomMessage } from \"../messages.ts\";\nimport type { SessionEntry, SessionManager } from \"../session-manager.ts\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { BACKGROUND_USAGE_TYPE, getBackgroundUsageRecord } from \"../usage-totals.ts\";\nimport { BACKGROUND_HISTORY_VERSION } from \"./history.ts\";\nimport { backgroundCompletionMessage } from \"./presentation.ts\";\nimport { BackgroundService } from \"./service.ts\";\nimport { type BackgroundTask, isBackgroundTerminal } from \"./types.ts\";\n\ninterface BackgroundSessionOptions {\n\tmanager: SessionManager;\n\trole: \"main\" | \"subagent\";\n\t/** The main session owns prompt queues, preflight and idle state. */\n\tcanDeliver(): boolean;\n\t/**\n\t * Hand one completion to the host's prompt path. The promise must settle only after the\n\t * message is persisted, or after it can no longer be persisted: a claim is released for\n\t * a delivery attempt that ended without the transcript containing the message.\n\t */\n\tdeliver(message: CustomMessage): Promise<void>;\n\tonEntry(entry: SessionEntry): void;\n\tonError(event: string, message: string): void;\n}\n\nexport interface QuarantinedBackgroundSettlement {\n\tsessionId: string;\n\tgeneration: number;\n\ttask: BackgroundTask;\n\tusage?: Usage;\n}\n\ninterface Delivery {\n\tid: string;\n\tservice: BackgroundService;\n\tpersisted: boolean;\n}\n\n/** Session persistence and completion delivery; execution supervision stays in BackgroundService. */\nexport class BackgroundSession {\n\tprivate readonly options: BackgroundSessionOptions;\n\tprivate _service: BackgroundService;\n\tprivate enabled = false;\n\tprivate disposed = false;\n\tprivate generation = 0;\n\tprivate pauses = 0;\n\tprivate timer?: ReturnType<typeof setTimeout>;\n\tprivate delivery?: Delivery;\n\tprivate readonly failures = new Set<string>();\n\tprivate readonly quarantine: QuarantinedBackgroundSettlement[] = [];\n\n\tconstructor(options: BackgroundSessionOptions) {\n\t\tthis.options = options;\n\t\tthis._service = this.createService();\n\t}\n\n\tget service(): BackgroundService {\n\t\treturn this._service;\n\t}\n\n\tget quarantinedSettlements(): readonly QuarantinedBackgroundSettlement[] {\n\t\treturn structuredClone(this.quarantine);\n\t}\n\n\tsetEnabled(enabled: boolean): void {\n\t\tthis.enabled = enabled && this.options.role === \"main\";\n\t\tthis.service.setEnabled(this.enabled);\n\t}\n\n\t/** Called after the old service's bounded shutdown, while lifecycle delivery is paused. */\n\treplaceService(): void {\n\t\tthis.service.close();\n\t\tthis._service = this.createService();\n\t\tthis.failures.clear();\n\t}\n\n\tprivate createService(): BackgroundService {\n\t\tconst { manager, role } = this.options;\n\t\tconst generation = ++this.generation;\n\t\tconst sessionId = manager.getSessionId();\n\t\tconst sessionFile = manager.getSessionFile();\n\t\tconst service = new BackgroundService({\n\t\t\tenabled: this.enabled,\n\t\t\trole,\n\t\t\tanchor: () => manager.getLeafId(),\n\t\t\tonCleanupError: (message) => this.warn(\"background_cleanup\", message),\n\t\t\tonSettled: (task, usage) => {\n\t\t\t\tconst onBranch =\n\t\t\t\t\tmanager.getSessionId() === sessionId &&\n\t\t\t\t\t(task.anchorId === null || manager.getBranch().some((entry) => entry.id === task.anchorId));\n\t\t\t\tif (this.disposed || this.service !== service || !onBranch) {\n\t\t\t\t\tthis.quarantineSettlement({ sessionId, generation, task, usage }, sessionFile);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.persistSettlement(task, usage);\n\t\t\t},\n\t\t});\n\t\tthis.restoreHistory(service);\n\t\tservice.subscribe(() => this.schedule());\n\t\treturn service;\n\t}\n\n\trestoreHistory(service = this.service): void {\n\t\tservice.restoreHistory(\n\t\t\tthis.options.manager\n\t\t\t\t.getBranch()\n\t\t\t\t.flatMap((entry) =>\n\t\t\t\t\tentry.type === \"custom\" && entry.customType === \"background-task-result\" ? [entry.data] : [],\n\t\t\t\t),\n\t\t);\n\t}\n\n\tprivate quarantineSettlement(record: QuarantinedBackgroundSettlement, sessionFile: string | undefined): void {\n\t\t// Never move the active leaf to append late usage: JSONL's last entry also\n\t\t// selects its resumed branch. The sidecar is diagnostic evidence only.\n\t\tthis.quarantine.push(structuredClone(record));\n\t\tif (this.quarantine.length > 32) this.quarantine.shift();\n\t\tlet persistence =\n\t\t\t\"Not persisted: only the latest 32 snapshots are retained in quarantinedBackgroundSettlements; late usage is not accounted in session totals.\";\n\t\tif (sessionFile) {\n\t\t\ttry {\n\t\t\t\tmkdirSync(dirname(sessionFile), { recursive: true });\n\t\t\t\tappendFileSync(`${sessionFile}.background-late.jsonl`, `${JSON.stringify({ version: 1, ...record })}\\n`);\n\t\t\t\tpersistence = `Saved diagnostic sidecar: ${sessionFile}.background-late.jsonl (not included in normal session totals).`;\n\t\t\t} catch {\n\t\t\t\tpersistence = `Sidecar write failed. ${persistence}`;\n\t\t\t}\n\t\t}\n\t\tthis.warn(\n\t\t\t\"background_settlement_quarantined\",\n\t\t\t`Late background settlement ${record.task.id} was quarantined. ${persistence}`,\n\t\t);\n\t}\n\n\tprivate persistSettlement(task: BackgroundTask, usage: Usage | undefined): void {\n\t\tconst manager = this.options.manager;\n\t\tconst appended: SessionEntry[] = [];\n\t\tconst append = (customType: string, data: unknown) => {\n\t\t\tconst entry = manager.getEntry(manager.appendCustomEntry(customType, data));\n\t\t\tif (entry) appended.push(entry);\n\t\t};\n\t\ttry {\n\t\t\tif (usage && !manager.getEntries().some((entry) => getBackgroundUsageRecord(entry)?.taskId === task.id)) {\n\t\t\t\tappend(BACKGROUND_USAGE_TYPE, { version: 1, taskId: task.id, usage });\n\t\t\t}\n\t\t\tappend(\"background-task-result\", JSON.parse(JSON.stringify({ version: BACKGROUND_HISTORY_VERSION, task })));\n\t\t} finally {\n\t\t\t// Complete the writes before observers can replace the runtime or its manager.\n\t\t\t// If a write fails, still report entries that were successfully appended.\n\t\t\tfor (const entry of appended) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.options.onEntry(entry);\n\t\t\t\t} catch {\n\t\t\t\t\t// Observers cannot interrupt settlement or result publication.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate warn(event: string, message: string): void {\n\t\ttry {\n\t\t\tthis.options.onError(event, truncateHead(message, { maxBytes: 4096, maxLines: 32 }).content);\n\t\t} catch {\n\t\t\t// Diagnostics cannot reject settlement, cleanup or scheduled callbacks.\n\t\t}\n\t}\n\n\t/** Nestable across asynchronous preflight and service replacement. */\n\tpause(): () => void {\n\t\tthis.pauses++;\n\t\tconst releaseService = this.service.pause();\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tthis.pauses--;\n\t\t\treleaseService();\n\t\t\tthis.schedule();\n\t\t};\n\t}\n\n\tretry(): void {\n\t\tthis.failures.clear();\n\t\tthis.schedule();\n\t}\n\n\tprivate schedule(): void {\n\t\tif (this.disposed || this.timer || this.delivery) return;\n\t\tthis.timer = setTimeout(() => {\n\t\t\tthis.timer = undefined;\n\t\t\tvoid this.drain().catch(() =>\n\t\t\t\tthis.warn(\"background_delivery\", \"Background notification drain failed; delivery was not confirmed.\"),\n\t\t\t);\n\t\t}, 0);\n\t\tthis.timer.unref?.();\n\t}\n\n\tprivate canDeliver(service: BackgroundService): boolean {\n\t\treturn (\n\t\t\t!this.disposed && service === this.service && service.enabled && this.pauses === 0 && this.options.canDeliver()\n\t\t);\n\t}\n\n\tprivate async drain(): Promise<void> {\n\t\tconst service = this.service;\n\t\tif (this.delivery || !this.canDeliver(service)) return;\n\t\tif (this.failures.size) {\n\t\t\tconst retained = new Set(service.list().map((task) => task.id));\n\t\t\tfor (const id of this.failures) if (!retained.has(id)) this.failures.delete(id);\n\t\t}\n\t\tconst task = service.pendingNotifications().find((task) => !this.failures.has(task.id));\n\t\tif (!task || !service.claimNotification(task.id)) return;\n\t\t// Exactly one completion may be in flight, whether queued for steering or running its\n\t\t// own turn; there is no separate claim registry.\n\t\tconst delivery: Delivery = { id: task.id, service, persisted: false };\n\t\tthis.delivery = delivery;\n\t\tlet deliveryError: unknown;\n\t\ttry {\n\t\t\tawait this.options.deliver(backgroundCompletionMessage(task));\n\t\t} catch (error) {\n\t\t\tdeliveryError = error;\n\t\t} finally {\n\t\t\tif (!delivery.persisted) {\n\t\t\t\tservice.releaseNotification(task.id);\n\t\t\t\tif (service === this.service) this.failures.add(task.id);\n\t\t\t\tconst reason = deliveryError instanceof Error ? `: ${deliveryError.message}` : \"\";\n\t\t\t\tthis.warn(\n\t\t\t\t\t\"background_delivery\",\n\t\t\t\t\t`Background completion delivery failed for ${task.id}${reason}; it will retry on the next prompt.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.delivery = undefined;\n\t\t\tconst current = this.service;\n\t\t\tif (this.canDeliver(current) && current.pendingNotifications().some((task) => !this.failures.has(task.id)))\n\t\t\t\tthis.schedule();\n\t\t}\n\t}\n\n\t/** Capture before message hooks, invoke only after the resulting message was persisted. */\n\tmessageAcknowledgement(message: AgentMessage): (() => void) | undefined {\n\t\tif (message.role !== \"custom\" || message.customType !== \"background-completion\") return;\n\t\tconst details = message.details as { taskId?: unknown } | undefined;\n\t\tconst delivery = this.delivery;\n\t\tif (!delivery || details?.taskId !== delivery.id) return;\n\t\treturn () => {\n\t\t\tif (delivery.persisted) return;\n\t\t\tdelivery.persisted = true;\n\t\t\tdelivery.service.markDelivered(delivery.id);\n\t\t};\n\t}\n\n\t/** A wait result claims delivery only through its final, persisted marker. */\n\tacknowledgeWaitResult(details: unknown): void {\n\t\tif (!details || typeof details !== \"object\" || !(\"backgroundTaskId\" in details)) return;\n\t\tconst id = details.backgroundTaskId;\n\t\tif (\n\t\t\ttypeof id === \"string\" &&\n\t\t\tthis.service\n\t\t\t\t.list()\n\t\t\t\t.some((task) => task.id === id && task.mode === \"background\" && isBackgroundTerminal(task.status))\n\t\t)\n\t\t\tthis.service.markDelivered(id);\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.service.close();\n\t\tif (this.timer) clearTimeout(this.timer);\n\t\tthis.timer = undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/core/background/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { CustomMessage } from \"../messages.ts\";\nimport type { SessionEntry, SessionManager } from \"../session-manager.ts\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { BACKGROUND_USAGE_TYPE, getBackgroundUsageRecord } from \"../usage-totals.ts\";\nimport { BACKGROUND_HISTORY_VERSION } from \"./history.ts\";\nimport { backgroundCompletionMessage } from \"./presentation.ts\";\nimport { BackgroundService } from \"./service.ts\";\nimport { type BackgroundTask, isBackgroundTerminal } from \"./types.ts\";\n\ninterface BackgroundSessionOptions {\n\tmanager: SessionManager;\n\trole: \"main\" | \"subagent\";\n\t/** The main session owns prompt queues, preflight and idle state. */\n\tcanDeliver(): boolean;\n\t/**\n\t * Start a completion turn, or enqueue the message and return waitForPersistence().\n\t * The host owns prompt routing; this adapter owns the queued delivery's lifetime.\n\t */\n\tdeliver(message: CustomMessage, waitForPersistence: () => Promise<void>): Promise<void>;\n\tonEntry(entry: SessionEntry): void;\n\tonError(event: string, message: string): void;\n}\n\nexport interface QuarantinedBackgroundSettlement {\n\tsessionId: string;\n\tgeneration: number;\n\ttask: BackgroundTask;\n\tusage?: Usage;\n}\n\ninterface Delivery {\n\tid: string;\n\tservice: BackgroundService;\n\t/** Agent-core preserves message identity; extension rewrites mutate it in place. */\n\tmessage: CustomMessage;\n\tphase: \"pending\" | \"started\" | \"persisted\";\n\tqueued?: { resolve(): void; reject(reason: Error): void };\n}\n\n/** Session persistence and completion delivery; execution supervision stays in BackgroundService. */\nexport class BackgroundSession {\n\tprivate readonly options: BackgroundSessionOptions;\n\tprivate _service: BackgroundService;\n\tprivate enabled = false;\n\tprivate disposed = false;\n\tprivate generation = 0;\n\tprivate pauses = 0;\n\tprivate timer?: ReturnType<typeof setTimeout>;\n\tprivate delivery?: Delivery;\n\tprivate readonly failures = new Set<string>();\n\tprivate readonly quarantine: QuarantinedBackgroundSettlement[] = [];\n\n\tconstructor(options: BackgroundSessionOptions) {\n\t\tthis.options = options;\n\t\tthis._service = this.createService();\n\t}\n\n\tget service(): BackgroundService {\n\t\treturn this._service;\n\t}\n\n\tget quarantinedSettlements(): readonly QuarantinedBackgroundSettlement[] {\n\t\treturn structuredClone(this.quarantine);\n\t}\n\n\tsetEnabled(enabled: boolean): void {\n\t\tthis.enabled = enabled && this.options.role === \"main\";\n\t\tthis.service.setEnabled(this.enabled);\n\t}\n\n\t/** Called after the old service's bounded shutdown, while lifecycle delivery is paused. */\n\treplaceService(): void {\n\t\tthis.service.close();\n\t\tthis._service = this.createService();\n\t\tthis.failures.clear();\n\t}\n\n\tprivate createService(): BackgroundService {\n\t\tconst { manager, role } = this.options;\n\t\tconst generation = ++this.generation;\n\t\tconst sessionId = manager.getSessionId();\n\t\tconst sessionFile = manager.getSessionFile();\n\t\tconst service = new BackgroundService({\n\t\t\tenabled: this.enabled,\n\t\t\trole,\n\t\t\tanchor: () => manager.getLeafId(),\n\t\t\tonCleanupError: (message) => this.warn(\"background_cleanup\", message),\n\t\t\tonSettled: (task, usage) => {\n\t\t\t\tconst onBranch =\n\t\t\t\t\tmanager.getSessionId() === sessionId &&\n\t\t\t\t\t(task.anchorId === null || manager.getBranch().some((entry) => entry.id === task.anchorId));\n\t\t\t\tif (this.disposed || this.service !== service || !onBranch) {\n\t\t\t\t\tthis.quarantineSettlement({ sessionId, generation, task, usage }, sessionFile);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.persistSettlement(task, usage);\n\t\t\t},\n\t\t});\n\t\tthis.restoreHistory(service);\n\t\tservice.subscribe(() => this.schedule());\n\t\treturn service;\n\t}\n\n\trestoreHistory(service = this.service): void {\n\t\tservice.restoreHistory(\n\t\t\tthis.options.manager\n\t\t\t\t.getBranch()\n\t\t\t\t.flatMap((entry) =>\n\t\t\t\t\tentry.type === \"custom\" && entry.customType === \"background-task-result\" ? [entry.data] : [],\n\t\t\t\t),\n\t\t);\n\t}\n\n\tprivate quarantineSettlement(record: QuarantinedBackgroundSettlement, sessionFile: string | undefined): void {\n\t\t// Never move the active leaf to append late usage: JSONL's last entry also\n\t\t// selects its resumed branch. The sidecar is diagnostic evidence only.\n\t\tthis.quarantine.push(structuredClone(record));\n\t\tif (this.quarantine.length > 32) this.quarantine.shift();\n\t\tlet persistence =\n\t\t\t\"Not persisted: only the latest 32 snapshots are retained in quarantinedBackgroundSettlements; late usage is not accounted in session totals.\";\n\t\tif (sessionFile) {\n\t\t\ttry {\n\t\t\t\tmkdirSync(dirname(sessionFile), { recursive: true });\n\t\t\t\tappendFileSync(`${sessionFile}.background-late.jsonl`, `${JSON.stringify({ version: 1, ...record })}\\n`);\n\t\t\t\tpersistence = `Saved diagnostic sidecar: ${sessionFile}.background-late.jsonl (not included in normal session totals).`;\n\t\t\t} catch {\n\t\t\t\tpersistence = `Sidecar write failed. ${persistence}`;\n\t\t\t}\n\t\t}\n\t\tthis.warn(\n\t\t\t\"background_settlement_quarantined\",\n\t\t\t`Late background settlement ${record.task.id} was quarantined. ${persistence}`,\n\t\t);\n\t}\n\n\tprivate persistSettlement(task: BackgroundTask, usage: Usage | undefined): void {\n\t\tconst manager = this.options.manager;\n\t\tconst appended: SessionEntry[] = [];\n\t\tconst append = (customType: string, data: unknown) => {\n\t\t\tconst entry = manager.getEntry(manager.appendCustomEntry(customType, data));\n\t\t\tif (entry) appended.push(entry);\n\t\t};\n\t\ttry {\n\t\t\tif (usage && !manager.getEntries().some((entry) => getBackgroundUsageRecord(entry)?.taskId === task.id)) {\n\t\t\t\tappend(BACKGROUND_USAGE_TYPE, { version: 1, taskId: task.id, usage });\n\t\t\t}\n\t\t\tappend(\"background-task-result\", JSON.parse(JSON.stringify({ version: BACKGROUND_HISTORY_VERSION, task })));\n\t\t} finally {\n\t\t\t// Complete the writes before observers can replace the runtime or its manager.\n\t\t\t// If a write fails, still report entries that were successfully appended.\n\t\t\tfor (const entry of appended) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.options.onEntry(entry);\n\t\t\t\t} catch {\n\t\t\t\t\t// Observers cannot interrupt settlement or result publication.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate warn(event: string, message: string): void {\n\t\ttry {\n\t\t\tthis.options.onError(event, truncateHead(message, { maxBytes: 4096, maxLines: 32 }).content);\n\t\t} catch {\n\t\t\t// Diagnostics cannot reject settlement, cleanup or scheduled callbacks.\n\t\t}\n\t}\n\n\t/** Nestable across asynchronous preflight and service replacement. */\n\tpause(): () => void {\n\t\tthis.pauses++;\n\t\tconst releaseService = this.service.pause();\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tthis.pauses--;\n\t\t\treleaseService();\n\t\t\tthis.schedule();\n\t\t};\n\t}\n\n\tretry(): void {\n\t\tthis.failures.clear();\n\t\tthis.schedule();\n\t}\n\n\tprivate schedule(): void {\n\t\tif (this.disposed || this.timer || this.delivery) return;\n\t\tthis.timer = setTimeout(() => {\n\t\t\tthis.timer = undefined;\n\t\t\tvoid this.drain().catch(() =>\n\t\t\t\tthis.warn(\"background_delivery\", \"Background notification drain failed; delivery was not confirmed.\"),\n\t\t\t);\n\t\t}, 0);\n\t\tthis.timer.unref?.();\n\t}\n\n\tprivate canDeliver(service: BackgroundService): boolean {\n\t\treturn (\n\t\t\t!this.disposed && service === this.service && service.enabled && this.pauses === 0 && this.options.canDeliver()\n\t\t);\n\t}\n\n\tprivate async drain(): Promise<void> {\n\t\tconst service = this.service;\n\t\tif (this.delivery || !this.canDeliver(service)) return;\n\t\tif (this.failures.size) {\n\t\t\tconst retained = new Set(service.list().map((task) => task.id));\n\t\t\tfor (const id of this.failures) if (!retained.has(id)) this.failures.delete(id);\n\t\t}\n\t\tconst task = service.pendingNotifications().find((task) => !this.failures.has(task.id));\n\t\tif (!task) return;\n\t\tconst message = backgroundCompletionMessage(task);\n\t\tif (!service.claimNotification(task.id)) return;\n\t\t// Exactly one completion may be in flight, whether queued for steering or running its\n\t\t// own turn; there is no separate claim registry.\n\t\tconst delivery: Delivery = {\n\t\t\tid: task.id,\n\t\t\tservice,\n\t\t\tmessage,\n\t\t\tphase: \"pending\",\n\t\t};\n\t\tthis.delivery = delivery;\n\t\tlet deliveryError: unknown;\n\t\ttry {\n\t\t\tawait this.options.deliver(\n\t\t\t\tdelivery.message,\n\t\t\t\t() =>\n\t\t\t\t\tnew Promise<void>((resolve, reject) => {\n\t\t\t\t\t\tif (delivery.phase === \"persisted\") resolve();\n\t\t\t\t\t\telse delivery.queued = { resolve, reject };\n\t\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tdeliveryError = error;\n\t\t} finally {\n\t\t\tif (delivery.phase !== \"persisted\") {\n\t\t\t\tservice.releaseNotification(task.id);\n\t\t\t\tif (service === this.service) this.failures.add(task.id);\n\t\t\t\tconst reason = deliveryError instanceof Error ? `: ${deliveryError.message}` : \"\";\n\t\t\t\tthis.warn(\n\t\t\t\t\t\"background_delivery\",\n\t\t\t\t\t`Background completion delivery failed for ${task.id}${reason}; it will retry on the next prompt.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.delivery = undefined;\n\t\t\tconst current = this.service;\n\t\t\tif (this.canDeliver(current) && current.pendingNotifications().some((task) => !this.failures.has(task.id)))\n\t\t\t\tthis.schedule();\n\t\t}\n\t}\n\n\t/** Record dequeueing before message hooks can fail or rewrite the notification. */\n\tmessageStarted(message: AgentMessage): void {\n\t\tconst delivery = this.delivery;\n\t\tif (delivery?.message === message && delivery.phase === \"pending\") delivery.phase = \"started\";\n\t}\n\n\t/** A queued message that was never emitted remains claimed for the next run. */\n\tagentEnded(): void {\n\t\tconst delivery = this.delivery;\n\t\tif (delivery?.phase === \"started\") {\n\t\t\tdelivery.queued?.reject(new Error(\"the completion message was not persisted\"));\n\t\t}\n\t}\n\n\tqueueCleared(): void {\n\t\tthis.delivery?.queued?.reject(new Error(\"the completion message was dequeued before delivery\"));\n\t}\n\n\t/** Acknowledge only successful appends, using identity even when metadata was rewritten. */\n\tmessagePersisted(message: AgentMessage): void {\n\t\tconst delivery = this.delivery;\n\t\tif (delivery?.message === message && delivery.phase !== \"persisted\") {\n\t\t\tdelivery.phase = \"persisted\";\n\t\t\tdelivery.service.markDelivered(delivery.id);\n\t\t\tdelivery.queued?.resolve();\n\t\t}\n\t\tif (message.role === \"toolResult\") this.acknowledgeWaitResult(message.details);\n\t}\n\n\t/** A wait result claims delivery only through its final, persisted marker. */\n\tprivate acknowledgeWaitResult(details: unknown): void {\n\t\tif (!details || typeof details !== \"object\" || !(\"backgroundTaskId\" in details)) return;\n\t\tconst id = details.backgroundTaskId;\n\t\tif (\n\t\t\ttypeof id === \"string\" &&\n\t\t\tthis.service\n\t\t\t\t.list()\n\t\t\t\t.some((task) => task.id === id && task.mode === \"background\" && isBackgroundTerminal(task.status))\n\t\t)\n\t\t\tthis.service.markDelivered(id);\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.service.close();\n\t\tthis.delivery?.queued?.reject(new Error(\"the session was disposed\"));\n\t\tif (this.timer) clearTimeout(this.timer);\n\t\tthis.timer = undefined;\n\t}\n}\n"]}
@@ -20,27 +20,40 @@ export interface ContextSnapshot {
20
20
  /** Includes provider hooks and header transforms, but never the main run's abort signal. */
21
21
  streamOptions: ModelsSimpleStreamOptions;
22
22
  }
23
+ /** What a session needs from the SDK to describe the request it would send next. */
24
+ export interface ContextSnapshotSource {
25
+ /** Prepare `messages` exactly as the next request would, reusing the recorded main prefix. */
26
+ prepareMessages(messages: AgentMessage[]): Promise<Message[]>;
27
+ /** The stream options the SDK would send for `model`, including provider hooks and header transforms. */
28
+ resolveStreamOptions(model: Model<Api>, options: ModelsSimpleStreamOptions): ModelsSimpleStreamOptions;
29
+ }
23
30
  /**
24
31
  * Records the actual pre-provider message prefix, after context hooks, the session's request
25
32
  * projections, and image policy. A snapshot can reuse it and convert only newly settled
26
33
  * messages. In particular, a time-dependent context hook is not rerun over an already
27
34
  * prepared cache prefix.
35
+ *
36
+ * The SDK's own `convertToLlm` and request-option builder stay where upstream defines them;
37
+ * this class wraps the former and borrows the latter, so it never keeps a second copy of
38
+ * either.
28
39
  */
29
- export declare class ContextSnapshotCapture {
40
+ export declare class ContextSnapshotCapture implements ContextSnapshotSource {
30
41
  private readonly settings;
31
42
  private readonly runnerRef;
43
+ private readonly buildRequestOptions;
32
44
  private readonly pending;
33
45
  private prepared;
46
+ private agent;
34
47
  constructor(settings: SettingsManager, runnerRef: {
35
48
  current?: ExtensionRunner;
36
- });
49
+ }, buildRequestOptions: ContextSnapshotSource["resolveStreamOptions"]);
37
50
  /**
38
51
  * Record the source of every request context. Install after all other `transformContext`
39
52
  * wrappers so the recorded prefix is exactly the array the request converts; a wrapper
40
53
  * installed later would return a different array and the prefix would never be reused.
41
54
  */
42
55
  install(agent: Agent): void;
43
- convertToLlm: (messages: AgentMessage[]) => Message[];
44
- capture: (messages: AgentMessage[]) => Promise<Message[]>;
56
+ resolveStreamOptions(model: Model<Api>, options: ModelsSimpleStreamOptions): ModelsSimpleStreamOptions;
57
+ prepareMessages(messages: AgentMessage[]): Promise<Message[]>;
45
58
  }
46
59
  //# sourceMappingURL=context-snapshot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-snapshot.d.ts","sourceRoot":"","sources":["../../src/core/context-snapshot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACxF,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,4FAA4F;IAC5F,aAAa,EAAE,yBAAyB,CAAC;CACzC;AA6BD;;;;;GAKG;AACH,qBAAa,sBAAsB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiD;IACzE,OAAO,CAAC,QAAQ,CAAoF;gBAExF,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE;QAAE,OAAO,CAAC,EAAE,eAAe,CAAA;KAAE;IAK/E;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAY3B,YAAY,GAAI,UAAU,YAAY,EAAE,KAAG,OAAO,EAAE,CASlD;IAEF,OAAO,GAAU,UAAU,YAAY,EAAE,KAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAmB5D;CACF"}
1
+ {"version":3,"file":"context-snapshot.d.ts","sourceRoot":"","sources":["../../src/core/context-snapshot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACxF,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,4FAA4F;IAC5F,aAAa,EAAE,yBAAyB,CAAC;CACzC;AAED,oFAAoF;AACpF,MAAM,WAAW,qBAAqB;IACrC,8FAA8F;IAC9F,eAAe,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,yGAAyG;IACzG,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,yBAAyB,GAAG,yBAAyB,CAAC;CACvG;AAOD;;;;;;;;;GASG;AACH,qBAAa,sBAAuB,YAAW,qBAAqB;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAgD;IACpF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiD;IACzE,OAAO,CAAC,QAAQ,CAAoF;IACpG,OAAO,CAAC,KAAK,CAAoB;gBAGhC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE;QAAE,OAAO,CAAC,EAAE,eAAe,CAAA;KAAE,EACxC,mBAAmB,EAAE,qBAAqB,CAAC,sBAAsB,CAAC;IAOnE;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IA6B3B,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,yBAAyB,GAAG,yBAAyB;IAIhG,eAAe,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAsBnE"}
@@ -1,63 +1,20 @@
1
1
  import { isDeepStrictEqual } from "node:util";
2
- import { convertToLlm } from "./messages.js";
3
- function convertWithImagePolicy(messages, blockImages) {
4
- const converted = convertToLlm(messages);
5
- if (!blockImages)
6
- return converted;
7
- return converted.map((message) => {
8
- if (message.role !== "user" && message.role !== "toolResult")
9
- return message;
10
- if (!Array.isArray(message.content) || !message.content.some((part) => part.type === "image"))
11
- return message;
12
- const content = message.content
13
- .map((part) => (part.type === "image" ? { type: "text", text: "Image reading is disabled." } : part))
14
- .filter((part, i, all) => !(part.type === "text" &&
15
- part.text === "Image reading is disabled." &&
16
- i > 0 &&
17
- all[i - 1].type === "text" &&
18
- all[i - 1].text === part.text));
19
- return { ...message, content };
20
- });
21
- }
22
2
  /**
23
3
  * Records the actual pre-provider message prefix, after context hooks, the session's request
24
4
  * projections, and image policy. A snapshot can reuse it and convert only newly settled
25
5
  * messages. In particular, a time-dependent context hook is not rerun over an already
26
6
  * prepared cache prefix.
7
+ *
8
+ * The SDK's own `convertToLlm` and request-option builder stay where upstream defines them;
9
+ * this class wraps the former and borrows the latter, so it never keeps a second copy of
10
+ * either.
27
11
  */
28
12
  export class ContextSnapshotCapture {
29
- constructor(settings, runnerRef) {
13
+ constructor(settings, runnerRef, buildRequestOptions) {
30
14
  this.pending = new WeakMap();
31
- this.convertToLlm = (messages) => {
32
- const blockImages = this.settings.getBlockImages();
33
- const converted = convertWithImagePolicy(messages, blockImages);
34
- const source = this.pending.get(messages);
35
- if (source) {
36
- this.pending.delete(messages);
37
- this.prepared = { source, messages: structuredClone(converted), blockImages };
38
- }
39
- return converted;
40
- };
41
- this.capture = async (messages) => {
42
- const runner = this.runnerRef.current;
43
- const blockImages = this.settings.getBlockImages();
44
- const prepared = this.prepared;
45
- if (prepared &&
46
- prepared.source.runner === runner &&
47
- prepared.blockImages === blockImages &&
48
- isDeepStrictEqual(messages.slice(0, prepared.source.messages.length), prepared.source.messages)) {
49
- return [
50
- ...structuredClone(prepared.messages),
51
- ...convertWithImagePolicy(messages.slice(prepared.source.messages.length), blockImages),
52
- ];
53
- }
54
- // No request yet, or the branch/context policy changed. Prepare this detached
55
- // snapshot once; it never replaces the prefix recorded from the main request.
56
- const transformed = runner ? await runner.emitContext(messages) : messages;
57
- return structuredClone(convertWithImagePolicy(transformed, blockImages));
58
- };
59
15
  this.settings = settings;
60
16
  this.runnerRef = runnerRef;
17
+ this.buildRequestOptions = buildRequestOptions;
61
18
  }
62
19
  /**
63
20
  * Record the source of every request context. Install after all other `transformContext`
@@ -65,6 +22,7 @@ export class ContextSnapshotCapture {
65
22
  * installed later would return a different array and the prefix would never be reused.
66
23
  */
67
24
  install(agent) {
25
+ this.agent = agent;
68
26
  const transform = agent.transformContext;
69
27
  agent.transformContext = async (messages, signal) => {
70
28
  const runner = this.runnerRef.current;
@@ -73,7 +31,47 @@ export class ContextSnapshotCapture {
73
31
  this.pending.set(transformed, source);
74
32
  return transformed;
75
33
  };
76
- agent.convertToLlm = this.convertToLlm;
34
+ const convert = agent.convertToLlm;
35
+ const record = (messages, converted) => {
36
+ const source = this.pending.get(messages);
37
+ if (source) {
38
+ this.pending.delete(messages);
39
+ this.prepared = {
40
+ source,
41
+ messages: structuredClone(converted),
42
+ blockImages: this.settings.getBlockImages(),
43
+ };
44
+ }
45
+ return converted;
46
+ };
47
+ agent.convertToLlm = (messages) => {
48
+ const converted = convert(messages);
49
+ return Array.isArray(converted) ? record(messages, converted) : converted.then((all) => record(messages, all));
50
+ };
51
+ }
52
+ resolveStreamOptions(model, options) {
53
+ return this.buildRequestOptions(model, options);
54
+ }
55
+ async prepareMessages(messages) {
56
+ const agent = this.agent;
57
+ if (!agent)
58
+ throw new Error("Context snapshot capture is not installed");
59
+ const runner = this.runnerRef.current;
60
+ const blockImages = this.settings.getBlockImages();
61
+ const prepared = this.prepared;
62
+ if (prepared &&
63
+ prepared.source.runner === runner &&
64
+ prepared.blockImages === blockImages &&
65
+ isDeepStrictEqual(messages.slice(0, prepared.source.messages.length), prepared.source.messages)) {
66
+ return [
67
+ ...structuredClone(prepared.messages),
68
+ ...(await agent.convertToLlm(messages.slice(prepared.source.messages.length))),
69
+ ];
70
+ }
71
+ // No request yet, or the branch/context policy changed. Prepare this detached
72
+ // snapshot once; it never replaces the prefix recorded from the main request.
73
+ const transformed = runner ? await runner.emitContext(messages) : messages;
74
+ return structuredClone(await agent.convertToLlm(transformed));
77
75
  }
78
76
  }
79
77
  //# sourceMappingURL=context-snapshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-snapshot.js","sourceRoot":"","sources":["../../src/core/context-snapshot.ts"],"names":[],"mappings":"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","sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\nimport type { Agent, AgentMessage, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Message, Model, ModelsSimpleStreamOptions, Tool } from \"@earendil-works/pi-ai\";\nimport type { ExtensionRunner } from \"./extensions/runner.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Detached model input and request configuration. Contains no tool executors or session writer. */\nexport interface ContextSnapshot {\n\tcapturedAt: number;\n\tsessionId: string;\n\tleafId: string | null;\n\tmodel: Model<Api>;\n\tthinkingLevel: ThinkingLevel;\n\t/**\n\t * The prompt replayed from the prepared transcript, which is the text the provider received.\n\t * Before the first request it is the session's current prompt, which a consumer's Agent\n\t * declares itself when `messages` carry no system message.\n\t */\n\tsystemPrompt: string;\n\tmessages: Message[];\n\ttools: Tool[];\n\t/** Includes provider hooks and header transforms, but never the main run's abort signal. */\n\tstreamOptions: ModelsSimpleStreamOptions;\n}\n\nfunction convertWithImagePolicy(messages: AgentMessage[], blockImages: boolean): Message[] {\n\tconst converted = convertToLlm(messages);\n\tif (!blockImages) return converted;\n\treturn converted.map((message) => {\n\t\tif (message.role !== \"user\" && message.role !== \"toolResult\") return message;\n\t\tif (!Array.isArray(message.content) || !message.content.some((part) => part.type === \"image\")) return message;\n\t\tconst content = message.content\n\t\t\t.map((part) => (part.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : part))\n\t\t\t.filter(\n\t\t\t\t(part, i, all) =>\n\t\t\t\t\t!(\n\t\t\t\t\t\tpart.type === \"text\" &&\n\t\t\t\t\t\tpart.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\tall[i - 1].type === \"text\" &&\n\t\t\t\t\t\t(all[i - 1] as { type: \"text\"; text: string }).text === part.text\n\t\t\t\t\t),\n\t\t\t);\n\t\treturn { ...message, content };\n\t});\n}\n\ninterface PreparedSource {\n\tmessages: AgentMessage[];\n\trunner: ExtensionRunner | undefined;\n}\n\n/**\n * Records the actual pre-provider message prefix, after context hooks, the session's request\n * projections, and image policy. A snapshot can reuse it and convert only newly settled\n * messages. In particular, a time-dependent context hook is not rerun over an already\n * prepared cache prefix.\n */\nexport class ContextSnapshotCapture {\n\tprivate readonly settings: SettingsManager;\n\tprivate readonly runnerRef: { current?: ExtensionRunner };\n\tprivate readonly pending = new WeakMap<AgentMessage[], PreparedSource>();\n\tprivate prepared: { source: PreparedSource; messages: Message[]; blockImages: boolean } | undefined;\n\n\tconstructor(settings: SettingsManager, runnerRef: { current?: ExtensionRunner }) {\n\t\tthis.settings = settings;\n\t\tthis.runnerRef = runnerRef;\n\t}\n\n\t/**\n\t * Record the source of every request context. Install after all other `transformContext`\n\t * wrappers so the recorded prefix is exactly the array the request converts; a wrapper\n\t * installed later would return a different array and the prefix would never be reused.\n\t */\n\tinstall(agent: Agent): void {\n\t\tconst transform = agent.transformContext;\n\t\tagent.transformContext = async (messages, signal) => {\n\t\t\tconst runner = this.runnerRef.current;\n\t\t\tconst source = { messages: structuredClone(messages), runner };\n\t\t\tconst transformed = transform ? await transform(messages, signal) : messages;\n\t\t\tthis.pending.set(transformed, source);\n\t\t\treturn transformed;\n\t\t};\n\t\tagent.convertToLlm = this.convertToLlm;\n\t}\n\n\tconvertToLlm = (messages: AgentMessage[]): Message[] => {\n\t\tconst blockImages = this.settings.getBlockImages();\n\t\tconst converted = convertWithImagePolicy(messages, blockImages);\n\t\tconst source = this.pending.get(messages);\n\t\tif (source) {\n\t\t\tthis.pending.delete(messages);\n\t\t\tthis.prepared = { source, messages: structuredClone(converted), blockImages };\n\t\t}\n\t\treturn converted;\n\t};\n\n\tcapture = async (messages: AgentMessage[]): Promise<Message[]> => {\n\t\tconst runner = this.runnerRef.current;\n\t\tconst blockImages = this.settings.getBlockImages();\n\t\tconst prepared = this.prepared;\n\t\tif (\n\t\t\tprepared &&\n\t\t\tprepared.source.runner === runner &&\n\t\t\tprepared.blockImages === blockImages &&\n\t\t\tisDeepStrictEqual(messages.slice(0, prepared.source.messages.length), prepared.source.messages)\n\t\t) {\n\t\t\treturn [\n\t\t\t\t...structuredClone(prepared.messages),\n\t\t\t\t...convertWithImagePolicy(messages.slice(prepared.source.messages.length), blockImages),\n\t\t\t];\n\t\t}\n\t\t// No request yet, or the branch/context policy changed. Prepare this detached\n\t\t// snapshot once; it never replaces the prefix recorded from the main request.\n\t\tconst transformed = runner ? await runner.emitContext(messages) : messages;\n\t\treturn structuredClone(convertWithImagePolicy(transformed, blockImages));\n\t};\n}\n"]}
1
+ {"version":3,"file":"context-snapshot.js","sourceRoot":"","sources":["../../src/core/context-snapshot.ts"],"names":[],"mappings":"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","sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\nimport type { Agent, AgentMessage, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Message, Model, ModelsSimpleStreamOptions, Tool } from \"@earendil-works/pi-ai\";\nimport type { ExtensionRunner } from \"./extensions/runner.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Detached model input and request configuration. Contains no tool executors or session writer. */\nexport interface ContextSnapshot {\n\tcapturedAt: number;\n\tsessionId: string;\n\tleafId: string | null;\n\tmodel: Model<Api>;\n\tthinkingLevel: ThinkingLevel;\n\t/**\n\t * The prompt replayed from the prepared transcript, which is the text the provider received.\n\t * Before the first request it is the session's current prompt, which a consumer's Agent\n\t * declares itself when `messages` carry no system message.\n\t */\n\tsystemPrompt: string;\n\tmessages: Message[];\n\ttools: Tool[];\n\t/** Includes provider hooks and header transforms, but never the main run's abort signal. */\n\tstreamOptions: ModelsSimpleStreamOptions;\n}\n\n/** What a session needs from the SDK to describe the request it would send next. */\nexport interface ContextSnapshotSource {\n\t/** Prepare `messages` exactly as the next request would, reusing the recorded main prefix. */\n\tprepareMessages(messages: AgentMessage[]): Promise<Message[]>;\n\t/** The stream options the SDK would send for `model`, including provider hooks and header transforms. */\n\tresolveStreamOptions(model: Model<Api>, options: ModelsSimpleStreamOptions): ModelsSimpleStreamOptions;\n}\n\ninterface PreparedSource {\n\tmessages: AgentMessage[];\n\trunner: ExtensionRunner | undefined;\n}\n\n/**\n * Records the actual pre-provider message prefix, after context hooks, the session's request\n * projections, and image policy. A snapshot can reuse it and convert only newly settled\n * messages. In particular, a time-dependent context hook is not rerun over an already\n * prepared cache prefix.\n *\n * The SDK's own `convertToLlm` and request-option builder stay where upstream defines them;\n * this class wraps the former and borrows the latter, so it never keeps a second copy of\n * either.\n */\nexport class ContextSnapshotCapture implements ContextSnapshotSource {\n\tprivate readonly settings: SettingsManager;\n\tprivate readonly runnerRef: { current?: ExtensionRunner };\n\tprivate readonly buildRequestOptions: ContextSnapshotSource[\"resolveStreamOptions\"];\n\tprivate readonly pending = new WeakMap<AgentMessage[], PreparedSource>();\n\tprivate prepared: { source: PreparedSource; messages: Message[]; blockImages: boolean } | undefined;\n\tprivate agent: Agent | undefined;\n\n\tconstructor(\n\t\tsettings: SettingsManager,\n\t\trunnerRef: { current?: ExtensionRunner },\n\t\tbuildRequestOptions: ContextSnapshotSource[\"resolveStreamOptions\"],\n\t) {\n\t\tthis.settings = settings;\n\t\tthis.runnerRef = runnerRef;\n\t\tthis.buildRequestOptions = buildRequestOptions;\n\t}\n\n\t/**\n\t * Record the source of every request context. Install after all other `transformContext`\n\t * wrappers so the recorded prefix is exactly the array the request converts; a wrapper\n\t * installed later would return a different array and the prefix would never be reused.\n\t */\n\tinstall(agent: Agent): void {\n\t\tthis.agent = agent;\n\t\tconst transform = agent.transformContext;\n\t\tagent.transformContext = async (messages, signal) => {\n\t\t\tconst runner = this.runnerRef.current;\n\t\t\tconst source = { messages: structuredClone(messages), runner };\n\t\t\tconst transformed = transform ? await transform(messages, signal) : messages;\n\t\t\tthis.pending.set(transformed, source);\n\t\t\treturn transformed;\n\t\t};\n\t\tconst convert = agent.convertToLlm;\n\t\tconst record = (messages: AgentMessage[], converted: Message[]): Message[] => {\n\t\t\tconst source = this.pending.get(messages);\n\t\t\tif (source) {\n\t\t\t\tthis.pending.delete(messages);\n\t\t\t\tthis.prepared = {\n\t\t\t\t\tsource,\n\t\t\t\t\tmessages: structuredClone(converted),\n\t\t\t\t\tblockImages: this.settings.getBlockImages(),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn converted;\n\t\t};\n\t\tagent.convertToLlm = (messages) => {\n\t\t\tconst converted = convert(messages);\n\t\t\treturn Array.isArray(converted) ? record(messages, converted) : converted.then((all) => record(messages, all));\n\t\t};\n\t}\n\n\tresolveStreamOptions(model: Model<Api>, options: ModelsSimpleStreamOptions): ModelsSimpleStreamOptions {\n\t\treturn this.buildRequestOptions(model, options);\n\t}\n\n\tasync prepareMessages(messages: AgentMessage[]): Promise<Message[]> {\n\t\tconst agent = this.agent;\n\t\tif (!agent) throw new Error(\"Context snapshot capture is not installed\");\n\t\tconst runner = this.runnerRef.current;\n\t\tconst blockImages = this.settings.getBlockImages();\n\t\tconst prepared = this.prepared;\n\t\tif (\n\t\t\tprepared &&\n\t\t\tprepared.source.runner === runner &&\n\t\t\tprepared.blockImages === blockImages &&\n\t\t\tisDeepStrictEqual(messages.slice(0, prepared.source.messages.length), prepared.source.messages)\n\t\t) {\n\t\t\treturn [\n\t\t\t\t...structuredClone(prepared.messages),\n\t\t\t\t...(await agent.convertToLlm(messages.slice(prepared.source.messages.length))),\n\t\t\t];\n\t\t}\n\t\t// No request yet, or the branch/context policy changed. Prepare this detached\n\t\t// snapshot once; it never replaces the prefix recorded from the main request.\n\t\tconst transformed = runner ? await runner.emitContext(messages) : messages;\n\t\treturn structuredClone(await agent.convertToLlm(transformed));\n\t}\n}\n"]}
@@ -29,13 +29,6 @@ export interface EditorHost {
29
29
  /** Raw input only while the main editor has focus, without overlays or autocomplete. */
30
30
  onInput(handler: TerminalInputHandler): () => void;
31
31
  }
32
- /**
33
- * Message thrown when a captured extension ctx/pi is used after the owning
34
- * session was replaced (newSession/fork/switchSession/reload). Single source of
35
- * truth so extensions can detect the condition with
36
- * isStaleExtensionContextError instead of matching message text.
37
- */
38
- export declare const STALE_EXTENSION_CONTEXT_MESSAGE = "This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";
39
32
  /** True when an error came from using a stale extension ctx/pi after session replacement. */
40
33
  export declare function isStaleExtensionContextError(error: unknown): boolean;
41
34
  //# sourceMappingURL=distribution-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"distribution-api.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/distribution-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,iBAAiB;IACjC,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;CAC3B;AAED,0FAA0F;AAC1F,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC;AAEnH,0FAA0F;AAC1F,MAAM,WAAW,UAAU;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAAC;IACnD,kFAAkF;IAClF,SAAS,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,wFAAwF;IACxF,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAAC;CACnD;AAED;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,gXACkU,CAAC;AAE/W,6FAA6F;AAC7F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpE"}
1
+ {"version":3,"file":"distribution-api.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/distribution-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,iBAAiB;IACjC,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;CAC3B;AAED,0FAA0F;AAC1F,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC;AAEnH,0FAA0F;AAC1F,MAAM,WAAW,UAAU;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAAC;IACnD,kFAAkF;IAClF,SAAS,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,wFAAwF;IACxF,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAAC;CACnD;AAUD,6FAA6F;AAC7F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpE"}
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Message thrown when a captured extension ctx/pi is used after the owning
3
- * session was replaced (newSession/fork/switchSession/reload). Single source of
4
- * truth so extensions can detect the condition with
5
- * isStaleExtensionContextError instead of matching message text.
2
+ * Upstream words the error it throws when a captured extension ctx/pi is used after the owning
3
+ * session was replaced (newSession/fork/switchSession/reload) in three places. Recognize it by
4
+ * its stable opening rather than copying the whole message, so extensions can detect the
5
+ * condition with isStaleExtensionContextError instead of matching text themselves.
6
6
  */
7
- export const STALE_EXTENSION_CONTEXT_MESSAGE = "This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";
7
+ const STALE_EXTENSION_CONTEXT_PREFIX = "This extension ctx is stale";
8
8
  /** True when an error came from using a stale extension ctx/pi after session replacement. */
9
9
  export function isStaleExtensionContextError(error) {
10
- return error instanceof Error && error.message === STALE_EXTENSION_CONTEXT_MESSAGE;
10
+ return error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_PREFIX);
11
11
  }
12
12
  //# sourceMappingURL=distribution-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"distribution-api.js","sourceRoot":"","sources":["../../../src/core/extensions/distribution-api.ts"],"names":[],"mappings":"AA8BA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAC3C,6WAA6W,CAAC;AAE/W,6FAA6F;AAC7F,MAAM,UAAU,4BAA4B,CAAC,KAAc;IAC1D,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,+BAA+B,CAAC;AACpF,CAAC","sourcesContent":["/**\n * This distribution's additions to the extension API. `types.ts` re-exports them, so\n * extensions import them from the same place as the upstream API.\n */\nimport type { TerminalInputHandler } from \"./types.ts\";\n\nexport type { BackgroundContext } from \"../background/types.ts\";\nexport type { ContextSnapshot } from \"../context-snapshot.ts\";\nexport type { ModelRuntime } from \"../model-runtime.ts\";\n\nexport interface EditorSubmitEvent {\n\t/** Expanded, trimmed editor text, before history, command dispatch, or any main-agent queue. */\n\ttext: string;\n\tkind: \"prompt\" | \"command\" | \"bash\";\n\tmode: \"steer\" | \"followUp\";\n}\n\n/** Handlers must claim input synchronously; start asynchronous work after claiming it. */\nexport type EditorSubmitHandler = (event: EditorSubmitEvent) => { handled: true; editorText?: string } | undefined;\n\n/** Main-editor capabilities, present only where a host renders the interactive editor. */\nexport interface EditorHost {\n\t/** Intercept editor submissions, including during compaction. First claim wins. */\n\tonSubmit(handler: EditorSubmitHandler): () => void;\n\t/** Logical cursor position when the editor exposes it. Indices are zero-based. */\n\tgetCursor(): { line: number; col: number } | undefined;\n\t/** Raw input only while the main editor has focus, without overlays or autocomplete. */\n\tonInput(handler: TerminalInputHandler): () => void;\n}\n\n/**\n * Message thrown when a captured extension ctx/pi is used after the owning\n * session was replaced (newSession/fork/switchSession/reload). Single source of\n * truth so extensions can detect the condition with\n * isStaleExtensionContextError instead of matching message text.\n */\nexport const STALE_EXTENSION_CONTEXT_MESSAGE =\n\t\"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n\n/** True when an error came from using a stale extension ctx/pi after session replacement. */\nexport function isStaleExtensionContextError(error: unknown): boolean {\n\treturn error instanceof Error && error.message === STALE_EXTENSION_CONTEXT_MESSAGE;\n}\n"]}
1
+ {"version":3,"file":"distribution-api.js","sourceRoot":"","sources":["../../../src/core/extensions/distribution-api.ts"],"names":[],"mappings":"AA8BA;;;;;GAKG;AACH,MAAM,8BAA8B,GAAG,6BAA6B,CAAC;AAErE,6FAA6F;AAC7F,MAAM,UAAU,4BAA4B,CAAC,KAAc;IAC1D,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC;AAC3F,CAAC","sourcesContent":["/**\n * This distribution's additions to the extension API. `types.ts` re-exports them, so\n * extensions import them from the same place as the upstream API.\n */\nimport type { TerminalInputHandler } from \"./types.ts\";\n\nexport type { BackgroundContext } from \"../background/types.ts\";\nexport type { ContextSnapshot } from \"../context-snapshot.ts\";\nexport type { ModelRuntime } from \"../model-runtime.ts\";\n\nexport interface EditorSubmitEvent {\n\t/** Expanded, trimmed editor text, before history, command dispatch, or any main-agent queue. */\n\ttext: string;\n\tkind: \"prompt\" | \"command\" | \"bash\";\n\tmode: \"steer\" | \"followUp\";\n}\n\n/** Handlers must claim input synchronously; start asynchronous work after claiming it. */\nexport type EditorSubmitHandler = (event: EditorSubmitEvent) => { handled: true; editorText?: string } | undefined;\n\n/** Main-editor capabilities, present only where a host renders the interactive editor. */\nexport interface EditorHost {\n\t/** Intercept editor submissions, including during compaction. First claim wins. */\n\tonSubmit(handler: EditorSubmitHandler): () => void;\n\t/** Logical cursor position when the editor exposes it. Indices are zero-based. */\n\tgetCursor(): { line: number; col: number } | undefined;\n\t/** Raw input only while the main editor has focus, without overlays or autocomplete. */\n\tonInput(handler: TerminalInputHandler): () => void;\n}\n\n/**\n * Upstream words the error it throws when a captured extension ctx/pi is used after the owning\n * session was replaced (newSession/fork/switchSession/reload) in three places. Recognize it by\n * its stable opening rather than copying the whole message, so extensions can detect the\n * condition with isStaleExtensionContextError instead of matching text themselves.\n */\nconst STALE_EXTENSION_CONTEXT_PREFIX = \"This extension ctx is stale\";\n\n/** True when an error came from using a stale extension ctx/pi after session replacement. */\nexport function isStaleExtensionContextError(error: unknown): boolean {\n\treturn error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_PREFIX);\n}\n"]}
@@ -8,6 +8,6 @@ export { createExtensionRuntime, discoverAndLoadExtensions, loadExtensionFromFac
8
8
  export type { ExtensionErrorListener, ForkHandler, NavigateTreeHandler, NewSessionHandler, ShutdownHandler, SwitchSessionHandler, } from "./runner.ts";
9
9
  export { ExtensionRunner } from "./runner.ts";
10
10
  export type { AfterProviderResponseEvent, AgentActivityOutcome, AgentBeforeSettleEvent, AgentBeforeSettleEventResult, AgentEndEvent, AgentSettledEvent, AgentStartEvent, AgentToolResult, AgentToolUpdateCallback, AppendEntryHandler, AppKeybinding, AutocompleteProviderFactory, BashToolCallEvent, BashToolResultEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderHeadersEvent, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, BoundaryContextPreview, BoundaryResult, BoundaryState, BuildSystemPromptOptions, CacheWarmingDecisionEvent, CacheWarmingDecisionEventResult, CompactionEntryDraft, CompactOptions, ContextEditEntryDraft, ContextEvent, ContextEventResult, ContextSnapshot, ContextUsage, ContextWithSystemEvent, CustomEntryDraft, CustomMessageEntryDraft, CustomToolCallEvent, CustomToolResultEvent, EditorFactory, EditorHost, EditorSubmitEvent, EditorSubmitHandler, EditToolCallEvent, EditToolResultEvent, EntryRenderer, EntryRenderOptions, ExecOptions, ExecResult, Extension, ExtensionActions, ExtensionAPI, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFactory, ExtensionFlag, ExtensionHandler, ExtensionMode, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetOptions, FindToolCallEvent, FindToolResultEvent, GetActiveToolsHandler, GetAllToolsHandler, GetCommandsHandler, GetThinkingLevelHandler, GrepToolCallEvent, GrepToolResultEvent, InlineExtension, InputEvent, InputEventResult, InputSource, KeybindingsManager, LoadExtensionsResult, LsToolCallEvent, LsToolResultEvent, MarkdownTransformContext, MarkdownTransformer, MessageEndEvent, MessageEndEventResult, MessageRenderer, MessageRenderOptions, MessageStartEvent, MessageUpdateEvent, ModelSelectEvent, ModelSelectSource, NormalizedBuildSystemPromptOptions, PowerShellToolCallEvent, PowerShellToolResultEvent, ProjectTrustContext, ProjectTrustEvent, ProjectTrustEventDecision, ProjectTrustEventResult, ProjectTrustHandler, ProviderConfig, ProviderModelConfig, ReadToolCallEvent, ReadToolResultEvent, RegisteredCommand, RegisteredTool, ReplacedSessionContext, ResolvedCommand, ResourcesDiscoverEvent, ResourcesDiscoverResult, SendMessageHandler, SendUserMessageHandler, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeForkEvent, SessionBeforeForkResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBoundaryDraft, SessionCompactEvent, SessionCompactFailedEvent, SessionEvent, SessionInfoChangedEvent, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent, SetActiveToolsHandler, SetLabelHandler, SetModelHandler, SetThinkingLevelHandler, TerminalInputHandler, ThinkingLevelSelectEvent, ToolCallEvent, ToolCallEventResult, ToolDefinition, ToolExecutionEndEvent, ToolExecutionMode, ToolExecutionStartEvent, ToolExecutionUpdateEvent, ToolInfo, ToolRenderResultOptions, ToolResultEvent, ToolResultEventResult, TreePreparation, TurnEndEvent, TurnEndEventResult, TurnStartEvent, UIPromptEndEvent, UIPromptKind, UIPromptStartEvent, UserBashEvent, UserBashEventResult, WidgetPlacement, WorkingIndicatorOptions, WriteToolCallEvent, WriteToolResultEvent, } from "./types.ts";
11
- export { defineTool, isBashToolResult, isEditToolResult, isFindToolResult, isGrepToolResult, isLsToolResult, isPowerShellToolResult, isReadToolResult, isStaleExtensionContextError, isToolCallEventType, isWriteToolResult, STALE_EXTENSION_CONTEXT_MESSAGE, } from "./types.ts";
11
+ export { defineTool, isBashToolResult, isEditToolResult, isFindToolResult, isGrepToolResult, isLsToolResult, isPowerShellToolResult, isReadToolResult, isStaleExtensionContextError, isToolCallEventType, isWriteToolResult, } from "./types.ts";
12
12
  export { wrapRegisteredTool, wrapRegisteredTools } from "./wrapper.ts";
13
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/index.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,6 @@
4
4
  export { createExtensionRuntime, discoverAndLoadExtensions, loadExtensionFromFactory, loadExtensions, } from "./loader.js";
5
5
  export { ExtensionRunner } from "./runner.js";
6
6
  // Type guards
7
- export { defineTool, isBashToolResult, isEditToolResult, isFindToolResult, isGrepToolResult, isLsToolResult, isPowerShellToolResult, isReadToolResult, isStaleExtensionContextError, isToolCallEventType, isWriteToolResult, STALE_EXTENSION_CONTEXT_MESSAGE, } from "./types.js";
7
+ export { defineTool, isBashToolResult, isEditToolResult, isFindToolResult, isGrepToolResult, isLsToolResult, isPowerShellToolResult, isReadToolResult, isStaleExtensionContextError, isToolCallEventType, isWriteToolResult, } from "./types.js";
8
8
  export { wrapRegisteredTool, wrapRegisteredTools } from "./wrapper.js";
9
9
  //# sourceMappingURL=index.js.map