@bastani/atomic 0.9.3-alpha.4 → 0.9.3-alpha.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 (335) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  3. package/dist/builtin/cursor/package.json +3 -3
  4. package/dist/builtin/cursor/src/auth.ts +1 -1
  5. package/dist/builtin/cursor/src/model-mapper.ts +1 -1
  6. package/dist/builtin/cursor/src/model-reference.ts +1 -1
  7. package/dist/builtin/cursor/src/proto/protobuf-codec-request.ts +1 -1
  8. package/dist/builtin/cursor/src/provider.ts +1 -1
  9. package/dist/builtin/cursor/src/stream.ts +1 -1
  10. package/dist/builtin/cursor/src/transport-types.ts +1 -1
  11. package/dist/builtin/intercom/CHANGELOG.md +12 -0
  12. package/dist/builtin/intercom/package.json +2 -2
  13. package/dist/builtin/mcp/CHANGELOG.md +12 -0
  14. package/dist/builtin/mcp/package.json +3 -3
  15. package/dist/builtin/mcp/sampling-handler.ts +1 -1
  16. package/dist/builtin/mcp/types.ts +1 -1
  17. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  18. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  19. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  20. package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
  21. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  22. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
  23. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  24. package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
  25. package/dist/builtin/subagents/agents/debugger.md +1 -1
  26. package/dist/builtin/subagents/agents/worker.md +1 -1
  27. package/dist/builtin/subagents/package.json +4 -4
  28. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +1 -1
  29. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +1 -1
  31. package/dist/builtin/subagents/src/runs/shared/structured-output.ts +1 -1
  32. package/dist/builtin/subagents/src/shared/types-results.ts +1 -1
  33. package/dist/builtin/subagents/src/shared/utils.ts +1 -1
  34. package/dist/builtin/subagents/src/slash/slash-live-state.ts +1 -1
  35. package/dist/builtin/web-access/CHANGELOG.md +12 -0
  36. package/dist/builtin/web-access/package.json +2 -2
  37. package/dist/builtin/web-access/summary-review.ts +1 -1
  38. package/dist/builtin/web-access/web-search-summary.ts +1 -1
  39. package/dist/builtin/web-access/web-search-tool.ts +1 -1
  40. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  41. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +6 -1
  42. package/dist/builtin/workflows/builtin/goal-runner.ts +12 -2
  43. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +4 -0
  44. package/dist/builtin/workflows/builtin/ralph-models.ts +40 -6
  45. package/dist/builtin/workflows/package.json +2 -2
  46. package/dist/bun/register-bedrock.d.ts.map +1 -1
  47. package/dist/bun/register-bedrock.js +1 -1
  48. package/dist/bun/register-bedrock.js.map +1 -1
  49. package/dist/cli/file-processor.d.ts +1 -1
  50. package/dist/cli/file-processor.d.ts.map +1 -1
  51. package/dist/cli/file-processor.js.map +1 -1
  52. package/dist/cli/initial-message.d.ts +1 -1
  53. package/dist/cli/initial-message.d.ts.map +1 -1
  54. package/dist/cli/initial-message.js.map +1 -1
  55. package/dist/cli/list-models.d.ts.map +1 -1
  56. package/dist/cli/list-models.js.map +1 -1
  57. package/dist/core/agent-session-auto-compaction.d.ts +1 -1
  58. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  59. package/dist/core/agent-session-auto-compaction.js +1 -1
  60. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  61. package/dist/core/agent-session-events.d.ts +1 -1
  62. package/dist/core/agent-session-events.d.ts.map +1 -1
  63. package/dist/core/agent-session-events.js +1 -1
  64. package/dist/core/agent-session-events.js.map +1 -1
  65. package/dist/core/agent-session-export.d.ts.map +1 -1
  66. package/dist/core/agent-session-export.js.map +1 -1
  67. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  68. package/dist/core/agent-session-extension-bindings.js +1 -1
  69. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  70. package/dist/core/agent-session-message-queue.d.ts +1 -1
  71. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  72. package/dist/core/agent-session-message-queue.js.map +1 -1
  73. package/dist/core/agent-session-methods.d.ts +1 -1
  74. package/dist/core/agent-session-methods.d.ts.map +1 -1
  75. package/dist/core/agent-session-methods.js.map +1 -1
  76. package/dist/core/agent-session-models.d.ts +1 -1
  77. package/dist/core/agent-session-models.d.ts.map +1 -1
  78. package/dist/core/agent-session-models.js +1 -1
  79. package/dist/core/agent-session-models.js.map +1 -1
  80. package/dist/core/agent-session-prompt.d.ts +1 -1
  81. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  82. package/dist/core/agent-session-prompt.js.map +1 -1
  83. package/dist/core/agent-session-retry.d.ts +1 -1
  84. package/dist/core/agent-session-retry.d.ts.map +1 -1
  85. package/dist/core/agent-session-retry.js +1 -1
  86. package/dist/core/agent-session-retry.js.map +1 -1
  87. package/dist/core/agent-session-services.d.ts +1 -1
  88. package/dist/core/agent-session-services.d.ts.map +1 -1
  89. package/dist/core/agent-session-services.js.map +1 -1
  90. package/dist/core/agent-session-state.d.ts +1 -1
  91. package/dist/core/agent-session-state.d.ts.map +1 -1
  92. package/dist/core/agent-session-state.js.map +1 -1
  93. package/dist/core/agent-session-types.d.ts +1 -1
  94. package/dist/core/agent-session-types.d.ts.map +1 -1
  95. package/dist/core/agent-session-types.js.map +1 -1
  96. package/dist/core/agent-session.d.ts +1 -1
  97. package/dist/core/agent-session.d.ts.map +1 -1
  98. package/dist/core/agent-session.js.map +1 -1
  99. package/dist/core/anthropic-thinking-guard.d.ts +1 -1
  100. package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
  101. package/dist/core/anthropic-thinking-guard.js.map +1 -1
  102. package/dist/core/auth-storage.d.ts +2 -2
  103. package/dist/core/auth-storage.d.ts.map +1 -1
  104. package/dist/core/auth-storage.js +1 -1
  105. package/dist/core/auth-storage.js.map +1 -1
  106. package/dist/core/codex-fast-mode.d.ts +1 -1
  107. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  108. package/dist/core/codex-fast-mode.js +1 -1
  109. package/dist/core/codex-fast-mode.js.map +1 -1
  110. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  111. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  112. package/dist/core/compaction/branch-summarization.js +1 -1
  113. package/dist/core/compaction/branch-summarization.js.map +1 -1
  114. package/dist/core/compaction/compaction.d.ts +1 -1
  115. package/dist/core/compaction/compaction.d.ts.map +1 -1
  116. package/dist/core/compaction/compaction.js.map +1 -1
  117. package/dist/core/compaction/context-compaction-runner.d.ts +1 -1
  118. package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
  119. package/dist/core/compaction/context-compaction-runner.js +1 -1
  120. package/dist/core/compaction/context-compaction-runner.js.map +1 -1
  121. package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +1 -1
  122. package/dist/core/compaction/context-deletion-tool-definitions.js +1 -1
  123. package/dist/core/compaction/context-deletion-tool-definitions.js.map +1 -1
  124. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  125. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  126. package/dist/core/compaction/utils.d.ts +1 -1
  127. package/dist/core/compaction/utils.d.ts.map +1 -1
  128. package/dist/core/compaction/utils.js.map +1 -1
  129. package/dist/core/context-window.d.ts +2 -2
  130. package/dist/core/context-window.d.ts.map +1 -1
  131. package/dist/core/context-window.js.map +1 -1
  132. package/dist/core/copilot-gemini-payload-sanitizer.d.ts +1 -1
  133. package/dist/core/copilot-gemini-payload-sanitizer.d.ts.map +1 -1
  134. package/dist/core/copilot-gemini-payload-sanitizer.js.map +1 -1
  135. package/dist/core/copilot-gemini-reasoning.d.ts +1 -1
  136. package/dist/core/copilot-gemini-reasoning.d.ts.map +1 -1
  137. package/dist/core/copilot-gemini-reasoning.js.map +1 -1
  138. package/dist/core/copilot-gemini-tool-arguments.d.ts +1 -1
  139. package/dist/core/copilot-gemini-tool-arguments.d.ts.map +1 -1
  140. package/dist/core/copilot-gemini-tool-arguments.js.map +1 -1
  141. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  142. package/dist/core/export-html/tool-renderer.js.map +1 -1
  143. package/dist/core/extensions/agent-events.d.ts +1 -1
  144. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  145. package/dist/core/extensions/agent-events.js.map +1 -1
  146. package/dist/core/extensions/api-types.d.ts +1 -1
  147. package/dist/core/extensions/api-types.d.ts.map +1 -1
  148. package/dist/core/extensions/api-types.js.map +1 -1
  149. package/dist/core/extensions/context-types.d.ts +1 -1
  150. package/dist/core/extensions/context-types.d.ts.map +1 -1
  151. package/dist/core/extensions/context-types.js.map +1 -1
  152. package/dist/core/extensions/event-results.d.ts +1 -1
  153. package/dist/core/extensions/event-results.d.ts.map +1 -1
  154. package/dist/core/extensions/event-results.js.map +1 -1
  155. package/dist/core/extensions/loader-virtual-modules.d.ts +12 -0
  156. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  157. package/dist/core/extensions/loader-virtual-modules.js +18 -2
  158. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  159. package/dist/core/extensions/provider-types.d.ts +1 -1
  160. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  161. package/dist/core/extensions/provider-types.js.map +1 -1
  162. package/dist/core/extensions/runner-context.d.ts +1 -1
  163. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  164. package/dist/core/extensions/runner-context.js.map +1 -1
  165. package/dist/core/extensions/runner-events.d.ts +1 -1
  166. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  167. package/dist/core/extensions/runner-events.js.map +1 -1
  168. package/dist/core/extensions/runner.d.ts +1 -1
  169. package/dist/core/extensions/runner.d.ts.map +1 -1
  170. package/dist/core/extensions/runner.js.map +1 -1
  171. package/dist/core/extensions/runtime-types.d.ts +1 -1
  172. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  173. package/dist/core/extensions/runtime-types.js.map +1 -1
  174. package/dist/core/extensions/tool-events.d.ts +1 -1
  175. package/dist/core/extensions/tool-events.d.ts.map +1 -1
  176. package/dist/core/extensions/tool-events.js.map +1 -1
  177. package/dist/core/footer-data-provider.d.ts +5 -0
  178. package/dist/core/footer-data-provider.d.ts.map +1 -1
  179. package/dist/core/footer-data-provider.js +46 -12
  180. package/dist/core/footer-data-provider.js.map +1 -1
  181. package/dist/core/http-dispatcher.d.ts +3 -1
  182. package/dist/core/http-dispatcher.d.ts.map +1 -1
  183. package/dist/core/http-dispatcher.js +4 -1
  184. package/dist/core/http-dispatcher.js.map +1 -1
  185. package/dist/core/keybindings.d.ts +1 -1
  186. package/dist/core/messages.d.ts +1 -1
  187. package/dist/core/messages.d.ts.map +1 -1
  188. package/dist/core/messages.js.map +1 -1
  189. package/dist/core/model-registry-auth.d.ts +1 -1
  190. package/dist/core/model-registry-auth.d.ts.map +1 -1
  191. package/dist/core/model-registry-auth.js.map +1 -1
  192. package/dist/core/model-registry-builtins.d.ts +1 -1
  193. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  194. package/dist/core/model-registry-builtins.js +1 -1
  195. package/dist/core/model-registry-builtins.js.map +1 -1
  196. package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
  197. package/dist/core/model-registry-custom-loader.js +1 -1
  198. package/dist/core/model-registry-custom-loader.js.map +1 -1
  199. package/dist/core/model-registry-dynamic.d.ts +1 -1
  200. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  201. package/dist/core/model-registry-dynamic.js +1 -1
  202. package/dist/core/model-registry-dynamic.js.map +1 -1
  203. package/dist/core/model-registry-loader.d.ts.map +1 -1
  204. package/dist/core/model-registry-loader.js.map +1 -1
  205. package/dist/core/model-registry-types.d.ts +1 -1
  206. package/dist/core/model-registry-types.d.ts.map +1 -1
  207. package/dist/core/model-registry-types.js.map +1 -1
  208. package/dist/core/model-registry.d.ts +1 -1
  209. package/dist/core/model-registry.d.ts.map +1 -1
  210. package/dist/core/model-registry.js +1 -1
  211. package/dist/core/model-registry.js.map +1 -1
  212. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  213. package/dist/core/model-resolver-cli.js.map +1 -1
  214. package/dist/core/model-resolver-defaults.d.ts +1 -1
  215. package/dist/core/model-resolver-defaults.d.ts.map +1 -1
  216. package/dist/core/model-resolver-defaults.js.map +1 -1
  217. package/dist/core/model-resolver-initial.d.ts +1 -1
  218. package/dist/core/model-resolver-initial.d.ts.map +1 -1
  219. package/dist/core/model-resolver-initial.js.map +1 -1
  220. package/dist/core/model-resolver-patterns.d.ts +1 -1
  221. package/dist/core/model-resolver-patterns.d.ts.map +1 -1
  222. package/dist/core/model-resolver-patterns.js.map +1 -1
  223. package/dist/core/model-resolver-scope.d.ts.map +1 -1
  224. package/dist/core/model-resolver-scope.js +1 -1
  225. package/dist/core/model-resolver-scope.js.map +1 -1
  226. package/dist/core/model-resolver-types.d.ts +1 -1
  227. package/dist/core/model-resolver-types.d.ts.map +1 -1
  228. package/dist/core/model-resolver-types.js.map +1 -1
  229. package/dist/core/provider-attribution.d.ts +2 -2
  230. package/dist/core/provider-attribution.d.ts.map +1 -1
  231. package/dist/core/provider-attribution.js +4 -0
  232. package/dist/core/provider-attribution.js.map +1 -1
  233. package/dist/core/sdk-types.d.ts +1 -1
  234. package/dist/core/sdk-types.d.ts.map +1 -1
  235. package/dist/core/sdk-types.js.map +1 -1
  236. package/dist/core/sdk.d.ts +1 -1
  237. package/dist/core/sdk.d.ts.map +1 -1
  238. package/dist/core/sdk.js +2 -2
  239. package/dist/core/sdk.js.map +1 -1
  240. package/dist/core/session-manager-core.d.ts +1 -1
  241. package/dist/core/session-manager-core.d.ts.map +1 -1
  242. package/dist/core/session-manager-core.js.map +1 -1
  243. package/dist/core/session-manager-entries.d.ts +1 -1
  244. package/dist/core/session-manager-entries.d.ts.map +1 -1
  245. package/dist/core/session-manager-entries.js.map +1 -1
  246. package/dist/core/session-manager-list.d.ts.map +1 -1
  247. package/dist/core/session-manager-list.js.map +1 -1
  248. package/dist/core/session-manager-types.d.ts +1 -1
  249. package/dist/core/session-manager-types.d.ts.map +1 -1
  250. package/dist/core/session-manager-types.js.map +1 -1
  251. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  252. package/dist/core/settings-manager-basic-accessors.js +1 -1
  253. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  254. package/dist/core/settings-types.d.ts +1 -1
  255. package/dist/core/settings-types.d.ts.map +1 -1
  256. package/dist/core/settings-types.js.map +1 -1
  257. package/dist/core/tools/oversized-tool-result.d.ts +1 -1
  258. package/dist/core/tools/oversized-tool-result.d.ts.map +1 -1
  259. package/dist/core/tools/oversized-tool-result.js.map +1 -1
  260. package/dist/core/tools/read-url.d.ts +1 -1
  261. package/dist/core/tools/read-url.d.ts.map +1 -1
  262. package/dist/core/tools/read-url.js.map +1 -1
  263. package/dist/core/tools/read.d.ts.map +1 -1
  264. package/dist/core/tools/read.js.map +1 -1
  265. package/dist/core/tools/render-utils.d.ts +1 -1
  266. package/dist/core/tools/render-utils.d.ts.map +1 -1
  267. package/dist/core/tools/render-utils.js.map +1 -1
  268. package/dist/core/tools/todos-types.d.ts.map +1 -1
  269. package/dist/core/tools/todos-types.js +1 -1
  270. package/dist/core/tools/todos-types.js.map +1 -1
  271. package/dist/main-app-mode.d.ts +1 -1
  272. package/dist/main-app-mode.d.ts.map +1 -1
  273. package/dist/main-app-mode.js.map +1 -1
  274. package/dist/main-session-options.d.ts.map +1 -1
  275. package/dist/main-session-options.js +1 -1
  276. package/dist/main-session-options.js.map +1 -1
  277. package/dist/modes/interactive/components/assistant-message.d.ts +1 -1
  278. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  279. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  280. package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -1
  281. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  282. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  283. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  284. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  285. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  286. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  287. package/dist/modes/interactive/components/model-selector.js +1 -1
  288. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  289. package/dist/modes/interactive/components/scoped-models-selector.d.ts +1 -1
  290. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  291. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  292. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  293. package/dist/modes/interactive/components/settings-selector-handlers.js +2 -2
  294. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  295. package/dist/modes/interactive/components/settings-selector-types.d.ts +1 -1
  296. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  297. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  298. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  299. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  300. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  301. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  302. package/dist/modes/print-mode.d.ts +1 -1
  303. package/dist/modes/print-mode.d.ts.map +1 -1
  304. package/dist/modes/print-mode.js.map +1 -1
  305. package/dist/modes/rpc/rpc-client.d.ts +1 -1
  306. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  307. package/dist/modes/rpc/rpc-client.js.map +1 -1
  308. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  309. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  310. package/dist/modes/rpc/rpc-types.js.map +1 -1
  311. package/docs/changelog.mdx +15 -0
  312. package/docs/custom-provider.md +2 -1
  313. package/docs/sdk.md +2 -2
  314. package/docs/settings.md +7 -7
  315. package/examples/extensions/custom-footer.ts +1 -1
  316. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  317. package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
  318. package/examples/extensions/custom-provider-gitlab-duo/test.ts +1 -1
  319. package/examples/extensions/handoff.ts +1 -1
  320. package/examples/extensions/hello.ts +1 -1
  321. package/examples/extensions/plan-mode/index.ts +1 -1
  322. package/examples/extensions/preset.ts +1 -1
  323. package/examples/extensions/qna.ts +1 -1
  324. package/examples/extensions/subagent/display.ts +1 -1
  325. package/examples/extensions/subagent/runner.ts +1 -1
  326. package/examples/extensions/subagent/schemas.ts +1 -1
  327. package/examples/extensions/subagent/types.ts +1 -1
  328. package/examples/extensions/summarize.ts +1 -1
  329. package/examples/extensions/tic-tac-toe.ts +1 -1
  330. package/examples/extensions/todo.ts +1 -1
  331. package/examples/extensions/tool-override.ts +1 -1
  332. package/examples/sdk/02-custom-model.ts +1 -1
  333. package/examples/sdk/12-full-control.ts +1 -1
  334. package/examples/sdk/README.md +1 -1
  335. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-events.js","sourceRoot":"","sources":["../../src/core/agent-session-events.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEvent, AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Message, TextContent } from \"@earendil-works/pi-ai\";\nimport { cleanupSessionResources } from \"@earendil-works/pi-ai\";\nimport { formatCopilotProviderError } from \"./copilot-errors.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport { customMessageExcludesContext, isSingleGenericAbortTextContent, replacementAbortContent, type AgentSessionEvent, type AgentSessionEventListener } from \"./agent-session-types.ts\";\nimport type { MessageEndEvent, MessageStartEvent, MessageUpdateEvent, ToolExecutionEndEvent, ToolExecutionStartEvent, ToolExecutionUpdateEvent, TurnEndEvent, TurnStartEvent } from \"./extensions/index.ts\";\n\nexport function _emit(this: AgentSession, event: AgentSessionEvent): void {\n\tfor (const l of this._eventListeners) {\n\t\tl(event);\n\t}\n}\n\n\nexport function _emitQueueUpdate(this: AgentSession): void {\n\tthis._emit({\n\t\ttype: \"queue_update\",\n\t\tsteering: [...this._steeringMessages],\n\t\tfollowUp: [...this._followUpMessages],\n\t});\n}\n\n/** Internal handler for agent events - shared by subscribe and reconnect */\n\nexport function _handleAgentEvent(this: AgentSession, event: AgentEvent): void {\n\t// Create retry promise synchronously before queueing async processing.\n\t// Agent.emit() calls this handler synchronously, and prompt() calls waitForRetry()\n\t// as soon as agent.prompt() resolves. If _retryPromise is created only inside\n\t// _processAgentEvent, slow earlier queued events can delay agent_end processing\n\t// and waitForRetry() can miss the in-flight retry.\n\tthis._createRetryPromiseForAgentEnd(event);\n\n\tthis._agentEventQueue = this._agentEventQueue.then(\n\t\t() => this._processAgentEvent(event),\n\t\t() => this._processAgentEvent(event),\n\t);\n\n\t// Keep queue alive if an event handler fails\n\tthis._agentEventQueue.catch(() => {});\n}\n\n\nexport function _createRetryPromiseForAgentEnd(this: AgentSession, event: AgentEvent): void {\n\tif (event.type !== \"agent_end\" || this._retryPromise) {\n\t\treturn;\n\t}\n\n\tconst settings = this.settingsManager.getRetrySettings();\n\tif (!settings.enabled) {\n\t\treturn;\n\t}\n\n\tconst lastAssistant = this._findLastAssistantInMessages(event.messages);\n\tif (!lastAssistant) {\n\t\treturn;\n\t}\n\n\tconst shouldRetry = this._isRetryableError(lastAssistant) || this._isEmptyCompletion(lastAssistant);\n\tif (!shouldRetry) {\n\t\treturn;\n\t}\n\n\tthis._retryPromise = new Promise((resolve) => {\n\t\tthis._retryResolve = resolve;\n\t});\n}\n\n\nexport function _findLastAssistantInMessages(this: AgentSession, messages: AgentMessage[]): AssistantMessage | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (message.role === \"assistant\") {\n\t\t\treturn message as AssistantMessage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n\nexport async function _processAgentEvent(this: AgentSession, event: AgentEvent): Promise<void> {\n\t// When a user message starts, check if it's from either queue and remove it BEFORE emitting\n\t// This ensures the UI sees the updated queue state\n\tif (event.type === \"message_start\" && event.message.role === \"user\") {\n\t\tthis._overflowRecoveryAttempted = false;\n\t\tconst messageText = this._getUserMessageText(event.message);\n\t\tif (messageText) {\n\t\t\t// Check steering queue first\n\t\t\tconst steeringIndex = this._steeringMessages.indexOf(messageText);\n\t\t\tif (steeringIndex !== -1) {\n\t\t\t\tthis._steeringMessages.splice(steeringIndex, 1);\n\t\t\t\tthis._emitQueueUpdate();\n\t\t\t} else {\n\t\t\t\t// Check follow-up queue\n\t\t\t\tconst followUpIndex = this._followUpMessages.indexOf(messageText);\n\t\t\t\tif (followUpIndex !== -1) {\n\t\t\t\t\tthis._followUpMessages.splice(followUpIndex, 1);\n\t\t\t\t\tthis._emitQueueUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tthis._applyInterruptAbortMessage(event);\n\tthis._applyProviderErrorGuidance(event);\n\n\t// Emit to extensions first\n\tawait this._emitExtensionEvent(event);\n\n\t// Notify all listeners\n\tthis._emit(event);\n\n\t// Handle session persistence\n\tif (event.type === \"message_end\") {\n\t\t// Check if this is a custom message from extensions\n\t\tif (event.message.role === \"custom\") {\n\t\t\t// Persist as CustomMessageEntry\n\t\t\tthis.sessionManager.appendCustomMessageEntry(\n\t\t\t\tevent.message.customType,\n\t\t\t\tevent.message.content,\n\t\t\t\tevent.message.display,\n\t\t\t\tevent.message.details,\n\t\t\t\tcustomMessageExcludesContext(event.message),\n\t\t\t);\n\t\t} else if (\n\t\t\tevent.message.role === \"user\" ||\n\t\t\tevent.message.role === \"assistant\" ||\n\t\t\tevent.message.role === \"toolResult\"\n\t\t) {\n\t\t\tif (event.message.role === \"assistant\") {\n\t\t\t\tthis._normalizePersistedGeminiToolArgs(event.message);\n\t\t\t}\n\t\t\t// Regular LLM message - persist as SessionMessageEntry\n\t\t\tthis.sessionManager.appendMessage(event.message);\n\t\t}\n\t\t// Other message types (bashExecution, branchSummary) are persisted elsewhere\n\n\t\t// Track assistant message for auto-compaction (checked on agent_end)\n\t\tif (event.message.role === \"assistant\") {\n\t\t\tthis._lastAssistantMessage = event.message;\n\n\t\t\tconst assistantMsg = event.message as AssistantMessage;\n\t\t\t// Treat degenerate empty completions (no content, zero output tokens) as\n\t\t\t// failures alongside stopReason === \"error\". Otherwise an empty turn that\n\t\t\t// stops with reason \"stop\" would reset the retry counter on every attempt,\n\t\t\t// causing unbounded retries instead of honoring maxRetries.\n\t\t\tconst assistantFailed = assistantMsg.stopReason === \"error\" || this._isEmptyCompletion(assistantMsg);\n\t\t\tif (!assistantFailed) {\n\t\t\t\tthis._overflowRecoveryAttempted = false;\n\t\t\t}\n\n\t\t\t// Reset retry counter immediately on successful assistant response\n\t\t\t// This prevents accumulation across multiple LLM calls within a turn\n\t\t\tif (!assistantFailed && this._retryAttempt > 0) {\n\t\t\t\tthis._emit({\n\t\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tattempt: this._retryAttempt,\n\t\t\t\t});\n\t\t\t\tthis._retryAttempt = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check auto-retry and auto-compaction after agent completes\n\tif (event.type === \"agent_end\" && this._lastAssistantMessage) {\n\t\tconst msg = this._lastAssistantMessage;\n\t\tthis._lastAssistantMessage = undefined;\n\n\t\t// Check for retryable errors first (overloaded, rate limit, server errors,\n\t\t// transient provider finish_reason errors, or degenerate empty completions)\n\t\tconst retryableError = this._isRetryableError(msg);\n\t\tconst emptyCompletion = !retryableError && this._isEmptyCompletion(msg);\n\t\tif (retryableError || emptyCompletion) {\n\t\t\tif (emptyCompletion && !msg.errorMessage) {\n\t\t\t\t// Surface a clear reason in the retry banner; empty completions carry no\n\t\t\t\t// provider error message of their own.\n\t\t\t\tmsg.errorMessage = \"Provider returned an empty completion\";\n\t\t\t}\n\t\t\tconst didRetry = await this._handleRetryableError(msg);\n\t\t\tif (didRetry) return; // Retry was initiated, don't proceed to compaction\n\t\t}\n\n\t\tthis._resolveRetry();\n\t\tawait this._checkCompaction(msg);\n\t}\n}\n\n\nexport function _applyInterruptAbortMessage(this: AgentSession, event: AgentEvent): void {\n\tconst abortMessage = this._activeInterruptAbortMessage;\n\tif (!abortMessage) return;\n\n\tif (event.type === \"tool_execution_end\" && event.isError && isSingleGenericAbortTextContent(event.result.content)) {\n\t\tevent.result.content = replacementAbortContent(abortMessage);\n\t\treturn;\n\t}\n\n\tif (event.type !== \"message_start\" && event.type !== \"message_end\") return;\n\n\tif (event.message.role === \"toolResult\" && event.message.isError && isSingleGenericAbortTextContent(event.message.content)) {\n\t\tevent.message.content = replacementAbortContent(abortMessage);\n\t\treturn;\n\t}\n\n\tif (event.message.role === \"assistant\") {\n\t\tconst assistantMessage = event.message as AssistantMessage;\n\t\tif (assistantMessage.stopReason === \"aborted\") {\n\t\t\tassistantMessage.errorMessage = abortMessage;\n\t\t}\n\t}\n}\n\n\nexport function _applyProviderErrorGuidance(this: AgentSession, event: AgentEvent): void {\n\tif (event.type !== \"message_start\" && event.type !== \"message_update\" && event.type !== \"message_end\") return;\n\tif (event.message.role !== \"assistant\") return;\n\n\tconst assistantMessage = event.message as AssistantMessage;\n\tif (assistantMessage.stopReason !== \"error\" || !assistantMessage.errorMessage) return;\n\n\tassistantMessage.errorMessage = formatCopilotProviderError(\n\t\tassistantMessage.provider,\n\t\tassistantMessage.errorMessage,\n\t);\n}\n\n/** Resolve the pending retry promise */\n\nexport function _resolveRetry(this: AgentSession): void {\n\tif (this._retryResolve) {\n\t\tthis._retryResolve();\n\t\tthis._retryResolve = undefined;\n\t\tthis._retryPromise = undefined;\n\t}\n}\n\n/** Extract text content from a message */\n\nexport function _getUserMessageText(this: AgentSession, message: Message): string {\n\tif (message.role !== \"user\") return \"\";\n\tconst content = message.content;\n\tif (typeof content === \"string\") return content;\n\tconst textBlocks = content.filter((c) => c.type === \"text\");\n\treturn textBlocks.map((c) => (c as TextContent).text).join(\"\");\n}\n\n/** Find the last assistant message in agent state (including aborted ones) */\n\nexport function _findLastAssistantMessage(this: AgentSession): AssistantMessage | undefined {\n\tconst messages = this.agent.state.messages;\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i];\n\t\tif (msg.role === \"assistant\") {\n\t\t\treturn msg as AssistantMessage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n\nexport function _replaceMessageInPlace(this: AgentSession, target: AgentMessage, replacement: AgentMessage): void {\n\t// Agent-core stores the finalized message object in its state before emitting message_end.\n\t// SessionManager persistence happens later in _processAgentEvent() with event.message.\n\t// Mutating this object in place keeps agent state, later turn/agent events, listeners,\n\t// and the eventual SessionManager.appendMessage(event.message) persistence in sync.\n\tif (target === replacement) {\n\t\treturn;\n\t}\n\n\tconst targetRecord = target as unknown as Record<string, unknown>;\n\tfor (const key of Object.keys(targetRecord)) {\n\t\tdelete targetRecord[key];\n\t}\n\tObject.assign(targetRecord, replacement);\n}\n\n/** Emit extension events based on agent events */\n\nexport async function _emitExtensionEvent(this: AgentSession, event: AgentEvent): Promise<void> {\n\tif (event.type === \"agent_start\") {\n\t\tthis._turnIndex = 0;\n\t\tawait this._extensionRunner.emit({ type: \"agent_start\" });\n\t} else if (event.type === \"agent_end\") {\n\t\tawait this._extensionRunner.emit({ type: \"agent_end\", messages: event.messages });\n\t} else if (event.type === \"turn_start\") {\n\t\tconst extensionEvent: TurnStartEvent = {\n\t\t\ttype: \"turn_start\",\n\t\t\tturnIndex: this._turnIndex,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"turn_end\") {\n\t\tconst extensionEvent: TurnEndEvent = {\n\t\t\ttype: \"turn_end\",\n\t\t\tturnIndex: this._turnIndex,\n\t\t\tmessage: event.message,\n\t\t\ttoolResults: event.toolResults,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t\tthis._turnIndex++;\n\t} else if (event.type === \"message_start\") {\n\t\tconst extensionEvent: MessageStartEvent = {\n\t\t\ttype: \"message_start\",\n\t\t\tmessage: event.message,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"message_update\") {\n\t\tconst extensionEvent: MessageUpdateEvent = {\n\t\t\ttype: \"message_update\",\n\t\t\tmessage: event.message,\n\t\t\tassistantMessageEvent: event.assistantMessageEvent,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"message_end\") {\n\t\tconst extensionEvent: MessageEndEvent = {\n\t\t\ttype: \"message_end\",\n\t\t\tmessage: event.message,\n\t\t};\n\t\tconst replacement = await this._extensionRunner.emitMessageEnd(extensionEvent);\n\t\tif (replacement) {\n\t\t\tthis._replaceMessageInPlace(event.message, replacement);\n\t\t}\n\t} else if (event.type === \"tool_execution_start\") {\n\t\tconst extensionEvent: ToolExecutionStartEvent = {\n\t\t\ttype: \"tool_execution_start\",\n\t\t\ttoolCallId: event.toolCallId,\n\t\t\ttoolName: event.toolName,\n\t\t\targs: event.args,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"tool_execution_update\") {\n\t\tconst extensionEvent: ToolExecutionUpdateEvent = {\n\t\t\ttype: \"tool_execution_update\",\n\t\t\ttoolCallId: event.toolCallId,\n\t\t\ttoolName: event.toolName,\n\t\t\targs: event.args,\n\t\t\tpartialResult: event.partialResult,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"tool_execution_end\") {\n\t\tconst extensionEvent: ToolExecutionEndEvent = {\n\t\t\ttype: \"tool_execution_end\",\n\t\t\ttoolCallId: event.toolCallId,\n\t\t\ttoolName: event.toolName,\n\t\t\tresult: event.result,\n\t\t\tisError: event.isError,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t}\n}\n\n/**\n * Subscribe to agent events.\n * Session persistence is handled internally (saves messages on message_end).\n * Multiple listeners can be added. Returns unsubscribe function for this listener.\n */\n\nexport function subscribe(this: AgentSession, listener: AgentSessionEventListener): () => void {\n\tthis._eventListeners.push(listener);\n\n\t// Return unsubscribe function for this specific listener\n\treturn () => {\n\t\tconst index = this._eventListeners.indexOf(listener);\n\t\tif (index !== -1) {\n\t\t\tthis._eventListeners.splice(index, 1);\n\t\t}\n\t};\n}\n\n/**\n * Temporarily disconnect from agent events.\n * User listeners are preserved and will receive events again after resubscribe().\n * Used internally during operations that need to pause event processing.\n */\n\nexport function _disconnectFromAgent(this: AgentSession): void {\n\tif (this._unsubscribeAgent) {\n\t\tthis._unsubscribeAgent();\n\t\tthis._unsubscribeAgent = undefined;\n\t}\n}\n\n/**\n * Reconnect to agent events after _disconnectFromAgent().\n * Preserves all existing listeners.\n */\n\nexport function _reconnectToAgent(this: AgentSession): void {\n\tif (this._unsubscribeAgent) return; // Already connected\n\tthis._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);\n}\n\n/**\n * Remove all listeners and disconnect from agent.\n * Call this when completely done with the session.\n */\n\nexport function dispose(this: AgentSession): void {\n\tthis._extensionRunner.invalidate(\n\t\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\t);\n\tthis._disconnectFromAgent();\n\tthis._eventListeners = [];\n\tcleanupSessionResources(this.sessionId);\n}\n\n// =========================================================================\n// Read-only State Access\n// =========================================================================\n\n/** Full agent state */\n\nexport const agentSessionEventsMethods = {\n\t_emit,\n\t_emitQueueUpdate,\n\t_handleAgentEvent,\n\t_createRetryPromiseForAgentEnd,\n\t_findLastAssistantInMessages,\n\t_processAgentEvent,\n\t_applyInterruptAbortMessage,\n\t_applyProviderErrorGuidance,\n\t_resolveRetry,\n\t_getUserMessageText,\n\t_findLastAssistantMessage,\n\t_replaceMessageInPlace,\n\t_emitExtensionEvent,\n\tsubscribe,\n\t_disconnectFromAgent,\n\t_reconnectToAgent,\n\tdispose,\n};\n"]}
1
+ {"version":3,"file":"agent-session-events.js","sourceRoot":"","sources":["../../src/core/agent-session-events.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEvent, AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Message, TextContent } from \"@earendil-works/pi-ai/compat\";\nimport { cleanupSessionResources } from \"@earendil-works/pi-ai/compat\";\nimport { formatCopilotProviderError } from \"./copilot-errors.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport { customMessageExcludesContext, isSingleGenericAbortTextContent, replacementAbortContent, type AgentSessionEvent, type AgentSessionEventListener } from \"./agent-session-types.ts\";\nimport type { MessageEndEvent, MessageStartEvent, MessageUpdateEvent, ToolExecutionEndEvent, ToolExecutionStartEvent, ToolExecutionUpdateEvent, TurnEndEvent, TurnStartEvent } from \"./extensions/index.ts\";\n\nexport function _emit(this: AgentSession, event: AgentSessionEvent): void {\n\tfor (const l of this._eventListeners) {\n\t\tl(event);\n\t}\n}\n\n\nexport function _emitQueueUpdate(this: AgentSession): void {\n\tthis._emit({\n\t\ttype: \"queue_update\",\n\t\tsteering: [...this._steeringMessages],\n\t\tfollowUp: [...this._followUpMessages],\n\t});\n}\n\n/** Internal handler for agent events - shared by subscribe and reconnect */\n\nexport function _handleAgentEvent(this: AgentSession, event: AgentEvent): void {\n\t// Create retry promise synchronously before queueing async processing.\n\t// Agent.emit() calls this handler synchronously, and prompt() calls waitForRetry()\n\t// as soon as agent.prompt() resolves. If _retryPromise is created only inside\n\t// _processAgentEvent, slow earlier queued events can delay agent_end processing\n\t// and waitForRetry() can miss the in-flight retry.\n\tthis._createRetryPromiseForAgentEnd(event);\n\n\tthis._agentEventQueue = this._agentEventQueue.then(\n\t\t() => this._processAgentEvent(event),\n\t\t() => this._processAgentEvent(event),\n\t);\n\n\t// Keep queue alive if an event handler fails\n\tthis._agentEventQueue.catch(() => {});\n}\n\n\nexport function _createRetryPromiseForAgentEnd(this: AgentSession, event: AgentEvent): void {\n\tif (event.type !== \"agent_end\" || this._retryPromise) {\n\t\treturn;\n\t}\n\n\tconst settings = this.settingsManager.getRetrySettings();\n\tif (!settings.enabled) {\n\t\treturn;\n\t}\n\n\tconst lastAssistant = this._findLastAssistantInMessages(event.messages);\n\tif (!lastAssistant) {\n\t\treturn;\n\t}\n\n\tconst shouldRetry = this._isRetryableError(lastAssistant) || this._isEmptyCompletion(lastAssistant);\n\tif (!shouldRetry) {\n\t\treturn;\n\t}\n\n\tthis._retryPromise = new Promise((resolve) => {\n\t\tthis._retryResolve = resolve;\n\t});\n}\n\n\nexport function _findLastAssistantInMessages(this: AgentSession, messages: AgentMessage[]): AssistantMessage | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (message.role === \"assistant\") {\n\t\t\treturn message as AssistantMessage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n\nexport async function _processAgentEvent(this: AgentSession, event: AgentEvent): Promise<void> {\n\t// When a user message starts, check if it's from either queue and remove it BEFORE emitting\n\t// This ensures the UI sees the updated queue state\n\tif (event.type === \"message_start\" && event.message.role === \"user\") {\n\t\tthis._overflowRecoveryAttempted = false;\n\t\tconst messageText = this._getUserMessageText(event.message);\n\t\tif (messageText) {\n\t\t\t// Check steering queue first\n\t\t\tconst steeringIndex = this._steeringMessages.indexOf(messageText);\n\t\t\tif (steeringIndex !== -1) {\n\t\t\t\tthis._steeringMessages.splice(steeringIndex, 1);\n\t\t\t\tthis._emitQueueUpdate();\n\t\t\t} else {\n\t\t\t\t// Check follow-up queue\n\t\t\t\tconst followUpIndex = this._followUpMessages.indexOf(messageText);\n\t\t\t\tif (followUpIndex !== -1) {\n\t\t\t\t\tthis._followUpMessages.splice(followUpIndex, 1);\n\t\t\t\t\tthis._emitQueueUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tthis._applyInterruptAbortMessage(event);\n\tthis._applyProviderErrorGuidance(event);\n\n\t// Emit to extensions first\n\tawait this._emitExtensionEvent(event);\n\n\t// Notify all listeners\n\tthis._emit(event);\n\n\t// Handle session persistence\n\tif (event.type === \"message_end\") {\n\t\t// Check if this is a custom message from extensions\n\t\tif (event.message.role === \"custom\") {\n\t\t\t// Persist as CustomMessageEntry\n\t\t\tthis.sessionManager.appendCustomMessageEntry(\n\t\t\t\tevent.message.customType,\n\t\t\t\tevent.message.content,\n\t\t\t\tevent.message.display,\n\t\t\t\tevent.message.details,\n\t\t\t\tcustomMessageExcludesContext(event.message),\n\t\t\t);\n\t\t} else if (\n\t\t\tevent.message.role === \"user\" ||\n\t\t\tevent.message.role === \"assistant\" ||\n\t\t\tevent.message.role === \"toolResult\"\n\t\t) {\n\t\t\tif (event.message.role === \"assistant\") {\n\t\t\t\tthis._normalizePersistedGeminiToolArgs(event.message);\n\t\t\t}\n\t\t\t// Regular LLM message - persist as SessionMessageEntry\n\t\t\tthis.sessionManager.appendMessage(event.message);\n\t\t}\n\t\t// Other message types (bashExecution, branchSummary) are persisted elsewhere\n\n\t\t// Track assistant message for auto-compaction (checked on agent_end)\n\t\tif (event.message.role === \"assistant\") {\n\t\t\tthis._lastAssistantMessage = event.message;\n\n\t\t\tconst assistantMsg = event.message as AssistantMessage;\n\t\t\t// Treat degenerate empty completions (no content, zero output tokens) as\n\t\t\t// failures alongside stopReason === \"error\". Otherwise an empty turn that\n\t\t\t// stops with reason \"stop\" would reset the retry counter on every attempt,\n\t\t\t// causing unbounded retries instead of honoring maxRetries.\n\t\t\tconst assistantFailed = assistantMsg.stopReason === \"error\" || this._isEmptyCompletion(assistantMsg);\n\t\t\tif (!assistantFailed) {\n\t\t\t\tthis._overflowRecoveryAttempted = false;\n\t\t\t}\n\n\t\t\t// Reset retry counter immediately on successful assistant response\n\t\t\t// This prevents accumulation across multiple LLM calls within a turn\n\t\t\tif (!assistantFailed && this._retryAttempt > 0) {\n\t\t\t\tthis._emit({\n\t\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tattempt: this._retryAttempt,\n\t\t\t\t});\n\t\t\t\tthis._retryAttempt = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check auto-retry and auto-compaction after agent completes\n\tif (event.type === \"agent_end\" && this._lastAssistantMessage) {\n\t\tconst msg = this._lastAssistantMessage;\n\t\tthis._lastAssistantMessage = undefined;\n\n\t\t// Check for retryable errors first (overloaded, rate limit, server errors,\n\t\t// transient provider finish_reason errors, or degenerate empty completions)\n\t\tconst retryableError = this._isRetryableError(msg);\n\t\tconst emptyCompletion = !retryableError && this._isEmptyCompletion(msg);\n\t\tif (retryableError || emptyCompletion) {\n\t\t\tif (emptyCompletion && !msg.errorMessage) {\n\t\t\t\t// Surface a clear reason in the retry banner; empty completions carry no\n\t\t\t\t// provider error message of their own.\n\t\t\t\tmsg.errorMessage = \"Provider returned an empty completion\";\n\t\t\t}\n\t\t\tconst didRetry = await this._handleRetryableError(msg);\n\t\t\tif (didRetry) return; // Retry was initiated, don't proceed to compaction\n\t\t}\n\n\t\tthis._resolveRetry();\n\t\tawait this._checkCompaction(msg);\n\t}\n}\n\n\nexport function _applyInterruptAbortMessage(this: AgentSession, event: AgentEvent): void {\n\tconst abortMessage = this._activeInterruptAbortMessage;\n\tif (!abortMessage) return;\n\n\tif (event.type === \"tool_execution_end\" && event.isError && isSingleGenericAbortTextContent(event.result.content)) {\n\t\tevent.result.content = replacementAbortContent(abortMessage);\n\t\treturn;\n\t}\n\n\tif (event.type !== \"message_start\" && event.type !== \"message_end\") return;\n\n\tif (event.message.role === \"toolResult\" && event.message.isError && isSingleGenericAbortTextContent(event.message.content)) {\n\t\tevent.message.content = replacementAbortContent(abortMessage);\n\t\treturn;\n\t}\n\n\tif (event.message.role === \"assistant\") {\n\t\tconst assistantMessage = event.message as AssistantMessage;\n\t\tif (assistantMessage.stopReason === \"aborted\") {\n\t\t\tassistantMessage.errorMessage = abortMessage;\n\t\t}\n\t}\n}\n\n\nexport function _applyProviderErrorGuidance(this: AgentSession, event: AgentEvent): void {\n\tif (event.type !== \"message_start\" && event.type !== \"message_update\" && event.type !== \"message_end\") return;\n\tif (event.message.role !== \"assistant\") return;\n\n\tconst assistantMessage = event.message as AssistantMessage;\n\tif (assistantMessage.stopReason !== \"error\" || !assistantMessage.errorMessage) return;\n\n\tassistantMessage.errorMessage = formatCopilotProviderError(\n\t\tassistantMessage.provider,\n\t\tassistantMessage.errorMessage,\n\t);\n}\n\n/** Resolve the pending retry promise */\n\nexport function _resolveRetry(this: AgentSession): void {\n\tif (this._retryResolve) {\n\t\tthis._retryResolve();\n\t\tthis._retryResolve = undefined;\n\t\tthis._retryPromise = undefined;\n\t}\n}\n\n/** Extract text content from a message */\n\nexport function _getUserMessageText(this: AgentSession, message: Message): string {\n\tif (message.role !== \"user\") return \"\";\n\tconst content = message.content;\n\tif (typeof content === \"string\") return content;\n\tconst textBlocks = content.filter((c) => c.type === \"text\");\n\treturn textBlocks.map((c) => (c as TextContent).text).join(\"\");\n}\n\n/** Find the last assistant message in agent state (including aborted ones) */\n\nexport function _findLastAssistantMessage(this: AgentSession): AssistantMessage | undefined {\n\tconst messages = this.agent.state.messages;\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i];\n\t\tif (msg.role === \"assistant\") {\n\t\t\treturn msg as AssistantMessage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n\nexport function _replaceMessageInPlace(this: AgentSession, target: AgentMessage, replacement: AgentMessage): void {\n\t// Agent-core stores the finalized message object in its state before emitting message_end.\n\t// SessionManager persistence happens later in _processAgentEvent() with event.message.\n\t// Mutating this object in place keeps agent state, later turn/agent events, listeners,\n\t// and the eventual SessionManager.appendMessage(event.message) persistence in sync.\n\tif (target === replacement) {\n\t\treturn;\n\t}\n\n\tconst targetRecord = target as unknown as Record<string, unknown>;\n\tfor (const key of Object.keys(targetRecord)) {\n\t\tdelete targetRecord[key];\n\t}\n\tObject.assign(targetRecord, replacement);\n}\n\n/** Emit extension events based on agent events */\n\nexport async function _emitExtensionEvent(this: AgentSession, event: AgentEvent): Promise<void> {\n\tif (event.type === \"agent_start\") {\n\t\tthis._turnIndex = 0;\n\t\tawait this._extensionRunner.emit({ type: \"agent_start\" });\n\t} else if (event.type === \"agent_end\") {\n\t\tawait this._extensionRunner.emit({ type: \"agent_end\", messages: event.messages });\n\t} else if (event.type === \"turn_start\") {\n\t\tconst extensionEvent: TurnStartEvent = {\n\t\t\ttype: \"turn_start\",\n\t\t\tturnIndex: this._turnIndex,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"turn_end\") {\n\t\tconst extensionEvent: TurnEndEvent = {\n\t\t\ttype: \"turn_end\",\n\t\t\tturnIndex: this._turnIndex,\n\t\t\tmessage: event.message,\n\t\t\ttoolResults: event.toolResults,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t\tthis._turnIndex++;\n\t} else if (event.type === \"message_start\") {\n\t\tconst extensionEvent: MessageStartEvent = {\n\t\t\ttype: \"message_start\",\n\t\t\tmessage: event.message,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"message_update\") {\n\t\tconst extensionEvent: MessageUpdateEvent = {\n\t\t\ttype: \"message_update\",\n\t\t\tmessage: event.message,\n\t\t\tassistantMessageEvent: event.assistantMessageEvent,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"message_end\") {\n\t\tconst extensionEvent: MessageEndEvent = {\n\t\t\ttype: \"message_end\",\n\t\t\tmessage: event.message,\n\t\t};\n\t\tconst replacement = await this._extensionRunner.emitMessageEnd(extensionEvent);\n\t\tif (replacement) {\n\t\t\tthis._replaceMessageInPlace(event.message, replacement);\n\t\t}\n\t} else if (event.type === \"tool_execution_start\") {\n\t\tconst extensionEvent: ToolExecutionStartEvent = {\n\t\t\ttype: \"tool_execution_start\",\n\t\t\ttoolCallId: event.toolCallId,\n\t\t\ttoolName: event.toolName,\n\t\t\targs: event.args,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"tool_execution_update\") {\n\t\tconst extensionEvent: ToolExecutionUpdateEvent = {\n\t\t\ttype: \"tool_execution_update\",\n\t\t\ttoolCallId: event.toolCallId,\n\t\t\ttoolName: event.toolName,\n\t\t\targs: event.args,\n\t\t\tpartialResult: event.partialResult,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t} else if (event.type === \"tool_execution_end\") {\n\t\tconst extensionEvent: ToolExecutionEndEvent = {\n\t\t\ttype: \"tool_execution_end\",\n\t\t\ttoolCallId: event.toolCallId,\n\t\t\ttoolName: event.toolName,\n\t\t\tresult: event.result,\n\t\t\tisError: event.isError,\n\t\t};\n\t\tawait this._extensionRunner.emit(extensionEvent);\n\t}\n}\n\n/**\n * Subscribe to agent events.\n * Session persistence is handled internally (saves messages on message_end).\n * Multiple listeners can be added. Returns unsubscribe function for this listener.\n */\n\nexport function subscribe(this: AgentSession, listener: AgentSessionEventListener): () => void {\n\tthis._eventListeners.push(listener);\n\n\t// Return unsubscribe function for this specific listener\n\treturn () => {\n\t\tconst index = this._eventListeners.indexOf(listener);\n\t\tif (index !== -1) {\n\t\t\tthis._eventListeners.splice(index, 1);\n\t\t}\n\t};\n}\n\n/**\n * Temporarily disconnect from agent events.\n * User listeners are preserved and will receive events again after resubscribe().\n * Used internally during operations that need to pause event processing.\n */\n\nexport function _disconnectFromAgent(this: AgentSession): void {\n\tif (this._unsubscribeAgent) {\n\t\tthis._unsubscribeAgent();\n\t\tthis._unsubscribeAgent = undefined;\n\t}\n}\n\n/**\n * Reconnect to agent events after _disconnectFromAgent().\n * Preserves all existing listeners.\n */\n\nexport function _reconnectToAgent(this: AgentSession): void {\n\tif (this._unsubscribeAgent) return; // Already connected\n\tthis._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);\n}\n\n/**\n * Remove all listeners and disconnect from agent.\n * Call this when completely done with the session.\n */\n\nexport function dispose(this: AgentSession): void {\n\tthis._extensionRunner.invalidate(\n\t\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\t);\n\tthis._disconnectFromAgent();\n\tthis._eventListeners = [];\n\tcleanupSessionResources(this.sessionId);\n}\n\n// =========================================================================\n// Read-only State Access\n// =========================================================================\n\n/** Full agent state */\n\nexport const agentSessionEventsMethods = {\n\t_emit,\n\t_emitQueueUpdate,\n\t_handleAgentEvent,\n\t_createRetryPromiseForAgentEnd,\n\t_findLastAssistantInMessages,\n\t_processAgentEvent,\n\t_applyInterruptAbortMessage,\n\t_applyProviderErrorGuidance,\n\t_resolveRetry,\n\t_getUserMessageText,\n\t_findLastAssistantMessage,\n\t_replaceMessageInPlace,\n\t_emitExtensionEvent,\n\tsubscribe,\n\t_disconnectFromAgent,\n\t_reconnectToAgent,\n\tdispose,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-export.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-export.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAIlF,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CA2ChE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,CA4C5E;AAED;;;;GAIG;AAEH,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe3F;AAED;;;;;GAKG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CA+B7E;AAMD;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAsB3E;AAOD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAQvF;AAED;;GAEG;AAEH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;CAQrC,CAAC","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { calculateContextTokens, estimateContextTokens } from \"./compaction/index.ts\";\nimport type { ContextUsage, ReplacedSessionContext } from \"./extensions/index.ts\";\nimport { exportSessionToHtml, type ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport { createToolHtmlRenderer } from \"./export-html/tool-renderer.ts\";\nimport { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry, type SessionHeader } from \"./session-manager.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { SessionStats } from \"./agent-session-types.ts\";\n\nexport function getSessionStats(this: AgentSession): SessionStats {\n\tconst state = this.state;\n\tconst userMessages = state.messages.filter((m) => m.role === \"user\").length;\n\tconst assistantMessages = state.messages.filter((m) => m.role === \"assistant\").length;\n\tconst toolResults = state.messages.filter((m) => m.role === \"toolResult\").length;\n\n\tlet toolCalls = 0;\n\tlet totalInput = 0;\n\tlet totalOutput = 0;\n\tlet totalCacheRead = 0;\n\tlet totalCacheWrite = 0;\n\tlet totalCost = 0;\n\n\tfor (const message of state.messages) {\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst assistantMsg = message as AssistantMessage;\n\t\t\ttoolCalls += assistantMsg.content.filter((c) => c.type === \"toolCall\").length;\n\t\t\ttotalInput += assistantMsg.usage.input;\n\t\t\ttotalOutput += assistantMsg.usage.output;\n\t\t\ttotalCacheRead += assistantMsg.usage.cacheRead;\n\t\t\ttotalCacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\ttotalCost += assistantMsg.usage.cost.total;\n\t\t}\n\t}\n\n\treturn {\n\t\tsessionFile: this.sessionFile,\n\t\tsessionId: this.sessionId,\n\t\tuserMessages,\n\t\tassistantMessages,\n\t\ttoolCalls,\n\t\ttoolResults,\n\t\ttotalMessages: state.messages.length,\n\t\ttokens: {\n\t\t\tinput: totalInput,\n\t\t\toutput: totalOutput,\n\t\t\tcacheRead: totalCacheRead,\n\t\t\tcacheWrite: totalCacheWrite,\n\t\t\ttotal: totalInput + totalOutput + totalCacheRead + totalCacheWrite,\n\t\t},\n\t\tcost: totalCost,\n\t\tcontextUsage: this.getContextUsage(),\n\t};\n}\n\n\nexport function getContextUsage(this: AgentSession): ContextUsage | undefined {\n\tconst model = this.model;\n\tif (!model) return undefined;\n\n\tconst contextWindow = model.contextWindow ?? 0;\n\tif (contextWindow <= 0) return undefined;\n\n\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t// We can only trust usage from an assistant that responded after the latest compaction.\n\t// If no such assistant exists, context token count is unknown until the next LLM response.\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);\n\n\tif (latestCompactionBoundary) {\n\t\t// Check if there's a valid assistant usage after the compaction boundary\n\t\tconst compactionIndex = branchEntries.lastIndexOf(latestCompactionBoundary);\n\t\tlet hasPostCompactionUsage = false;\n\t\tfor (let i = branchEntries.length - 1; i > compactionIndex; i--) {\n\t\t\tconst entry = branchEntries[i];\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\tconst assistant = entry.message;\n\t\t\t\tif (assistant.stopReason !== \"aborted\" && assistant.stopReason !== \"error\") {\n\t\t\t\t\tconst contextTokens = calculateContextTokens(assistant.usage);\n\t\t\t\t\tif (contextTokens > 0) {\n\t\t\t\t\t\thasPostCompactionUsage = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!hasPostCompactionUsage) {\n\t\t\treturn { tokens: null, contextWindow, percent: null };\n\t\t}\n\t}\n\n\tconst estimate = estimateContextTokens(this.messages);\n\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\treturn {\n\t\ttokens: estimate.tokens,\n\t\tcontextWindow,\n\t\tpercent,\n\t};\n}\n\n/**\n * Export session to HTML.\n * @param outputPath Optional output path (defaults to session directory)\n * @returns Path to exported file\n */\n\nexport async function exportToHtml(this: AgentSession, outputPath?: string): Promise<string> {\n\tconst themeName = this.settingsManager.getTheme();\n\n\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\tgetToolDefinition: (name) => this.getToolDefinition(name),\n\t\ttheme,\n\t\tcwd: this.sessionManager.getCwd(),\n\t});\n\n\treturn await exportSessionToHtml(this.sessionManager, this.state, {\n\t\toutputPath,\n\t\tthemeName,\n\t\ttoolRenderer,\n\t});\n}\n\n/**\n * Export the current session branch to a JSONL file.\n * Writes the session header followed by all entries on the current branch path.\n * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n * @returns The resolved output file path.\n */\n\nexport function exportToJsonl(this: AgentSession, outputPath?: string): string {\n\tconst filePath = resolvePath(\n\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\tprocess.cwd(),\n\t);\n\tconst dir = dirname(filePath);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\tconst header: SessionHeader = {\n\t\ttype: \"session\",\n\t\tversion: CURRENT_SESSION_VERSION,\n\t\tid: this.sessionManager.getSessionId(),\n\t\ttimestamp: new Date().toISOString(),\n\t\tcwd: this.sessionManager.getCwd(),\n\t};\n\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst lines = [JSON.stringify(header)];\n\n\t// Re-chain parentIds to form a linear sequence\n\tlet prevId: string | null = null;\n\tfor (const entry of branchEntries) {\n\t\tconst linear = { ...entry, parentId: prevId };\n\t\tlines.push(JSON.stringify(linear));\n\t\tprevId = entry.id;\n\t}\n\n\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\treturn filePath;\n}\n\n// =========================================================================\n// Utilities\n// =========================================================================\n\n/**\n * Get text content of last assistant message.\n * Useful for /copy command.\n * @returns Text content, or undefined if no assistant message exists\n */\n\nexport function getLastAssistantText(this: AgentSession): string | undefined {\n\tconst lastAssistant = this.messages\n\t\t.slice()\n\t\t.reverse()\n\t\t.find((m) => {\n\t\t\tif (m.role !== \"assistant\") return false;\n\t\t\tconst msg = m as AssistantMessage;\n\t\t\t// Skip aborted messages with no content\n\t\t\tif (msg.stopReason === \"aborted\" && msg.content.length === 0) return false;\n\t\t\treturn true;\n\t\t});\n\n\tif (!lastAssistant) return undefined;\n\n\tlet text = \"\";\n\tfor (const content of (lastAssistant as AssistantMessage).content) {\n\t\tif (content.type === \"text\") {\n\t\t\ttext += content.text;\n\t\t}\n\t}\n\n\treturn text.trim() || undefined;\n}\n\n// =========================================================================\n// Extension System\n// =========================================================================\n\n\nexport function createReplacedSessionContext(this: AgentSession): ReplacedSessionContext {\n\tconst context = Object.defineProperties(\n\t\t{},\n\t\tObject.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()),\n\t) as ReplacedSessionContext;\n\tcontext.sendMessage = (message, options) => this.sendCustomMessage(message, options);\n\tcontext.sendUserMessage = (content, options) => this.sendUserMessage(content, options);\n\treturn context;\n}\n\n/**\n * Check if extensions have handlers for a specific event type.\n */\n\nexport function hasExtensionHandlers(this: AgentSession, eventType: string): boolean {\n\treturn this._extensionRunner.hasHandlers(eventType);\n}\n\n/**\n * Get the extension runner (for setting UI context and error handlers).\n */\n\nexport const agentSessionExportMethods = {\n\tgetSessionStats,\n\tgetContextUsage,\n\texportToHtml,\n\texportToJsonl,\n\tgetLastAssistantText,\n\tcreateReplacedSessionContext,\n\thasExtensionHandlers,\n};\n"]}
1
+ {"version":3,"file":"agent-session-export.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-export.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAIlF,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CA2ChE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,CA4C5E;AAED;;;;GAIG;AAEH,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe3F;AAED;;;;;GAKG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CA+B7E;AAMD;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAsB3E;AAOD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAQvF;AAED;;GAEG;AAEH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;CAQrC,CAAC","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai/compat\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { calculateContextTokens, estimateContextTokens } from \"./compaction/index.ts\";\nimport type { ContextUsage, ReplacedSessionContext } from \"./extensions/index.ts\";\nimport { exportSessionToHtml, type ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport { createToolHtmlRenderer } from \"./export-html/tool-renderer.ts\";\nimport { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry, type SessionHeader } from \"./session-manager.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { SessionStats } from \"./agent-session-types.ts\";\n\nexport function getSessionStats(this: AgentSession): SessionStats {\n\tconst state = this.state;\n\tconst userMessages = state.messages.filter((m) => m.role === \"user\").length;\n\tconst assistantMessages = state.messages.filter((m) => m.role === \"assistant\").length;\n\tconst toolResults = state.messages.filter((m) => m.role === \"toolResult\").length;\n\n\tlet toolCalls = 0;\n\tlet totalInput = 0;\n\tlet totalOutput = 0;\n\tlet totalCacheRead = 0;\n\tlet totalCacheWrite = 0;\n\tlet totalCost = 0;\n\n\tfor (const message of state.messages) {\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst assistantMsg = message as AssistantMessage;\n\t\t\ttoolCalls += assistantMsg.content.filter((c) => c.type === \"toolCall\").length;\n\t\t\ttotalInput += assistantMsg.usage.input;\n\t\t\ttotalOutput += assistantMsg.usage.output;\n\t\t\ttotalCacheRead += assistantMsg.usage.cacheRead;\n\t\t\ttotalCacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\ttotalCost += assistantMsg.usage.cost.total;\n\t\t}\n\t}\n\n\treturn {\n\t\tsessionFile: this.sessionFile,\n\t\tsessionId: this.sessionId,\n\t\tuserMessages,\n\t\tassistantMessages,\n\t\ttoolCalls,\n\t\ttoolResults,\n\t\ttotalMessages: state.messages.length,\n\t\ttokens: {\n\t\t\tinput: totalInput,\n\t\t\toutput: totalOutput,\n\t\t\tcacheRead: totalCacheRead,\n\t\t\tcacheWrite: totalCacheWrite,\n\t\t\ttotal: totalInput + totalOutput + totalCacheRead + totalCacheWrite,\n\t\t},\n\t\tcost: totalCost,\n\t\tcontextUsage: this.getContextUsage(),\n\t};\n}\n\n\nexport function getContextUsage(this: AgentSession): ContextUsage | undefined {\n\tconst model = this.model;\n\tif (!model) return undefined;\n\n\tconst contextWindow = model.contextWindow ?? 0;\n\tif (contextWindow <= 0) return undefined;\n\n\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t// We can only trust usage from an assistant that responded after the latest compaction.\n\t// If no such assistant exists, context token count is unknown until the next LLM response.\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);\n\n\tif (latestCompactionBoundary) {\n\t\t// Check if there's a valid assistant usage after the compaction boundary\n\t\tconst compactionIndex = branchEntries.lastIndexOf(latestCompactionBoundary);\n\t\tlet hasPostCompactionUsage = false;\n\t\tfor (let i = branchEntries.length - 1; i > compactionIndex; i--) {\n\t\t\tconst entry = branchEntries[i];\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\tconst assistant = entry.message;\n\t\t\t\tif (assistant.stopReason !== \"aborted\" && assistant.stopReason !== \"error\") {\n\t\t\t\t\tconst contextTokens = calculateContextTokens(assistant.usage);\n\t\t\t\t\tif (contextTokens > 0) {\n\t\t\t\t\t\thasPostCompactionUsage = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!hasPostCompactionUsage) {\n\t\t\treturn { tokens: null, contextWindow, percent: null };\n\t\t}\n\t}\n\n\tconst estimate = estimateContextTokens(this.messages);\n\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\treturn {\n\t\ttokens: estimate.tokens,\n\t\tcontextWindow,\n\t\tpercent,\n\t};\n}\n\n/**\n * Export session to HTML.\n * @param outputPath Optional output path (defaults to session directory)\n * @returns Path to exported file\n */\n\nexport async function exportToHtml(this: AgentSession, outputPath?: string): Promise<string> {\n\tconst themeName = this.settingsManager.getTheme();\n\n\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\tgetToolDefinition: (name) => this.getToolDefinition(name),\n\t\ttheme,\n\t\tcwd: this.sessionManager.getCwd(),\n\t});\n\n\treturn await exportSessionToHtml(this.sessionManager, this.state, {\n\t\toutputPath,\n\t\tthemeName,\n\t\ttoolRenderer,\n\t});\n}\n\n/**\n * Export the current session branch to a JSONL file.\n * Writes the session header followed by all entries on the current branch path.\n * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n * @returns The resolved output file path.\n */\n\nexport function exportToJsonl(this: AgentSession, outputPath?: string): string {\n\tconst filePath = resolvePath(\n\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\tprocess.cwd(),\n\t);\n\tconst dir = dirname(filePath);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\tconst header: SessionHeader = {\n\t\ttype: \"session\",\n\t\tversion: CURRENT_SESSION_VERSION,\n\t\tid: this.sessionManager.getSessionId(),\n\t\ttimestamp: new Date().toISOString(),\n\t\tcwd: this.sessionManager.getCwd(),\n\t};\n\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst lines = [JSON.stringify(header)];\n\n\t// Re-chain parentIds to form a linear sequence\n\tlet prevId: string | null = null;\n\tfor (const entry of branchEntries) {\n\t\tconst linear = { ...entry, parentId: prevId };\n\t\tlines.push(JSON.stringify(linear));\n\t\tprevId = entry.id;\n\t}\n\n\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\treturn filePath;\n}\n\n// =========================================================================\n// Utilities\n// =========================================================================\n\n/**\n * Get text content of last assistant message.\n * Useful for /copy command.\n * @returns Text content, or undefined if no assistant message exists\n */\n\nexport function getLastAssistantText(this: AgentSession): string | undefined {\n\tconst lastAssistant = this.messages\n\t\t.slice()\n\t\t.reverse()\n\t\t.find((m) => {\n\t\t\tif (m.role !== \"assistant\") return false;\n\t\t\tconst msg = m as AssistantMessage;\n\t\t\t// Skip aborted messages with no content\n\t\t\tif (msg.stopReason === \"aborted\" && msg.content.length === 0) return false;\n\t\t\treturn true;\n\t\t});\n\n\tif (!lastAssistant) return undefined;\n\n\tlet text = \"\";\n\tfor (const content of (lastAssistant as AssistantMessage).content) {\n\t\tif (content.type === \"text\") {\n\t\t\ttext += content.text;\n\t\t}\n\t}\n\n\treturn text.trim() || undefined;\n}\n\n// =========================================================================\n// Extension System\n// =========================================================================\n\n\nexport function createReplacedSessionContext(this: AgentSession): ReplacedSessionContext {\n\tconst context = Object.defineProperties(\n\t\t{},\n\t\tObject.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()),\n\t) as ReplacedSessionContext;\n\tcontext.sendMessage = (message, options) => this.sendCustomMessage(message, options);\n\tcontext.sendUserMessage = (content, options) => this.sendUserMessage(content, options);\n\treturn context;\n}\n\n/**\n * Check if extensions have handlers for a specific event type.\n */\n\nexport function hasExtensionHandlers(this: AgentSession, eventType: string): boolean {\n\treturn this._extensionRunner.hasHandlers(eventType);\n}\n\n/**\n * Get the extension runner (for setting UI context and error handlers).\n */\n\nexport const agentSessionExportMethods = {\n\tgetSessionStats,\n\tgetContextUsage,\n\texportToHtml,\n\texportToJsonl,\n\tgetLastAssistantText,\n\tcreateReplacedSessionContext,\n\thasExtensionHandlers,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-export.js","sourceRoot":"","sources":["../../src/core/agent-session-export.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { calculateContextTokens, estimateContextTokens } from \"./compaction/index.ts\";\nimport type { ContextUsage, ReplacedSessionContext } from \"./extensions/index.ts\";\nimport { exportSessionToHtml, type ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport { createToolHtmlRenderer } from \"./export-html/tool-renderer.ts\";\nimport { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry, type SessionHeader } from \"./session-manager.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { SessionStats } from \"./agent-session-types.ts\";\n\nexport function getSessionStats(this: AgentSession): SessionStats {\n\tconst state = this.state;\n\tconst userMessages = state.messages.filter((m) => m.role === \"user\").length;\n\tconst assistantMessages = state.messages.filter((m) => m.role === \"assistant\").length;\n\tconst toolResults = state.messages.filter((m) => m.role === \"toolResult\").length;\n\n\tlet toolCalls = 0;\n\tlet totalInput = 0;\n\tlet totalOutput = 0;\n\tlet totalCacheRead = 0;\n\tlet totalCacheWrite = 0;\n\tlet totalCost = 0;\n\n\tfor (const message of state.messages) {\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst assistantMsg = message as AssistantMessage;\n\t\t\ttoolCalls += assistantMsg.content.filter((c) => c.type === \"toolCall\").length;\n\t\t\ttotalInput += assistantMsg.usage.input;\n\t\t\ttotalOutput += assistantMsg.usage.output;\n\t\t\ttotalCacheRead += assistantMsg.usage.cacheRead;\n\t\t\ttotalCacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\ttotalCost += assistantMsg.usage.cost.total;\n\t\t}\n\t}\n\n\treturn {\n\t\tsessionFile: this.sessionFile,\n\t\tsessionId: this.sessionId,\n\t\tuserMessages,\n\t\tassistantMessages,\n\t\ttoolCalls,\n\t\ttoolResults,\n\t\ttotalMessages: state.messages.length,\n\t\ttokens: {\n\t\t\tinput: totalInput,\n\t\t\toutput: totalOutput,\n\t\t\tcacheRead: totalCacheRead,\n\t\t\tcacheWrite: totalCacheWrite,\n\t\t\ttotal: totalInput + totalOutput + totalCacheRead + totalCacheWrite,\n\t\t},\n\t\tcost: totalCost,\n\t\tcontextUsage: this.getContextUsage(),\n\t};\n}\n\n\nexport function getContextUsage(this: AgentSession): ContextUsage | undefined {\n\tconst model = this.model;\n\tif (!model) return undefined;\n\n\tconst contextWindow = model.contextWindow ?? 0;\n\tif (contextWindow <= 0) return undefined;\n\n\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t// We can only trust usage from an assistant that responded after the latest compaction.\n\t// If no such assistant exists, context token count is unknown until the next LLM response.\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);\n\n\tif (latestCompactionBoundary) {\n\t\t// Check if there's a valid assistant usage after the compaction boundary\n\t\tconst compactionIndex = branchEntries.lastIndexOf(latestCompactionBoundary);\n\t\tlet hasPostCompactionUsage = false;\n\t\tfor (let i = branchEntries.length - 1; i > compactionIndex; i--) {\n\t\t\tconst entry = branchEntries[i];\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\tconst assistant = entry.message;\n\t\t\t\tif (assistant.stopReason !== \"aborted\" && assistant.stopReason !== \"error\") {\n\t\t\t\t\tconst contextTokens = calculateContextTokens(assistant.usage);\n\t\t\t\t\tif (contextTokens > 0) {\n\t\t\t\t\t\thasPostCompactionUsage = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!hasPostCompactionUsage) {\n\t\t\treturn { tokens: null, contextWindow, percent: null };\n\t\t}\n\t}\n\n\tconst estimate = estimateContextTokens(this.messages);\n\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\treturn {\n\t\ttokens: estimate.tokens,\n\t\tcontextWindow,\n\t\tpercent,\n\t};\n}\n\n/**\n * Export session to HTML.\n * @param outputPath Optional output path (defaults to session directory)\n * @returns Path to exported file\n */\n\nexport async function exportToHtml(this: AgentSession, outputPath?: string): Promise<string> {\n\tconst themeName = this.settingsManager.getTheme();\n\n\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\tgetToolDefinition: (name) => this.getToolDefinition(name),\n\t\ttheme,\n\t\tcwd: this.sessionManager.getCwd(),\n\t});\n\n\treturn await exportSessionToHtml(this.sessionManager, this.state, {\n\t\toutputPath,\n\t\tthemeName,\n\t\ttoolRenderer,\n\t});\n}\n\n/**\n * Export the current session branch to a JSONL file.\n * Writes the session header followed by all entries on the current branch path.\n * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n * @returns The resolved output file path.\n */\n\nexport function exportToJsonl(this: AgentSession, outputPath?: string): string {\n\tconst filePath = resolvePath(\n\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\tprocess.cwd(),\n\t);\n\tconst dir = dirname(filePath);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\tconst header: SessionHeader = {\n\t\ttype: \"session\",\n\t\tversion: CURRENT_SESSION_VERSION,\n\t\tid: this.sessionManager.getSessionId(),\n\t\ttimestamp: new Date().toISOString(),\n\t\tcwd: this.sessionManager.getCwd(),\n\t};\n\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst lines = [JSON.stringify(header)];\n\n\t// Re-chain parentIds to form a linear sequence\n\tlet prevId: string | null = null;\n\tfor (const entry of branchEntries) {\n\t\tconst linear = { ...entry, parentId: prevId };\n\t\tlines.push(JSON.stringify(linear));\n\t\tprevId = entry.id;\n\t}\n\n\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\treturn filePath;\n}\n\n// =========================================================================\n// Utilities\n// =========================================================================\n\n/**\n * Get text content of last assistant message.\n * Useful for /copy command.\n * @returns Text content, or undefined if no assistant message exists\n */\n\nexport function getLastAssistantText(this: AgentSession): string | undefined {\n\tconst lastAssistant = this.messages\n\t\t.slice()\n\t\t.reverse()\n\t\t.find((m) => {\n\t\t\tif (m.role !== \"assistant\") return false;\n\t\t\tconst msg = m as AssistantMessage;\n\t\t\t// Skip aborted messages with no content\n\t\t\tif (msg.stopReason === \"aborted\" && msg.content.length === 0) return false;\n\t\t\treturn true;\n\t\t});\n\n\tif (!lastAssistant) return undefined;\n\n\tlet text = \"\";\n\tfor (const content of (lastAssistant as AssistantMessage).content) {\n\t\tif (content.type === \"text\") {\n\t\t\ttext += content.text;\n\t\t}\n\t}\n\n\treturn text.trim() || undefined;\n}\n\n// =========================================================================\n// Extension System\n// =========================================================================\n\n\nexport function createReplacedSessionContext(this: AgentSession): ReplacedSessionContext {\n\tconst context = Object.defineProperties(\n\t\t{},\n\t\tObject.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()),\n\t) as ReplacedSessionContext;\n\tcontext.sendMessage = (message, options) => this.sendCustomMessage(message, options);\n\tcontext.sendUserMessage = (content, options) => this.sendUserMessage(content, options);\n\treturn context;\n}\n\n/**\n * Check if extensions have handlers for a specific event type.\n */\n\nexport function hasExtensionHandlers(this: AgentSession, eventType: string): boolean {\n\treturn this._extensionRunner.hasHandlers(eventType);\n}\n\n/**\n * Get the extension runner (for setting UI context and error handlers).\n */\n\nexport const agentSessionExportMethods = {\n\tgetSessionStats,\n\tgetContextUsage,\n\texportToHtml,\n\texportToJsonl,\n\tgetLastAssistantText,\n\tcreateReplacedSessionContext,\n\thasExtensionHandlers,\n};\n"]}
1
+ {"version":3,"file":"agent-session-export.js","sourceRoot":"","sources":["../../src/core/agent-session-export.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai/compat\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { calculateContextTokens, estimateContextTokens } from \"./compaction/index.ts\";\nimport type { ContextUsage, ReplacedSessionContext } from \"./extensions/index.ts\";\nimport { exportSessionToHtml, type ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport { createToolHtmlRenderer } from \"./export-html/tool-renderer.ts\";\nimport { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry, type SessionHeader } from \"./session-manager.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { SessionStats } from \"./agent-session-types.ts\";\n\nexport function getSessionStats(this: AgentSession): SessionStats {\n\tconst state = this.state;\n\tconst userMessages = state.messages.filter((m) => m.role === \"user\").length;\n\tconst assistantMessages = state.messages.filter((m) => m.role === \"assistant\").length;\n\tconst toolResults = state.messages.filter((m) => m.role === \"toolResult\").length;\n\n\tlet toolCalls = 0;\n\tlet totalInput = 0;\n\tlet totalOutput = 0;\n\tlet totalCacheRead = 0;\n\tlet totalCacheWrite = 0;\n\tlet totalCost = 0;\n\n\tfor (const message of state.messages) {\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst assistantMsg = message as AssistantMessage;\n\t\t\ttoolCalls += assistantMsg.content.filter((c) => c.type === \"toolCall\").length;\n\t\t\ttotalInput += assistantMsg.usage.input;\n\t\t\ttotalOutput += assistantMsg.usage.output;\n\t\t\ttotalCacheRead += assistantMsg.usage.cacheRead;\n\t\t\ttotalCacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\ttotalCost += assistantMsg.usage.cost.total;\n\t\t}\n\t}\n\n\treturn {\n\t\tsessionFile: this.sessionFile,\n\t\tsessionId: this.sessionId,\n\t\tuserMessages,\n\t\tassistantMessages,\n\t\ttoolCalls,\n\t\ttoolResults,\n\t\ttotalMessages: state.messages.length,\n\t\ttokens: {\n\t\t\tinput: totalInput,\n\t\t\toutput: totalOutput,\n\t\t\tcacheRead: totalCacheRead,\n\t\t\tcacheWrite: totalCacheWrite,\n\t\t\ttotal: totalInput + totalOutput + totalCacheRead + totalCacheWrite,\n\t\t},\n\t\tcost: totalCost,\n\t\tcontextUsage: this.getContextUsage(),\n\t};\n}\n\n\nexport function getContextUsage(this: AgentSession): ContextUsage | undefined {\n\tconst model = this.model;\n\tif (!model) return undefined;\n\n\tconst contextWindow = model.contextWindow ?? 0;\n\tif (contextWindow <= 0) return undefined;\n\n\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t// We can only trust usage from an assistant that responded after the latest compaction.\n\t// If no such assistant exists, context token count is unknown until the next LLM response.\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);\n\n\tif (latestCompactionBoundary) {\n\t\t// Check if there's a valid assistant usage after the compaction boundary\n\t\tconst compactionIndex = branchEntries.lastIndexOf(latestCompactionBoundary);\n\t\tlet hasPostCompactionUsage = false;\n\t\tfor (let i = branchEntries.length - 1; i > compactionIndex; i--) {\n\t\t\tconst entry = branchEntries[i];\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\tconst assistant = entry.message;\n\t\t\t\tif (assistant.stopReason !== \"aborted\" && assistant.stopReason !== \"error\") {\n\t\t\t\t\tconst contextTokens = calculateContextTokens(assistant.usage);\n\t\t\t\t\tif (contextTokens > 0) {\n\t\t\t\t\t\thasPostCompactionUsage = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!hasPostCompactionUsage) {\n\t\t\treturn { tokens: null, contextWindow, percent: null };\n\t\t}\n\t}\n\n\tconst estimate = estimateContextTokens(this.messages);\n\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\treturn {\n\t\ttokens: estimate.tokens,\n\t\tcontextWindow,\n\t\tpercent,\n\t};\n}\n\n/**\n * Export session to HTML.\n * @param outputPath Optional output path (defaults to session directory)\n * @returns Path to exported file\n */\n\nexport async function exportToHtml(this: AgentSession, outputPath?: string): Promise<string> {\n\tconst themeName = this.settingsManager.getTheme();\n\n\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\tgetToolDefinition: (name) => this.getToolDefinition(name),\n\t\ttheme,\n\t\tcwd: this.sessionManager.getCwd(),\n\t});\n\n\treturn await exportSessionToHtml(this.sessionManager, this.state, {\n\t\toutputPath,\n\t\tthemeName,\n\t\ttoolRenderer,\n\t});\n}\n\n/**\n * Export the current session branch to a JSONL file.\n * Writes the session header followed by all entries on the current branch path.\n * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n * @returns The resolved output file path.\n */\n\nexport function exportToJsonl(this: AgentSession, outputPath?: string): string {\n\tconst filePath = resolvePath(\n\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\tprocess.cwd(),\n\t);\n\tconst dir = dirname(filePath);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\tconst header: SessionHeader = {\n\t\ttype: \"session\",\n\t\tversion: CURRENT_SESSION_VERSION,\n\t\tid: this.sessionManager.getSessionId(),\n\t\ttimestamp: new Date().toISOString(),\n\t\tcwd: this.sessionManager.getCwd(),\n\t};\n\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst lines = [JSON.stringify(header)];\n\n\t// Re-chain parentIds to form a linear sequence\n\tlet prevId: string | null = null;\n\tfor (const entry of branchEntries) {\n\t\tconst linear = { ...entry, parentId: prevId };\n\t\tlines.push(JSON.stringify(linear));\n\t\tprevId = entry.id;\n\t}\n\n\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\treturn filePath;\n}\n\n// =========================================================================\n// Utilities\n// =========================================================================\n\n/**\n * Get text content of last assistant message.\n * Useful for /copy command.\n * @returns Text content, or undefined if no assistant message exists\n */\n\nexport function getLastAssistantText(this: AgentSession): string | undefined {\n\tconst lastAssistant = this.messages\n\t\t.slice()\n\t\t.reverse()\n\t\t.find((m) => {\n\t\t\tif (m.role !== \"assistant\") return false;\n\t\t\tconst msg = m as AssistantMessage;\n\t\t\t// Skip aborted messages with no content\n\t\t\tif (msg.stopReason === \"aborted\" && msg.content.length === 0) return false;\n\t\t\treturn true;\n\t\t});\n\n\tif (!lastAssistant) return undefined;\n\n\tlet text = \"\";\n\tfor (const content of (lastAssistant as AssistantMessage).content) {\n\t\tif (content.type === \"text\") {\n\t\t\ttext += content.text;\n\t\t}\n\t}\n\n\treturn text.trim() || undefined;\n}\n\n// =========================================================================\n// Extension System\n// =========================================================================\n\n\nexport function createReplacedSessionContext(this: AgentSession): ReplacedSessionContext {\n\tconst context = Object.defineProperties(\n\t\t{},\n\t\tObject.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()),\n\t) as ReplacedSessionContext;\n\tcontext.sendMessage = (message, options) => this.sendCustomMessage(message, options);\n\tcontext.sendUserMessage = (content, options) => this.sendUserMessage(content, options);\n\treturn context;\n}\n\n/**\n * Check if extensions have handlers for a specific event type.\n */\n\nexport function hasExtensionHandlers(this: AgentSession, eventType: string): boolean {\n\treturn this._extensionRunner.hasHandlers(eventType);\n}\n\n/**\n * Get the extension runner (for setting UI context and error handlers).\n */\n\nexport const agentSessionExportMethods = {\n\tgetSessionStats,\n\tgetContextUsage,\n\texportToHtml,\n\texportToJsonl,\n\tgetLastAssistantText,\n\tcreateReplacedSessionContext,\n\thasExtensionHandlers,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-extension-bindings.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-extension-bindings.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAK7D,wBAAsB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBnG;AAGD,wBAAsB,6BAA6B,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBnH;AAGD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,KAAK,CAAC;IAC/H,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxF,CAAC,CAcD;AAGD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAOzF;AAGD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAQzF;AAGD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAiBzE;AAGD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA+GpF;AAGD,wBAAsB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB9D;AAMD;;;GAGG;AAEH,eAAO,MAAM,oCAAoC;;;;;;;;;CAShD,CAAC","sourcesContent":["import { basename, dirname } from \"node:path\";\nimport { resetApiProviders } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ExtensionBindings } from \"./agent-session-types.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport type { ResourceExtensionPaths } from \"./resource-loader.ts\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.ts\";\nimport type { SlashCommandInfo } from \"./slash-commands.ts\";\n\nexport async function bindExtensions(this: AgentSession, bindings: ExtensionBindings): Promise<void> {\n\tif (bindings.uiContext !== undefined) {\n\t\tthis._extensionUIContext = bindings.uiContext;\n\t}\n\tif (bindings.mode !== undefined) {\n\t\tthis._extensionMode = bindings.mode;\n\t}\n\tif (bindings.commandContextActions !== undefined) {\n\t\tthis._extensionCommandContextActions = bindings.commandContextActions;\n\t}\n\tif (bindings.shutdownHandler !== undefined) {\n\t\tthis._extensionShutdownHandler = bindings.shutdownHandler;\n\t}\n\tif (bindings.onError !== undefined) {\n\t\tthis._extensionErrorListener = bindings.onError;\n\t}\n\n\tthis._applyExtensionBindings(this._extensionRunner);\n\tawait this._extensionRunner.emit(this._sessionStartEvent);\n\tawait this.extendResourcesFromExtensions(this._sessionStartEvent.reason === \"reload\" ? \"reload\" : \"startup\");\n}\n\n\nexport async function extendResourcesFromExtensions(this: AgentSession, reason: \"startup\" | \"reload\"): Promise<void> {\n\tif (!this._extensionRunner.hasHandlers(\"resources_discover\")) {\n\t\treturn;\n\t}\n\n\tconst { skillPaths, promptPaths, themePaths } = await this._extensionRunner.emitResourcesDiscover(\n\t\tthis._cwd,\n\t\treason,\n\t);\n\n\tif (skillPaths.length === 0 && promptPaths.length === 0 && themePaths.length === 0) {\n\t\treturn;\n\t}\n\n\tconst extensionPaths: ResourceExtensionPaths = {\n\t\tskillPaths: this.buildExtensionResourcePaths(skillPaths),\n\t\tpromptPaths: this.buildExtensionResourcePaths(promptPaths),\n\t\tthemePaths: this.buildExtensionResourcePaths(themePaths),\n\t};\n\n\tthis._resourceLoader.extendResources(extensionPaths);\n\tthis._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());\n\tthis.agent.state.systemPrompt = this._baseSystemPrompt;\n}\n\n\nexport function buildExtensionResourcePaths(this: AgentSession, entries: Array<{ path: string; extensionPath: string }>): Array<{\n\tpath: string;\n\tmetadata: { source: string; scope: \"temporary\"; origin: \"top-level\"; baseDir?: string };\n}> {\n\treturn entries.map((entry) => {\n\t\tconst source = this.getExtensionSourceLabel(entry.extensionPath);\n\t\tconst baseDir = entry.extensionPath.startsWith(\"<\") ? undefined : dirname(entry.extensionPath);\n\t\treturn {\n\t\t\tpath: entry.path,\n\t\t\tmetadata: {\n\t\t\t\tsource,\n\t\t\t\tscope: \"temporary\",\n\t\t\t\torigin: \"top-level\",\n\t\t\t\tbaseDir,\n\t\t\t},\n\t\t};\n\t});\n}\n\n\nexport function getExtensionSourceLabel(this: AgentSession, extensionPath: string): string {\n\tif (extensionPath.startsWith(\"<\")) {\n\t\treturn `extension:${extensionPath.replace(/[<>]/g, \"\")}`;\n\t}\n\tconst base = basename(extensionPath);\n\tconst name = base.replace(/\\.(ts|js)$/, \"\");\n\treturn `extension:${name}`;\n}\n\n\nexport function _applyExtensionBindings(this: AgentSession, runner: ExtensionRunner): void {\n\trunner.setUIContext(this._extensionUIContext, this._extensionMode);\n\trunner.bindCommandContext(this._extensionCommandContextActions);\n\n\tthis._extensionErrorUnsubscriber?.();\n\tthis._extensionErrorUnsubscriber = this._extensionErrorListener\n\t\t? runner.onError(this._extensionErrorListener)\n\t\t: undefined;\n}\n\n\nexport function _refreshCurrentModelFromRegistry(this: AgentSession): void {\n\tconst currentModel = this.model;\n\tif (!currentModel) {\n\t\treturn;\n\t}\n\n\tconst refreshedModel = this._modelRegistry.find(currentModel.provider, currentModel.id);\n\tif (!refreshedModel || refreshedModel === currentModel) {\n\t\treturn;\n\t}\n\n\tconst replay = this._getResumeContextWindowReplayForModel(refreshedModel);\n\tthis.agent.state.model = replay.model;\n\tif (currentModel.contextWindow !== replay.contextWindow) {\n\t\tthis._emit({ type: \"context_window_changed\", contextWindow: replay.contextWindow });\n\t}\n\tthis._refreshBaseSystemPromptFromActiveTools();\n}\n\n\nexport function _bindExtensionCore(this: AgentSession, runner: ExtensionRunner): void {\n\tconst getCommands = (): SlashCommandInfo[] => {\n\t\tconst extensionCommands: SlashCommandInfo[] = runner.getRegisteredCommands().map((command) => ({\n\t\t\tname: command.invocationName,\n\t\t\tdescription: command.description,\n\t\t\tsource: \"extension\",\n\t\t\tsourceInfo: command.sourceInfo,\n\t\t}));\n\n\t\tconst templates: SlashCommandInfo[] = this.promptTemplates.map((template) => ({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description,\n\t\t\tsource: \"prompt\",\n\t\t\tsourceInfo: template.sourceInfo,\n\t\t}));\n\n\t\tconst skills: SlashCommandInfo[] = this._resourceLoader.getSkills().skills.map((skill) => ({\n\t\t\tname: `skill:${skill.name}`,\n\t\t\tdescription: skill.description,\n\t\t\tsource: \"skill\",\n\t\t\tsourceInfo: skill.sourceInfo,\n\t\t}));\n\n\t\treturn [...extensionCommands, ...templates, ...skills];\n\t};\n\n\trunner.bindCore(\n\t\t{\n\t\t\tsendMessage: (message, options) => {\n\t\t\t\tthis.sendCustomMessage(message, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tsendUserMessage: (content, options) => {\n\t\t\t\tthis.sendUserMessage(content, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_user_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tappendEntry: (customType, data) => {\n\t\t\t\tthis.sessionManager.appendCustomEntry(customType, data);\n\t\t\t},\n\t\t\tsetSessionName: (name) => {\n\t\t\t\tthis.setSessionName(name);\n\t\t\t},\n\t\t\tgetSessionName: () => {\n\t\t\t\treturn this.sessionManager.getSessionName();\n\t\t\t},\n\t\t\tsetLabel: (entryId, label) => {\n\t\t\t\tthis.sessionManager.appendLabelChange(entryId, label);\n\t\t\t},\n\t\t\tgetActiveTools: () => this.getActiveToolNames(),\n\t\t\tgetAllTools: () => this.getAllTools(),\n\t\t\tsetActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),\n\t\t\trefreshTools: () => this._refreshToolRegistry(),\n\t\t\tgetCommands,\n\t\t\tsetModel: async (model) => {\n\t\t\t\tif (!this.modelRegistry.hasConfiguredAuth(model)) return false;\n\t\t\t\tawait this.setModel(model);\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tgetThinkingLevel: () => this.thinkingLevel,\n\t\t\tsetThinkingLevel: (level) => this.setThinkingLevel(level),\n\t\t},\n\t\t{\n\t\t\tgetModel: () => this.model,\n\t\t\tisIdle: () => !this.isStreaming,\n\t\t\tisProjectTrusted: () => this.settingsManager.isProjectTrusted(),\n\t\t\tgetSignal: () => this.agent.signal,\n\t\t\tabort: () => this.abort(),\n\t\t\thasPendingMessages: () => this.pendingMessageCount > 0,\n\t\t\tshutdown: () => {\n\t\t\t\tthis._extensionShutdownHandler?.();\n\t\t\t},\n\t\t\tgetContextUsage: () => this.getContextUsage(),\n\t\t\tcompact: (options) => {\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await this.compact({\n\t\t\t\t\t\t\t...(options?.compression_ratio === undefined ? {} : { compression_ratio: options.compression_ratio }),\n\t\t\t\t\t\t\t...(options?.preserve_recent === undefined ? {} : { preserve_recent: options.preserve_recent }),\n\t\t\t\t\t\t\t...(options?.query === undefined ? {} : { query: options.query }),\n\t\t\t\t\t\t});\n\t\t\t\t\t\toptions?.onComplete?.(result);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t\toptions?.onError?.(err);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t},\n\t\t\tgetSystemPrompt: () => this.systemPrompt,\n\t\t\tgetSystemPromptOptions: () => this._baseSystemPromptOptions,\n\t\t},\n\t\t{\n\t\t\tregisterProvider: (name, config) => {\n\t\t\t\tthis._modelRegistry.registerProvider(name, config);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t\tunregisterProvider: (name) => {\n\t\t\t\tthis._modelRegistry.unregisterProvider(name);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t},\n\t);\n}\n\n\nexport async function reload(this: AgentSession): Promise<void> {\n\tconst previousFlagValues = this._extensionRunner.getFlagValues();\n\tawait emitSessionShutdownEvent(this._extensionRunner, { type: \"session_shutdown\", reason: \"reload\" });\n\tawait this.settingsManager.reload();\n\tresetApiProviders();\n\tawait this._resourceLoader.reload();\n\tthis._buildRuntime({\n\t\tactiveToolNames: this.getActiveToolNames(),\n\t\tflagValues: previousFlagValues,\n\t\tincludeAllExtensionTools: true,\n\t});\n\n\tconst hasBindings =\n\t\tthis._extensionUIContext ||\n\t\tthis._extensionCommandContextActions ||\n\t\tthis._extensionShutdownHandler ||\n\t\tthis._extensionErrorListener;\n\tif (hasBindings) {\n\t\tawait this._extensionRunner.emit({ type: \"session_start\", reason: \"reload\" });\n\t\tawait this.extendResourcesFromExtensions(\"reload\");\n\t}\n}\n\n// =========================================================================\n// Auto-Retry\n// =========================================================================\n\n/**\n * Check if an error is retryable (overloaded, rate limit, server errors).\n * Context overflow errors are NOT retryable (handled by compaction instead).\n */\n\nexport const agentSessionExtensionBindingsMethods = {\n\tbindExtensions,\n\textendResourcesFromExtensions,\n\tbuildExtensionResourcePaths,\n\tgetExtensionSourceLabel,\n\t_applyExtensionBindings,\n\t_refreshCurrentModelFromRegistry,\n\t_bindExtensionCore,\n\treload,\n};\n"]}
1
+ {"version":3,"file":"agent-session-extension-bindings.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-extension-bindings.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAK7D,wBAAsB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBnG;AAGD,wBAAsB,6BAA6B,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBnH;AAGD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,KAAK,CAAC;IAC/H,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxF,CAAC,CAcD;AAGD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAOzF;AAGD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAQzF;AAGD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAiBzE;AAGD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA+GpF;AAGD,wBAAsB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB9D;AAMD;;;GAGG;AAEH,eAAO,MAAM,oCAAoC;;;;;;;;;CAShD,CAAC","sourcesContent":["import { basename, dirname } from \"node:path\";\nimport { resetApiProviders } from \"@earendil-works/pi-ai/compat\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ExtensionBindings } from \"./agent-session-types.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport type { ResourceExtensionPaths } from \"./resource-loader.ts\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.ts\";\nimport type { SlashCommandInfo } from \"./slash-commands.ts\";\n\nexport async function bindExtensions(this: AgentSession, bindings: ExtensionBindings): Promise<void> {\n\tif (bindings.uiContext !== undefined) {\n\t\tthis._extensionUIContext = bindings.uiContext;\n\t}\n\tif (bindings.mode !== undefined) {\n\t\tthis._extensionMode = bindings.mode;\n\t}\n\tif (bindings.commandContextActions !== undefined) {\n\t\tthis._extensionCommandContextActions = bindings.commandContextActions;\n\t}\n\tif (bindings.shutdownHandler !== undefined) {\n\t\tthis._extensionShutdownHandler = bindings.shutdownHandler;\n\t}\n\tif (bindings.onError !== undefined) {\n\t\tthis._extensionErrorListener = bindings.onError;\n\t}\n\n\tthis._applyExtensionBindings(this._extensionRunner);\n\tawait this._extensionRunner.emit(this._sessionStartEvent);\n\tawait this.extendResourcesFromExtensions(this._sessionStartEvent.reason === \"reload\" ? \"reload\" : \"startup\");\n}\n\n\nexport async function extendResourcesFromExtensions(this: AgentSession, reason: \"startup\" | \"reload\"): Promise<void> {\n\tif (!this._extensionRunner.hasHandlers(\"resources_discover\")) {\n\t\treturn;\n\t}\n\n\tconst { skillPaths, promptPaths, themePaths } = await this._extensionRunner.emitResourcesDiscover(\n\t\tthis._cwd,\n\t\treason,\n\t);\n\n\tif (skillPaths.length === 0 && promptPaths.length === 0 && themePaths.length === 0) {\n\t\treturn;\n\t}\n\n\tconst extensionPaths: ResourceExtensionPaths = {\n\t\tskillPaths: this.buildExtensionResourcePaths(skillPaths),\n\t\tpromptPaths: this.buildExtensionResourcePaths(promptPaths),\n\t\tthemePaths: this.buildExtensionResourcePaths(themePaths),\n\t};\n\n\tthis._resourceLoader.extendResources(extensionPaths);\n\tthis._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());\n\tthis.agent.state.systemPrompt = this._baseSystemPrompt;\n}\n\n\nexport function buildExtensionResourcePaths(this: AgentSession, entries: Array<{ path: string; extensionPath: string }>): Array<{\n\tpath: string;\n\tmetadata: { source: string; scope: \"temporary\"; origin: \"top-level\"; baseDir?: string };\n}> {\n\treturn entries.map((entry) => {\n\t\tconst source = this.getExtensionSourceLabel(entry.extensionPath);\n\t\tconst baseDir = entry.extensionPath.startsWith(\"<\") ? undefined : dirname(entry.extensionPath);\n\t\treturn {\n\t\t\tpath: entry.path,\n\t\t\tmetadata: {\n\t\t\t\tsource,\n\t\t\t\tscope: \"temporary\",\n\t\t\t\torigin: \"top-level\",\n\t\t\t\tbaseDir,\n\t\t\t},\n\t\t};\n\t});\n}\n\n\nexport function getExtensionSourceLabel(this: AgentSession, extensionPath: string): string {\n\tif (extensionPath.startsWith(\"<\")) {\n\t\treturn `extension:${extensionPath.replace(/[<>]/g, \"\")}`;\n\t}\n\tconst base = basename(extensionPath);\n\tconst name = base.replace(/\\.(ts|js)$/, \"\");\n\treturn `extension:${name}`;\n}\n\n\nexport function _applyExtensionBindings(this: AgentSession, runner: ExtensionRunner): void {\n\trunner.setUIContext(this._extensionUIContext, this._extensionMode);\n\trunner.bindCommandContext(this._extensionCommandContextActions);\n\n\tthis._extensionErrorUnsubscriber?.();\n\tthis._extensionErrorUnsubscriber = this._extensionErrorListener\n\t\t? runner.onError(this._extensionErrorListener)\n\t\t: undefined;\n}\n\n\nexport function _refreshCurrentModelFromRegistry(this: AgentSession): void {\n\tconst currentModel = this.model;\n\tif (!currentModel) {\n\t\treturn;\n\t}\n\n\tconst refreshedModel = this._modelRegistry.find(currentModel.provider, currentModel.id);\n\tif (!refreshedModel || refreshedModel === currentModel) {\n\t\treturn;\n\t}\n\n\tconst replay = this._getResumeContextWindowReplayForModel(refreshedModel);\n\tthis.agent.state.model = replay.model;\n\tif (currentModel.contextWindow !== replay.contextWindow) {\n\t\tthis._emit({ type: \"context_window_changed\", contextWindow: replay.contextWindow });\n\t}\n\tthis._refreshBaseSystemPromptFromActiveTools();\n}\n\n\nexport function _bindExtensionCore(this: AgentSession, runner: ExtensionRunner): void {\n\tconst getCommands = (): SlashCommandInfo[] => {\n\t\tconst extensionCommands: SlashCommandInfo[] = runner.getRegisteredCommands().map((command) => ({\n\t\t\tname: command.invocationName,\n\t\t\tdescription: command.description,\n\t\t\tsource: \"extension\",\n\t\t\tsourceInfo: command.sourceInfo,\n\t\t}));\n\n\t\tconst templates: SlashCommandInfo[] = this.promptTemplates.map((template) => ({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description,\n\t\t\tsource: \"prompt\",\n\t\t\tsourceInfo: template.sourceInfo,\n\t\t}));\n\n\t\tconst skills: SlashCommandInfo[] = this._resourceLoader.getSkills().skills.map((skill) => ({\n\t\t\tname: `skill:${skill.name}`,\n\t\t\tdescription: skill.description,\n\t\t\tsource: \"skill\",\n\t\t\tsourceInfo: skill.sourceInfo,\n\t\t}));\n\n\t\treturn [...extensionCommands, ...templates, ...skills];\n\t};\n\n\trunner.bindCore(\n\t\t{\n\t\t\tsendMessage: (message, options) => {\n\t\t\t\tthis.sendCustomMessage(message, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tsendUserMessage: (content, options) => {\n\t\t\t\tthis.sendUserMessage(content, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_user_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tappendEntry: (customType, data) => {\n\t\t\t\tthis.sessionManager.appendCustomEntry(customType, data);\n\t\t\t},\n\t\t\tsetSessionName: (name) => {\n\t\t\t\tthis.setSessionName(name);\n\t\t\t},\n\t\t\tgetSessionName: () => {\n\t\t\t\treturn this.sessionManager.getSessionName();\n\t\t\t},\n\t\t\tsetLabel: (entryId, label) => {\n\t\t\t\tthis.sessionManager.appendLabelChange(entryId, label);\n\t\t\t},\n\t\t\tgetActiveTools: () => this.getActiveToolNames(),\n\t\t\tgetAllTools: () => this.getAllTools(),\n\t\t\tsetActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),\n\t\t\trefreshTools: () => this._refreshToolRegistry(),\n\t\t\tgetCommands,\n\t\t\tsetModel: async (model) => {\n\t\t\t\tif (!this.modelRegistry.hasConfiguredAuth(model)) return false;\n\t\t\t\tawait this.setModel(model);\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tgetThinkingLevel: () => this.thinkingLevel,\n\t\t\tsetThinkingLevel: (level) => this.setThinkingLevel(level),\n\t\t},\n\t\t{\n\t\t\tgetModel: () => this.model,\n\t\t\tisIdle: () => !this.isStreaming,\n\t\t\tisProjectTrusted: () => this.settingsManager.isProjectTrusted(),\n\t\t\tgetSignal: () => this.agent.signal,\n\t\t\tabort: () => this.abort(),\n\t\t\thasPendingMessages: () => this.pendingMessageCount > 0,\n\t\t\tshutdown: () => {\n\t\t\t\tthis._extensionShutdownHandler?.();\n\t\t\t},\n\t\t\tgetContextUsage: () => this.getContextUsage(),\n\t\t\tcompact: (options) => {\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await this.compact({\n\t\t\t\t\t\t\t...(options?.compression_ratio === undefined ? {} : { compression_ratio: options.compression_ratio }),\n\t\t\t\t\t\t\t...(options?.preserve_recent === undefined ? {} : { preserve_recent: options.preserve_recent }),\n\t\t\t\t\t\t\t...(options?.query === undefined ? {} : { query: options.query }),\n\t\t\t\t\t\t});\n\t\t\t\t\t\toptions?.onComplete?.(result);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t\toptions?.onError?.(err);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t},\n\t\t\tgetSystemPrompt: () => this.systemPrompt,\n\t\t\tgetSystemPromptOptions: () => this._baseSystemPromptOptions,\n\t\t},\n\t\t{\n\t\t\tregisterProvider: (name, config) => {\n\t\t\t\tthis._modelRegistry.registerProvider(name, config);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t\tunregisterProvider: (name) => {\n\t\t\t\tthis._modelRegistry.unregisterProvider(name);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t},\n\t);\n}\n\n\nexport async function reload(this: AgentSession): Promise<void> {\n\tconst previousFlagValues = this._extensionRunner.getFlagValues();\n\tawait emitSessionShutdownEvent(this._extensionRunner, { type: \"session_shutdown\", reason: \"reload\" });\n\tawait this.settingsManager.reload();\n\tresetApiProviders();\n\tawait this._resourceLoader.reload();\n\tthis._buildRuntime({\n\t\tactiveToolNames: this.getActiveToolNames(),\n\t\tflagValues: previousFlagValues,\n\t\tincludeAllExtensionTools: true,\n\t});\n\n\tconst hasBindings =\n\t\tthis._extensionUIContext ||\n\t\tthis._extensionCommandContextActions ||\n\t\tthis._extensionShutdownHandler ||\n\t\tthis._extensionErrorListener;\n\tif (hasBindings) {\n\t\tawait this._extensionRunner.emit({ type: \"session_start\", reason: \"reload\" });\n\t\tawait this.extendResourcesFromExtensions(\"reload\");\n\t}\n}\n\n// =========================================================================\n// Auto-Retry\n// =========================================================================\n\n/**\n * Check if an error is retryable (overloaded, rate limit, server errors).\n * Context overflow errors are NOT retryable (handled by compaction instead).\n */\n\nexport const agentSessionExtensionBindingsMethods = {\n\tbindExtensions,\n\textendResourcesFromExtensions,\n\tbuildExtensionResourcePaths,\n\tgetExtensionSourceLabel,\n\t_applyExtensionBindings,\n\t_refreshCurrentModelFromRegistry,\n\t_bindExtensionCore,\n\treload,\n};\n"]}
@@ -1,5 +1,5 @@
1
1
  import { basename, dirname } from "node:path";
2
- import { resetApiProviders } from "@earendil-works/pi-ai";
2
+ import { resetApiProviders } from "@earendil-works/pi-ai/compat";
3
3
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
4
4
  export async function bindExtensions(bindings) {
5
5
  if (bindings.uiContext !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-extension-bindings.js","sourceRoot":"","sources":["../../src/core/agent-session-extension-bindings.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname } from \"node:path\";\nimport { resetApiProviders } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ExtensionBindings } from \"./agent-session-types.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport type { ResourceExtensionPaths } from \"./resource-loader.ts\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.ts\";\nimport type { SlashCommandInfo } from \"./slash-commands.ts\";\n\nexport async function bindExtensions(this: AgentSession, bindings: ExtensionBindings): Promise<void> {\n\tif (bindings.uiContext !== undefined) {\n\t\tthis._extensionUIContext = bindings.uiContext;\n\t}\n\tif (bindings.mode !== undefined) {\n\t\tthis._extensionMode = bindings.mode;\n\t}\n\tif (bindings.commandContextActions !== undefined) {\n\t\tthis._extensionCommandContextActions = bindings.commandContextActions;\n\t}\n\tif (bindings.shutdownHandler !== undefined) {\n\t\tthis._extensionShutdownHandler = bindings.shutdownHandler;\n\t}\n\tif (bindings.onError !== undefined) {\n\t\tthis._extensionErrorListener = bindings.onError;\n\t}\n\n\tthis._applyExtensionBindings(this._extensionRunner);\n\tawait this._extensionRunner.emit(this._sessionStartEvent);\n\tawait this.extendResourcesFromExtensions(this._sessionStartEvent.reason === \"reload\" ? \"reload\" : \"startup\");\n}\n\n\nexport async function extendResourcesFromExtensions(this: AgentSession, reason: \"startup\" | \"reload\"): Promise<void> {\n\tif (!this._extensionRunner.hasHandlers(\"resources_discover\")) {\n\t\treturn;\n\t}\n\n\tconst { skillPaths, promptPaths, themePaths } = await this._extensionRunner.emitResourcesDiscover(\n\t\tthis._cwd,\n\t\treason,\n\t);\n\n\tif (skillPaths.length === 0 && promptPaths.length === 0 && themePaths.length === 0) {\n\t\treturn;\n\t}\n\n\tconst extensionPaths: ResourceExtensionPaths = {\n\t\tskillPaths: this.buildExtensionResourcePaths(skillPaths),\n\t\tpromptPaths: this.buildExtensionResourcePaths(promptPaths),\n\t\tthemePaths: this.buildExtensionResourcePaths(themePaths),\n\t};\n\n\tthis._resourceLoader.extendResources(extensionPaths);\n\tthis._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());\n\tthis.agent.state.systemPrompt = this._baseSystemPrompt;\n}\n\n\nexport function buildExtensionResourcePaths(this: AgentSession, entries: Array<{ path: string; extensionPath: string }>): Array<{\n\tpath: string;\n\tmetadata: { source: string; scope: \"temporary\"; origin: \"top-level\"; baseDir?: string };\n}> {\n\treturn entries.map((entry) => {\n\t\tconst source = this.getExtensionSourceLabel(entry.extensionPath);\n\t\tconst baseDir = entry.extensionPath.startsWith(\"<\") ? undefined : dirname(entry.extensionPath);\n\t\treturn {\n\t\t\tpath: entry.path,\n\t\t\tmetadata: {\n\t\t\t\tsource,\n\t\t\t\tscope: \"temporary\",\n\t\t\t\torigin: \"top-level\",\n\t\t\t\tbaseDir,\n\t\t\t},\n\t\t};\n\t});\n}\n\n\nexport function getExtensionSourceLabel(this: AgentSession, extensionPath: string): string {\n\tif (extensionPath.startsWith(\"<\")) {\n\t\treturn `extension:${extensionPath.replace(/[<>]/g, \"\")}`;\n\t}\n\tconst base = basename(extensionPath);\n\tconst name = base.replace(/\\.(ts|js)$/, \"\");\n\treturn `extension:${name}`;\n}\n\n\nexport function _applyExtensionBindings(this: AgentSession, runner: ExtensionRunner): void {\n\trunner.setUIContext(this._extensionUIContext, this._extensionMode);\n\trunner.bindCommandContext(this._extensionCommandContextActions);\n\n\tthis._extensionErrorUnsubscriber?.();\n\tthis._extensionErrorUnsubscriber = this._extensionErrorListener\n\t\t? runner.onError(this._extensionErrorListener)\n\t\t: undefined;\n}\n\n\nexport function _refreshCurrentModelFromRegistry(this: AgentSession): void {\n\tconst currentModel = this.model;\n\tif (!currentModel) {\n\t\treturn;\n\t}\n\n\tconst refreshedModel = this._modelRegistry.find(currentModel.provider, currentModel.id);\n\tif (!refreshedModel || refreshedModel === currentModel) {\n\t\treturn;\n\t}\n\n\tconst replay = this._getResumeContextWindowReplayForModel(refreshedModel);\n\tthis.agent.state.model = replay.model;\n\tif (currentModel.contextWindow !== replay.contextWindow) {\n\t\tthis._emit({ type: \"context_window_changed\", contextWindow: replay.contextWindow });\n\t}\n\tthis._refreshBaseSystemPromptFromActiveTools();\n}\n\n\nexport function _bindExtensionCore(this: AgentSession, runner: ExtensionRunner): void {\n\tconst getCommands = (): SlashCommandInfo[] => {\n\t\tconst extensionCommands: SlashCommandInfo[] = runner.getRegisteredCommands().map((command) => ({\n\t\t\tname: command.invocationName,\n\t\t\tdescription: command.description,\n\t\t\tsource: \"extension\",\n\t\t\tsourceInfo: command.sourceInfo,\n\t\t}));\n\n\t\tconst templates: SlashCommandInfo[] = this.promptTemplates.map((template) => ({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description,\n\t\t\tsource: \"prompt\",\n\t\t\tsourceInfo: template.sourceInfo,\n\t\t}));\n\n\t\tconst skills: SlashCommandInfo[] = this._resourceLoader.getSkills().skills.map((skill) => ({\n\t\t\tname: `skill:${skill.name}`,\n\t\t\tdescription: skill.description,\n\t\t\tsource: \"skill\",\n\t\t\tsourceInfo: skill.sourceInfo,\n\t\t}));\n\n\t\treturn [...extensionCommands, ...templates, ...skills];\n\t};\n\n\trunner.bindCore(\n\t\t{\n\t\t\tsendMessage: (message, options) => {\n\t\t\t\tthis.sendCustomMessage(message, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tsendUserMessage: (content, options) => {\n\t\t\t\tthis.sendUserMessage(content, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_user_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tappendEntry: (customType, data) => {\n\t\t\t\tthis.sessionManager.appendCustomEntry(customType, data);\n\t\t\t},\n\t\t\tsetSessionName: (name) => {\n\t\t\t\tthis.setSessionName(name);\n\t\t\t},\n\t\t\tgetSessionName: () => {\n\t\t\t\treturn this.sessionManager.getSessionName();\n\t\t\t},\n\t\t\tsetLabel: (entryId, label) => {\n\t\t\t\tthis.sessionManager.appendLabelChange(entryId, label);\n\t\t\t},\n\t\t\tgetActiveTools: () => this.getActiveToolNames(),\n\t\t\tgetAllTools: () => this.getAllTools(),\n\t\t\tsetActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),\n\t\t\trefreshTools: () => this._refreshToolRegistry(),\n\t\t\tgetCommands,\n\t\t\tsetModel: async (model) => {\n\t\t\t\tif (!this.modelRegistry.hasConfiguredAuth(model)) return false;\n\t\t\t\tawait this.setModel(model);\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tgetThinkingLevel: () => this.thinkingLevel,\n\t\t\tsetThinkingLevel: (level) => this.setThinkingLevel(level),\n\t\t},\n\t\t{\n\t\t\tgetModel: () => this.model,\n\t\t\tisIdle: () => !this.isStreaming,\n\t\t\tisProjectTrusted: () => this.settingsManager.isProjectTrusted(),\n\t\t\tgetSignal: () => this.agent.signal,\n\t\t\tabort: () => this.abort(),\n\t\t\thasPendingMessages: () => this.pendingMessageCount > 0,\n\t\t\tshutdown: () => {\n\t\t\t\tthis._extensionShutdownHandler?.();\n\t\t\t},\n\t\t\tgetContextUsage: () => this.getContextUsage(),\n\t\t\tcompact: (options) => {\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await this.compact({\n\t\t\t\t\t\t\t...(options?.compression_ratio === undefined ? {} : { compression_ratio: options.compression_ratio }),\n\t\t\t\t\t\t\t...(options?.preserve_recent === undefined ? {} : { preserve_recent: options.preserve_recent }),\n\t\t\t\t\t\t\t...(options?.query === undefined ? {} : { query: options.query }),\n\t\t\t\t\t\t});\n\t\t\t\t\t\toptions?.onComplete?.(result);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t\toptions?.onError?.(err);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t},\n\t\t\tgetSystemPrompt: () => this.systemPrompt,\n\t\t\tgetSystemPromptOptions: () => this._baseSystemPromptOptions,\n\t\t},\n\t\t{\n\t\t\tregisterProvider: (name, config) => {\n\t\t\t\tthis._modelRegistry.registerProvider(name, config);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t\tunregisterProvider: (name) => {\n\t\t\t\tthis._modelRegistry.unregisterProvider(name);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t},\n\t);\n}\n\n\nexport async function reload(this: AgentSession): Promise<void> {\n\tconst previousFlagValues = this._extensionRunner.getFlagValues();\n\tawait emitSessionShutdownEvent(this._extensionRunner, { type: \"session_shutdown\", reason: \"reload\" });\n\tawait this.settingsManager.reload();\n\tresetApiProviders();\n\tawait this._resourceLoader.reload();\n\tthis._buildRuntime({\n\t\tactiveToolNames: this.getActiveToolNames(),\n\t\tflagValues: previousFlagValues,\n\t\tincludeAllExtensionTools: true,\n\t});\n\n\tconst hasBindings =\n\t\tthis._extensionUIContext ||\n\t\tthis._extensionCommandContextActions ||\n\t\tthis._extensionShutdownHandler ||\n\t\tthis._extensionErrorListener;\n\tif (hasBindings) {\n\t\tawait this._extensionRunner.emit({ type: \"session_start\", reason: \"reload\" });\n\t\tawait this.extendResourcesFromExtensions(\"reload\");\n\t}\n}\n\n// =========================================================================\n// Auto-Retry\n// =========================================================================\n\n/**\n * Check if an error is retryable (overloaded, rate limit, server errors).\n * Context overflow errors are NOT retryable (handled by compaction instead).\n */\n\nexport const agentSessionExtensionBindingsMethods = {\n\tbindExtensions,\n\textendResourcesFromExtensions,\n\tbuildExtensionResourcePaths,\n\tgetExtensionSourceLabel,\n\t_applyExtensionBindings,\n\t_refreshCurrentModelFromRegistry,\n\t_bindExtensionCore,\n\treload,\n};\n"]}
1
+ {"version":3,"file":"agent-session-extension-bindings.js","sourceRoot":"","sources":["../../src/core/agent-session-extension-bindings.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname } from \"node:path\";\nimport { resetApiProviders } from \"@earendil-works/pi-ai/compat\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ExtensionBindings } from \"./agent-session-types.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport type { ResourceExtensionPaths } from \"./resource-loader.ts\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.ts\";\nimport type { SlashCommandInfo } from \"./slash-commands.ts\";\n\nexport async function bindExtensions(this: AgentSession, bindings: ExtensionBindings): Promise<void> {\n\tif (bindings.uiContext !== undefined) {\n\t\tthis._extensionUIContext = bindings.uiContext;\n\t}\n\tif (bindings.mode !== undefined) {\n\t\tthis._extensionMode = bindings.mode;\n\t}\n\tif (bindings.commandContextActions !== undefined) {\n\t\tthis._extensionCommandContextActions = bindings.commandContextActions;\n\t}\n\tif (bindings.shutdownHandler !== undefined) {\n\t\tthis._extensionShutdownHandler = bindings.shutdownHandler;\n\t}\n\tif (bindings.onError !== undefined) {\n\t\tthis._extensionErrorListener = bindings.onError;\n\t}\n\n\tthis._applyExtensionBindings(this._extensionRunner);\n\tawait this._extensionRunner.emit(this._sessionStartEvent);\n\tawait this.extendResourcesFromExtensions(this._sessionStartEvent.reason === \"reload\" ? \"reload\" : \"startup\");\n}\n\n\nexport async function extendResourcesFromExtensions(this: AgentSession, reason: \"startup\" | \"reload\"): Promise<void> {\n\tif (!this._extensionRunner.hasHandlers(\"resources_discover\")) {\n\t\treturn;\n\t}\n\n\tconst { skillPaths, promptPaths, themePaths } = await this._extensionRunner.emitResourcesDiscover(\n\t\tthis._cwd,\n\t\treason,\n\t);\n\n\tif (skillPaths.length === 0 && promptPaths.length === 0 && themePaths.length === 0) {\n\t\treturn;\n\t}\n\n\tconst extensionPaths: ResourceExtensionPaths = {\n\t\tskillPaths: this.buildExtensionResourcePaths(skillPaths),\n\t\tpromptPaths: this.buildExtensionResourcePaths(promptPaths),\n\t\tthemePaths: this.buildExtensionResourcePaths(themePaths),\n\t};\n\n\tthis._resourceLoader.extendResources(extensionPaths);\n\tthis._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());\n\tthis.agent.state.systemPrompt = this._baseSystemPrompt;\n}\n\n\nexport function buildExtensionResourcePaths(this: AgentSession, entries: Array<{ path: string; extensionPath: string }>): Array<{\n\tpath: string;\n\tmetadata: { source: string; scope: \"temporary\"; origin: \"top-level\"; baseDir?: string };\n}> {\n\treturn entries.map((entry) => {\n\t\tconst source = this.getExtensionSourceLabel(entry.extensionPath);\n\t\tconst baseDir = entry.extensionPath.startsWith(\"<\") ? undefined : dirname(entry.extensionPath);\n\t\treturn {\n\t\t\tpath: entry.path,\n\t\t\tmetadata: {\n\t\t\t\tsource,\n\t\t\t\tscope: \"temporary\",\n\t\t\t\torigin: \"top-level\",\n\t\t\t\tbaseDir,\n\t\t\t},\n\t\t};\n\t});\n}\n\n\nexport function getExtensionSourceLabel(this: AgentSession, extensionPath: string): string {\n\tif (extensionPath.startsWith(\"<\")) {\n\t\treturn `extension:${extensionPath.replace(/[<>]/g, \"\")}`;\n\t}\n\tconst base = basename(extensionPath);\n\tconst name = base.replace(/\\.(ts|js)$/, \"\");\n\treturn `extension:${name}`;\n}\n\n\nexport function _applyExtensionBindings(this: AgentSession, runner: ExtensionRunner): void {\n\trunner.setUIContext(this._extensionUIContext, this._extensionMode);\n\trunner.bindCommandContext(this._extensionCommandContextActions);\n\n\tthis._extensionErrorUnsubscriber?.();\n\tthis._extensionErrorUnsubscriber = this._extensionErrorListener\n\t\t? runner.onError(this._extensionErrorListener)\n\t\t: undefined;\n}\n\n\nexport function _refreshCurrentModelFromRegistry(this: AgentSession): void {\n\tconst currentModel = this.model;\n\tif (!currentModel) {\n\t\treturn;\n\t}\n\n\tconst refreshedModel = this._modelRegistry.find(currentModel.provider, currentModel.id);\n\tif (!refreshedModel || refreshedModel === currentModel) {\n\t\treturn;\n\t}\n\n\tconst replay = this._getResumeContextWindowReplayForModel(refreshedModel);\n\tthis.agent.state.model = replay.model;\n\tif (currentModel.contextWindow !== replay.contextWindow) {\n\t\tthis._emit({ type: \"context_window_changed\", contextWindow: replay.contextWindow });\n\t}\n\tthis._refreshBaseSystemPromptFromActiveTools();\n}\n\n\nexport function _bindExtensionCore(this: AgentSession, runner: ExtensionRunner): void {\n\tconst getCommands = (): SlashCommandInfo[] => {\n\t\tconst extensionCommands: SlashCommandInfo[] = runner.getRegisteredCommands().map((command) => ({\n\t\t\tname: command.invocationName,\n\t\t\tdescription: command.description,\n\t\t\tsource: \"extension\",\n\t\t\tsourceInfo: command.sourceInfo,\n\t\t}));\n\n\t\tconst templates: SlashCommandInfo[] = this.promptTemplates.map((template) => ({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description,\n\t\t\tsource: \"prompt\",\n\t\t\tsourceInfo: template.sourceInfo,\n\t\t}));\n\n\t\tconst skills: SlashCommandInfo[] = this._resourceLoader.getSkills().skills.map((skill) => ({\n\t\t\tname: `skill:${skill.name}`,\n\t\t\tdescription: skill.description,\n\t\t\tsource: \"skill\",\n\t\t\tsourceInfo: skill.sourceInfo,\n\t\t}));\n\n\t\treturn [...extensionCommands, ...templates, ...skills];\n\t};\n\n\trunner.bindCore(\n\t\t{\n\t\t\tsendMessage: (message, options) => {\n\t\t\t\tthis.sendCustomMessage(message, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tsendUserMessage: (content, options) => {\n\t\t\t\tthis.sendUserMessage(content, options).catch((err) => {\n\t\t\t\t\trunner.emitError({\n\t\t\t\t\t\textensionPath: \"<runtime>\",\n\t\t\t\t\t\tevent: \"send_user_message\",\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tappendEntry: (customType, data) => {\n\t\t\t\tthis.sessionManager.appendCustomEntry(customType, data);\n\t\t\t},\n\t\t\tsetSessionName: (name) => {\n\t\t\t\tthis.setSessionName(name);\n\t\t\t},\n\t\t\tgetSessionName: () => {\n\t\t\t\treturn this.sessionManager.getSessionName();\n\t\t\t},\n\t\t\tsetLabel: (entryId, label) => {\n\t\t\t\tthis.sessionManager.appendLabelChange(entryId, label);\n\t\t\t},\n\t\t\tgetActiveTools: () => this.getActiveToolNames(),\n\t\t\tgetAllTools: () => this.getAllTools(),\n\t\t\tsetActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),\n\t\t\trefreshTools: () => this._refreshToolRegistry(),\n\t\t\tgetCommands,\n\t\t\tsetModel: async (model) => {\n\t\t\t\tif (!this.modelRegistry.hasConfiguredAuth(model)) return false;\n\t\t\t\tawait this.setModel(model);\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tgetThinkingLevel: () => this.thinkingLevel,\n\t\t\tsetThinkingLevel: (level) => this.setThinkingLevel(level),\n\t\t},\n\t\t{\n\t\t\tgetModel: () => this.model,\n\t\t\tisIdle: () => !this.isStreaming,\n\t\t\tisProjectTrusted: () => this.settingsManager.isProjectTrusted(),\n\t\t\tgetSignal: () => this.agent.signal,\n\t\t\tabort: () => this.abort(),\n\t\t\thasPendingMessages: () => this.pendingMessageCount > 0,\n\t\t\tshutdown: () => {\n\t\t\t\tthis._extensionShutdownHandler?.();\n\t\t\t},\n\t\t\tgetContextUsage: () => this.getContextUsage(),\n\t\t\tcompact: (options) => {\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await this.compact({\n\t\t\t\t\t\t\t...(options?.compression_ratio === undefined ? {} : { compression_ratio: options.compression_ratio }),\n\t\t\t\t\t\t\t...(options?.preserve_recent === undefined ? {} : { preserve_recent: options.preserve_recent }),\n\t\t\t\t\t\t\t...(options?.query === undefined ? {} : { query: options.query }),\n\t\t\t\t\t\t});\n\t\t\t\t\t\toptions?.onComplete?.(result);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t\toptions?.onError?.(err);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t},\n\t\t\tgetSystemPrompt: () => this.systemPrompt,\n\t\t\tgetSystemPromptOptions: () => this._baseSystemPromptOptions,\n\t\t},\n\t\t{\n\t\t\tregisterProvider: (name, config) => {\n\t\t\t\tthis._modelRegistry.registerProvider(name, config);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t\tunregisterProvider: (name) => {\n\t\t\t\tthis._modelRegistry.unregisterProvider(name);\n\t\t\t\tthis._refreshCurrentModelFromRegistry();\n\t\t\t},\n\t\t},\n\t);\n}\n\n\nexport async function reload(this: AgentSession): Promise<void> {\n\tconst previousFlagValues = this._extensionRunner.getFlagValues();\n\tawait emitSessionShutdownEvent(this._extensionRunner, { type: \"session_shutdown\", reason: \"reload\" });\n\tawait this.settingsManager.reload();\n\tresetApiProviders();\n\tawait this._resourceLoader.reload();\n\tthis._buildRuntime({\n\t\tactiveToolNames: this.getActiveToolNames(),\n\t\tflagValues: previousFlagValues,\n\t\tincludeAllExtensionTools: true,\n\t});\n\n\tconst hasBindings =\n\t\tthis._extensionUIContext ||\n\t\tthis._extensionCommandContextActions ||\n\t\tthis._extensionShutdownHandler ||\n\t\tthis._extensionErrorListener;\n\tif (hasBindings) {\n\t\tawait this._extensionRunner.emit({ type: \"session_start\", reason: \"reload\" });\n\t\tawait this.extendResourcesFromExtensions(\"reload\");\n\t}\n}\n\n// =========================================================================\n// Auto-Retry\n// =========================================================================\n\n/**\n * Check if an error is retryable (overloaded, rate limit, server errors).\n * Context overflow errors are NOT retryable (handled by compaction instead).\n */\n\nexport const agentSessionExtensionBindingsMethods = {\n\tbindExtensions,\n\textendResourcesFromExtensions,\n\tbuildExtensionResourcePaths,\n\tgetExtensionSourceLabel,\n\t_applyExtensionBindings,\n\t_refreshCurrentModelFromRegistry,\n\t_bindExtensionCore,\n\treload,\n};\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
- import type { ImageContent } from "@earendil-works/pi-ai";
2
+ import type { ImageContent } from "@earendil-works/pi-ai/compat";
3
3
  import type { CustomMessage } from "./messages.ts";
4
4
  import type { SendMessageOptions } from "./extensions/index.ts";
5
5
  import type { AgentSessionInternalSurface as AgentSession } from "./agent-session-methods.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-message-queue.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-message-queue.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { CustomMessage } from \"./messages.ts\";\nimport type { SendMessageOptions } from \"./extensions/index.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport { customMessageExcludesContext, drainAgentMessageQueue, normalizeInterruptAbortMessage, type AgentQueueAccess, type DrainedAgentQueues, type InterruptQueueHold } from \"./agent-session-types.ts\";\n\nexport async function _queueSteer(this: AgentSession, text: string, images?: ImageContent[]): Promise<void> {\n\tthis._steeringMessages.push(text);\n\tthis._emitQueueUpdate();\n\tconst content: (TextContent | ImageContent)[] = [{ type: \"text\", text }];\n\tif (images) {\n\t\tcontent.push(...images);\n\t}\n\tthis._queueAgentMessage(\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t\t\"steer\",\n\t);\n}\n\n/**\n * Internal: Queue a follow-up message (already expanded, no extension command check).\n */\n\nexport async function _queueFollowUp(this: AgentSession, text: string, images?: ImageContent[]): Promise<void> {\n\tthis._followUpMessages.push(text);\n\tthis._emitQueueUpdate();\n\tconst content: (TextContent | ImageContent)[] = [{ type: \"text\", text }];\n\tif (images) {\n\t\tcontent.push(...images);\n\t}\n\tthis._queueAgentMessage(\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t\t\"followUp\",\n\t);\n}\n\n/**\n * Throw an error if the text is an extension command.\n */\n\nexport function _throwIfExtensionCommand(this: AgentSession, text: string): void {\n\tconst spaceIndex = text.indexOf(\" \");\n\tconst commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);\n\tconst command = this._extensionRunner.getCommand(commandName);\n\n\tif (command) {\n\t\tthrow new Error(\n\t\t\t`Extension command \"/${commandName}\" cannot be queued. Use prompt() or execute the command when not streaming.`,\n\t\t);\n\t}\n}\n\n/**\n * Send a custom message to the session. Creates a CustomMessageEntry.\n *\n * Handles five cases:\n * - Streaming + interrupt trigger: aborts the active run and starts an immediate custom-message turn\n * - Streaming + explicit display-only context exclusion: appends to state/session, no turn and no queue\n * - Streaming otherwise: queues message, processed when loop pulls from queue\n * - Not streaming + triggerTurn: appends to state/session, starts new turn\n * - Not streaming + no trigger: appends to state/session, no turn\n *\n * @param message Custom message with customType, content, display, details\n * @param options.triggerTurn If true and not streaming, triggers a new LLM turn\n * @param options.deliverAs Delivery mode: \"steer\", \"followUp\", \"nextTurn\", or \"interrupt\"\n */\n\nexport async function sendCustomMessage<T = unknown>(this: AgentSession, \n\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\toptions?: SendMessageOptions,\n): Promise<void> {\n\tconst appMessage = {\n\t\trole: \"custom\" as const,\n\t\tcustomType: message.customType,\n\t\tcontent: message.content,\n\t\tdisplay: message.display,\n\t\tdetails: message.details,\n\t\ttimestamp: Date.now(),\n\t\t...(options?.excludeFromContext === true ? { excludeFromContext: true } : {}),\n\t} satisfies CustomMessage<T>;\n\tif (options?.deliverAs === \"nextTurn\") {\n\t\tthis._pendingNextTurnMessages.push(appMessage);\n\t} else if (options?.deliverAs === \"interrupt\" && options.triggerTurn) {\n\t\tawait this._enqueueInterruptCustomMessage(appMessage, options);\n\t} else if (this.isStreaming && options?.excludeFromContext === true && options.triggerTurn !== true && options.deliverAs === undefined) {\n\t\tthis._appendCustomMessage(appMessage);\n\t} else if (this.isStreaming) {\n\t\tthis._queueAgentMessage(appMessage, options?.deliverAs === \"followUp\" ? \"followUp\" : \"steer\");\n\t} else if (options?.triggerTurn) {\n\t\tawait this._runAgentPrompt(appMessage);\n\t} else {\n\t\tthis._appendCustomMessage(appMessage);\n\t}\n}\n\n\nexport function _appendCustomMessage<T>(this: AgentSession, message: CustomMessage<T>): void {\n\tthis.agent.state.messages.push(message);\n\tthis.sessionManager.appendCustomMessageEntry(\n\t\tmessage.customType,\n\t\tmessage.content,\n\t\tmessage.display,\n\t\tmessage.details,\n\t\tcustomMessageExcludesContext(message),\n\t);\n\tthis._emit({ type: \"message_start\", message });\n\tthis._emit({ type: \"message_end\", message });\n}\n\n\nexport function _enqueueInterruptCustomMessage<T>(this: AgentSession, message: CustomMessage<T>, options?: SendMessageOptions): Promise<void> {\n\tthis._pendingInterruptDeliveries += 1;\n\t// Establish the hold synchronously when the interrupt is enqueued, not when\n\t// the serialized delivery callback later starts. Callers commonly fire and\n\t// forget sendCustomMessage(), then queue additional steer/follow-up messages\n\t// before the promise chain gets a microtask; those messages must be captured\n\t// in the active interrupt hold instead of pi-agent-core's live queues.\n\tthis._ensureActiveInterruptQueueHold();\n\tconst delivery = this._interruptDeliveryQueue.then(async () => {\n\t\ttry {\n\t\t\tawait this._sendInterruptCustomMessageNow(message, options);\n\t\t} finally {\n\t\t\tthis._pendingInterruptDeliveries -= 1;\n\t\t\tif (this._pendingInterruptDeliveries === 0) {\n\t\t\t\tthis._restoreAndClearActiveInterruptQueueHold();\n\t\t\t}\n\t\t}\n\t});\n\tthis._interruptDeliveryQueue = delivery.catch(() => undefined);\n\treturn delivery;\n}\n\n\nexport async function _sendInterruptCustomMessageNow<T>(this: AgentSession, \n\tmessage: CustomMessage<T>,\n\toptions?: SendMessageOptions,\n): Promise<void> {\n\tthis.abortRetry();\n\tthis._ensureActiveInterruptQueueHold();\n\tif (this.isStreaming) {\n\t\tconst previousAbortMessage = this._activeInterruptAbortMessage;\n\t\tthis._activeInterruptAbortMessage = normalizeInterruptAbortMessage(options?.interruptAbortMessage);\n\t\ttry {\n\t\t\tthis.agent.abort();\n\t\t\tawait this.agent.waitForIdle();\n\t\t\tawait this._agentEventQueue;\n\t\t} finally {\n\t\t\tthis._activeInterruptAbortMessage = previousAbortMessage;\n\t\t}\n\t}\n\tawait this.agent.prompt(message);\n}\n\n\nexport function _ensureActiveInterruptQueueHold(this: AgentSession): InterruptQueueHold {\n\tif (this._activeInterruptQueueHold !== undefined) {\n\t\treturn this._activeInterruptQueueHold;\n\t}\n\tconst drained = this._drainQueuedAgentMessages();\n\tthis._activeInterruptQueueHold = {\n\t\tsteering: [...drained.steering],\n\t\tfollowUp: [...drained.followUp],\n\t};\n\treturn this._activeInterruptQueueHold;\n}\n\n\nexport function _restoreAndClearActiveInterruptQueueHold(this: AgentSession): void {\n\tconst hold = this._activeInterruptQueueHold;\n\tif (hold === undefined) {\n\t\treturn;\n\t}\n\tconst currentCoreQueues = this._drainQueuedAgentMessages();\n\tthis._restoreQueuedAgentMessages({\n\t\tsteering: [...hold.steering, ...currentCoreQueues.steering],\n\t\tfollowUp: [...hold.followUp, ...currentCoreQueues.followUp],\n\t});\n\tthis._activeInterruptQueueHold = undefined;\n}\n\n\nexport function _queueAgentMessage(this: AgentSession, message: AgentMessage, delivery: \"steer\" | \"followUp\"): void {\n\tconst hold = this._activeInterruptQueueHold;\n\tif (hold !== undefined) {\n\t\tif (delivery === \"followUp\") {\n\t\t\thold.followUp.push(message);\n\t\t} else {\n\t\t\thold.steering.push(message);\n\t\t}\n\t\treturn;\n\t}\n\tif (delivery === \"followUp\") {\n\t\tthis.agent.followUp(message);\n\t} else {\n\t\tthis.agent.steer(message);\n\t}\n}\n\n\nexport function _drainQueuedAgentMessages(this: AgentSession): DrainedAgentQueues {\n\t// pi-agent-core exposes public clear methods but no public drain/restore pair.\n\t// Interrupts need to prevent the aborting run from consuming queued steer/follow-up\n\t// messages while still preserving those queues for a later turn.\n\tconst agentWithQueues = this.agent as unknown as AgentQueueAccess;\n\treturn {\n\t\tsteering: drainAgentMessageQueue(agentWithQueues.steeringQueue),\n\t\tfollowUp: drainAgentMessageQueue(agentWithQueues.followUpQueue),\n\t};\n}\n\n\nexport function _restoreQueuedAgentMessages(this: AgentSession, queues: DrainedAgentQueues): void {\n\tfor (const message of queues.steering) {\n\t\tthis.agent.steer(message);\n\t}\n\tfor (const message of queues.followUp) {\n\t\tthis.agent.followUp(message);\n\t}\n}\n\n/**\n * Send a user message to the agent. Always triggers a turn.\n * When the agent is streaming, use deliverAs to specify how to queue the message.\n *\n * @param content User message content (string or content array)\n * @param options.deliverAs Delivery mode when streaming: \"steer\" or \"followUp\"\n */\n\nexport function clearQueue(this: AgentSession): { steering: string[]; followUp: string[] } {\n\tconst steering = [...this._steeringMessages];\n\tconst followUp = [...this._followUpMessages];\n\tthis._steeringMessages = [];\n\tthis._followUpMessages = [];\n\tthis.agent.clearAllQueues();\n\tif (this._activeInterruptQueueHold !== undefined) {\n\t\tthis._activeInterruptQueueHold.steering.length = 0;\n\t\tthis._activeInterruptQueueHold.followUp.length = 0;\n\t}\n\tthis._emitQueueUpdate();\n\treturn { steering, followUp };\n}\n\n/** Number of pending messages (includes both steering and follow-up) */\n\nexport function getSteeringMessages(this: AgentSession): readonly string[] {\n\treturn this._steeringMessages;\n}\n\n/** Get pending follow-up messages (read-only) */\n\nexport function getFollowUpMessages(this: AgentSession): readonly string[] {\n\treturn this._followUpMessages;\n}\n\n\nexport async function abort(this: AgentSession): Promise<void> {\n\tthis.abortRetry();\n\tthis.agent.abort();\n\tawait this.agent.waitForIdle();\n}\n\n// =========================================================================\n// Model Management\n// =========================================================================\n\n\nexport function setSteeringMode(this: AgentSession, mode: \"all\" | \"one-at-a-time\"): void {\n\tthis.agent.steeringMode = mode;\n\tthis.settingsManager.setSteeringMode(mode);\n}\n\n/**\n * Set follow-up message mode.\n * Saves to settings.\n */\n\nexport function setFollowUpMode(this: AgentSession, mode: \"all\" | \"one-at-a-time\"): void {\n\tthis.agent.followUpMode = mode;\n\tthis.settingsManager.setFollowUpMode(mode);\n}\n\n// =========================================================================\n// Compaction\n// =========================================================================\n\n/**\n * Apply validated logical deletions and rebuild active agent context.\n * Retained transcript entries/content blocks stay verbatim.\n */\n\nexport const agentSessionMessageQueueMethods = {\n\t_queueSteer,\n\t_queueFollowUp,\n\t_throwIfExtensionCommand,\n\tsendCustomMessage,\n\t_appendCustomMessage,\n\t_enqueueInterruptCustomMessage,\n\t_sendInterruptCustomMessageNow,\n\t_ensureActiveInterruptQueueHold,\n\t_restoreAndClearActiveInterruptQueueHold,\n\t_queueAgentMessage,\n\t_drainQueuedAgentMessages,\n\t_restoreQueuedAgentMessages,\n\tclearQueue,\n\tgetSteeringMessages,\n\tgetFollowUpMessages,\n\tabort,\n\tsetSteeringMode,\n\tsetFollowUpMode,\n};\n"]}
1
+ {"version":3,"file":"agent-session-message-queue.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-message-queue.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai/compat\";\nimport type { CustomMessage } from \"./messages.ts\";\nimport type { SendMessageOptions } from \"./extensions/index.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport { customMessageExcludesContext, drainAgentMessageQueue, normalizeInterruptAbortMessage, type AgentQueueAccess, type DrainedAgentQueues, type InterruptQueueHold } from \"./agent-session-types.ts\";\n\nexport async function _queueSteer(this: AgentSession, text: string, images?: ImageContent[]): Promise<void> {\n\tthis._steeringMessages.push(text);\n\tthis._emitQueueUpdate();\n\tconst content: (TextContent | ImageContent)[] = [{ type: \"text\", text }];\n\tif (images) {\n\t\tcontent.push(...images);\n\t}\n\tthis._queueAgentMessage(\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t\t\"steer\",\n\t);\n}\n\n/**\n * Internal: Queue a follow-up message (already expanded, no extension command check).\n */\n\nexport async function _queueFollowUp(this: AgentSession, text: string, images?: ImageContent[]): Promise<void> {\n\tthis._followUpMessages.push(text);\n\tthis._emitQueueUpdate();\n\tconst content: (TextContent | ImageContent)[] = [{ type: \"text\", text }];\n\tif (images) {\n\t\tcontent.push(...images);\n\t}\n\tthis._queueAgentMessage(\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t\t\"followUp\",\n\t);\n}\n\n/**\n * Throw an error if the text is an extension command.\n */\n\nexport function _throwIfExtensionCommand(this: AgentSession, text: string): void {\n\tconst spaceIndex = text.indexOf(\" \");\n\tconst commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);\n\tconst command = this._extensionRunner.getCommand(commandName);\n\n\tif (command) {\n\t\tthrow new Error(\n\t\t\t`Extension command \"/${commandName}\" cannot be queued. Use prompt() or execute the command when not streaming.`,\n\t\t);\n\t}\n}\n\n/**\n * Send a custom message to the session. Creates a CustomMessageEntry.\n *\n * Handles five cases:\n * - Streaming + interrupt trigger: aborts the active run and starts an immediate custom-message turn\n * - Streaming + explicit display-only context exclusion: appends to state/session, no turn and no queue\n * - Streaming otherwise: queues message, processed when loop pulls from queue\n * - Not streaming + triggerTurn: appends to state/session, starts new turn\n * - Not streaming + no trigger: appends to state/session, no turn\n *\n * @param message Custom message with customType, content, display, details\n * @param options.triggerTurn If true and not streaming, triggers a new LLM turn\n * @param options.deliverAs Delivery mode: \"steer\", \"followUp\", \"nextTurn\", or \"interrupt\"\n */\n\nexport async function sendCustomMessage<T = unknown>(this: AgentSession, \n\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\toptions?: SendMessageOptions,\n): Promise<void> {\n\tconst appMessage = {\n\t\trole: \"custom\" as const,\n\t\tcustomType: message.customType,\n\t\tcontent: message.content,\n\t\tdisplay: message.display,\n\t\tdetails: message.details,\n\t\ttimestamp: Date.now(),\n\t\t...(options?.excludeFromContext === true ? { excludeFromContext: true } : {}),\n\t} satisfies CustomMessage<T>;\n\tif (options?.deliverAs === \"nextTurn\") {\n\t\tthis._pendingNextTurnMessages.push(appMessage);\n\t} else if (options?.deliverAs === \"interrupt\" && options.triggerTurn) {\n\t\tawait this._enqueueInterruptCustomMessage(appMessage, options);\n\t} else if (this.isStreaming && options?.excludeFromContext === true && options.triggerTurn !== true && options.deliverAs === undefined) {\n\t\tthis._appendCustomMessage(appMessage);\n\t} else if (this.isStreaming) {\n\t\tthis._queueAgentMessage(appMessage, options?.deliverAs === \"followUp\" ? \"followUp\" : \"steer\");\n\t} else if (options?.triggerTurn) {\n\t\tawait this._runAgentPrompt(appMessage);\n\t} else {\n\t\tthis._appendCustomMessage(appMessage);\n\t}\n}\n\n\nexport function _appendCustomMessage<T>(this: AgentSession, message: CustomMessage<T>): void {\n\tthis.agent.state.messages.push(message);\n\tthis.sessionManager.appendCustomMessageEntry(\n\t\tmessage.customType,\n\t\tmessage.content,\n\t\tmessage.display,\n\t\tmessage.details,\n\t\tcustomMessageExcludesContext(message),\n\t);\n\tthis._emit({ type: \"message_start\", message });\n\tthis._emit({ type: \"message_end\", message });\n}\n\n\nexport function _enqueueInterruptCustomMessage<T>(this: AgentSession, message: CustomMessage<T>, options?: SendMessageOptions): Promise<void> {\n\tthis._pendingInterruptDeliveries += 1;\n\t// Establish the hold synchronously when the interrupt is enqueued, not when\n\t// the serialized delivery callback later starts. Callers commonly fire and\n\t// forget sendCustomMessage(), then queue additional steer/follow-up messages\n\t// before the promise chain gets a microtask; those messages must be captured\n\t// in the active interrupt hold instead of pi-agent-core's live queues.\n\tthis._ensureActiveInterruptQueueHold();\n\tconst delivery = this._interruptDeliveryQueue.then(async () => {\n\t\ttry {\n\t\t\tawait this._sendInterruptCustomMessageNow(message, options);\n\t\t} finally {\n\t\t\tthis._pendingInterruptDeliveries -= 1;\n\t\t\tif (this._pendingInterruptDeliveries === 0) {\n\t\t\t\tthis._restoreAndClearActiveInterruptQueueHold();\n\t\t\t}\n\t\t}\n\t});\n\tthis._interruptDeliveryQueue = delivery.catch(() => undefined);\n\treturn delivery;\n}\n\n\nexport async function _sendInterruptCustomMessageNow<T>(this: AgentSession, \n\tmessage: CustomMessage<T>,\n\toptions?: SendMessageOptions,\n): Promise<void> {\n\tthis.abortRetry();\n\tthis._ensureActiveInterruptQueueHold();\n\tif (this.isStreaming) {\n\t\tconst previousAbortMessage = this._activeInterruptAbortMessage;\n\t\tthis._activeInterruptAbortMessage = normalizeInterruptAbortMessage(options?.interruptAbortMessage);\n\t\ttry {\n\t\t\tthis.agent.abort();\n\t\t\tawait this.agent.waitForIdle();\n\t\t\tawait this._agentEventQueue;\n\t\t} finally {\n\t\t\tthis._activeInterruptAbortMessage = previousAbortMessage;\n\t\t}\n\t}\n\tawait this.agent.prompt(message);\n}\n\n\nexport function _ensureActiveInterruptQueueHold(this: AgentSession): InterruptQueueHold {\n\tif (this._activeInterruptQueueHold !== undefined) {\n\t\treturn this._activeInterruptQueueHold;\n\t}\n\tconst drained = this._drainQueuedAgentMessages();\n\tthis._activeInterruptQueueHold = {\n\t\tsteering: [...drained.steering],\n\t\tfollowUp: [...drained.followUp],\n\t};\n\treturn this._activeInterruptQueueHold;\n}\n\n\nexport function _restoreAndClearActiveInterruptQueueHold(this: AgentSession): void {\n\tconst hold = this._activeInterruptQueueHold;\n\tif (hold === undefined) {\n\t\treturn;\n\t}\n\tconst currentCoreQueues = this._drainQueuedAgentMessages();\n\tthis._restoreQueuedAgentMessages({\n\t\tsteering: [...hold.steering, ...currentCoreQueues.steering],\n\t\tfollowUp: [...hold.followUp, ...currentCoreQueues.followUp],\n\t});\n\tthis._activeInterruptQueueHold = undefined;\n}\n\n\nexport function _queueAgentMessage(this: AgentSession, message: AgentMessage, delivery: \"steer\" | \"followUp\"): void {\n\tconst hold = this._activeInterruptQueueHold;\n\tif (hold !== undefined) {\n\t\tif (delivery === \"followUp\") {\n\t\t\thold.followUp.push(message);\n\t\t} else {\n\t\t\thold.steering.push(message);\n\t\t}\n\t\treturn;\n\t}\n\tif (delivery === \"followUp\") {\n\t\tthis.agent.followUp(message);\n\t} else {\n\t\tthis.agent.steer(message);\n\t}\n}\n\n\nexport function _drainQueuedAgentMessages(this: AgentSession): DrainedAgentQueues {\n\t// pi-agent-core exposes public clear methods but no public drain/restore pair.\n\t// Interrupts need to prevent the aborting run from consuming queued steer/follow-up\n\t// messages while still preserving those queues for a later turn.\n\tconst agentWithQueues = this.agent as unknown as AgentQueueAccess;\n\treturn {\n\t\tsteering: drainAgentMessageQueue(agentWithQueues.steeringQueue),\n\t\tfollowUp: drainAgentMessageQueue(agentWithQueues.followUpQueue),\n\t};\n}\n\n\nexport function _restoreQueuedAgentMessages(this: AgentSession, queues: DrainedAgentQueues): void {\n\tfor (const message of queues.steering) {\n\t\tthis.agent.steer(message);\n\t}\n\tfor (const message of queues.followUp) {\n\t\tthis.agent.followUp(message);\n\t}\n}\n\n/**\n * Send a user message to the agent. Always triggers a turn.\n * When the agent is streaming, use deliverAs to specify how to queue the message.\n *\n * @param content User message content (string or content array)\n * @param options.deliverAs Delivery mode when streaming: \"steer\" or \"followUp\"\n */\n\nexport function clearQueue(this: AgentSession): { steering: string[]; followUp: string[] } {\n\tconst steering = [...this._steeringMessages];\n\tconst followUp = [...this._followUpMessages];\n\tthis._steeringMessages = [];\n\tthis._followUpMessages = [];\n\tthis.agent.clearAllQueues();\n\tif (this._activeInterruptQueueHold !== undefined) {\n\t\tthis._activeInterruptQueueHold.steering.length = 0;\n\t\tthis._activeInterruptQueueHold.followUp.length = 0;\n\t}\n\tthis._emitQueueUpdate();\n\treturn { steering, followUp };\n}\n\n/** Number of pending messages (includes both steering and follow-up) */\n\nexport function getSteeringMessages(this: AgentSession): readonly string[] {\n\treturn this._steeringMessages;\n}\n\n/** Get pending follow-up messages (read-only) */\n\nexport function getFollowUpMessages(this: AgentSession): readonly string[] {\n\treturn this._followUpMessages;\n}\n\n\nexport async function abort(this: AgentSession): Promise<void> {\n\tthis.abortRetry();\n\tthis.agent.abort();\n\tawait this.agent.waitForIdle();\n}\n\n// =========================================================================\n// Model Management\n// =========================================================================\n\n\nexport function setSteeringMode(this: AgentSession, mode: \"all\" | \"one-at-a-time\"): void {\n\tthis.agent.steeringMode = mode;\n\tthis.settingsManager.setSteeringMode(mode);\n}\n\n/**\n * Set follow-up message mode.\n * Saves to settings.\n */\n\nexport function setFollowUpMode(this: AgentSession, mode: \"all\" | \"one-at-a-time\"): void {\n\tthis.agent.followUpMode = mode;\n\tthis.settingsManager.setFollowUpMode(mode);\n}\n\n// =========================================================================\n// Compaction\n// =========================================================================\n\n/**\n * Apply validated logical deletions and rebuild active agent context.\n * Retained transcript entries/content blocks stay verbatim.\n */\n\nexport const agentSessionMessageQueueMethods = {\n\t_queueSteer,\n\t_queueFollowUp,\n\t_throwIfExtensionCommand,\n\tsendCustomMessage,\n\t_appendCustomMessage,\n\t_enqueueInterruptCustomMessage,\n\t_sendInterruptCustomMessageNow,\n\t_ensureActiveInterruptQueueHold,\n\t_restoreAndClearActiveInterruptQueueHold,\n\t_queueAgentMessage,\n\t_drainQueuedAgentMessages,\n\t_restoreQueuedAgentMessages,\n\tclearQueue,\n\tgetSteeringMessages,\n\tgetFollowUpMessages,\n\tabort,\n\tsetSteeringMode,\n\tsetFollowUpMode,\n};\n"]}