@bastani/atomic 0.9.9-alpha.1 → 0.9.9-alpha.3

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 (576) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  3. package/dist/builtin/cursor/package.json +3 -3
  4. package/dist/builtin/intercom/CHANGELOG.md +14 -0
  5. package/dist/builtin/intercom/README.md +10 -3
  6. package/dist/builtin/intercom/broker/client.ts +2 -0
  7. package/dist/builtin/intercom/broker/send-handler.ts +22 -20
  8. package/dist/builtin/intercom/foreground-detach-handoff.ts +3 -1
  9. package/dist/builtin/intercom/inbound-idle-queue.ts +82 -0
  10. package/dist/builtin/intercom/index-heavy.ts +47 -37
  11. package/dist/builtin/intercom/intercom-tool.ts +6 -4
  12. package/dist/builtin/intercom/intercom-utils.ts +30 -0
  13. package/dist/builtin/intercom/lifecycle.ts +8 -5
  14. package/dist/builtin/intercom/package.json +3 -3
  15. package/dist/builtin/intercom/reply-tracker.ts +19 -19
  16. package/dist/builtin/intercom/session-target.ts +68 -0
  17. package/dist/builtin/intercom/skills/intercom/SKILL.md +7 -4
  18. package/dist/builtin/intercom/source-ownership.ts +34 -0
  19. package/dist/builtin/intercom/subagent-relay.ts +45 -20
  20. package/dist/builtin/intercom/terminal-ordering-barrier.ts +111 -0
  21. package/dist/builtin/intercom/types.ts +5 -0
  22. package/dist/builtin/mcp/CHANGELOG.md +13 -0
  23. package/dist/builtin/mcp/package.json +4 -4
  24. package/dist/builtin/subagents/CHANGELOG.md +13 -0
  25. package/dist/builtin/subagents/package.json +5 -5
  26. package/dist/builtin/subagents/src/runs/background/notify.ts +53 -9
  27. package/dist/builtin/subagents/src/shared/types-config.ts +1 -0
  28. package/dist/builtin/web-access/CHANGELOG.md +13 -0
  29. package/dist/builtin/web-access/package.json +3 -3
  30. package/dist/builtin/web-access/web-search-tool.ts +1 -2
  31. package/dist/builtin/workflows/CHANGELOG.md +13 -0
  32. package/dist/builtin/workflows/package.json +3 -3
  33. package/dist/builtin/workflows/src/extension/workflow-tool.ts +18 -2
  34. package/dist/builtin/workflows/src/shared/serializable.ts +1 -1
  35. package/dist/bun/cli.d.ts.map +1 -1
  36. package/dist/bun/internal-intercom-broker.d.ts.map +1 -1
  37. package/dist/bun/register-bedrock.d.ts.map +1 -1
  38. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  39. package/dist/bun/split-loader.d.ts.map +1 -1
  40. package/dist/cli/args.d.ts.map +1 -1
  41. package/dist/cli/config-selector.d.ts.map +1 -1
  42. package/dist/cli/file-processor.d.ts.map +1 -1
  43. package/dist/cli/initial-message.d.ts.map +1 -1
  44. package/dist/cli/list-models.d.ts.map +1 -1
  45. package/dist/cli/project-trust.d.ts.map +1 -1
  46. package/dist/cli/session-picker.d.ts.map +1 -1
  47. package/dist/cli/startup-ui.d.ts.map +1 -1
  48. package/dist/cli.d.ts.map +1 -1
  49. package/dist/config-self-update.d.ts.map +1 -1
  50. package/dist/config.d.ts.map +1 -1
  51. package/dist/core/agent-session-accessors.d.ts.map +1 -1
  52. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  53. package/dist/core/agent-session-bash.d.ts.map +1 -1
  54. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  55. package/dist/core/agent-session-events.d.ts.map +1 -1
  56. package/dist/core/agent-session-export.d.ts.map +1 -1
  57. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  58. package/dist/core/agent-session-extension-bindings.js +9 -0
  59. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  60. package/dist/core/agent-session-message-queue.d.ts +4 -1
  61. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  62. package/dist/core/agent-session-message-queue.js +35 -0
  63. package/dist/core/agent-session-message-queue.js.map +1 -1
  64. package/dist/core/agent-session-methods.d.ts +2 -1
  65. package/dist/core/agent-session-methods.d.ts.map +1 -1
  66. package/dist/core/agent-session-methods.js.map +1 -1
  67. package/dist/core/agent-session-models.d.ts.map +1 -1
  68. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  69. package/dist/core/agent-session-retry.d.ts.map +1 -1
  70. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  71. package/dist/core/agent-session-services.d.ts.map +1 -1
  72. package/dist/core/agent-session-skill-block.d.ts.map +1 -1
  73. package/dist/core/agent-session-state.d.ts.map +1 -1
  74. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  75. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  76. package/dist/core/agent-session-tree.d.ts.map +1 -1
  77. package/dist/core/agent-session-types.d.ts.map +1 -1
  78. package/dist/core/agent-session.d.ts.map +1 -1
  79. package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
  80. package/dist/core/async/format.d.ts.map +1 -1
  81. package/dist/core/async/job-manager.d.ts.map +1 -1
  82. package/dist/core/async/session-manager.d.ts.map +1 -1
  83. package/dist/core/async/types.d.ts.map +1 -1
  84. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  85. package/dist/core/auth-guidance.d.ts.map +1 -1
  86. package/dist/core/auth-storage-backends.d.ts.map +1 -1
  87. package/dist/core/auth-storage.d.ts +4 -0
  88. package/dist/core/auth-storage.d.ts.map +1 -1
  89. package/dist/core/bash-executor.d.ts.map +1 -1
  90. package/dist/core/builtin-packages.d.ts.map +1 -1
  91. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  92. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  93. package/dist/core/compaction/compaction-boundary.d.ts.map +1 -1
  94. package/dist/core/compaction/compaction-parameters.d.ts.map +1 -1
  95. package/dist/core/compaction/compaction-runner.d.ts.map +1 -1
  96. package/dist/core/compaction/compaction-types.d.ts.map +1 -1
  97. package/dist/core/compaction/compaction.d.ts.map +1 -1
  98. package/dist/core/compaction/deleted-ranges.d.ts.map +1 -1
  99. package/dist/core/compaction/index.d.ts.map +1 -1
  100. package/dist/core/compaction/range-planner.d.ts.map +1 -1
  101. package/dist/core/compaction/transcript-serialization.d.ts.map +1 -1
  102. package/dist/core/compaction/utils.d.ts.map +1 -1
  103. package/dist/core/context-window.d.ts.map +1 -1
  104. package/dist/core/copilot-anthropic-sse-repair.d.ts.map +1 -1
  105. package/dist/core/copilot-errors.d.ts.map +1 -1
  106. package/dist/core/copilot-gemini-payload-sanitizer.d.ts.map +1 -1
  107. package/dist/core/copilot-gemini-reasoning.d.ts.map +1 -1
  108. package/dist/core/copilot-gemini-tool-arguments.d.ts.map +1 -1
  109. package/dist/core/copilot-hosts.d.ts.map +1 -1
  110. package/dist/core/copilot-model-catalog.d.ts.map +1 -1
  111. package/dist/core/copilot-model-static-fallbacks.d.ts.map +1 -1
  112. package/dist/core/copilot-model-synthesis.d.ts.map +1 -1
  113. package/dist/core/defaults.d.ts.map +1 -1
  114. package/dist/core/diagnostics.d.ts.map +1 -1
  115. package/dist/core/event-bus.d.ts.map +1 -1
  116. package/dist/core/exec.d.ts.map +1 -1
  117. package/dist/core/experimental.d.ts.map +1 -1
  118. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  119. package/dist/core/export-html/index.d.ts.map +1 -1
  120. package/dist/core/export-html/template-script.d.ts.map +1 -1
  121. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  122. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  123. package/dist/core/extensions/api-types.d.ts +3 -1
  124. package/dist/core/extensions/api-types.d.ts.map +1 -1
  125. package/dist/core/extensions/api-types.js.map +1 -1
  126. package/dist/core/extensions/command-types.d.ts.map +1 -1
  127. package/dist/core/extensions/context-types.d.ts.map +1 -1
  128. package/dist/core/extensions/event-results.d.ts.map +1 -1
  129. package/dist/core/extensions/event-types.d.ts.map +1 -1
  130. package/dist/core/extensions/index.d.ts +1 -1
  131. package/dist/core/extensions/index.d.ts.map +1 -1
  132. package/dist/core/extensions/index.js.map +1 -1
  133. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  134. package/dist/core/extensions/loader-api.js +4 -0
  135. package/dist/core/extensions/loader-api.js.map +1 -1
  136. package/dist/core/extensions/loader-core.d.ts.map +1 -1
  137. package/dist/core/extensions/loader-discovery.d.ts.map +1 -1
  138. package/dist/core/extensions/loader-resources.d.ts.map +1 -1
  139. package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
  140. package/dist/core/extensions/loader-runtime.js +1 -0
  141. package/dist/core/extensions/loader-runtime.js.map +1 -1
  142. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  143. package/dist/core/extensions/loader.d.ts.map +1 -1
  144. package/dist/core/extensions/message-types.d.ts +3 -0
  145. package/dist/core/extensions/message-types.d.ts.map +1 -1
  146. package/dist/core/extensions/message-types.js.map +1 -1
  147. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  148. package/dist/core/extensions/reactive-widget.d.ts.map +1 -1
  149. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  150. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  151. package/dist/core/extensions/runner-handlers.d.ts.map +1 -1
  152. package/dist/core/extensions/runner-project-trust.d.ts.map +1 -1
  153. package/dist/core/extensions/runner-registries.d.ts.map +1 -1
  154. package/dist/core/extensions/runner-shortcuts.d.ts.map +1 -1
  155. package/dist/core/extensions/runner-ui.d.ts.map +1 -1
  156. package/dist/core/extensions/runner.d.ts.map +1 -1
  157. package/dist/core/extensions/runner.js +1 -0
  158. package/dist/core/extensions/runner.js.map +1 -1
  159. package/dist/core/extensions/runtime-types.d.ts +3 -1
  160. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  161. package/dist/core/extensions/runtime-types.js.map +1 -1
  162. package/dist/core/extensions/session-events.d.ts.map +1 -1
  163. package/dist/core/extensions/tool-events.d.ts.map +1 -1
  164. package/dist/core/extensions/tool-types.d.ts.map +1 -1
  165. package/dist/core/extensions/types.d.ts.map +1 -1
  166. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  167. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  168. package/dist/core/flattened-tool-arguments.d.ts.map +1 -1
  169. package/dist/core/footer-data-provider.d.ts.map +1 -1
  170. package/dist/core/http-dispatcher.d.ts.map +1 -1
  171. package/dist/core/index.d.ts.map +1 -1
  172. package/dist/core/keybindings.d.ts.map +1 -1
  173. package/dist/core/messages.d.ts.map +1 -1
  174. package/dist/core/model-registry-auth.d.ts.map +1 -1
  175. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  176. package/dist/core/model-registry-builtins.js.map +1 -1
  177. package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
  178. package/dist/core/model-registry-custom-loader.js.map +1 -1
  179. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  180. package/dist/core/model-registry-loader.d.ts.map +1 -1
  181. package/dist/core/model-registry-schemas.d.ts +65 -13
  182. package/dist/core/model-registry-schemas.d.ts.map +1 -1
  183. package/dist/core/model-registry-schemas.js +5 -1
  184. package/dist/core/model-registry-schemas.js.map +1 -1
  185. package/dist/core/model-registry-types.d.ts.map +1 -1
  186. package/dist/core/model-registry.d.ts.map +1 -1
  187. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  188. package/dist/core/model-resolver-defaults.d.ts.map +1 -1
  189. package/dist/core/model-resolver-initial.d.ts.map +1 -1
  190. package/dist/core/model-resolver-patterns.d.ts.map +1 -1
  191. package/dist/core/model-resolver-scope.d.ts.map +1 -1
  192. package/dist/core/model-resolver-types.d.ts.map +1 -1
  193. package/dist/core/model-resolver.d.ts.map +1 -1
  194. package/dist/core/openai-responses-payload-sanitizer.d.ts.map +1 -1
  195. package/dist/core/output-guard.d.ts.map +1 -1
  196. package/dist/core/package-manager-auto-resources.d.ts.map +1 -1
  197. package/dist/core/package-manager-command.d.ts.map +1 -1
  198. package/dist/core/package-manager-constants.d.ts.map +1 -1
  199. package/dist/core/package-manager-env.d.ts.map +1 -1
  200. package/dist/core/package-manager-git.d.ts.map +1 -1
  201. package/dist/core/package-manager-manifest.d.ts.map +1 -1
  202. package/dist/core/package-manager-npm.d.ts.map +1 -1
  203. package/dist/core/package-manager-operations.d.ts.map +1 -1
  204. package/dist/core/package-manager-paths.d.ts.map +1 -1
  205. package/dist/core/package-manager-progress.d.ts.map +1 -1
  206. package/dist/core/package-manager-resolver.d.ts.map +1 -1
  207. package/dist/core/package-manager-resource-accumulator.d.ts.map +1 -1
  208. package/dist/core/package-manager-resource-collector.d.ts.map +1 -1
  209. package/dist/core/package-manager-resource-files.d.ts.map +1 -1
  210. package/dist/core/package-manager-resource-patterns.d.ts.map +1 -1
  211. package/dist/core/package-manager-settings.d.ts.map +1 -1
  212. package/dist/core/package-manager-source.d.ts.map +1 -1
  213. package/dist/core/package-manager-types.d.ts.map +1 -1
  214. package/dist/core/package-manager.d.ts.map +1 -1
  215. package/dist/core/project-trust.d.ts.map +1 -1
  216. package/dist/core/prompt-templates-async.d.ts.map +1 -1
  217. package/dist/core/prompt-templates.d.ts.map +1 -1
  218. package/dist/core/provider-attribution.d.ts.map +1 -1
  219. package/dist/core/provider-context-usage.d.ts.map +1 -1
  220. package/dist/core/provider-display-names.d.ts.map +1 -1
  221. package/dist/core/resolve-config-value.d.ts.map +1 -1
  222. package/dist/core/resource-loader-assets.d.ts.map +1 -1
  223. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  224. package/dist/core/resource-loader-core.d.ts.map +1 -1
  225. package/dist/core/resource-loader-discovery.d.ts.map +1 -1
  226. package/dist/core/resource-loader-extensions.d.ts.map +1 -1
  227. package/dist/core/resource-loader-helpers.d.ts.map +1 -1
  228. package/dist/core/resource-loader-internals.d.ts.map +1 -1
  229. package/dist/core/resource-loader-package-resources.d.ts.map +1 -1
  230. package/dist/core/resource-loader-paths.d.ts.map +1 -1
  231. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  232. package/dist/core/resource-loader-source-info.d.ts.map +1 -1
  233. package/dist/core/resource-loader-types.d.ts.map +1 -1
  234. package/dist/core/resource-loader.d.ts.map +1 -1
  235. package/dist/core/sdk-exports.d.ts.map +1 -1
  236. package/dist/core/sdk-types.d.ts.map +1 -1
  237. package/dist/core/sdk.d.ts.map +1 -1
  238. package/dist/core/session-cwd.d.ts.map +1 -1
  239. package/dist/core/session-entry-normalization.d.ts.map +1 -1
  240. package/dist/core/session-manager-archive.d.ts.map +1 -1
  241. package/dist/core/session-manager-classification.d.ts.map +1 -1
  242. package/dist/core/session-manager-core.d.ts.map +1 -1
  243. package/dist/core/session-manager-entries.d.ts.map +1 -1
  244. package/dist/core/session-manager-history.d.ts.map +1 -1
  245. package/dist/core/session-manager-list.d.ts.map +1 -1
  246. package/dist/core/session-manager-migrations.d.ts.map +1 -1
  247. package/dist/core/session-manager-paths.d.ts.map +1 -1
  248. package/dist/core/session-manager-storage.d.ts.map +1 -1
  249. package/dist/core/session-manager-types.d.ts.map +1 -1
  250. package/dist/core/session-manager-validation.d.ts.map +1 -1
  251. package/dist/core/session-manager.d.ts.map +1 -1
  252. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  253. package/dist/core/settings-manager-core.d.ts.map +1 -1
  254. package/dist/core/settings-manager-internals.d.ts.map +1 -1
  255. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  256. package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
  257. package/dist/core/settings-manager.d.ts.map +1 -1
  258. package/dist/core/settings-merge.d.ts.map +1 -1
  259. package/dist/core/settings-storage.d.ts.map +1 -1
  260. package/dist/core/settings-types.d.ts.map +1 -1
  261. package/dist/core/skills-async.d.ts.map +1 -1
  262. package/dist/core/skills.d.ts.map +1 -1
  263. package/dist/core/slash-commands.d.ts.map +1 -1
  264. package/dist/core/source-info.d.ts.map +1 -1
  265. package/dist/core/system-prompt.d.ts.map +1 -1
  266. package/dist/core/telemetry.d.ts.map +1 -1
  267. package/dist/core/thinking-blocks.d.ts.map +1 -1
  268. package/dist/core/timings.d.ts.map +1 -1
  269. package/dist/core/tools/artifact-protocol.d.ts.map +1 -1
  270. package/dist/core/tools/artifacts.d.ts.map +1 -1
  271. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  272. package/dist/core/tools/ask-user-question/config.d.ts.map +1 -1
  273. package/dist/core/tools/ask-user-question/index.d.ts.map +1 -1
  274. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts.map +1 -1
  275. package/dist/core/tools/ask-user-question/state/inline-input.d.ts.map +1 -1
  276. package/dist/core/tools/ask-user-question/state/key-router.d.ts.map +1 -1
  277. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
  278. package/dist/core/tools/ask-user-question/state/row-intent.d.ts.map +1 -1
  279. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -1
  280. package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts.map +1 -1
  281. package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts.map +1 -1
  282. package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -1
  283. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -1
  284. package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -1
  285. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -1
  286. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -1
  287. package/dist/core/tools/ask-user-question/tool/types.d.ts.map +1 -1
  288. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts.map +1 -1
  289. package/dist/core/tools/ask-user-question/view/body-residual-spacer.d.ts.map +1 -1
  290. package/dist/core/tools/ask-user-question/view/component-binding.d.ts.map +1 -1
  291. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts.map +1 -1
  292. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts.map +1 -1
  293. package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts.map +1 -1
  294. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts.map +1 -1
  295. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts.map +1 -1
  296. package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.d.ts.map +1 -1
  297. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts.map +1 -1
  298. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts.map +1 -1
  299. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts.map +1 -1
  300. package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts.map +1 -1
  301. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -1
  302. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts.map +1 -1
  303. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -1
  304. package/dist/core/tools/ask-user-question/view/stateful-view.d.ts.map +1 -1
  305. package/dist/core/tools/ask-user-question/view/tab-components.d.ts.map +1 -1
  306. package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts.map +1 -1
  307. package/dist/core/tools/bash-async-execution.d.ts.map +1 -1
  308. package/dist/core/tools/bash-async-jobs.d.ts.map +1 -1
  309. package/dist/core/tools/bash-async-output.d.ts.map +1 -1
  310. package/dist/core/tools/bash-interceptor.d.ts.map +1 -1
  311. package/dist/core/tools/bash-leading-cd.d.ts.map +1 -1
  312. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  313. package/dist/core/tools/bash.d.ts.map +1 -1
  314. package/dist/core/tools/block-resolver.d.ts.map +1 -1
  315. package/dist/core/tools/conflict-registry.d.ts.map +1 -1
  316. package/dist/core/tools/directory-tree.d.ts.map +1 -1
  317. package/dist/core/tools/edit-diff-preserve.d.ts.map +1 -1
  318. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  319. package/dist/core/tools/edit.d.ts.map +1 -1
  320. package/dist/core/tools/fetch-url.d.ts.map +1 -1
  321. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  322. package/dist/core/tools/find.d.ts.map +1 -1
  323. package/dist/core/tools/glob-path-utils.d.ts.map +1 -1
  324. package/dist/core/tools/grep.d.ts.map +1 -1
  325. package/dist/core/tools/hashline-engine/apply.d.ts.map +1 -1
  326. package/dist/core/tools/hashline-engine/block.d.ts.map +1 -1
  327. package/dist/core/tools/hashline-engine/diff-preview.d.ts.map +1 -1
  328. package/dist/core/tools/hashline-engine/format.d.ts.map +1 -1
  329. package/dist/core/tools/hashline-engine/fs.d.ts.map +1 -1
  330. package/dist/core/tools/hashline-engine/index.d.ts.map +1 -1
  331. package/dist/core/tools/hashline-engine/input.d.ts.map +1 -1
  332. package/dist/core/tools/hashline-engine/messages.d.ts.map +1 -1
  333. package/dist/core/tools/hashline-engine/mismatch.d.ts.map +1 -1
  334. package/dist/core/tools/hashline-engine/normalize.d.ts.map +1 -1
  335. package/dist/core/tools/hashline-engine/parser.d.ts.map +1 -1
  336. package/dist/core/tools/hashline-engine/patcher.d.ts.map +1 -1
  337. package/dist/core/tools/hashline-engine/prefixes.d.ts.map +1 -1
  338. package/dist/core/tools/hashline-engine/recovery.d.ts.map +1 -1
  339. package/dist/core/tools/hashline-engine/snapshots.d.ts.map +1 -1
  340. package/dist/core/tools/hashline-engine/stream.d.ts.map +1 -1
  341. package/dist/core/tools/hashline-engine/tokenizer.d.ts.map +1 -1
  342. package/dist/core/tools/hashline-engine/types.d.ts.map +1 -1
  343. package/dist/core/tools/hashline.d.ts.map +1 -1
  344. package/dist/core/tools/index.d.ts.map +1 -1
  345. package/dist/core/tools/ls.d.ts.map +1 -1
  346. package/dist/core/tools/notebook.d.ts.map +1 -1
  347. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  348. package/dist/core/tools/oversized-tool-result.d.ts.map +1 -1
  349. package/dist/core/tools/path-utils.d.ts.map +1 -1
  350. package/dist/core/tools/read-document-extract.d.ts.map +1 -1
  351. package/dist/core/tools/read-selectors.d.ts.map +1 -1
  352. package/dist/core/tools/read-url.d.ts.map +1 -1
  353. package/dist/core/tools/read.d.ts.map +1 -1
  354. package/dist/core/tools/render-utils.d.ts.map +1 -1
  355. package/dist/core/tools/resource-selectors.d.ts.map +1 -1
  356. package/dist/core/tools/search-details.d.ts.map +1 -1
  357. package/dist/core/tools/search-line-ranges.d.ts.map +1 -1
  358. package/dist/core/tools/search-native.d.ts.map +1 -1
  359. package/dist/core/tools/search.d.ts.map +1 -1
  360. package/dist/core/tools/structured-output.d.ts.map +1 -1
  361. package/dist/core/tools/todos-execute.d.ts.map +1 -1
  362. package/dist/core/tools/todos-locks.d.ts.map +1 -1
  363. package/dist/core/tools/todos-model.d.ts.map +1 -1
  364. package/dist/core/tools/todos-mutations.d.ts.map +1 -1
  365. package/dist/core/tools/todos-paths.d.ts.map +1 -1
  366. package/dist/core/tools/todos-render.d.ts.map +1 -1
  367. package/dist/core/tools/todos-storage.d.ts.map +1 -1
  368. package/dist/core/tools/todos-types.d.ts.map +1 -1
  369. package/dist/core/tools/todos-types.js +1 -1
  370. package/dist/core/tools/todos-types.js.map +1 -1
  371. package/dist/core/tools/todos.d.ts.map +1 -1
  372. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  373. package/dist/core/tools/tool-definition-wrapper.js +6 -2
  374. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  375. package/dist/core/tools/tool-limits.d.ts.map +1 -1
  376. package/dist/core/tools/truncate.d.ts.map +1 -1
  377. package/dist/core/tools/url-ip-guards.d.ts.map +1 -1
  378. package/dist/core/tools/write.d.ts.map +1 -1
  379. package/dist/core/trust-manager.d.ts.map +1 -1
  380. package/dist/core/typebox-compat.d.ts +12 -0
  381. package/dist/core/typebox-compat.d.ts.map +1 -0
  382. package/dist/core/typebox-compat.js +10 -0
  383. package/dist/core/typebox-compat.js.map +1 -0
  384. package/dist/index-extensions.d.ts.map +1 -1
  385. package/dist/index.d.ts +1 -0
  386. package/dist/index.d.ts.map +1 -1
  387. package/dist/index.js +1 -0
  388. package/dist/index.js.map +1 -1
  389. package/dist/main-app-mode.d.ts.map +1 -1
  390. package/dist/main-deferred-startup.d.ts.map +1 -1
  391. package/dist/main-early-input.d.ts.map +1 -1
  392. package/dist/main-session-options.d.ts.map +1 -1
  393. package/dist/main-session.d.ts.map +1 -1
  394. package/dist/main-stdio.d.ts.map +1 -1
  395. package/dist/main.d.ts.map +1 -1
  396. package/dist/migrations-config-values.d.ts.map +1 -1
  397. package/dist/migrations.d.ts.map +1 -1
  398. package/dist/modes/index.d.ts.map +1 -1
  399. package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  401. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  402. package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -1
  403. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  404. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  405. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  406. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  407. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  408. package/dist/modes/interactive/components/chat-session-host-editor.d.ts.map +1 -1
  409. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  410. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  411. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
  412. package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
  413. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.d.ts.map +1 -1
  414. package/dist/modes/interactive/components/chat-session-host-types.d.ts.map +1 -1
  415. package/dist/modes/interactive/components/chat-session-host-utils.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  417. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  418. package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -1
  419. package/dist/modes/interactive/components/config-selector-list.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  421. package/dist/modes/interactive/components/context-window-selector.d.ts.map +1 -1
  422. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  423. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  424. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  425. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  426. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  427. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  428. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  429. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  430. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  431. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  432. package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -1
  433. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  434. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  436. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  437. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  439. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  440. package/dist/modes/interactive/components/session-selector-delete.d.ts.map +1 -1
  441. package/dist/modes/interactive/components/session-selector-header.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
  443. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  444. package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -1
  445. package/dist/modes/interactive/components/session-selector-types.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/session-selector-utils.d.ts.map +1 -1
  447. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  448. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  449. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/settings-selector-options.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/settings-selector-submenus.d.ts.map +1 -1
  452. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  454. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  457. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  458. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/tree-selector-component.d.ts.map +1 -1
  460. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/tree-selector-help.d.ts.map +1 -1
  462. package/dist/modes/interactive/components/tree-selector-label-input.d.ts.map +1 -1
  463. package/dist/modes/interactive/components/tree-selector-list.d.ts.map +1 -1
  464. package/dist/modes/interactive/components/tree-selector-model.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/tree-selector-types.d.ts.map +1 -1
  466. package/dist/modes/interactive/components/tree-selector-viewport.d.ts.map +1 -1
  467. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  469. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  470. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  472. package/dist/modes/interactive/components/working-status.d.ts.map +1 -1
  473. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  474. package/dist/modes/interactive/interactive-auth-login.d.ts.map +1 -1
  475. package/dist/modes/interactive/interactive-auth-routing.d.ts.map +1 -1
  476. package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  477. package/dist/modes/interactive/interactive-bash-compact.d.ts.map +1 -1
  478. package/dist/modes/interactive/interactive-child-ordering.d.ts.map +1 -1
  479. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  480. package/dist/modes/interactive/interactive-editor-actions.d.ts.map +1 -1
  481. package/dist/modes/interactive/interactive-extension-context.d.ts.map +1 -1
  482. package/dist/modes/interactive/interactive-extension-custom-ui.d.ts.map +1 -1
  483. package/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  484. package/dist/modes/interactive/interactive-extension-runtime.d.ts.map +1 -1
  485. package/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  486. package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
  487. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  488. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  489. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  490. package/dist/modes/interactive/interactive-mode-helpers.d.ts.map +1 -1
  491. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  492. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  493. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  494. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  495. package/dist/modes/interactive/interactive-onboarding.d.ts.map +1 -1
  496. package/dist/modes/interactive/interactive-process-lifecycle.d.ts.map +1 -1
  497. package/dist/modes/interactive/interactive-queueing.d.ts.map +1 -1
  498. package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
  499. package/dist/modes/interactive/interactive-resource-disclosure.d.ts.map +1 -1
  500. package/dist/modes/interactive/interactive-resource-paths.d.ts.map +1 -1
  501. package/dist/modes/interactive/interactive-resource-rendering.d.ts.map +1 -1
  502. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  503. package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
  504. package/dist/modes/interactive/interactive-session-runtime.d.ts.map +1 -1
  505. package/dist/modes/interactive/interactive-slash-commands.d.ts.map +1 -1
  506. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  507. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  508. package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
  509. package/dist/modes/interactive/theme/export-colors.d.ts.map +1 -1
  510. package/dist/modes/interactive/theme/global-theme.d.ts.map +1 -1
  511. package/dist/modes/interactive/theme/terminal-detection.d.ts.map +1 -1
  512. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  513. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  514. package/dist/modes/interactive/theme/theme-loading.d.ts.map +1 -1
  515. package/dist/modes/interactive/theme/theme-parse.d.ts.map +1 -1
  516. package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  517. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  518. package/dist/modes/interactive/theme/tui-theme.d.ts.map +1 -1
  519. package/dist/modes/interactive/whimsical-messages.d.ts.map +1 -1
  520. package/dist/modes/print-mode.d.ts.map +1 -1
  521. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  522. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  523. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  524. package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
  525. package/dist/modes/rpc/rpc-input.d.ts.map +1 -1
  526. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  527. package/dist/modes/rpc/rpc-responses.d.ts.map +1 -1
  528. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  529. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  530. package/dist/package-manager-cli-parser.d.ts.map +1 -1
  531. package/dist/package-manager-cli.d.ts.map +1 -1
  532. package/dist/rpc-entry.d.ts.map +1 -1
  533. package/dist/utils/ansi.d.ts.map +1 -1
  534. package/dist/utils/changelog.d.ts.map +1 -1
  535. package/dist/utils/child-process.d.ts.map +1 -1
  536. package/dist/utils/clipboard-image.d.ts.map +1 -1
  537. package/dist/utils/clipboard-native.d.ts.map +1 -1
  538. package/dist/utils/clipboard.d.ts.map +1 -1
  539. package/dist/utils/deprecation.d.ts.map +1 -1
  540. package/dist/utils/event-loop.d.ts.map +1 -1
  541. package/dist/utils/exif-orientation.d.ts.map +1 -1
  542. package/dist/utils/frontmatter.d.ts.map +1 -1
  543. package/dist/utils/fs-watch.d.ts.map +1 -1
  544. package/dist/utils/git-env.d.ts.map +1 -1
  545. package/dist/utils/git.d.ts.map +1 -1
  546. package/dist/utils/html.d.ts.map +1 -1
  547. package/dist/utils/image-convert.d.ts.map +1 -1
  548. package/dist/utils/image-process.d.ts.map +1 -1
  549. package/dist/utils/image-resize-core.d.ts.map +1 -1
  550. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  551. package/dist/utils/image-resize.d.ts.map +1 -1
  552. package/dist/utils/json.d.ts.map +1 -1
  553. package/dist/utils/markit.d.ts.map +1 -1
  554. package/dist/utils/mime.d.ts.map +1 -1
  555. package/dist/utils/module-require.d.ts.map +1 -1
  556. package/dist/utils/open-browser.d.ts.map +1 -1
  557. package/dist/utils/paths.d.ts.map +1 -1
  558. package/dist/utils/photon.d.ts.map +1 -1
  559. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  560. package/dist/utils/shell.d.ts.map +1 -1
  561. package/dist/utils/sleep.d.ts.map +1 -1
  562. package/dist/utils/split-launcher.d.ts.map +1 -1
  563. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  564. package/dist/utils/tools-manager.d.ts.map +1 -1
  565. package/dist/utils/version-check.d.ts.map +1 -1
  566. package/dist/utils/windows-self-update.d.ts.map +1 -1
  567. package/docs/custom-provider.md +7 -1
  568. package/docs/extensions.md +19 -4
  569. package/docs/subagents.md +2 -0
  570. package/docs/workflows.md +2 -2
  571. package/examples/extensions/README.md +3 -1
  572. package/examples/extensions/subagent/schemas.ts +1 -1
  573. package/examples/extensions/tic-tac-toe.ts +1 -2
  574. package/examples/extensions/todo.ts +1 -2
  575. package/npm-shrinkwrap.json +214 -98
  576. package/package.json +12 -12
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAoDhD;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA+CnD;AAiJD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC;IACF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAQA","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentConfigPaths, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\nimport { migrateAuthJsonConfigValues, migrateModelsJsonConfigValues } from \"./migrations-config-values.ts\";\nfunction getAgentDirsForConfigMigration(): string[] {\n\tconst dirs = new Set<string>();\n\tfor (const path of [...getAgentConfigPaths(\"auth.json\"), ...getAgentConfigPaths(\"models.json\")]) {\n\t\tdirs.add(dirname(path));\n\t}\n\treturn [...dirs];\n}\n\nfunction migrateExplicitEnvVarConfigValues(): void {\n\tconst migrations = getAgentDirsForConfigMigration().flatMap((agentDir) => [\n\t\t...migrateAuthJsonConfigValues(agentDir),\n\t\t...migrateModelsJsonConfigValues(agentDir),\n\t]);\n\tif (migrations.length === 0) return;\n\n\tconst details = migrations.map((migration) => ` - ${migration.location}: ${migration.from} -> ${migration.to}`);\n\tconsole.log(\n\t\tchalk.yellow(\n\t\t\t[\n\t\t\t\t\"Warning: Migrated API key/header environment references to explicit $ENV_VAR syntax. Plain strings will be treated as literals.\",\n\t\t\t\t...details,\n\t\t\t].join(\"\\n\"),\n\t\t),\n\t);\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string, options?: { projectTrusted?: boolean }): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tif (options?.projectTrusted !== false) {\n\t\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\t}\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...(options?.projectTrusted === false ? [] : checkDeprecatedExtensionDirs(projectDir, \"Project\")),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(\n\tcwd: string,\n\toptions?: { projectTrusted?: boolean },\n): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateExplicitEnvVarConfigValues();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd, options);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAoDhD;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA+CnD;AAiJD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC;IACF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAQA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACX,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,eAAe,GACf,MAAM,oBAAoB,CAAC","sourcesContent":["/**\n * Run modes for the coding agent.\n */\n\nexport { InteractiveMode, type InteractiveModeOptions } from \"./interactive/interactive-mode.ts\";\nexport { type PrintModeOptions, runPrintMode } from \"./print-mode.ts\";\nexport { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from \"./rpc/rpc-client.ts\";\nexport { runRpcMode } from \"./rpc/rpc-mode.ts\";\nexport type {\n\tRpcCommand,\n\tRpcContextWindowInfo,\n\tRpcEvent,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc/rpc-types.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACX,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,eAAe,GACf,MAAM,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input-actions.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/chat-input-actions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAOlD,MAAM,WAAW,kBAAkB;IACjC,IAAI,IAAI,IAAI,CAAC;IACb,KAAK,IAAI,IAAI,CAAC;IACd,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAoBD,wBAAgB,0BAA0B,CAAC,GAAG,SAAa,GAAG,IAAI,CAkBjE;AAiDD,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,WAAW,EAAE,MAAM,GAClB,MAAM,CAKR;AAED,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,0BAA0B,EAClC,aAAa,CAAC,EAAE,MAAM,IAAI,EAC1B,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC,GAAG,kBAAkB,EACxE,OAAO,GAAE,qBAA0B,GAClC,MAAM,GAAG,SAAS,CAqDpB","sourcesContent":["import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport type { TUI } from \"@earendil-works/pi-tui\";\nimport {\n extensionForImageMimeType,\n readClipboardImage,\n} from \"../../utils/clipboard-image.ts\";\nimport { APP_NAME } from \"../../config.ts\";\n\nexport interface ExternalEditorHost {\n stop(): void;\n start(): void;\n requestRender(force?: boolean): void;\n}\n\nexport interface ExternalEditorOptions {\n editorCommand?: string;\n showWarning?: (message: string) => void;\n}\n\nexport interface ClipboardImageEditorOptions {\n showWarning?: (message: string) => void;\n cleanupDelayMs?: number;\n}\n\nconst CLIPBOARD_CLEANUP_DELAY_MS = 60 * 60 * 1000;\nconst CLIPBOARD_STALE_AGE_MS = 24 * 60 * 60 * 1000;\n\nfunction appTempPrefix(kind: string): string {\n return `${APP_NAME}-${kind}-`;\n}\n\nfunction scheduleTempFileCleanup(filePath: string, delayMs: number): void {\n const timer = setTimeout(() => {\n try {\n fs.unlinkSync(filePath);\n } catch {\n // Ignore best-effort cleanup failures.\n }\n }, delayMs);\n timer.unref?.();\n}\n\nexport function cleanupStaleClipboardFiles(now = Date.now()): void {\n const prefix = appTempPrefix(\"clipboard\");\n let entries: string[];\n try {\n entries = fs.readdirSync(os.tmpdir());\n } catch {\n return;\n }\n for (const entry of entries) {\n if (!entry.startsWith(prefix)) continue;\n const filePath = path.join(os.tmpdir(), entry);\n try {\n const stat = fs.statSync(filePath);\n if (stat.isFile() && now - stat.mtimeMs >= CLIPBOARD_STALE_AGE_MS) fs.unlinkSync(filePath);\n } catch {\n // Ignore best-effort cleanup failures.\n }\n }\n}\n\nfunction parseEditorCommand(command: string): string[] {\n const args: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | null = null;\n let escaped = false;\n let started = false;\n\n for (const ch of command) {\n if (escaped) {\n current += ch;\n escaped = false;\n started = true;\n continue;\n }\n if (ch === \"\\\\\" && quote !== \"'\") {\n escaped = true;\n started = true;\n continue;\n }\n if (quote) {\n if (ch === quote) quote = null;\n else current += ch;\n started = true;\n continue;\n }\n if (ch === \"'\" || ch === '\"') {\n quote = ch;\n started = true;\n continue;\n }\n if (/\\s/.test(ch)) {\n if (started) {\n args.push(current);\n current = \"\";\n started = false;\n }\n continue;\n }\n current += ch;\n started = true;\n }\n\n if (escaped) current += \"\\\\\";\n if (started) args.push(current);\n return args;\n}\n\nexport function combineQueuedMessagesForEditor(\n queuedMessages: readonly string[],\n currentText: string,\n): string {\n return [\n ...queuedMessages,\n ...(currentText.trim() ? [currentText] : []),\n ].join(\"\\n\\n\");\n}\n\nexport interface ClipboardImageEditorTarget {\n insertTextAtCursor?: (text: string) => void;\n getText?: () => string;\n setText?: (text: string) => void;\n}\n\nexport async function pasteClipboardImageToEditor(\n editor: ClipboardImageEditorTarget,\n requestRender?: () => void,\n options: ClipboardImageEditorOptions = {},\n): Promise<boolean> {\n try {\n cleanupStaleClipboardFiles();\n const image = await readClipboardImage();\n if (!image) return false;\n\n const ext = extensionForImageMimeType(image.mimeType) ?? \"png\";\n const fileName = `${appTempPrefix(\"clipboard\")}${crypto.randomUUID()}.${ext}`;\n const filePath = path.join(os.tmpdir(), fileName);\n fs.writeFileSync(filePath, Buffer.from(image.bytes), { flag: \"wx\", mode: 0o600 });\n scheduleTempFileCleanup(filePath, options.cleanupDelayMs ?? CLIPBOARD_CLEANUP_DELAY_MS);\n\n if (editor.insertTextAtCursor) editor.insertTextAtCursor(filePath);\n else if (editor.getText && editor.setText) editor.setText(`${editor.getText()}${filePath}`);\n else return false;\n requestRender?.();\n return true;\n } catch (error) {\n options.showWarning?.(\n `Failed to paste clipboard image: ${error instanceof Error ? error.message : String(error)}`,\n );\n return false;\n }\n}\n\nexport function openExternalEditorForText(\n text: string,\n host: Pick<TUI, \"stop\" | \"start\" | \"requestRender\"> | ExternalEditorHost,\n options: ExternalEditorOptions = {},\n): string | undefined {\n const editorCommand = options.editorCommand ?? process.env.VISUAL ?? process.env.EDITOR;\n if (!editorCommand) {\n options.showWarning?.(\"No editor configured. Set $VISUAL or $EDITOR environment variable.\");\n return undefined;\n }\n\n const tmpFile = path.join(\n os.tmpdir(),\n // Keep the app name in both the prefix and extension so editor tabs and\n // file-type hints stay branded while preserving the legacy .<app>.md shape.\n `${APP_NAME}-editor-${crypto.randomUUID()}.${APP_NAME}.md`,\n );\n let tmpFileCreated = false;\n let hostStopped = false;\n try {\n fs.writeFileSync(tmpFile, text, {\n encoding: \"utf-8\",\n flag: \"wx\",\n mode: 0o600,\n });\n tmpFileCreated = true;\n host.stop();\n hostStopped = true;\n\n const [editor, ...editorArgs] = parseEditorCommand(editorCommand);\n if (!editor) return undefined;\n const result = spawnSync(editor, [...editorArgs, tmpFile], {\n stdio: \"inherit\",\n // Windows editor commands often rely on shell resolution for .cmd/.bat\n // launchers; keep this limited to trusted $VISUAL/$EDITOR input.\n shell: process.platform === \"win32\",\n });\n\n if (result.error) {\n options.showWarning?.(`Failed to open editor: ${result.error.message}`);\n return undefined;\n }\n if (result.status !== 0) return undefined;\n return fs.readFileSync(tmpFile, \"utf-8\").replace(/\\n$/, \"\");\n } finally {\n if (tmpFileCreated) {\n try {\n fs.unlinkSync(tmpFile);\n } catch {\n // Ignore cleanup errors.\n }\n }\n if (hostStopped) {\n host.start();\n host.requestRender(true);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"chat-input-actions.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/chat-input-actions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAOlD,MAAM,WAAW,kBAAkB;IACjC,IAAI,IAAI,IAAI,CAAC;IACb,KAAK,IAAI,IAAI,CAAC;IACd,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAoBD,wBAAgB,0BAA0B,CAAC,GAAG,SAAa,GAAG,IAAI,CAkBjE;AAiDD,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,WAAW,EAAE,MAAM,GAClB,MAAM,CAKR;AAED,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,0BAA0B,EAClC,aAAa,CAAC,EAAE,MAAM,IAAI,EAC1B,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC,GAAG,kBAAkB,EACxE,OAAO,GAAE,qBAA0B,GAClC,MAAM,GAAG,SAAS,CAqDpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"armin.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/armin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAuD7D,qBAAa,cAAe,YAAW,SAAS;IAC/C,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,aAAa,CAAM;IAE3B,YAAY,EAAE,EAAE,GAAG,EAQlB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB9B;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAgElB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,UAAU;IAqBlB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,QAAQ;IAmDhB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,UAAU;IAgClB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,aAAa;IAIrB,OAAO,IAAI,IAAI,CAEd;CACD","sourcesContent":["/**\n * Armin says hi! A fun easter egg with animated XBM art.\n */\n\nimport type { Component, TUI } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\n\n// XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground\nconst WIDTH = 31;\nconst HEIGHT = 36;\nconst BITS = [\n\t0xff, 0xff, 0xff, 0x7f, 0xff, 0xf0, 0xff, 0x7f, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdb, 0xff, 0x7f, 0xff, 0xb7, 0xff,\n\t0x7f, 0xff, 0x77, 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f, 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3,\n\t0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f, 0xf7, 0x0f, 0xf7, 0x7f, 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7,\n\t0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70, 0x0f, 0xff, 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53,\n\t0xc1, 0xff, 0xef, 0x57, 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f, 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50,\n\t0x6c, 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03, 0x9c, 0x78, 0xff, 0x07,\n\t0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78, 0xff, 0xff, 0xdf, 0x78, 0xff,\n\t0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f,\n];\n\nconst BYTES_PER_ROW = Math.ceil(WIDTH / 8);\nconst DISPLAY_HEIGHT = Math.ceil(HEIGHT / 2); // Half-block rendering\n\ntype Effect = \"typewriter\" | \"scanline\" | \"rain\" | \"fade\" | \"crt\" | \"glitch\" | \"dissolve\";\n\nconst EFFECTS: Effect[] = [\"typewriter\", \"scanline\", \"rain\", \"fade\", \"crt\", \"glitch\", \"dissolve\"];\n\n// Get pixel at (x, y): true = foreground, false = background\nfunction getPixel(x: number, y: number): boolean {\n\tif (y >= HEIGHT) return false;\n\tconst byteIndex = y * BYTES_PER_ROW + Math.floor(x / 8);\n\tconst bitIndex = x % 8;\n\treturn ((BITS[byteIndex] >> bitIndex) & 1) === 0;\n}\n\n// Get the character for a cell (2 vertical pixels packed)\nfunction getChar(x: number, row: number): string {\n\tconst upper = getPixel(x, row * 2);\n\tconst lower = getPixel(x, row * 2 + 1);\n\tif (upper && lower) return \"█\";\n\tif (upper) return \"▀\";\n\tif (lower) return \"▄\";\n\treturn \" \";\n}\n\n// Build the final image grid\nfunction buildFinalGrid(): string[][] {\n\tconst grid: string[][] = [];\n\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\tconst line: string[] = [];\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tline.push(getChar(x, row));\n\t\t}\n\t\tgrid.push(line);\n\t}\n\treturn grid;\n}\n\nexport class ArminComponent implements Component {\n\tprivate ui: TUI;\n\tprivate interval: ReturnType<typeof setInterval> | null = null;\n\tprivate effect: Effect;\n\tprivate finalGrid: string[][];\n\tprivate currentGrid: string[][];\n\tprivate effectState: Record<string, unknown> = {};\n\tprivate cachedLines: string[] = [];\n\tprivate cachedWidth = 0;\n\tprivate gridVersion = 0;\n\tprivate cachedVersion = -1;\n\n\tconstructor(ui: TUI) {\n\t\tthis.ui = ui;\n\t\tthis.effect = EFFECTS[Math.floor(Math.random() * EFFECTS.length)];\n\t\tthis.finalGrid = buildFinalGrid();\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\tthis.initEffect();\n\t\tthis.startAnimation();\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedWidth = 0;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width === this.cachedWidth && this.cachedVersion === this.gridVersion) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\tconst padding = 1;\n\t\tconst availableWidth = width - padding;\n\n\t\tthis.cachedLines = this.currentGrid.map((row) => {\n\t\t\t// Clip row to available width before applying color\n\t\t\tconst clipped = row.slice(0, availableWidth).join(\"\");\n\t\t\tconst padRight = Math.max(0, width - padding - clipped.length);\n\t\t\treturn ` ${theme.fg(\"accent\", clipped)}${\" \".repeat(padRight)}`;\n\t\t});\n\n\t\t// Add \"ARMIN SAYS HI\" at the end\n\t\tconst message = \"ARMIN SAYS HI\";\n\t\tconst msgPadRight = Math.max(0, width - padding - message.length);\n\t\tthis.cachedLines.push(` ${theme.fg(\"accent\", message)}${\" \".repeat(msgPadRight)}`);\n\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedVersion = this.gridVersion;\n\n\t\treturn this.cachedLines;\n\t}\n\n\tprivate createEmptyGrid(): string[][] {\n\t\treturn Array.from({ length: DISPLAY_HEIGHT }, () => Array(WIDTH).fill(\" \"));\n\t}\n\n\tprivate initEffect(): void {\n\t\tswitch (this.effect) {\n\t\t\tcase \"typewriter\":\n\t\t\t\tthis.effectState = { pos: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"scanline\":\n\t\t\t\tthis.effectState = { row: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"rain\":\n\t\t\t\t// Track falling position for each column\n\t\t\t\tthis.effectState = {\n\t\t\t\t\tdrops: Array.from({ length: WIDTH }, () => ({\n\t\t\t\t\t\ty: -Math.floor(Math.random() * DISPLAY_HEIGHT * 2),\n\t\t\t\t\t\tsettled: 0,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase \"fade\": {\n\t\t\t\t// Shuffle all pixel positions\n\t\t\t\tconst positions: [number, number][] = [];\n\t\t\t\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\t\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\t\t\tpositions.push([row, x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fisher-Yates shuffle\n\t\t\t\tfor (let i = positions.length - 1; i > 0; i--) {\n\t\t\t\t\tconst j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t\t[positions[i], positions[j]] = [positions[j], positions[i]];\n\t\t\t\t}\n\t\t\t\tthis.effectState = { positions, idx: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"crt\":\n\t\t\t\tthis.effectState = { expansion: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"glitch\":\n\t\t\t\tthis.effectState = { phase: 0, glitchFrames: 8 };\n\t\t\t\tbreak;\n\t\t\tcase \"dissolve\": {\n\t\t\t\t// Start with random noise\n\t\t\t\tthis.currentGrid = Array.from({ length: DISPLAY_HEIGHT }, () =>\n\t\t\t\t\tArray.from({ length: WIDTH }, () => {\n\t\t\t\t\t\tconst chars = [\" \", \"░\", \"▒\", \"▓\", \"█\", \"▀\", \"▄\"];\n\t\t\t\t\t\treturn chars[Math.floor(Math.random() * chars.length)];\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\t// Shuffle positions for gradual resolve\n\t\t\t\tconst dissolvePositions: [number, number][] = [];\n\t\t\t\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\t\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\t\t\tdissolvePositions.push([row, x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (let i = dissolvePositions.length - 1; i > 0; i--) {\n\t\t\t\t\tconst j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t\t[dissolvePositions[i], dissolvePositions[j]] = [dissolvePositions[j], dissolvePositions[i]];\n\t\t\t\t}\n\t\t\t\tthis.effectState = { positions: dissolvePositions, idx: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate startAnimation(): void {\n\t\tconst fps = this.effect === \"glitch\" ? 60 : 30;\n\t\tthis.interval = setInterval(() => {\n\t\t\tconst done = this.tickEffect();\n\t\t\tthis.updateDisplay();\n\t\t\tthis.ui.requestRender();\n\t\t\tif (done) {\n\t\t\t\tthis.stopAnimation();\n\t\t\t}\n\t\t}, 1000 / fps);\n\t}\n\n\tprivate stopAnimation(): void {\n\t\tif (this.interval) {\n\t\t\tclearInterval(this.interval);\n\t\t\tthis.interval = null;\n\t\t}\n\t}\n\n\tprivate tickEffect(): boolean {\n\t\tswitch (this.effect) {\n\t\t\tcase \"typewriter\":\n\t\t\t\treturn this.tickTypewriter();\n\t\t\tcase \"scanline\":\n\t\t\t\treturn this.tickScanline();\n\t\t\tcase \"rain\":\n\t\t\t\treturn this.tickRain();\n\t\t\tcase \"fade\":\n\t\t\t\treturn this.tickFade();\n\t\t\tcase \"crt\":\n\t\t\t\treturn this.tickCrt();\n\t\t\tcase \"glitch\":\n\t\t\t\treturn this.tickGlitch();\n\t\t\tcase \"dissolve\":\n\t\t\t\treturn this.tickDissolve();\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\tprivate tickTypewriter(): boolean {\n\t\tconst state = this.effectState as { pos: number };\n\t\tconst pixelsPerFrame = 3;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tconst row = Math.floor(state.pos / WIDTH);\n\t\t\tconst x = state.pos % WIDTH;\n\t\t\tif (row >= DISPLAY_HEIGHT) return true;\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.pos++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate tickScanline(): boolean {\n\t\tconst state = this.effectState as { row: number };\n\t\tif (state.row >= DISPLAY_HEIGHT) return true;\n\n\t\t// Copy row\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tthis.currentGrid[state.row][x] = this.finalGrid[state.row][x];\n\t\t}\n\t\tstate.row++;\n\t\treturn false;\n\t}\n\n\tprivate tickRain(): boolean {\n\t\tconst state = this.effectState as {\n\t\t\tdrops: { y: number; settled: number }[];\n\t\t};\n\n\t\tlet allSettled = true;\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tconst drop = state.drops[x];\n\n\t\t\t// Draw settled pixels\n\t\t\tfor (let row = DISPLAY_HEIGHT - 1; row >= DISPLAY_HEIGHT - drop.settled; row--) {\n\t\t\t\tif (row >= 0) {\n\t\t\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this column is done\n\t\t\tif (drop.settled >= DISPLAY_HEIGHT) continue;\n\n\t\t\tallSettled = false;\n\n\t\t\t// Find the target row for this column (lowest non-space pixel)\n\t\t\tlet targetRow = -1;\n\t\t\tfor (let row = DISPLAY_HEIGHT - 1 - drop.settled; row >= 0; row--) {\n\t\t\t\tif (this.finalGrid[row][x] !== \" \") {\n\t\t\t\t\ttargetRow = row;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Move drop down\n\t\t\tdrop.y++;\n\n\t\t\t// Draw falling drop\n\t\t\tif (drop.y >= 0 && drop.y < DISPLAY_HEIGHT) {\n\t\t\t\tif (targetRow >= 0 && drop.y >= targetRow) {\n\t\t\t\t\t// Settle\n\t\t\t\t\tdrop.settled = DISPLAY_HEIGHT - targetRow;\n\t\t\t\t\tdrop.y = -Math.floor(Math.random() * 5) - 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Still falling\n\t\t\t\t\tthis.currentGrid[drop.y][x] = \"▓\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn allSettled;\n\t}\n\n\tprivate tickFade(): boolean {\n\t\tconst state = this.effectState as { positions: [number, number][]; idx: number };\n\t\tconst pixelsPerFrame = 15;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tif (state.idx >= state.positions.length) return true;\n\t\t\tconst [row, x] = state.positions[state.idx];\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.idx++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate tickCrt(): boolean {\n\t\tconst state = this.effectState as { expansion: number };\n\t\tconst midRow = Math.floor(DISPLAY_HEIGHT / 2);\n\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\t// Draw from middle expanding outward\n\t\tconst top = midRow - state.expansion;\n\t\tconst bottom = midRow + state.expansion;\n\n\t\tfor (let row = Math.max(0, top); row <= Math.min(DISPLAY_HEIGHT - 1, bottom); row++) {\n\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\t}\n\t\t}\n\n\t\tstate.expansion++;\n\t\treturn state.expansion > DISPLAY_HEIGHT;\n\t}\n\n\tprivate tickGlitch(): boolean {\n\t\tconst state = this.effectState as { phase: number; glitchFrames: number };\n\n\t\tif (state.phase < state.glitchFrames) {\n\t\t\t// Glitch phase: show corrupted version\n\t\t\tthis.currentGrid = this.finalGrid.map((row) => {\n\t\t\t\tconst offset = Math.floor(Math.random() * 7) - 3;\n\t\t\t\tconst glitchRow = [...row];\n\n\t\t\t\t// Random horizontal offset\n\t\t\t\tif (Math.random() < 0.3) {\n\t\t\t\t\tconst shifted = glitchRow.slice(offset).concat(glitchRow.slice(0, offset));\n\t\t\t\t\treturn shifted.slice(0, WIDTH);\n\t\t\t\t}\n\n\t\t\t\t// Random vertical swap\n\t\t\t\tif (Math.random() < 0.2) {\n\t\t\t\t\tconst swapRow = Math.floor(Math.random() * DISPLAY_HEIGHT);\n\t\t\t\t\treturn [...this.finalGrid[swapRow]];\n\t\t\t\t}\n\n\t\t\t\treturn glitchRow;\n\t\t\t});\n\t\t\tstate.phase++;\n\t\t\treturn false;\n\t\t}\n\n\t\t// Final frame: show clean image\n\t\tthis.currentGrid = this.finalGrid.map((row) => [...row]);\n\t\treturn true;\n\t}\n\n\tprivate tickDissolve(): boolean {\n\t\tconst state = this.effectState as { positions: [number, number][]; idx: number };\n\t\tconst pixelsPerFrame = 20;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tif (state.idx >= state.positions.length) return true;\n\t\t\tconst [row, x] = state.positions[state.idx];\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.idx++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tthis.gridVersion++;\n\t}\n\n\tdispose(): void {\n\t\tthis.stopAnimation();\n\t}\n}\n"]}
1
+ {"version":3,"file":"armin.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/armin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAuD7D,qBAAa,cAAe,YAAW,SAAS;IAC/C,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,aAAa,CAAM;IAE3B,YAAY,EAAE,EAAE,GAAG,EAQlB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB9B;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAgElB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,UAAU;IAqBlB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,QAAQ;IAmDhB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,UAAU;IAgClB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,aAAa;IAIrB,OAAO,IAAI,IAAI,CAEd;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AAO/F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EACnC,SAAS,SAAI,EAeb;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKlC;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAkF7C;CACD","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai/compat\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate outputPad: number;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t\toutputPad = 1,\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\t\tthis.outputPad = outputPad;\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), this.outputPad, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static thinking label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"muted\", this.hiddenThinkingLabel)), this.outputPad, 0),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in muted color, italic\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(content.thinking.trim(), this.outputPad, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"muted\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if incomplete/failed - show after partial content.\n\t\t// For aborted/error tool calls, tool execution components show the error.\n\t\t// Length stops can happen before a tool call is complete, so surface them here too.\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (message.stopReason === \"length\") {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\tthis.contentContainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\"Error: Model stopped because it reached the maximum output token limit. The response may be incomplete.\",\n\t\t\t\t\t),\n\t\t\t\t\tthis.outputPad,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), this.outputPad, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), this.outputPad, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AAO/F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EACnC,SAAS,SAAI,EAeb;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKlC;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAkF7C;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-banner.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/atomic-banner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAiB/C,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,aAAa,GAC3B,MAAM,EAAE,CAwBV","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Theme } from \"../theme/theme.ts\";\n\nconst ATOMIC_FORALL_BANNER_LINES: readonly string[] = [\n \" ██████▙ ▟██████ \",\n \" ██████▙ ▟██████ \",\n \" ██████▙ ▟██████ \",\n \" ██████▙ ▟██████ \",\n \" ████████████████████████ \",\n \" ██████▛ ▜██████ \",\n \" ██████▛ ▜██████ \",\n \" ██████▛ ▜██████ \",\n \" ██████▛ ▜██████ \",\n \" ████████████ \",\n];\n\nconst SHADOW_CHAR = \"░\";\n\nexport function renderAtomicAnsiBanner(\n theme: Theme,\n thinkingLevel: ThinkingLevel,\n): string[] {\n const colorize = theme.getThinkingBorderColor(thinkingLevel);\n const shadow = (text: string) => theme.fg(\"dim\", text);\n\n const blankLine = \" \".repeat(ATOMIC_FORALL_BANNER_LINES[0]?.length ?? 0);\n\n return [...ATOMIC_FORALL_BANNER_LINES, blankLine].map((line, row) => {\n const chars = [...line];\n const previousLine = ATOMIC_FORALL_BANNER_LINES[row - 1];\n if (previousLine !== undefined) {\n for (const [column, char] of [...previousLine].entries()) {\n const shadowColumn = column + 1;\n if (char !== \" \" && chars[shadowColumn] === \" \") {\n chars[shadowColumn] = SHADOW_CHAR;\n }\n }\n }\n\n return chars\n .map((char) =>\n char === SHADOW_CHAR ? shadow(char) : theme.bold(colorize(char)),\n )\n .join(\"\");\n });\n}\n"]}
1
+ {"version":3,"file":"atomic-banner.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/atomic-banner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAiB/C,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,aAAa,GAC3B,MAAM,EAAE,CAwBV"}
@@ -1 +1 @@
1
- {"version":3,"file":"bash-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bash-execution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAwB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,EAGN,KAAK,gBAAgB,EAErB,MAAM,iCAAiC,CAAC;AAUzC,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,MAAM,CAA6D;IAC3E,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAY;IAEpC,YAAY,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,kBAAkB,UAAQ,EAiC/D;IAED;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAEQ,UAAU,IAAI,IAAI,CAG1B;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAgBhC;IAED,WAAW,CACV,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,OAAO,EAClB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,cAAc,CAAC,EAAE,MAAM,GACrB,IAAI,CAcN;IAED,OAAO,CAAC,aAAa;IAwFrB;;OAEG;IACH,SAAS,IAAI,MAAM,CAElB;IAED;;OAEG;IACH,UAAU,IAAI,MAAM,CAEnB;CACD","sourcesContent":["/**\n * Component for displaying bash command execution with streaming output.\n */\n\nimport { Container, Loader, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\ttype TruncationResult,\n\ttruncateTail,\n} from \"../../../core/tools/truncate.ts\";\nimport { stripAnsi } from \"../../../utils/ansi.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint, keyText } from \"./keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"./visual-truncate.ts\";\n\n// Preview line limit when not expanded (matches tool execution behavior)\nconst PREVIEW_LINES = 20;\n\nexport class BashExecutionComponent extends Container {\n\tprivate command: string;\n\tprivate outputLines: string[] = [];\n\tprivate status: \"running\" | \"complete\" | \"cancelled\" | \"error\" = \"running\";\n\tprivate exitCode: number | undefined = undefined;\n\tprivate loader: Loader;\n\tprivate truncationResult?: TruncationResult;\n\tprivate fullOutputPath?: string;\n\tprivate expanded = false;\n\tprivate contentContainer: Container;\n\n\tconstructor(command: string, ui: TUI, excludeFromContext = false) {\n\t\tsuper();\n\t\tthis.command = command;\n\n\t\t// Use dim border for excluded-from-context commands (!! prefix)\n\t\tconst colorKey = excludeFromContext ? \"dim\" : \"bashMode\";\n\t\tconst borderColor = (str: string) => theme.fg(colorKey, str);\n\n\t\t// Add spacer\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Top border\n\t\tthis.addChild(new DynamicBorder(borderColor));\n\n\t\t// Content container (holds dynamic content between borders)\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\t// Command header\n\t\tconst header = new Text(theme.fg(colorKey, theme.bold(`$ ${command}`)), 1, 0);\n\t\tthis.contentContainer.addChild(header);\n\n\t\t// Loader\n\t\tthis.loader = new Loader(\n\t\t\tui,\n\t\t\t(spinner) => theme.fg(colorKey, spinner),\n\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t`Running... (${keyText(\"tui.select.cancel\")} Cancel)`, // Plain text for loader\n\t\t);\n\t\tthis.contentContainer.addChild(this.loader);\n\n\t\t// Bottom border\n\t\tthis.addChild(new DynamicBorder(borderColor));\n\t}\n\n\t/**\n\t * Set whether the output is expanded (shows full output) or collapsed (preview only).\n\t */\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\tappendOutput(chunk: string): void {\n\t\t// Strip ANSI codes and normalize line endings\n\t\t// Note: binary data is already sanitized in tui-renderer.ts executeBashCommand\n\t\tconst clean = stripAnsi(chunk).replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n\t\t// Append to output lines\n\t\tconst newLines = clean.split(\"\\n\");\n\t\tif (this.outputLines.length > 0 && newLines.length > 0) {\n\t\t\t// Append first chunk to last line (incomplete line continuation)\n\t\t\tthis.outputLines[this.outputLines.length - 1] += newLines[0];\n\t\t\tthis.outputLines.push(...newLines.slice(1));\n\t\t} else {\n\t\t\tthis.outputLines.push(...newLines);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tsetComplete(\n\t\texitCode: number | undefined,\n\t\tcancelled: boolean,\n\t\ttruncationResult?: TruncationResult,\n\t\tfullOutputPath?: string,\n\t): void {\n\t\tthis.exitCode = exitCode;\n\t\tthis.status = cancelled\n\t\t\t? \"cancelled\"\n\t\t\t: exitCode !== 0 && exitCode !== undefined && exitCode !== null\n\t\t\t\t? \"error\"\n\t\t\t\t: \"complete\";\n\t\tthis.truncationResult = truncationResult;\n\t\tthis.fullOutputPath = fullOutputPath;\n\n\t\t// Stop loader\n\t\tthis.loader.stop();\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Apply truncation for LLM context limits (same limits as bash tool)\n\t\tconst fullOutput = this.outputLines.join(\"\\n\");\n\t\tconst contextTruncation = truncateTail(fullOutput, {\n\t\t\tmaxLines: DEFAULT_MAX_LINES,\n\t\t\tmaxBytes: DEFAULT_MAX_BYTES,\n\t\t});\n\n\t\t// Get the lines to potentially display (after context truncation)\n\t\tconst availableLines = contextTruncation.content ? contextTruncation.content.split(\"\\n\") : [];\n\n\t\t// Apply preview truncation based on expanded state\n\t\tconst previewLogicalLines = availableLines.slice(-PREVIEW_LINES);\n\t\tconst hiddenLineCount = availableLines.length - previewLogicalLines.length;\n\n\t\t// Rebuild content container\n\t\tthis.contentContainer.clear();\n\n\t\t// Command header\n\t\tconst header = new Text(theme.fg(\"bashMode\", theme.bold(`$ ${this.command}`)), 1, 0);\n\t\tthis.contentContainer.addChild(header);\n\n\t\t// Output\n\t\tif (availableLines.length > 0) {\n\t\t\tif (this.expanded) {\n\t\t\t\t// Show all lines\n\t\t\t\tconst displayText = availableLines.map((line) => theme.fg(\"muted\", line)).join(\"\\n\");\n\t\t\t\tthis.contentContainer.addChild(new Text(`\\n${displayText}`, 1, 0));\n\t\t\t} else {\n\t\t\t\t// Use shared visual truncation utility with width-aware caching\n\t\t\t\tconst styledOutput = previewLogicalLines.map((line) => theme.fg(\"muted\", line)).join(\"\\n\");\n\t\t\t\tconst styledInput = `\\n${styledOutput}`;\n\t\t\t\tlet cachedWidth: number | undefined;\n\t\t\t\tlet cachedLines: string[] | undefined;\n\t\t\t\tthis.contentContainer.addChild({\n\t\t\t\t\trender: (width: number) => {\n\t\t\t\t\t\tif (cachedLines === undefined || cachedWidth !== width) {\n\t\t\t\t\t\t\tconst result = truncateToVisualLines(styledInput, PREVIEW_LINES, width, 1);\n\t\t\t\t\t\t\tcachedLines = result.visualLines;\n\t\t\t\t\t\t\tcachedWidth = width;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn cachedLines ?? [];\n\t\t\t\t\t},\n\t\t\t\t\tinvalidate: () => {\n\t\t\t\t\t\tcachedWidth = undefined;\n\t\t\t\t\t\tcachedLines = undefined;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Loader or status\n\t\tif (this.status === \"running\") {\n\t\t\tthis.contentContainer.addChild(this.loader);\n\t\t} else {\n\t\t\tconst statusParts: string[] = [];\n\n\t\t\t// Show how many lines are hidden (collapsed preview)\n\t\t\tif (hiddenLineCount > 0) {\n\t\t\t\tif (this.expanded) {\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\t`${theme.fg(\"muted\", \"(\")}${keyHint(\"app.tools.expand\", \"Collapse\")}${theme.fg(\"muted\", \")\")}`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\t`${theme.fg(\"muted\", `... ${hiddenLineCount} more lines (`)}${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.status === \"cancelled\") {\n\t\t\t\tstatusParts.push(theme.fg(\"warning\", \"(cancelled)\"));\n\t\t\t} else if (this.status === \"error\") {\n\t\t\t\tstatusParts.push(theme.fg(\"error\", `(exit ${this.exitCode})`));\n\t\t\t}\n\n\t\t\t// Add truncation warning (context truncation, not preview truncation)\n\t\t\tconst wasTruncated = this.truncationResult?.truncated || contextTruncation.truncated;\n\t\t\tif (wasTruncated && this.fullOutputPath) {\n\t\t\t\tstatusParts.push(theme.fg(\"warning\", `Output truncated. Full output: ${this.fullOutputPath}`));\n\t\t\t}\n\n\t\t\tif (statusParts.length > 0) {\n\t\t\t\tthis.contentContainer.addChild(new Text(`\\n${statusParts.join(\"\\n\")}`, 1, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the raw output for creating BashExecutionMessage.\n\t */\n\tgetOutput(): string {\n\t\treturn this.outputLines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Get the command that was executed.\n\t */\n\tgetCommand(): string {\n\t\treturn this.command;\n\t}\n}\n"]}
1
+ {"version":3,"file":"bash-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bash-execution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAwB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,EAGN,KAAK,gBAAgB,EAErB,MAAM,iCAAiC,CAAC;AAUzC,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,MAAM,CAA6D;IAC3E,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAY;IAEpC,YAAY,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,kBAAkB,UAAQ,EAiC/D;IAED;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAEQ,UAAU,IAAI,IAAI,CAG1B;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAgBhC;IAED,WAAW,CACV,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,OAAO,EAClB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,cAAc,CAAC,EAAE,MAAM,GACrB,IAAI,CAcN;IAED,OAAO,CAAC,aAAa;IAwFrB;;OAEG;IACH,SAAS,IAAI,MAAM,CAElB;IAED;;OAEG;IACH,UAAU,IAAI,MAAM,CAEnB;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"bordered-loader.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bordered-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,SAAS,EAAwB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C,mDAAmD;AACnD,qBAAa,cAAe,SAAQ,SAAS;IAC5C,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAE3C,YAAY,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,EA4BvF;IAED,IAAI,MAAM,IAAI,WAAW,CAKxB;IAED,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,EAIvC;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9B;IAED,OAAO,IAAI,IAAI,CAMd;CACD","sourcesContent":["import { CancellableLoader, Container, Loader, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\n/** Loader wrapped with borders for extension UI */\nexport class BorderedLoader extends Container {\n\tprivate loader: CancellableLoader | Loader;\n\tprivate cancellable: boolean;\n\tprivate signalController?: AbortController;\n\n\tconstructor(tui: TUI, theme: Theme, message: string, options?: { cancellable?: boolean }) {\n\t\tsuper();\n\t\tthis.cancellable = options?.cancellable ?? true;\n\t\tconst borderColor = (s: string) => theme.fg(\"border\", s);\n\t\tthis.addChild(new DynamicBorder(borderColor));\n\t\tif (this.cancellable) {\n\t\t\tthis.loader = new CancellableLoader(\n\t\t\t\ttui,\n\t\t\t\t(s) => theme.fg(\"accent\", s),\n\t\t\t\t(s) => theme.fg(\"muted\", s),\n\t\t\t\tmessage,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.signalController = new AbortController();\n\t\t\tthis.loader = new Loader(\n\t\t\t\ttui,\n\t\t\t\t(s) => theme.fg(\"accent\", s),\n\t\t\t\t(s) => theme.fg(\"muted\", s),\n\t\t\t\tmessage,\n\t\t\t);\n\t\t}\n\t\tthis.addChild(this.loader);\n\t\tif (this.cancellable) {\n\t\t\tthis.addChild(new Spacer(1));\n\t\t\tthis.addChild(new Text(keyHint(\"tui.select.cancel\", \"cancel\"), 1, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder(borderColor));\n\t}\n\n\tget signal(): AbortSignal {\n\t\tif (this.cancellable) {\n\t\t\treturn (this.loader as CancellableLoader).signal;\n\t\t}\n\t\treturn this.signalController?.signal ?? new AbortController().signal;\n\t}\n\n\tset onAbort(fn: (() => void) | undefined) {\n\t\tif (this.cancellable) {\n\t\t\t(this.loader as CancellableLoader).onAbort = fn;\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.cancellable) {\n\t\t\t(this.loader as CancellableLoader).handleInput(data);\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tif (\"dispose\" in this.loader && typeof this.loader.dispose === \"function\") {\n\t\t\tthis.loader.dispose();\n\t\t} else if (\"stop\" in this.loader && typeof this.loader.stop === \"function\") {\n\t\t\tthis.loader.stop();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"bordered-loader.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bordered-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,SAAS,EAAwB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C,mDAAmD;AACnD,qBAAa,cAAe,SAAQ,SAAS;IAC5C,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAE3C,YAAY,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,EA4BvF;IAED,IAAI,MAAM,IAAI,WAAW,CAKxB;IAED,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,EAIvC;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9B;IAED,OAAO,IAAI,IAAI,CAMd;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"branch-summary-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/branch-summary-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAItE;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,GAAG;IACrD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,aAAa,CAAgB;IAErC,YAAY,OAAO,EAAE,oBAAoB,EAAE,aAAa,GAAE,aAAkC,EAK3F;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAEQ,UAAU,IAAI,IAAI,CAG1B;IAED,OAAO,CAAC,aAAa;CA0BrB","sourcesContent":["import { Box, Markdown, type MarkdownTheme, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport type { BranchSummaryMessage } from \"../../../core/messages.ts\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\nimport { keyText } from \"./keybinding-hints.ts\";\n\n/**\n * Component that renders a branch summary message with collapsed/expanded state.\n * Uses same background color as custom messages for visual consistency.\n */\nexport class BranchSummaryMessageComponent extends Box {\n\tprivate expanded = false;\n\tprivate message: BranchSummaryMessage;\n\tprivate markdownTheme: MarkdownTheme;\n\n\tconstructor(message: BranchSummaryMessage, markdownTheme: MarkdownTheme = getMarkdownTheme()) {\n\t\tsuper(1, 1, (t) => theme.bg(\"customMessageBg\", t));\n\t\tthis.message = message;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tthis.clear();\n\n\t\tconst label = theme.fg(\"customMessageLabel\", `\\x1b[1m[branch]\\x1b[22m`);\n\t\tthis.addChild(new Text(label, 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tif (this.expanded) {\n\t\t\tconst header = \"**Branch Summary**\\n\\n\";\n\t\t\tthis.addChild(\n\t\t\t\tnew Markdown(header + this.message.summary, 0, 0, this.markdownTheme, {\n\t\t\t\t\tcolor: (text: string) => theme.fg(\"customMessageText\", text),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\"customMessageText\", \"Branch summary (\") +\n\t\t\t\t\t\ttheme.fg(\"dim\", keyText(\"app.tools.expand\")) +\n\t\t\t\t\t\ttheme.fg(\"customMessageText\", \" Expand)\"),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"branch-summary-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/branch-summary-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAItE;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,GAAG;IACrD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,aAAa,CAAgB;IAErC,YAAY,OAAO,EAAE,oBAAoB,EAAE,aAAa,GAAE,aAAkC,EAK3F;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAEQ,UAAU,IAAI,IAAI,CAG1B;IAED,OAAO,CAAC,aAAa;CA0BrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-message-renderer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-message-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage, ToolResultMessage } from \"@earendil-works/pi-ai/compat\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, type Component, type MarkdownTheme, type TUI } from \"@earendil-works/pi-tui\";\nimport type { TSchema } from \"typebox\";\nimport type { MessageRenderer, ToolDefinition } from \"../../../core/extensions/types.ts\";\nimport { isVerbatimCompactionMessage, type BashExecutionMessage, type BranchSummaryMessage, type CustomMessage } from \"../../../core/messages.ts\";\nimport { parseSkillBlock } from \"../../../core/agent-session.ts\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\nimport { AssistantMessageComponent } from \"./assistant-message.ts\";\nimport { BashExecutionComponent } from \"./bash-execution.ts\";\nimport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nimport { compactionBoundaryFromMessage } from \"./compaction-boundary-message.ts\";\nimport { CustomMessageComponent } from \"./custom-message.ts\";\nimport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nimport { ToolExecutionComponent } from \"./tool-execution.ts\";\nimport { UserMessageComponent } from \"./user-message.ts\";\nimport { extractMessageText } from \"./chat-session-host-utils.ts\";\nexport type ChatMessageEntry =\n | { role: \"assistant\"; kind: \"assistant\"; message: AssistantMessage }\n | { role: \"tool\"; kind: \"tool\"; toolName: string; toolCallId: string; args: unknown; result?: ToolResultMessage; isPartial?: boolean }\n | { role: \"tool\"; kind: \"bashExecution\"; message: BashExecutionMessage; isPartial?: boolean }\n | { role: \"user\"; kind: \"user\"; text: string }\n | { role: \"custom\"; kind: \"custom\"; message: CustomMessage<unknown> }\n | { role: \"summary\"; kind: \"branchSummary\"; message: BranchSummaryMessage }\n | { role: \"system\"; kind: \"system\"; text: string };\nexport interface ChatMessageRenderOptions {\n ui: Pick<TUI, \"requestRender\">; cwd: string; markdownTheme?: MarkdownTheme;\n hideThinkingBlock?: boolean; hiddenThinkingLabel?: string; toolOutputExpanded?: boolean;\n showImages?: boolean; imageWidthCells?: number; outputPad?: number; getToolDefinition?: (toolName: string) => ToolDefinition<TSchema, unknown> | undefined;\n getCustomMessageRenderer?: (customType: string) => MessageRenderer | undefined;\n}\nexport function chatEntriesFromAgentMessages(\n messages: readonly AgentMessage[],\n): ChatMessageEntry[] {\n const entries: ChatMessageEntry[] = [];\n const pendingTools = new Map<string, Extract<ChatMessageEntry, { kind: \"tool\" }>>();\n for (const message of messages) {\n if (isLegacyCompactionSummaryMessage(message)) continue;\n switch (message.role) {\n case \"assistant\": {\n entries.push({ role: \"assistant\", kind: \"assistant\", message });\n for (const content of message.content) {\n if (content.type !== \"toolCall\") continue;\n const toolEntry: ChatMessageEntry = {\n role: \"tool\",\n kind: \"tool\",\n toolName: content.name,\n toolCallId: content.id,\n args: content.arguments,\n isPartial: true,\n };\n entries.push(toolEntry);\n pendingTools.set(content.id, toolEntry);\n }\n if (message.stopReason === \"aborted\" || message.stopReason === \"error\") {\n const errorText = message.stopReason === \"aborted\"\n ? message.errorMessage || \"Operation aborted\"\n : message.errorMessage || \"Unknown error\";\n for (const toolEntry of pendingTools.values()) {\n toolEntry.result = {\n role: \"toolResult\",\n toolCallId: toolEntry.toolCallId,\n toolName: toolEntry.toolName,\n content: [{ type: \"text\", text: errorText }],\n isError: true,\n timestamp: message.timestamp,\n };\n toolEntry.isPartial = false;\n }\n pendingTools.clear();\n }\n break;\n }\n case \"toolResult\": {\n const toolEntry = pendingTools.get(message.toolCallId);\n if (toolEntry) {\n toolEntry.result = message;\n toolEntry.isPartial = false;\n pendingTools.delete(message.toolCallId);\n } else {\n entries.push({\n role: \"tool\",\n kind: \"tool\",\n toolName: message.toolName,\n toolCallId: message.toolCallId,\n args: {},\n result: message,\n isPartial: false,\n });\n }\n break;\n }\n case \"user\": {\n const text = getMessageText(message);\n if (text) entries.push({ role: \"user\", kind: \"user\", text });\n break;\n }\n case \"bashExecution\":\n entries.push({ role: \"tool\", kind: \"bashExecution\", message });\n break;\n case \"custom\":\n if (message.display) entries.push({ role: \"custom\", kind: \"custom\", message });\n break;\n case \"branchSummary\":\n entries.push({ role: \"summary\", kind: \"branchSummary\", message });\n break;\n default: {\n const role = (message as { role: string }).role;\n entries.push({ role: \"system\", kind: \"system\", text: role });\n break;\n }\n }\n }\n return entries;\n}\nexport interface LiveChatEventLike {\n readonly type?: unknown;\n readonly message?: unknown;\n readonly assistantMessageEvent?: { readonly type?: unknown; readonly delta?: unknown };\n readonly toolCallId?: unknown;\n readonly toolName?: unknown;\n readonly args?: unknown;\n readonly partialResult?: unknown;\n readonly result?: unknown;\n readonly isError?: unknown;\n}\ntype LiveChatEntry = ChatMessageEntry | { role: string };\nexport class LiveChatEntriesController {\n private streamingAssistantIndex: number | undefined;\n private pendingToolIndexes = new Map<string, number>();\n declare private readonly entries: LiveChatEntry[];\n constructor(entries: LiveChatEntry[]) {\n this.entries = entries;\n\t}\n appendMessages(messages: readonly AgentMessage[]): void {\n this.entries.push(...chatEntriesFromAgentMessages(messages));\n this.reindexPendingTools();\n }\n replaceMessages(\n messages: readonly AgentMessage[],\n preservedEntries: readonly { role: string }[] = [],\n ): void {\n this.entries.splice(0, this.entries.length, ...chatEntriesFromAgentMessages(messages), ...preservedEntries);\n this.streamingAssistantIndex = undefined;\n this.reindexPendingTools();\n }\n appendUserText(text: string): void {\n this.entries.push({ role: \"user\", kind: \"user\", text });\n }\n applyEvent(event: LiveChatEventLike): boolean {\n const type = String(event.type ?? \"\");\n switch (type) {\n case \"message_start\":\n return this.handleMessageStart(event.message);\n case \"message_update\":\n return this.handleMessageUpdate(event);\n case \"message_end\":\n return this.handleMessageEnd(event.message);\n case \"tool_execution_start\":\n return this.upsertToolEntry({\n toolCallId: typeof event.toolCallId === \"string\" ? event.toolCallId : undefined,\n toolName: typeof event.toolName === \"string\" ? event.toolName : \"tool\",\n args: event.args,\n isPartial: true,\n });\n case \"tool_execution_update\": {\n const toolCallId = typeof event.toolCallId === \"string\" ? event.toolCallId : undefined;\n if (!toolCallId) return false;\n return this.updateToolResult(toolCallId, event.partialResult, true, false);\n }\n case \"tool_execution_end\": {\n const toolCallId = typeof event.toolCallId === \"string\" ? event.toolCallId : undefined;\n if (!toolCallId) return false;\n return this.updateToolResult(toolCallId, event.result, false, event.isError === true);\n }\n default:\n return false;\n }\n }\n pendingToolIds(): string[] {\n return [...this.pendingToolIndexes.keys()];\n }\n clearPendingTools(): void {\n this.pendingToolIndexes.clear();\n }\n private handleMessageStart(message: unknown): boolean {\n if (!isAgentMessageLike(message)) return false;\n if (message.role === \"assistant\") {\n this.streamingAssistantIndex = undefined;\n return this.updateAssistantMessage(message as AssistantMessage);\n }\n if (message.role === \"toolResult\") {\n const toolResult = message as ToolResultMessage;\n if (this.findToolEntryIndex(toolResult.toolCallId) >= 0) return true;\n }\n const entries = chatEntriesFromAgentMessages([message as AgentMessage]);\n if (entries.length === 0) return false;\n this.entries.push(...entries);\n this.reindexPendingTools();\n return true;\n }\n private handleMessageUpdate(event: LiveChatEventLike): boolean {\n const message = event.message;\n let changed = false;\n const snapshotHasPayload = isAgentMessageLike(message) &&\n message.role === \"assistant\" &&\n assistantContentHasRenderablePayload((message as { content?: unknown }).content);\n if (isAgentMessageLike(message) && message.role === \"assistant\" && snapshotHasPayload) {\n changed = this.updateAssistantMessage(message as AssistantMessage) || changed;\n }\n const assistantEvent = event.assistantMessageEvent;\n const streamType = String(assistantEvent?.type ?? \"\");\n const delta = typeof assistantEvent?.delta === \"string\" ? assistantEvent.delta : \"\";\n if (!changed && streamType === \"text_delta\" && delta) {\n changed = this.appendAssistantTextDelta(delta);\n } else if (!changed && streamType === \"thinking_delta\" && delta) {\n changed = this.appendAssistantThinkingDelta(delta);\n }\n return changed;\n }\n private handleMessageEnd(message: unknown): boolean {\n if (!isAgentMessageLike(message) || message.role !== \"assistant\") return false;\n const changed = this.updateAssistantMessage(message as AssistantMessage);\n const stopReason = typeof message.stopReason === \"string\" ? message.stopReason : \"\";\n if (stopReason === \"aborted\" || stopReason === \"error\") {\n const errorText = typeof message.errorMessage === \"string\" && message.errorMessage\n ? message.errorMessage\n : stopReason === \"aborted\"\n ? \"Operation aborted\"\n : \"Unknown error\";\n for (const toolCallId of this.pendingToolIds()) {\n this.updateToolResult(toolCallId, { content: [{ type: \"text\", text: errorText }] }, false, true);\n }\n this.clearPendingTools();\n }\n this.streamingAssistantIndex = undefined;\n return changed || true;\n }\n private updateAssistantMessage(message: AssistantMessage): boolean {\n if (this.streamingAssistantIndex !== undefined && this.isAssistantEntry(this.entries[this.streamingAssistantIndex])) {\n this.entries[this.streamingAssistantIndex] = {\n ...(this.entries[this.streamingAssistantIndex] as Extract<ChatMessageEntry, { kind: \"assistant\" }>),\n message,\n };\n } else {\n this.entries.push({ role: \"assistant\", kind: \"assistant\", message });\n this.streamingAssistantIndex = this.entries.length - 1;\n }\n for (const content of message.content) {\n if (content.type !== \"toolCall\") continue;\n this.upsertToolEntry({\n toolCallId: content.id,\n toolName: content.name,\n args: content.arguments,\n isPartial: true,\n });\n }\n return true;\n }\n private appendAssistantTextDelta(delta: string): boolean {\n const current = this.currentStreamingAssistantMessage();\n const content = current ? [...current.content] : [];\n const lastText = [...content].reverse().find((item) => item.type === \"text\");\n if (lastText && lastText.type === \"text\") lastText.text += delta;\n else content.push({ type: \"text\", text: delta });\n return this.updateAssistantMessage({\n ...(current ?? minimalAssistantMessage()),\n content,\n });\n }\n private appendAssistantThinkingDelta(delta: string): boolean {\n const current = this.currentStreamingAssistantMessage();\n const content = current ? [...current.content] : [];\n const lastThinking = [...content].reverse().find((item) => item.type === \"thinking\");\n if (lastThinking && lastThinking.type === \"thinking\") lastThinking.thinking += delta;\n else content.push({ type: \"thinking\", thinking: delta });\n return this.updateAssistantMessage({\n ...(current ?? minimalAssistantMessage()),\n content,\n });\n }\n private currentStreamingAssistantMessage(): AssistantMessage | undefined {\n const entry = this.streamingAssistantIndex !== undefined ? this.entries[this.streamingAssistantIndex] : undefined;\n return this.isAssistantEntry(entry) ? entry.message : undefined;\n }\n private upsertToolEntry(update: {\n toolCallId?: string;\n toolName: string;\n args?: unknown;\n isPartial: boolean;\n }): boolean {\n const toolCallId = update.toolCallId ?? `live-${update.toolName}`;\n const index = this.pendingToolIndexes.get(toolCallId) ?? this.findToolEntryIndex(toolCallId, update.toolName);\n const previous = index >= 0 ? this.entries[index] : undefined;\n const previousTool = this.isToolEntry(previous) ? previous : undefined;\n const next: ChatMessageEntry = {\n role: \"tool\",\n kind: \"tool\",\n toolName: previousTool?.toolName ?? update.toolName,\n toolCallId,\n args: update.args ?? previousTool?.args ?? {},\n result: previousTool?.result,\n isPartial: update.isPartial,\n };\n if (index >= 0) this.entries[index] = next;\n else this.entries.push(next);\n this.pendingToolIndexes.set(toolCallId, index >= 0 ? index : this.entries.length - 1);\n return true;\n }\n private updateToolResult(toolCallId: string, result: unknown, isPartial: boolean, isError: boolean): boolean {\n const index = this.pendingToolIndexes.get(toolCallId) ?? this.findToolEntryIndex(toolCallId);\n if (index < 0) return false;\n const entry = this.entries[index];\n if (!this.isToolEntry(entry)) return false;\n const resultObject = toolResultFromUnknown(result, entry.toolName, toolCallId, isError);\n this.entries[index] = { ...entry, result: resultObject, isPartial };\n if (!isPartial) this.pendingToolIndexes.delete(toolCallId);\n return true;\n }\n private isSyntheticToolCallId(toolCallId: string): boolean {\n return toolCallId.startsWith(\"live-\");\n }\n private findToolEntryIndex(toolCallId: string, toolName?: string): number {\n for (let i = this.entries.length - 1; i >= 0; i--) {\n const entry = this.entries[i];\n if (!this.isToolEntry(entry)) continue;\n if (entry.toolCallId === toolCallId) return i;\n if (\n toolName &&\n entry.toolName === toolName &&\n entry.isPartial !== false &&\n (this.isSyntheticToolCallId(toolCallId) || this.isSyntheticToolCallId(entry.toolCallId))\n ) {\n return i;\n }\n }\n return -1;\n }\n private reindexPendingTools(): void {\n this.pendingToolIndexes.clear();\n for (let i = 0; i < this.entries.length; i++) {\n const entry = this.entries[i];\n if (this.isToolEntry(entry) && entry.isPartial !== false) this.pendingToolIndexes.set(entry.toolCallId, i);\n }\n }\n private isAssistantEntry(entry: LiveChatEntry | undefined): entry is Extract<ChatMessageEntry, { kind: \"assistant\" }> {\n return isChatMessageEntry(entry) && entry.kind === \"assistant\";\n }\n private isToolEntry(entry: LiveChatEntry | undefined): entry is Extract<ChatMessageEntry, { kind: \"tool\" }> {\n return isChatMessageEntry(entry) && entry.kind === \"tool\";\n }\n}\nfunction isChatMessageEntry(entry: LiveChatEntry | undefined): entry is ChatMessageEntry {\n return entry !== undefined && \"kind\" in entry;\n}\nfunction isLegacyCompactionSummaryMessage(message: AgentMessage): boolean {\n return message.role === \"compaction\" + \"Summary\";\n}\nfunction isAgentMessageLike(message: unknown): message is AgentMessage & { stopReason?: unknown; errorMessage?: unknown } {\n return message !== null && typeof message === \"object\" && \"role\" in message;\n}\nfunction assistantContentHasRenderablePayload(content: unknown): boolean {\n if (typeof content === \"string\") return content.length > 0;\n if (!Array.isArray(content)) return false;\n return content.some((item) => {\n if (typeof item === \"string\") return item.length > 0;\n if (item == null || typeof item !== \"object\") return false;\n const obj = item as { type?: unknown; text?: unknown; thinking?: unknown };\n return (obj.type === \"text\" && typeof obj.text === \"string\" && obj.text.length > 0) ||\n (obj.type === \"thinking\" && typeof obj.thinking === \"string\" && obj.thinking.length > 0) ||\n obj.type === \"toolCall\";\n });\n}\nfunction minimalAssistantMessage(): AssistantMessage {\n return {\n role: \"assistant\",\n content: [],\n stopReason: \"stop\",\n } as unknown as AssistantMessage;\n}\nfunction toolResultFromUnknown(\n result: unknown,\n toolName: string,\n toolCallId: string,\n isError: boolean,\n): ToolResultMessage {\n if (result !== null && typeof result === \"object\" && \"content\" in result) {\n const candidate = result as { content?: unknown; details?: unknown };\n const content = Array.isArray(candidate.content) ? candidate.content : [];\n return {\n role: \"toolResult\",\n toolCallId,\n toolName,\n content: content as ToolResultMessage[\"content\"],\n details: candidate.details,\n isError,\n timestamp: Date.now(),\n };\n }\n return {\n role: \"toolResult\",\n toolCallId,\n toolName,\n content: typeof result === \"string\" ? [{ type: \"text\", text: result }] : [],\n isError,\n timestamp: Date.now(),\n };\n}\nexport function renderChatMessageEntry(\n entry: ChatMessageEntry,\n options: ChatMessageRenderOptions,\n): Component {\n const messageEntry = entry as ChatMessageEntry;\n const markdownTheme = options.markdownTheme ?? getMarkdownTheme();\n switch (messageEntry.kind) {\n case \"assistant\":\n return new AssistantMessageComponent(\n messageEntry.message,\n options.hideThinkingBlock ?? false,\n markdownTheme,\n options.hiddenThinkingLabel ?? \"Thinking...\",\n options.outputPad ?? 1,\n );\n case \"tool\": {\n const component = new ToolExecutionComponent(\n messageEntry.toolName,\n messageEntry.toolCallId,\n messageEntry.args,\n {\n showImages: options.showImages ?? true,\n imageWidthCells: options.imageWidthCells,\n },\n options.getToolDefinition?.(messageEntry.toolName),\n options.ui as TUI,\n options.cwd,\n );\n component.setExpanded(options.toolOutputExpanded ?? false);\n if (messageEntry.result) component.updateResult(messageEntry.result, messageEntry.isPartial ?? false);\n return component;\n }\n case \"bashExecution\": {\n const component = new BashExecutionComponent(\n messageEntry.message.command,\n options.ui as TUI,\n messageEntry.message.excludeFromContext,\n );\n if (messageEntry.message.output) component.appendOutput(messageEntry.message.output);\n if (messageEntry.isPartial !== true) {\n component.setComplete(\n messageEntry.message.exitCode,\n messageEntry.message.cancelled,\n messageEntry.message.truncated\n ? ({ truncated: true } as Parameters<BashExecutionComponent[\"setComplete\"]>[2])\n : undefined,\n messageEntry.message.fullOutputPath,\n );\n }\n return component;\n }\n case \"user\":\n return userMessageComponent(messageEntry.text, markdownTheme, options.toolOutputExpanded ?? false, options.outputPad ?? 1);\n case \"custom\": {\n if (isVerbatimCompactionMessage(messageEntry.message)) {\n return compactionBoundaryFromMessage(messageEntry.message, options.toolOutputExpanded ?? false);\n }\n const component = new CustomMessageComponent(messageEntry.message, options.getCustomMessageRenderer?.(messageEntry.message.customType), markdownTheme);\n component.setExpanded(options.toolOutputExpanded ?? false);\n return component;\n }\n case \"branchSummary\": {\n const component = new BranchSummaryMessageComponent(messageEntry.message, markdownTheme);\n component.setExpanded(options.toolOutputExpanded ?? false);\n return component;\n }\n case \"system\":\n return new Text(theme.fg(\"dim\", messageEntry.text), 1, 0);\n }\n}\nfunction userMessageComponent(text: string, markdownTheme: MarkdownTheme, expanded: boolean, outputPad = 1): Component {\n const skillBlock = parseSkillBlock(text);\n if (!skillBlock) return new UserMessageComponent(text, markdownTheme, outputPad);\n const container = new Container();\n const skillComponent = new SkillInvocationMessageComponent(skillBlock, markdownTheme);\n skillComponent.setExpanded(expanded);\n container.addChild(skillComponent);\n if (skillBlock.userMessage) {\n container.addChild(new UserMessageComponent(skillBlock.userMessage, markdownTheme, outputPad));\n }\n return container;\n}\nfunction getMessageText(message: Extract<AgentMessage, { role: \"user\" }>): string {\n return extractMessageText(message.content).trim();\n}\n"]}
1
+ {"version":3,"file":"chat-message-renderer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-message-renderer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-actions.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-actions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAYpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAOzE,wBAAsB,oBAAoB,CACxC,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,iBAAiB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,IAAI,GAAE,MAAM,GAAG,UAAmB,EAClC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA4Ef;AAED,wBAAsB,0BAA0B,CAC9C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,oBAAoB,CAAC,WAAW,SAAS,uBAAuB,EACpF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,+BAA+B,CACnD,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBzD;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAkBnD","sourcesContent":["import type { BashExecutionMessage } from \"../../../core/messages.ts\";\nimport { combineQueuedMessagesForEditor } from \"../chat-input-actions.ts\";\nimport type { ChatMessageEntry } from \"./chat-message-renderer.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport { setChatSessionEditorText } from \"./chat-session-host-editor.ts\";\nimport {\n decrementOptimisticUserSignature,\n incrementOptimisticUserSignature,\n isChatSessionBashRunning,\n isChatSessionStreaming,\n notifyChatSessionStatus,\n notifyChatSessionWarning,\n requiredChatSessionCommand,\n syncChatSessionAnimationTick,\n} from \"./chat-session-host-runtime.ts\";\nimport type { ChatSessionHostState } from \"./chat-session-host-state.ts\";\nimport {\n errorMessage,\n parseBashInput,\n userMessageSignature,\n} from \"./chat-session-host-utils.ts\";\n\nexport async function interruptChatSession<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): Promise<void> {\n try {\n restoreQueuedMessagesToEditor(state);\n state.sdkBusy = false;\n state.workingMessage = undefined;\n await state.commands.interrupt?.();\n } catch (err) {\n state.statusMessage = errorMessage(err);\n } finally {\n syncChatSessionAnimationTick(state);\n state.requestRender?.();\n }\n}\n\nexport async function submitChatSession<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n mode: \"auto\" | \"followUp\" = \"auto\",\n submittedText?: string,\n): Promise<void> {\n const text = (submittedText ?? state.inputBuffer).trim();\n if (!text) return;\n if (text.startsWith(\"/\") && state.commands.handleSlashCommand) {\n const handled = await state.commands.handleSlashCommand(text);\n if (handled) {\n setChatSessionEditorText(state, \"\");\n state.requestRender?.();\n return;\n }\n }\n if (state.compacting) {\n setChatSessionEditorText(state, \"\");\n state.compactionQueuedMessages = [...state.compactionQueuedMessages, text];\n notifyChatSessionStatus(state, \"Queued message until compaction completes\");\n return;\n }\n const bash = parseBashInput(text);\n if (bash?.command) {\n if (isChatSessionBashRunning(state)) {\n notifyChatSessionWarning(state, \"A bash command is already running. esc cancel first.\");\n setChatSessionEditorText(state, text);\n return;\n }\n setChatSessionEditorText(state, \"\");\n await runChatSessionBashCommand(state, bash.command, bash.excludeFromContext);\n return;\n }\n setChatSessionEditorText(state, \"\");\n const isPaused = state.isPaused?.() === true;\n const isStreaming = isChatSessionStreaming(state);\n const shouldAppendOptimisticUser = mode === \"auto\" && !isStreaming;\n const optimisticSignature = shouldAppendOptimisticUser\n ? userMessageSignature(text)\n : undefined;\n if (optimisticSignature !== undefined) {\n state.liveChat.appendUserText(text);\n state.bodyViewport.scrollToBottom();\n incrementOptimisticUserSignature(state, optimisticSignature);\n }\n state.requestRender?.();\n try {\n if (isPaused) {\n state.sdkBusy = true;\n state.statusMessage = \"resuming…\";\n syncChatSessionAnimationTick(state);\n state.requestRender?.();\n await requiredChatSessionCommand(state, \"resume\")(text);\n state.sdkBusy = false;\n state.statusMessage = \"\";\n syncChatSessionAnimationTick(state);\n return;\n }\n if (mode === \"followUp\" && isStreaming) {\n await queueChatSessionFollowUp(state, text);\n return;\n }\n if (isStreaming) {\n await queueChatSessionSteer(state, text);\n } else {\n state.sdkBusy = true;\n syncChatSessionAnimationTick(state);\n await state.commands.ensureAttached?.();\n await requiredChatSessionCommand(state, \"prompt\")(text);\n state.sdkBusy = false;\n syncChatSessionAnimationTick(state);\n }\n } catch (err) {\n if (optimisticSignature !== undefined) {\n decrementOptimisticUserSignature(state, optimisticSignature);\n }\n state.sdkBusy = false;\n state.statusMessage = errorMessage(err);\n syncChatSessionAnimationTick(state);\n state.requestRender?.();\n }\n}\n\nexport async function abortChatSessionCompaction<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): Promise<void> {\n try {\n await state.commands.abortCompaction?.();\n state.compacting = false;\n state.sdkBusy = false;\n notifyChatSessionStatus(state, \"Compaction cancelled\");\n } catch (err) {\n notifyChatSessionWarning(state, errorMessage(err));\n } finally {\n syncChatSessionAnimationTick(state);\n state.requestRender?.();\n }\n}\n\nexport async function abortChatSessionBash<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): Promise<void> {\n try {\n await state.commands.abortBash?.();\n state.localBashRunning = false;\n notifyChatSessionStatus(state, \"Bash command cancelled\");\n } catch (err) {\n notifyChatSessionWarning(state, errorMessage(err));\n } finally {\n state.requestRender?.();\n }\n}\n\nexport async function flushChatSessionCompactionQueue<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): Promise<void> {\n const queued = [...state.compactionQueuedMessages];\n state.compactionQueuedMessages = [];\n if (queued.length === 0) return;\n let nextIndex = 0;\n try {\n const first = queued[0];\n if (first !== undefined) {\n await requiredChatSessionCommand(state, \"prompt\")(first);\n nextIndex = 1;\n }\n for (; nextIndex < queued.length; nextIndex++) {\n await queueChatSessionFollowUp(state, queued[nextIndex]!);\n }\n } catch (err) {\n state.compactionQueuedMessages = [\n ...queued.slice(nextIndex),\n ...state.compactionQueuedMessages,\n ];\n notifyChatSessionWarning(state, errorMessage(err));\n state.requestRender?.();\n }\n}\n\nexport function restoreQueuedMessagesToEditor<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): boolean {\n const queuedMessages = [\n ...state.pendingSteeringMessages,\n ...state.pendingFollowUpMessages,\n ...state.compactionQueuedMessages,\n ];\n if (queuedMessages.length === 0) {\n notifyChatSessionStatus(state, \"No queued messages to restore\");\n return false;\n }\n const restoredText = combineQueuedMessagesForEditor(queuedMessages, state.inputBuffer);\n state.pendingSteeringMessages = [];\n state.pendingFollowUpMessages = [];\n state.compactionQueuedMessages = [];\n setChatSessionEditorText(state, restoredText);\n state.getAgentSession?.()?.clearQueue();\n state.requestRender?.();\n return true;\n}\n\nasync function runChatSessionBashCommand<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n command: string,\n excludeFromContext: boolean,\n): Promise<void> {\n const runBash = state.commands.runBash;\n if (!runBash) {\n notifyChatSessionWarning(state, \"no bash command configured for this chat session\");\n return;\n }\n const bashMessage: BashExecutionMessage = {\n role: \"bashExecution\",\n command,\n output: \"\",\n exitCode: undefined,\n cancelled: false,\n truncated: false,\n timestamp: Date.now(),\n ...(excludeFromContext ? { excludeFromContext: true } : {}),\n };\n const bashEntry: ChatMessageEntry = {\n role: \"tool\",\n kind: \"bashExecution\",\n message: bashMessage,\n isPartial: true,\n };\n state.transcript.push(bashEntry);\n state.localBashRunning = true;\n state.bodyViewport.scrollToBottom();\n state.requestRender?.();\n try {\n const result = await runBash({\n command,\n excludeFromContext,\n onChunk: (chunk) => {\n bashMessage.output += chunk;\n state.requestRender?.();\n },\n });\n bashMessage.output = result.output;\n bashMessage.exitCode = result.exitCode;\n bashMessage.cancelled = result.cancelled;\n bashMessage.truncated = result.truncated;\n if (result.fullOutputPath !== undefined) {\n bashMessage.fullOutputPath = result.fullOutputPath;\n }\n } catch (err) {\n bashMessage.output = errorMessage(err);\n bashMessage.exitCode = undefined;\n bashMessage.cancelled = false;\n bashMessage.truncated = false;\n } finally {\n bashEntry.isPartial = false;\n state.localBashRunning = false;\n state.requestRender?.();\n }\n}\n\nasync function queueChatSessionSteer<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n text: string,\n): Promise<void> {\n const agentSession = state.getAgentSession?.();\n if (agentSession?.isStreaming) {\n await agentSession.prompt(text, { streamingBehavior: \"steer\" });\n return;\n }\n await requiredChatSessionCommand(state, \"steer\")(text);\n}\n\nasync function queueChatSessionFollowUp<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n text: string,\n): Promise<void> {\n const agentSession = state.getAgentSession?.();\n if (agentSession?.isStreaming) {\n await agentSession.prompt(text, { streamingBehavior: \"followUp\" });\n return;\n }\n await requiredChatSessionCommand(state, \"followUp\")(text);\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-actions.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-actions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAYpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAOzE,wBAAsB,oBAAoB,CACxC,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,iBAAiB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,IAAI,GAAE,MAAM,GAAG,UAAmB,EAClC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA4Ef;AAED,wBAAsB,0BAA0B,CAC9C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,oBAAoB,CAAC,WAAW,SAAS,uBAAuB,EACpF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,+BAA+B,CACnD,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBzD;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,OAAO,CAkBnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-editor.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAEhB,KAAK,GAAG,EACT,MAAM,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AASxE,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,6BAA6B,EAAE,MAAM,OAAO,CAAC;IAC7C,eAAe,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CACrC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,GAAG,EAAE,GAAG,GAAG,SAAS,EACpB,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,EAChE,SAAS,EAAE,0BAA0B,GACpC,eAAe,GAAG,SAAS,CAoE7B;AAED,wBAAgB,sBAAsB,CACpC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,0BAA0B,GACpC,OAAO,CA8CT;AAED,wBAAgB,wBAAwB,CACtC,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,IAAI,CAKN;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACpC,IAAI,CAKN;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAGhF","sourcesContent":["import {\n type EditorComponent,\n type EditorTheme,\n type Focusable,\n type TUI,\n} from \"@earendil-works/pi-tui\";\nimport {\n openExternalEditorForText,\n pasteClipboardImageToEditor,\n} from \"../chat-input-actions.ts\";\nimport { CustomEditor } from \"./custom-editor.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport type { ChatSessionHostState } from \"./chat-session-host-state.ts\";\nimport type { ChatSessionHostOpts } from \"./chat-session-host-types.ts\";\nimport {\n isChatSessionBashRunning,\n isChatSessionStreaming,\n notifyChatSessionStatus,\n notifyChatSessionWarning,\n} from \"./chat-session-host-runtime.ts\";\nimport { matchesKey } from \"./chat-session-host-utils.ts\";\n\nexport interface ChatSessionEditorCallbacks {\n submit: (mode: \"auto\" | \"followUp\", submittedText?: string) => void | Promise<void>;\n restoreQueuedMessagesToEditor: () => boolean;\n abortCompaction: () => void | Promise<void>;\n interrupt: () => void | Promise<void>;\n abortBash: () => void | Promise<void>;\n}\n\nexport function createChatSessionEditor<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n tui: TUI | undefined,\n keybindings: unknown,\n editorTheme: EditorTheme,\n editorFactory: ChatSessionHostOpts<TExtraEntry>[\"editorFactory\"],\n callbacks: ChatSessionEditorCallbacks,\n): EditorComponent | undefined {\n if (!tui || !keybindings) return undefined;\n const editor = createInheritedEditor(tui, editorTheme, keybindings, editorFactory) ??\n new CustomEditor(\n tui,\n editorTheme,\n keybindings as ConstructorParameters<typeof CustomEditor>[2],\n { paddingX: 0, autocompleteMaxVisible: 5 },\n );\n editor.onChange = (text) => {\n state.inputBuffer = text;\n state.isBashMode = text.trimStart().startsWith(\"!\");\n };\n editor.onSubmit = (text) => {\n void callbacks.submit(\"auto\", text);\n };\n const actionEditor = editor as EditorComponent & {\n onAction?: (action: string, handler: () => void) => void;\n onEscape?: () => void;\n onPasteImage?: () => void;\n };\n actionEditor.onAction?.(\"app.message.followUp\", () => {\n void callbacks.submit(\"followUp\");\n });\n actionEditor.onAction?.(\"app.message.dequeue\", () => {\n callbacks.restoreQueuedMessagesToEditor();\n });\n actionEditor.onAction?.(\"app.editor.external\", () => {\n openChatSessionExternalEditor(state);\n });\n if (state.actions) {\n for (const [action, handler] of Object.entries(state.actions)) {\n actionEditor.onAction?.(action, () => {\n void handler();\n });\n }\n }\n const previousPasteImage = actionEditor.onPasteImage;\n actionEditor.onPasteImage = () => {\n previousPasteImage?.();\n void pasteClipboardImageToEditor(\n chatSessionEditorAccess(state),\n () => state.requestRender?.(),\n { showWarning: (message) => notifyChatSessionWarning(state, message) },\n );\n };\n const previousEscape = actionEditor.onEscape;\n actionEditor.onEscape = () => {\n if (state.compacting) {\n void callbacks.abortCompaction();\n return;\n }\n if (isChatSessionStreaming(state)) {\n void callbacks.interrupt();\n return;\n }\n if (isChatSessionBashRunning(state)) {\n void callbacks.abortBash();\n return;\n }\n if (state.isBashMode) {\n setChatSessionEditorText(state, \"\");\n notifyChatSessionStatus(state, \"Bash mode cleared\");\n return;\n }\n previousEscape?.();\n };\n return editor;\n}\n\nexport function handleChatSessionInput<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n data: string,\n callbacks: ChatSessionEditorCallbacks,\n): boolean {\n if (state.bodyViewport.handleInput(data)) return true;\n if (matchesKey(data, \"alt+up\")) {\n callbacks.restoreQueuedMessagesToEditor();\n return true;\n }\n if (matchesKey(data, \"ctrl+f\")) {\n void callbacks.submit(\"followUp\");\n return true;\n }\n if (matchesKey(data, \"escape\")) {\n if (state.compacting) {\n void callbacks.abortCompaction();\n return true;\n }\n if (isChatSessionStreaming(state)) {\n void callbacks.interrupt();\n return true;\n }\n if (isChatSessionBashRunning(state)) {\n void callbacks.abortBash();\n return true;\n }\n if (state.isBashMode) {\n setChatSessionEditorText(state, \"\");\n notifyChatSessionStatus(state, \"Bash mode cleared\");\n return true;\n }\n }\n if (state.editor) {\n state.editor.handleInput(data);\n return true;\n }\n if (matchesKey(data, \"enter\")) {\n void callbacks.submit(\"auto\");\n return true;\n }\n if (matchesKey(data, \"backspace\")) {\n setChatSessionEditorText(state, state.inputBuffer.slice(0, -1));\n return true;\n }\n if (data.length === 1 && data >= \" \" && data <= \"~\") {\n setChatSessionEditorText(state, `${state.inputBuffer}${data}`);\n return true;\n }\n return false;\n}\n\nexport function setChatSessionEditorText<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>, text: string): void {\n state.inputBuffer = text;\n state.isBashMode = text.trimStart().startsWith(\"!\");\n state.editor?.setText(text);\n}\n\nexport function setEditorPlaceholder(\n editor: EditorComponent,\n placeholder: string | undefined,\n): void {\n const candidate = editor as EditorComponent & {\n setPlaceholder?: (value: string | undefined) => void;\n };\n candidate.setPlaceholder?.(placeholder);\n}\n\nexport function setEditorBorderColor(\n editor: EditorComponent,\n borderColor: (text: string) => string,\n): void {\n const candidate = editor as EditorComponent & {\n borderColor?: (text: string) => string;\n };\n if (candidate.borderColor !== undefined) candidate.borderColor = borderColor;\n}\n\nexport function setEditorFocused(editor: EditorComponent, focused: boolean): void {\n const candidate = editor as EditorComponent & Partial<Focusable>;\n if (\"focused\" in candidate) candidate.focused = focused;\n}\n\nfunction createInheritedEditor<TExtraEntry extends ChatTranscriptEntryLike>(\n tui: TUI,\n editorTheme: EditorTheme,\n keybindings: unknown,\n editorFactory: ChatSessionHostOpts<TExtraEntry>[\"editorFactory\"],\n): EditorComponent | undefined {\n if (!editorFactory) return undefined;\n try {\n return editorFactory(tui, editorTheme, keybindings);\n } catch {\n return undefined;\n }\n}\n\nfunction chatSessionEditorAccess<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): {\n insertTextAtCursor: (text: string) => void;\n getText: () => string;\n setText: (text: string) => void;\n} {\n return {\n insertTextAtCursor: (text: string) => {\n if (state.editor?.insertTextAtCursor) {\n state.editor.insertTextAtCursor(text);\n return;\n }\n setChatSessionEditorText(state, `${state.inputBuffer}${text}`);\n },\n getText: () => state.inputBuffer,\n setText: (text: string) => setChatSessionEditorText(state, text),\n };\n}\n\nfunction openChatSessionExternalEditor<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): void {\n if (!state.editor) return;\n const host = state.tui;\n if (!host) return;\n const currentText = state.editor.getExpandedText?.() ?? state.editor.getText();\n const updated = openExternalEditorForText(currentText, host, {\n showWarning: (message) => notifyChatSessionWarning(state, message),\n });\n if (updated !== undefined) setChatSessionEditorText(state, updated);\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-editor.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAEhB,KAAK,GAAG,EACT,MAAM,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AASxE,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,6BAA6B,EAAE,MAAM,OAAO,CAAC;IAC7C,eAAe,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CACrC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,GAAG,EAAE,GAAG,GAAG,SAAS,EACpB,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,EAChE,SAAS,EAAE,0BAA0B,GACpC,eAAe,GAAG,SAAS,CAoE7B;AAED,wBAAgB,sBAAsB,CACpC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,0BAA0B,GACpC,OAAO,CA8CT;AAED,wBAAgB,wBAAwB,CACtC,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,IAAI,CAKN;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACpC,IAAI,CAKN;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAGhF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-events.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAOxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAQpE,wBAAgB,0BAA0B,CACxC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAqIT","sourcesContent":["import type { AgentSessionEvent } from \"../../../core/agent-session.ts\";\nimport { pickWhimsicalWorkingMessage } from \"../whimsical-messages.ts\";\nimport { flushChatSessionCompactionQueue } from \"./chat-session-host-actions.ts\";\nimport {\n afterChatSessionEvent,\n decrementOptimisticUserSignature,\n} from \"./chat-session-host-runtime.ts\";\nimport type { ChatSessionHostState } from \"./chat-session-host-state.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport {\n extractMessageText,\n isMessageLike,\n isUserMessageLike,\n userMessageSignature,\n} from \"./chat-session-host-utils.ts\";\n\nexport function applyChatSessionAgentEvent<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n event: AgentSessionEvent,\n): boolean {\n const type = String((event as { type?: unknown }).type ?? \"\");\n if (type === \"message_start\") {\n const message = (event as { message?: unknown }).message;\n if (isUserMessageLike(message)) {\n const signature = userMessageSignature(extractMessageText(message.content));\n const count = state.optimisticUserSignatureCounts.get(signature) ?? 0;\n if (count > 0) {\n decrementOptimisticUserSignature(state, signature);\n return false;\n }\n }\n }\n if (isSharedLiveChatEvent(type)) {\n const changed = state.liveChat.applyEvent(event);\n const toolCallEvent = assistantToolCallEvent(event);\n const changedByToolCall = toolCallEvent !== undefined\n ? state.liveChat.applyEvent(toolCallEvent)\n : false;\n afterChatSessionEvent(state, changed || changedByToolCall);\n return changed || changedByToolCall;\n }\n let changed = false;\n switch (type) {\n case \"agent_start\":\n state.sdkBusy = true;\n state.liveChat.clearPendingTools();\n state.statusMessage = \"\";\n changed = true;\n break;\n case \"agent_end\":\n state.sdkBusy = false;\n state.workingMessage = undefined;\n state.liveChat.clearPendingTools();\n state.statusMessage = \"\";\n changed = true;\n break;\n case \"turn_start\":\n state.workingMessage = pickWhimsicalWorkingMessage();\n changed = true;\n break;\n case \"turn_end\":\n state.workingMessage = undefined;\n changed = true;\n break;\n case \"queue_update\": {\n const queue = event as { steering?: unknown; followUp?: unknown };\n state.pendingSteeringMessages = Array.isArray(queue.steering)\n ? queue.steering.filter((item): item is string => typeof item === \"string\")\n : [];\n state.pendingFollowUpMessages = Array.isArray(queue.followUp)\n ? queue.followUp.filter((item): item is string => typeof item === \"string\")\n : [];\n changed = true;\n break;\n }\n case \"tool_call\":\n case \"tool_use\":\n changed = state.liveChat.applyEvent(legacyToolStartEvent(event));\n break;\n case \"tool_result\":\n changed = state.liveChat.applyEvent(legacyToolResultEvent(event));\n break;\n case \"thinking_delta\":\n case \"thinking\":\n changed = state.liveChat.applyEvent(legacyThinkingEvent(event));\n break;\n case \"compaction_start\":\n state.compacting = true;\n state.sdkBusy = true;\n state.statusMessage = \"compacting context…\";\n changed = true;\n break;\n case \"compaction_end\": {\n const compaction = event as Extract<AgentSessionEvent, { type: \"compaction_end\" }>;\n state.compacting = false;\n state.sdkBusy = false;\n state.statusMessage = compaction.errorMessage ?? \"\";\n if (!compaction.aborted && !compaction.errorMessage && compaction.result) {\n const compactedMessages = state.getAgentSession?.()?.messages;\n if (compactedMessages) {\n state.liveChat.replaceMessages(compactedMessages, state.extraEntries);\n }\n }\n if (!compaction.aborted && !compaction.errorMessage && state.compactionQueuedMessages.length > 0) {\n void flushChatSessionCompactionQueue(state);\n }\n changed = true;\n break;\n }\n case \"auto_retry_start\":\n state.sdkBusy = true;\n state.statusMessage = \"retrying…\";\n changed = true;\n break;\n case \"model_fallback_start\":\n state.sdkBusy = true;\n state.statusMessage = \"switching model…\";\n changed = true;\n break;\n case \"model_fallback_end\": {\n const fallback = event as Extract<AgentSessionEvent, { type: \"model_fallback_end\" }>;\n state.statusMessage = fallback.success ? \"\" : (fallback.finalError ?? \"model fallback failed\");\n if (!fallback.success) {\n state.sdkBusy = false;\n state.workingMessage = undefined;\n }\n changed = true;\n break;\n }\n case \"auto_retry_end\": {\n const retry = event as Extract<AgentSessionEvent, { type: \"auto_retry_end\" }>;\n state.statusMessage = \"\";\n if (!retry.success) {\n state.sdkBusy = false;\n state.workingMessage = undefined;\n }\n changed = true;\n break;\n }\n case \"agent_continue_error\": {\n const continueError = event as Extract<AgentSessionEvent, { type: \"agent_continue_error\" }>;\n state.sdkBusy = false;\n state.statusMessage = continueError.errorMessage;\n state.workingMessage = undefined;\n changed = true;\n break;\n }\n default:\n changed = false;\n }\n afterChatSessionEvent(state, changed);\n return changed;\n}\n\nfunction isSharedLiveChatEvent(type: string): boolean {\n return (\n type === \"message_start\" ||\n type === \"message_update\" ||\n type === \"message_end\" ||\n type === \"tool_execution_start\" ||\n type === \"tool_execution_update\" ||\n type === \"tool_execution_end\"\n );\n}\n\nfunction assistantToolCallEvent(event: AgentSessionEvent): {\n type: \"tool_execution_start\";\n toolCallId: string;\n toolName: string;\n args: unknown;\n} | undefined {\n const assistantEvent = (event as {\n assistantMessageEvent?: {\n type?: unknown;\n contentIndex?: unknown;\n partial?: unknown;\n toolCall?: unknown;\n };\n }).assistantMessageEvent;\n const streamType = String(assistantEvent?.type ?? \"\");\n if (!streamType.startsWith(\"toolcall_\")) return undefined;\n const explicit = toolCallPayload(assistantEvent?.toolCall);\n if (explicit) return explicit;\n const contentIndex = typeof assistantEvent?.contentIndex === \"number\" ? assistantEvent.contentIndex : undefined;\n if (contentIndex === undefined) return undefined;\n const partial = assistantEvent?.partial;\n if (!isMessageLike(partial) || partial.role !== \"assistant\") return undefined;\n const content = partial.content;\n if (!Array.isArray(content)) return undefined;\n return toolCallPayload(content[contentIndex]);\n}\n\nfunction toolCallPayload(value: unknown): {\n type: \"tool_execution_start\";\n toolCallId: string;\n toolName: string;\n args: unknown;\n} | undefined {\n if (value === null || typeof value !== \"object\") return undefined;\n const candidate = value as { type?: unknown; id?: unknown; name?: unknown; arguments?: unknown };\n if (candidate.type !== \"toolCall\") return undefined;\n if (typeof candidate.id !== \"string\" || typeof candidate.name !== \"string\") return undefined;\n return {\n type: \"tool_execution_start\",\n toolCallId: candidate.id,\n toolName: candidate.name,\n args: candidate.arguments ?? {},\n };\n}\n\nfunction legacyToolStartEvent(event: AgentSessionEvent): {\n type: \"tool_execution_start\";\n toolCallId: string;\n toolName: string;\n args: unknown;\n} {\n const payload = event as { toolCallId?: unknown; name?: unknown; input?: unknown; args?: unknown };\n const toolName = typeof payload.name === \"string\" ? payload.name : \"tool\";\n const toolCallId =\n typeof payload.toolCallId === \"string\" ? payload.toolCallId : `live-${toolName}`;\n return {\n type: \"tool_execution_start\",\n toolCallId,\n toolName,\n args: payload.input ?? payload.args ?? {},\n };\n}\n\nfunction legacyToolResultEvent(event: AgentSessionEvent): {\n type: \"tool_execution_end\";\n toolCallId: string;\n toolName: string;\n result: unknown;\n isError: boolean;\n} {\n const payload = event as {\n toolCallId?: unknown;\n name?: unknown;\n output?: unknown;\n isError?: unknown;\n };\n const toolName = typeof payload.name === \"string\" ? payload.name : \"tool\";\n const toolCallId =\n typeof payload.toolCallId === \"string\" ? payload.toolCallId : `live-${toolName}`;\n const output = payload.output;\n return {\n type: \"tool_execution_end\",\n toolCallId,\n toolName,\n result:\n output !== null && typeof output === \"object\" && \"content\" in output\n ? output\n : { content: typeof output === \"string\" ? [{ type: \"text\", text: output }] : [] },\n isError: payload.isError === true,\n };\n}\n\nfunction legacyThinkingEvent(event: AgentSessionEvent): {\n type: \"message_update\";\n assistantMessageEvent: { type: \"thinking_delta\"; delta: string };\n message: { role: \"assistant\"; content: [] };\n} {\n const delta = String(\n (event as { delta?: unknown }).delta ??\n (event as { text?: unknown }).text ??\n \"\",\n );\n return {\n type: \"message_update\",\n assistantMessageEvent: { type: \"thinking_delta\", delta },\n message: { role: \"assistant\", content: [] },\n };\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-events.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAOxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAQpE,wBAAgB,0BAA0B,CACxC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAqIT"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-rendering.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-rendering.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAMf,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAgBzE,wBAAgB,qBAAqB,CACnC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAaV;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBnE;AAED,wBAAgB,8BAA8B,CAC5C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASnE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,SAAS,uBAAuB,EAChF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CAIV;AAED,wBAAgB,uBAAuB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,GACf,MAAM,EAAE,CAwBV;AAED,wBAAgB,uBAAuB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CAMV;AAED,wBAAgB,sBAAsB,CACpC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,SAAS,CAcX;AAED,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,uBAAuB,EAC5E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,CAQR","sourcesContent":["import {\n type Component,\n type TUI,\n Spacer,\n Text,\n truncateToWidth,\n visibleWidth,\n} from \"@earendil-works/pi-tui\";\nimport { UsageMeterComponent, FooterComponent } from \"./footer.ts\";\nimport {\n renderChatMessageEntry,\n type ChatMessageEntry,\n type ChatMessageRenderOptions,\n} from \"./chat-message-renderer.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport type { ChatSessionHostState } from \"./chat-session-host-state.ts\";\nimport type { ChatSessionHostEntry } from \"./chat-session-host-types.ts\";\nimport {\n setEditorBorderColor,\n setEditorFocused,\n setEditorPlaceholder,\n} from \"./chat-session-host-editor.ts\";\nimport { isChatSessionStreaming } from \"./chat-session-host-runtime.ts\";\nimport {\n cacheKey,\n isChatMessageEntry,\n spinnerFrame,\n stripAnsi,\n tailStreamingText,\n} from \"./chat-session-host-utils.ts\";\nimport { WorkingStatusComponent } from \"./working-status.ts\";\n\nexport function renderChatSessionBody<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n width: number,\n budget: number,\n): string[] {\n const components: Component[] = [];\n state.transcriptRenderSettingsKey = chatRenderSettingsCacheKey(state);\n if (state.transcript.length > 0) {\n components.push(state.transcriptComponent);\n }\n if (state.statusMessage) {\n components.push(new Spacer(1));\n components.push(new Text(state.style.dim(state.statusMessage), 2, 0));\n }\n state.bodyViewport.setVisibleRows(budget);\n state.bodyViewport.setComponents(components);\n return state.bodyViewport.render(width);\n}\n\nexport function renderChatSessionPendingMessages<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>, width: number): string[] {\n if (\n state.pendingSteeringMessages.length === 0 &&\n state.pendingFollowUpMessages.length === 0 &&\n state.compactionQueuedMessages.length === 0\n ) {\n return [];\n }\n const lines = [state.style.blank(width)];\n for (const message of state.pendingSteeringMessages) {\n lines.push(...pendingMessageLine(state, width, \"Steering\", message));\n }\n for (const message of state.pendingFollowUpMessages) {\n lines.push(...pendingMessageLine(state, width, \"Follow-up\", message));\n }\n for (const message of state.compactionQueuedMessages) {\n lines.push(...pendingMessageLine(state, width, \"Queued\", message));\n }\n const hint = state.getActionKeyDisplay?.(\"app.message.dequeue\") ?? \"alt+up\";\n lines.push(...new Text(state.style.dim(`↳ ${hint} to edit all queued messages`), 1, 0).render(width));\n return lines;\n}\n\nexport function renderChatSessionWorkingStatus<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>, width: number): string[] {\n if (!isChatSessionStreaming(state)) return [];\n const message = state.workingMessage ?? \"Working...\";\n return new WorkingStatusComponent({\n spinner: spinnerFrame(),\n message,\n spinnerColor: (text) => state.style.accentBold(text),\n messageColor: (text) => state.style.textMuted(text),\n }).render(width);\n}\n\nexport function renderChatSessionUsage<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n width: number,\n): string[] {\n const agentSession = state.getAgentSession?.();\n if (!agentSession) return [];\n return new UsageMeterComponent(agentSession).render(width);\n}\n\nexport function renderChatSessionEditor<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n width: number,\n focused: boolean,\n): string[] {\n const disabled = state.isDisabled?.() === true;\n const agentSession = state.getAgentSession?.();\n const ruleHex = state.style.editorRuleColor(disabled, agentSession, {\n isBashMode: state.isBashMode,\n });\n if (!disabled && state.editor) {\n setEditorFocused(state.editor, focused);\n setEditorPlaceholder(state.editor, undefined);\n setEditorBorderColor(state.editor, (text) => state.style.rule(ruleHex, text));\n return state.editor.render(width);\n }\n if (state.editor) setEditorFocused(state.editor, false);\n const rule = state.style.rule(ruleHex, \"─\".repeat(width));\n const available = Math.max(1, width - 3);\n const value = state.inputBuffer\n ? state.style.text(truncateToWidth(state.inputBuffer, available)) + state.style.cursor()\n : disabled\n ? \"\"\n : state.style.cursor();\n const left = state.style.accentBold(\"❯\") + \" \" + value;\n const gap = Math.max(0, width - visibleWidth(stripAnsi(left)));\n const body = left + \" \".repeat(gap);\n return [rule, body, rule];\n}\n\nexport function renderChatSessionFooter<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n width: number,\n): string[] {\n const agentSession = state.getAgentSession?.();\n if (agentSession && state.footerData) {\n return new FooterComponent(agentSession, state.footerData).render(width);\n }\n return [];\n}\n\nexport function renderChatSessionEntry<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n entry: ChatSessionHostEntry<TExtraEntry>,\n): Component {\n if (state.extraEntries.includes(entry as TExtraEntry)) {\n return state.renderExtraEntry?.(entry as TExtraEntry) ?? new Text(\"\", 0, 0);\n }\n if (isChatMessageEntry(entry)) {\n return renderChatMessageEntry(\n streamingWindowedEntry(state, entry),\n chatMessageRenderOptions(state),\n );\n }\n if (!state.renderExtraEntry) {\n return new Text(\"\", 0, 0);\n }\n return state.renderExtraEntry(entry);\n}\n\nexport function transcriptCacheKey<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n entry: ChatSessionHostEntry<TExtraEntry>,\n index: number,\n): string {\n return cacheKey([\n state.transcriptRenderSettingsKey,\n index,\n entry.role,\n renderIdentityKey(state, entry),\n entryContentCacheKey(state, entry),\n ]);\n}\n\nfunction streamingWindowedEntry<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n entry: ChatMessageEntry,\n): ChatMessageEntry {\n if (!isChatSessionStreaming(state) || state.bodyViewport.getScrollFromBottom() !== 0) {\n return entry;\n }\n if (entry.kind !== \"assistant\") return entry;\n const content = entry.message.content.map((item) => {\n if (item.type === \"text\") return { ...item, text: tailStreamingText(item.text) };\n if (item.type === \"thinking\") return { ...item, thinking: tailStreamingText(item.thinking) };\n return item;\n });\n return { ...entry, message: { ...entry.message, content } };\n}\n\nfunction chatMessageRenderOptions<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): ChatMessageRenderOptions {\n const inherited = state.getChatRenderSettings?.();\n return {\n ...inherited,\n ui: toolTui(state),\n cwd: state.getCwd?.() ?? state.getAgentSession?.()?.sessionManager.getCwd() ?? process.cwd(),\n markdownTheme: inherited?.markdownTheme ?? state.getMarkdownTheme?.(),\n showImages: inherited?.showImages ?? true,\n };\n}\n\nfunction toolTui<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): Pick<TUI, \"requestRender\"> {\n return { requestRender: () => state.requestRender?.() };\n}\n\nfunction chatRenderSettingsCacheKey<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): string {\n const inherited = state.getChatRenderSettings?.();\n return cacheKey([\n \"settings\",\n inherited?.hideThinkingBlock === true,\n inherited?.hiddenThinkingLabel ?? \"\",\n inherited?.toolOutputExpanded === true,\n inherited?.showImages !== false,\n inherited?.imageWidthCells ?? null,\n inherited?.outputPad ?? null,\n state.getCwd?.() ?? state.getAgentSession?.()?.sessionManager.getCwd() ?? process.cwd(),\n state.bodyViewport.getScrollFromBottom() === 0,\n isChatSessionStreaming(state),\n ]);\n}\n\nfunction entryContentCacheKey<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n entry: ChatSessionHostEntry<TExtraEntry>,\n): string {\n if (!isChatMessageEntry(entry)) return cacheKey([\"extra\"]);\n switch (entry.kind) {\n case \"assistant\":\n return cacheKey([\"assistant\", renderIdentityKey(state, entry.message)]);\n case \"tool\":\n return cacheKey([\"tool\", entry.toolCallId, entry.toolName, entry.isPartial === true, entry.result === undefined ? null : renderIdentityKey(state, entry.result)]);\n case \"bashExecution\":\n return cacheKey([\"bashExecution\", entry.isPartial === true, entry.message.command, entry.message.output, entry.message.exitCode ?? null, entry.message.cancelled, entry.message.truncated, entry.message.fullOutputPath ?? null]);\n case \"user\":\n return cacheKey([\"user\", entry.text]);\n case \"custom\":\n return cacheKey([\"custom\", renderIdentityKey(state, entry.message)]);\n case \"branchSummary\":\n return cacheKey([\"branchSummary\", renderIdentityKey(state, entry.message)]);\n case \"system\":\n return cacheKey([\"system\", entry.text]);\n }\n}\n\nfunction renderIdentityKey<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n value: object,\n): string {\n const existing = state.renderIdentityIds.get(value);\n if (existing !== undefined) return String(existing);\n const id = state.nextRenderIdentityId;\n state.nextRenderIdentityId += 1;\n state.renderIdentityIds.set(value, id);\n return String(id);\n}\n\nfunction pendingMessageLine<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n width: number,\n label: \"Steering\" | \"Follow-up\" | \"Queued\",\n message: string,\n): string[] {\n const text = `${label}: ${message}`;\n return new Text(\n state.style.dim(truncateToWidth(text, Math.max(1, width - 2))),\n 1,\n 0,\n ).render(width);\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-rendering.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-rendering.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAMf,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAgBzE,wBAAgB,qBAAqB,CACnC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAaV;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBnE;AAED,wBAAgB,8BAA8B,CAC5C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASnE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,SAAS,uBAAuB,EAChF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CAIV;AAED,wBAAgB,uBAAuB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,GACf,MAAM,EAAE,CAwBV;AAED,wBAAgB,uBAAuB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CAMV;AAED,wBAAgB,sBAAsB,CACpC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,SAAS,CAcX;AAED,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,uBAAuB,EAC5E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,CAQR"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-runtime.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAOzE,wBAAgB,sBAAsB,CAAC,WAAW,SAAS,uBAAuB,EAChF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,OAAO,CAET;AAED,wBAAgB,wBAAwB,CAAC,WAAW,SAAS,uBAAuB,EAClF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,OAAO,CAET;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,SAAS,EAAE,MAAM,GAChB,IAAI,CAKN;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,SAAS,EAAE,MAAM,GAChB,IAAI,CAIN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,IAAI,CAehD;AAED,wBAAgB,4CAA4C,CAC1D,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,IAAI,CAShD;AAED,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,uBAAuB,EAC5E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,IAAI,CAWN;AAED,wBAAgB,wBAAwB,CAAC,WAAW,SAAS,uBAAuB,EAClF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,IAAI,CAIN;AAED,wBAAgB,uBAAuB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CACxC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAC/C,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAuBlC;AAED,wBAAgB,qBAAqB,CAAC,WAAW,SAAS,uBAAuB,EAC/E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,OAAO,EAAE,OAAO,GACf,IAAI,CAIN","sourcesContent":["import type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport type { ChatSessionHostState } from \"./chat-session-host-state.ts\";\nimport { finalizeTerminalWorkflowToolEntries } from \"./chat-session-host-terminal-cleanup.ts\";\nimport {\n ANIMATION_FRAME_MS,\n STREAMING_RENDER_THROTTLE_MS,\n} from \"./chat-session-host-utils.ts\";\n\nexport function isChatSessionStreaming<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): boolean {\n return state.sdkBusy || state.isStreamingOverride?.() === true;\n}\n\nexport function isChatSessionBashRunning<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): boolean {\n return state.localBashRunning || state.isBashRunningOverride?.() === true;\n}\n\nexport function incrementOptimisticUserSignature<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n signature: string,\n): void {\n state.optimisticUserSignatureCounts.set(\n signature,\n (state.optimisticUserSignatureCounts.get(signature) ?? 0) + 1,\n );\n}\n\nexport function decrementOptimisticUserSignature<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n signature: string,\n): void {\n const count = state.optimisticUserSignatureCounts.get(signature) ?? 0;\n if (count <= 1) state.optimisticUserSignatureCounts.delete(signature);\n else state.optimisticUserSignatureCounts.set(signature, count - 1);\n}\n\nexport function syncChatSessionAnimationTick<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): void {\n const shouldAnimate =\n isChatSessionStreaming(state) ||\n (state.sdkBusy && state.liveChat.pendingToolIds().length > 0);\n if (shouldAnimate && !state.animationTimer) {\n state.animationTimer = setInterval(() => {\n state.requestRender?.();\n }, ANIMATION_FRAME_MS);\n state.animationTimer.unref?.();\n return;\n }\n if (!shouldAnimate && state.animationTimer) {\n clearInterval(state.animationTimer);\n state.animationTimer = undefined;\n }\n}\n\nexport function clearChatSessionBusyForTerminalWorkflowStage<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): void {\n state.sdkBusy = false;\n state.workingMessage = undefined;\n if (finalizeTerminalWorkflowToolEntries(state.transcript)) {\n state.transcriptComponent.invalidate();\n }\n state.liveChat.clearPendingTools();\n state.statusMessage = \"\";\n syncChatSessionAnimationTick(state);\n}\n\nexport function disposeChatSession<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n): void {\n if (state.animationTimer) {\n clearInterval(state.animationTimer);\n state.animationTimer = undefined;\n }\n if (state.renderThrottleTimer) {\n clearTimeout(state.renderThrottleTimer);\n state.renderThrottleTimer = undefined;\n }\n state.transcriptComponent.invalidate();\n state.editor = undefined;\n}\n\nexport function notifyChatSessionWarning<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n message: string,\n): void {\n state.statusMessage = message;\n state.showWarning?.(message);\n state.requestRender?.();\n}\n\nexport function notifyChatSessionStatus<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n message: string,\n): void {\n state.statusMessage = message;\n state.showStatus?.(message);\n state.requestRender?.();\n}\n\nexport function requiredChatSessionCommand<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(\n state: ChatSessionHostState<TExtraEntry>,\n name: \"prompt\" | \"steer\" | \"followUp\" | \"resume\",\n): (text?: string) => Promise<void> {\n switch (name) {\n case \"prompt\":\n return async (text) => {\n if (!state.commands.prompt) throw new Error(\"no prompt command configured for this chat session\");\n await state.commands.prompt(text ?? \"\");\n };\n case \"steer\":\n return async (text) => {\n if (!state.commands.steer) throw new Error(\"no steer command configured for this chat session\");\n await state.commands.steer(text ?? \"\");\n };\n case \"followUp\":\n return async (text) => {\n if (!state.commands.followUp) throw new Error(\"no followUp command configured for this chat session\");\n await state.commands.followUp(text ?? \"\");\n };\n case \"resume\":\n return async (text) => {\n if (!state.commands.resume) throw new Error(\"no resume command configured for this chat session\");\n await state.commands.resume(text);\n };\n }\n}\n\nexport function afterChatSessionEvent<TExtraEntry extends ChatTranscriptEntryLike>(\n state: ChatSessionHostState<TExtraEntry>,\n changed: boolean,\n): void {\n syncChatSessionAnimationTick(state);\n if (!changed) return;\n requestChatSessionEventRender(state);\n}\n\nfunction requestChatSessionEventRender<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(state: ChatSessionHostState<TExtraEntry>): void {\n if (!isChatSessionStreaming(state)) {\n state.requestRender?.();\n return;\n }\n if (state.renderThrottleTimer) return;\n state.renderThrottleTimer = setTimeout(() => {\n state.renderThrottleTimer = undefined;\n state.requestRender?.();\n }, STREAMING_RENDER_THROTTLE_MS);\n state.renderThrottleTimer.unref?.();\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-runtime.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAOzE,wBAAgB,sBAAsB,CAAC,WAAW,SAAS,uBAAuB,EAChF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,OAAO,CAET;AAED,wBAAgB,wBAAwB,CAAC,WAAW,SAAS,uBAAuB,EAClF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,OAAO,CAET;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,SAAS,EAAE,MAAM,GAChB,IAAI,CAKN;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,SAAS,EAAE,MAAM,GAChB,IAAI,CAIN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,IAAI,CAehD;AAED,wBAAgB,4CAA4C,CAC1D,WAAW,SAAS,uBAAuB,EAC3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GAAG,IAAI,CAShD;AAED,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,uBAAuB,EAC5E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,IAAI,CAWN;AAED,wBAAgB,wBAAwB,CAAC,WAAW,SAAS,uBAAuB,EAClF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,IAAI,CAIN;AAED,wBAAgB,uBAAuB,CAAC,WAAW,SAAS,uBAAuB,EACjF,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CACxC,WAAW,SAAS,uBAAuB,EAE3C,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAC/C,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAuBlC;AAED,wBAAgB,qBAAqB,CAAC,WAAW,SAAS,uBAAuB,EAC/E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,EACxC,OAAO,EAAE,OAAO,GACf,IAAI,CAIN"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-state.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-state.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type {\n Component,\n EditorComponent,\n MarkdownTheme,\n TUI,\n} from \"@earendil-works/pi-tui\";\nimport { LiveChatEntriesController } from \"./chat-message-renderer.ts\";\nimport {\n ChatTranscriptComponent,\n ScrollableComponentViewport,\n type ChatTranscriptEntryLike,\n} from \"./chat-transcript.ts\";\nimport type {\n ChatSessionHostCommands,\n ChatSessionHostEntry,\n ChatSessionHostOpts,\n ChatSessionHostStyle,\n} from \"./chat-session-host-types.ts\";\n\nexport interface ChatSessionHostStateCallbacks<\n TExtraEntry extends ChatTranscriptEntryLike,\n> {\n renderEntry: (\n state: ChatSessionHostState<TExtraEntry>,\n entry: ChatSessionHostEntry<TExtraEntry>,\n ) => Component;\n transcriptCacheKey: (\n state: ChatSessionHostState<TExtraEntry>,\n entry: ChatSessionHostEntry<TExtraEntry>,\n index: number,\n ) => string;\n}\n\nexport class ChatSessionHostState<\n TExtraEntry extends ChatTranscriptEntryLike = never,\n> {\n readonly style: ChatSessionHostStyle;\n readonly commands: ChatSessionHostCommands;\n readonly requestRender: (() => void) | undefined;\n readonly getAgentSession: (() => AgentSession | undefined) | undefined;\n readonly isStreamingOverride: (() => boolean) | undefined;\n readonly isPaused: (() => boolean) | undefined;\n readonly isDisabled: (() => boolean) | undefined;\n readonly isBashRunningOverride: (() => boolean) | undefined;\n readonly showWarning: ((message: string) => void) | undefined;\n readonly showStatus: ((message: string) => void) | undefined;\n readonly actions: Record<string, () => void | Promise<void>> | undefined;\n readonly getActionKeyDisplay: ((action: string) => string) | undefined;\n readonly getMarkdownTheme: (() => MarkdownTheme) | undefined;\n readonly getChatRenderSettings: ChatSessionHostOpts<TExtraEntry>[\"getChatRenderSettings\"];\n readonly getCwd: (() => string) | undefined;\n readonly footerData: ReadonlyFooterDataProvider | undefined;\n readonly renderExtraEntry: ((entry: TExtraEntry) => Component) | undefined;\n readonly tui: TUI | undefined;\n\n inputBuffer = \"\";\n transcript: ChatSessionHostEntry<TExtraEntry>[] = [];\n extraEntries: TExtraEntry[] = [];\n statusMessage = \"\";\n isBashMode = false;\n localBashRunning = false;\n sdkBusy = false;\n workingMessage: string | undefined;\n pendingSteeringMessages: readonly string[] = [];\n pendingFollowUpMessages: readonly string[] = [];\n compactionQueuedMessages: readonly string[] = [];\n compacting = false;\n animationTimer: ReturnType<typeof setInterval> | undefined;\n renderThrottleTimer: ReturnType<typeof setTimeout> | undefined;\n bodyViewport = new ScrollableComponentViewport();\n transcriptComponent: ChatTranscriptComponent<ChatSessionHostEntry<TExtraEntry>>;\n transcriptRenderSettingsKey = \"\";\n renderIdentityIds = new WeakMap<object, number>();\n nextRenderIdentityId = 1;\n liveChat: LiveChatEntriesController;\n editor: EditorComponent | undefined;\n optimisticUserSignatureCounts = new Map<string, number>();\n\n constructor(\n opts: ChatSessionHostOpts<TExtraEntry>,\n callbacks: ChatSessionHostStateCallbacks<TExtraEntry>,\n ) {\n this.style = opts.style;\n this.commands = opts.commands ?? {};\n this.requestRender = opts.requestRender;\n this.getAgentSession = opts.getAgentSession;\n this.isStreamingOverride = opts.isStreaming;\n this.isPaused = opts.isPaused;\n this.isDisabled = opts.isDisabled;\n this.isBashRunningOverride = opts.isBashRunning;\n this.showWarning = opts.showWarning;\n this.showStatus = opts.showStatus;\n this.actions = opts.actions;\n this.getActionKeyDisplay = opts.getActionKeyDisplay;\n this.getMarkdownTheme = opts.getMarkdownTheme;\n this.getChatRenderSettings = opts.getChatRenderSettings;\n this.getCwd = opts.getCwd;\n this.footerData = opts.footerData;\n this.renderExtraEntry = opts.renderExtraEntry;\n this.tui = opts.tui;\n this.liveChat = new LiveChatEntriesController(this.transcript);\n this.transcriptComponent = new ChatTranscriptComponent(\n this.transcript,\n (entry) => callbacks.renderEntry(this, entry),\n (entry, index) => callbacks.transcriptCacheKey(this, entry, index),\n );\n }\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-state.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-state.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-terminal-cleanup.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-terminal-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAMpE,wBAAgB,mCAAmC,CACjD,WAAW,SAAS,uBAAuB,EAC3C,OAAO,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,GAAG,OAAO,CAYvD","sourcesContent":["import type { ChatSessionHostEntry } from \"./chat-session-host-types.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\n\ntype ToolEntry = Extract<ChatSessionHostEntry<ChatTranscriptEntryLike>, { kind: \"tool\" }>;\ntype ToolResult = NonNullable<ToolEntry[\"result\"]>;\ntype ObjectRecord = Record<string, unknown>;\n\nexport function finalizeTerminalWorkflowToolEntries<\n TExtraEntry extends ChatTranscriptEntryLike,\n>(entries: ChatSessionHostEntry<TExtraEntry>[]): boolean {\n let changed = false;\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n if (!isToolEntry(entry)) continue;\n const finalized = finalizeToolEntry(entry);\n if (finalized !== entry) {\n entries[i] = finalized as ChatSessionHostEntry<TExtraEntry>;\n changed = true;\n }\n }\n return changed;\n}\n\nfunction finalizeToolEntry(entry: ToolEntry): ToolEntry {\n const result = entry.result ? finalizeToolResult(entry.result) : undefined;\n const resultChanged = result !== entry.result;\n if (entry.isPartial === false && !resultChanged) return entry;\n return {\n ...entry,\n ...(result ? { result } : {}),\n isPartial: false,\n };\n}\n\nfunction finalizeToolResult(result: ToolResult): ToolResult {\n const details = finalizeDetails(result.details);\n if (details === result.details) return result;\n return { ...result, details };\n}\n\nfunction finalizeDetails(details: unknown): unknown {\n if (!isRecord(details)) return details;\n let changed = false;\n const next: ObjectRecord = { ...details };\n const progress = finalizeProgressArray(next.progress);\n if (progress !== next.progress) {\n next.progress = progress;\n changed = true;\n }\n if (Array.isArray(next.results)) {\n const results = next.results.map((item) => finalizeResultEntry(item));\n if (results.some((item, index) => item !== (next.results as unknown[])[index])) {\n next.results = results;\n changed = true;\n }\n }\n const workflowGraph = finalizeWorkflowGraph(next.workflowGraph);\n if (workflowGraph !== next.workflowGraph) {\n next.workflowGraph = workflowGraph;\n changed = true;\n }\n return changed ? next : details;\n}\n\nfunction finalizeResultEntry(entry: unknown): unknown {\n if (!isRecord(entry)) return entry;\n const progress = finalizeProgress(entry.progress);\n if (progress === entry.progress) return entry;\n return { ...entry, progress };\n}\n\nfunction finalizeProgressArray(progress: unknown): unknown {\n if (!Array.isArray(progress)) return progress;\n let changed = false;\n const next = progress.map((entry) => {\n const finalized = finalizeProgress(entry);\n if (finalized !== entry) changed = true;\n return finalized;\n });\n return changed ? next : progress;\n}\n\nfunction finalizeProgress(progress: unknown): unknown {\n if (!isRecord(progress) || progress.status !== \"running\") return progress;\n return {\n ...progress,\n status: \"detached\",\n activityState: undefined,\n currentTool: undefined,\n currentToolArgs: undefined,\n currentToolStartedAt: undefined,\n };\n}\n\nfunction finalizeWorkflowGraph(graph: unknown): unknown {\n if (!isRecord(graph)) return graph;\n const nodes = finalizeWorkflowGraphNodes(graph.nodes);\n const shouldClearCurrent = graph.currentNodeId !== undefined;\n if (nodes === graph.nodes && !shouldClearCurrent) return graph;\n return { ...graph, nodes, currentNodeId: undefined };\n}\n\nfunction finalizeWorkflowGraphNodes(nodes: unknown): unknown {\n if (!Array.isArray(nodes)) return nodes;\n let changed = false;\n const next = nodes.map((node) => {\n const finalized = finalizeWorkflowGraphNode(node);\n if (finalized !== node) changed = true;\n return finalized;\n });\n return changed ? next : nodes;\n}\n\nfunction finalizeWorkflowGraphNode(node: unknown): unknown {\n if (!isRecord(node)) return node;\n let changed = false;\n const next: ObjectRecord = { ...node };\n if (next.status === \"running\") {\n next.status = \"detached\";\n changed = true;\n }\n const children = finalizeWorkflowGraphNodes(next.children);\n if (children !== next.children) {\n next.children = children;\n changed = true;\n }\n return changed ? next : node;\n}\n\nfunction isToolEntry(entry: ChatSessionHostEntry<ChatTranscriptEntryLike>): entry is ToolEntry {\n return entry.role === \"tool\" && \"kind\" in entry && entry.kind === \"tool\";\n}\n\nfunction isRecord(value: unknown): value is ObjectRecord {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-terminal-cleanup.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-terminal-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAMpE,wBAAgB,mCAAmC,CACjD,WAAW,SAAS,uBAAuB,EAC3C,OAAO,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,GAAG,OAAO,CAYvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-types.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-types.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { BashResult } from \"../../../core/bash-executor.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type {\n Component,\n EditorComponent,\n EditorTheme,\n MarkdownTheme,\n TUI,\n} from \"@earendil-works/pi-tui\";\nimport type {\n ChatMessageEntry,\n ChatMessageRenderOptions,\n} from \"./chat-message-renderer.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\n\nexport interface ChatSessionHostStyle {\n dim(text: string): string;\n text(text: string): string;\n textMuted(text: string): string;\n accent(text: string): string;\n accentBold(text: string): string;\n rule(hex: string, text: string): string;\n cursor(): string;\n blank(width: number): string;\n editorRuleColor(\n disabled: boolean,\n agentSession: AgentSession | undefined,\n state?: { isBashMode: boolean },\n ): string;\n}\n\nexport interface ChatSessionHostBashRequest {\n command: string;\n excludeFromContext: boolean;\n onChunk: (chunk: string) => void;\n}\n\nexport interface ChatSessionHostCommands {\n ensureAttached?: () => Promise<void>;\n prompt?: (text: string) => Promise<void>;\n steer?: (text: string) => Promise<void>;\n followUp?: (text: string) => Promise<void>;\n interrupt?: () => Promise<void>;\n resume?: (message?: string) => Promise<void>;\n runBash?: (request: ChatSessionHostBashRequest) => Promise<BashResult>;\n abortBash?: () => void | Promise<void>;\n abortCompaction?: () => void | Promise<void>;\n handleSlashCommand?: (text: string) => Promise<boolean> | boolean;\n}\n\nexport interface ChatSessionHostOpts<\n TExtraEntry extends ChatTranscriptEntryLike = never,\n> {\n style: ChatSessionHostStyle;\n commands?: ChatSessionHostCommands;\n requestRender?: () => void;\n getAgentSession?: () => AgentSession | undefined;\n isStreaming?: () => boolean;\n isPaused?: () => boolean;\n isDisabled?: () => boolean;\n isBashRunning?: () => boolean;\n showWarning?: (message: string) => void;\n showStatus?: (message: string) => void;\n actions?: Record<string, () => void | Promise<void>>;\n getActionKeyDisplay?: (action: string) => string;\n getMarkdownTheme?: () => MarkdownTheme;\n tui?: TUI;\n keybindings?: unknown;\n editorFactory?: (\n tui: TUI,\n theme: EditorTheme,\n keybindings: unknown,\n ) => EditorComponent;\n editorTheme: EditorTheme;\n getChatRenderSettings?: () =>\n | Partial<Omit<ChatMessageRenderOptions, \"ui\" | \"cwd\">>\n | undefined;\n getCwd?: () => string;\n footerData?: ReadonlyFooterDataProvider;\n renderExtraEntry?: (entry: TExtraEntry) => Component;\n}\n\nexport type ChatSessionHostEntry<\n TExtraEntry extends ChatTranscriptEntryLike = never,\n> = ChatMessageEntry | TExtraEntry;\n\nexport type AgentSnapshotMessage = AgentSession[\"messages\"][number];\nexport type CacheKeyPart = string | number | boolean | null;\n"]}
1
+ {"version":3,"file":"chat-session-host-types.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host-utils.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC,eAAO,MAAM,cAAc,UAAqD,CAAC;AACjF,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAI/C,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAC1D,OAAO,CAMT;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GACvC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAChD,SAAS,CAKZ;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAE/D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,uBAAuB,EAC5E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,KAAK,IAAI,gBAAgB,CAqB3B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAEhG;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,GACf,OAAO,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAEhD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAe3D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD","sourcesContent":["import { matchesKey as tuiMatchesKey } from \"@earendil-works/pi-tui\";\nimport type { ChatMessageEntry } from \"./chat-message-renderer.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport type {\n CacheKeyPart,\n ChatSessionHostEntry,\n} from \"./chat-session-host-types.ts\";\n\nexport const SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nexport const ANIMATION_FRAME_MS = 80;\nexport const STREAMING_RENDER_THROTTLE_MS = 80;\nconst STREAMING_TEXT_TAIL_LINES = 240;\nconst STREAMING_TEXT_TAIL_CHARS = 16_000;\n\nexport function matchesKey(\n data: string,\n key: \"enter\" | \"backspace\" | \"escape\" | \"ctrl+f\" | \"alt+up\",\n): boolean {\n if (key === \"enter\" && (data === \"\\r\" || data === \"\\n\")) return true;\n if (key === \"backspace\" && (data === \"\\x7f\" || data === \"\\b\")) return true;\n if (key === \"escape\" && data === \"\\x1b\") return true;\n if (key === \"ctrl+f\" && data === \"\\x06\") return true;\n return tuiMatchesKey(data, key);\n}\n\nexport function parseBashInput(text: string):\n | { command: string; excludeFromContext: boolean }\n | undefined {\n if (!text.startsWith(\"!\")) return undefined;\n const excludeFromContext = text.startsWith(\"!!\");\n const command = text.slice(excludeFromContext ? 2 : 1).trim();\n return { command, excludeFromContext };\n}\n\nexport function cacheKey(parts: readonly CacheKeyPart[]): string {\n return JSON.stringify(parts);\n}\n\nexport function isChatMessageEntry<TExtraEntry extends ChatTranscriptEntryLike>(\n entry: ChatSessionHostEntry<TExtraEntry>,\n): entry is ChatMessageEntry {\n if (!(\"role\" in entry) || !(\"kind\" in entry)) return false;\n const candidate = entry as { role?: unknown; kind?: unknown; message?: unknown; text?: unknown };\n switch (candidate.kind) {\n case \"assistant\":\n return candidate.role === \"assistant\" && candidate.message !== undefined;\n case \"tool\":\n return candidate.role === \"tool\" && \"toolName\" in candidate && \"toolCallId\" in candidate && \"args\" in candidate;\n case \"bashExecution\":\n return candidate.role === \"tool\" && candidate.message !== undefined;\n case \"user\":\n return candidate.role === \"user\" && typeof candidate.text === \"string\";\n case \"custom\":\n return candidate.role === \"custom\" && candidate.message !== undefined;\n case \"branchSummary\":\n return candidate.role === \"summary\" && candidate.message !== undefined;\n case \"system\":\n return candidate.role === \"system\" && typeof candidate.text === \"string\";\n default:\n return false;\n }\n}\n\nexport function isMessageLike(message: unknown): message is { role?: unknown; content?: unknown } {\n return message !== null && typeof message === \"object\" && \"role\" in message;\n}\n\nexport function isUserMessageLike(\n message: unknown,\n): message is { role: \"user\"; content?: unknown } {\n return isMessageLike(message) && message.role === \"user\";\n}\n\nexport function userMessageSignature(text: string): string {\n return text.trim();\n}\n\nexport function extractMessageText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const parts: string[] = [];\n for (const item of content) {\n if (item == null) continue;\n if (typeof item === \"string\") {\n parts.push(item);\n continue;\n }\n const obj = item as { type?: unknown; text?: unknown };\n if (typeof obj.text === \"string\") parts.push(obj.text);\n else if (obj.type === \"text\" && typeof obj.text === \"string\") parts.push(obj.text);\n }\n return parts.join(\"\");\n}\n\nexport function tailStreamingText(text: string): string {\n if (\n text.length <= STREAMING_TEXT_TAIL_CHARS &&\n text.split(\"\\n\").length <= STREAMING_TEXT_TAIL_LINES\n ) {\n return text;\n }\n const byChars = text.slice(-STREAMING_TEXT_TAIL_CHARS);\n const lines = byChars.split(\"\\n\");\n const tail =\n lines.length > STREAMING_TEXT_TAIL_LINES\n ? lines.slice(-STREAMING_TEXT_TAIL_LINES).join(\"\\n\")\n : byChars;\n return `[earlier streaming output hidden while attached]\\n\\n${tail.trimStart()}`;\n}\n\nexport function spinnerFrame(): string {\n const idx = Math.floor(Date.now() / ANIMATION_FRAME_MS) % SPINNER_FRAMES.length;\n return SPINNER_FRAMES[idx]!;\n}\n\nexport function stripAnsi(s: string): string {\n return s.replace(/\\x1B\\[[0-?]*[ -/]*[@-~]/g, \"\");\n}\n\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"]}
1
+ {"version":3,"file":"chat-session-host-utils.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC,eAAO,MAAM,cAAc,UAAqD,CAAC;AACjF,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAI/C,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAC1D,OAAO,CAMT;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GACvC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAChD,SAAS,CAKZ;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAE/D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,uBAAuB,EAC5E,KAAK,EAAE,oBAAoB,CAAC,WAAW,CAAC,GACvC,KAAK,IAAI,gBAAgB,CAqB3B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAEhG;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,GACf,OAAO,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAEhD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAe3D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-host.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AA+BpE,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EACV,0BAA0B,EAC1B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAEtC,qBAAa,eAAe,CAAC,WAAW,SAAS,uBAAuB,GAAG,KAAK,CAC9E,YAAW,SAAS,EAAE,SAAS;IAE/B,OAAO,UAAQ;IAEf,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAE1D,YAAY,IAAI,EAAE,mBAAmB,CAAC,WAAW,CAAC,EAcjD;IAED,cAAc,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI,CAE9D;IAED,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAUrD;IAED,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAGzC;IAED,OAAO,IAAI,SAAS,oBAAoB,CAAC,WAAW,CAAC,EAAE,CAEtD;IAED,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAEjD;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9B;IAED,UAAU,IAAI,IAAI,CAIjB;IAED,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAElD;IAED,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE7C;IAED,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3C;IAED,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnC;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpC;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpC;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvC;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjC;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/B;IAEK,MAAM,CAAC,IAAI,GAAE,MAAM,GAAG,UAAmB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtF;IAED,WAAW,IAAI,OAAO,CAErB;IAED,aAAa,IAAI,OAAO,CAEvB;IAED,oBAAoB,IAAI,OAAO,CAE9B;IAED,YAAY,IAAI,OAAO,CAEtB;IAED,YAAY,IAAI,OAAO,CAEtB;IAED,gBAAgB,IAAI,OAAO,CAE1B;IAED,oBAAoB,IAAI,MAAM,CAE7B;IAED,aAAa,IAAI,MAAM,CAEtB;IAED,SAAS,IAAI,MAAM,CAElB;IAED,UAAU,IAAI,MAAM,CAEnB;IAED,cAAc,IAAI,IAAI,CAErB;IAED,iBAAiB,IAAI,IAAI,CAExB;IAED,iCAAiC,IAAI,IAAI,CAExC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,6BAA6B,IAAI,OAAO,CAEvC;IAED,OAAO,CAAC,eAAe;CAexB","sourcesContent":["import type { AgentSessionEvent } from \"../../../core/agent-session.ts\";\nimport { type Component, type Focusable } from \"@earendil-works/pi-tui\";\nimport { SessionManager } from \"../../../core/session-manager.ts\";\nimport type { ChatTranscriptEntryLike } from \"./chat-transcript.ts\";\nimport {\n abortChatSessionBash,\n abortChatSessionCompaction,\n interruptChatSession,\n restoreQueuedMessagesToEditor,\n submitChatSession,\n} from \"./chat-session-host-actions.ts\";\nimport {\n createChatSessionEditor,\n handleChatSessionInput,\n} from \"./chat-session-host-editor.ts\";\nimport { applyChatSessionAgentEvent } from \"./chat-session-host-events.ts\";\nimport {\n renderChatSessionBody,\n renderChatSessionEditor,\n renderChatSessionEntry,\n renderChatSessionFooter,\n renderChatSessionPendingMessages,\n renderChatSessionUsage,\n renderChatSessionWorkingStatus,\n transcriptCacheKey,\n} from \"./chat-session-host-rendering.ts\";\nimport {\n clearChatSessionBusyForTerminalWorkflowStage,\n disposeChatSession,\n isChatSessionBashRunning,\n isChatSessionStreaming,\n syncChatSessionAnimationTick,\n} from \"./chat-session-host-runtime.ts\";\nimport { ChatSessionHostState } from \"./chat-session-host-state.ts\";\nimport type {\n AgentSnapshotMessage,\n ChatSessionHostEntry,\n ChatSessionHostOpts,\n} from \"./chat-session-host-types.ts\";\n\nexport type {\n ChatSessionHostBashRequest,\n ChatSessionHostCommands,\n ChatSessionHostEntry,\n ChatSessionHostOpts,\n ChatSessionHostStyle,\n} from \"./chat-session-host-types.ts\";\n\nexport class ChatSessionHost<TExtraEntry extends ChatTranscriptEntryLike = never>\n implements Component, Focusable\n{\n focused = true;\n\n private readonly state: ChatSessionHostState<TExtraEntry>;\n\n constructor(opts: ChatSessionHostOpts<TExtraEntry>) {\n this.state = new ChatSessionHostState(opts, {\n renderEntry: (state, entry) => renderChatSessionEntry(state, entry),\n transcriptCacheKey: (state, entry, index) => transcriptCacheKey(state, entry, index),\n });\n this.state.editor = createChatSessionEditor(\n this.state,\n opts.tui,\n opts.keybindings,\n opts.editorTheme,\n opts.editorFactory,\n this.editorCallbacks(),\n );\n this.syncAnimationTick();\n }\n\n appendMessages(messages: readonly AgentSnapshotMessage[]): void {\n this.state.liveChat.appendMessages(messages);\n }\n\n loadSessionFile(sessionFile: string | undefined): void {\n if (this.state.transcript.length > 0 || sessionFile === undefined) return;\n let messages: readonly AgentSnapshotMessage[];\n try {\n messages = SessionManager.open(sessionFile).buildSessionContext()\n .messages as readonly AgentSnapshotMessage[];\n } catch {\n return;\n }\n this.state.liveChat.appendMessages(messages);\n }\n\n appendExtraEntry(entry: TExtraEntry): void {\n this.state.extraEntries.push(entry);\n this.state.transcript.push(entry);\n }\n\n entries(): readonly ChatSessionHostEntry<TExtraEntry>[] {\n return this.state.transcript;\n }\n\n applyAgentEvent(event: AgentSessionEvent): boolean {\n return applyChatSessionAgentEvent(this.state, event);\n }\n\n render(width: number): string[] {\n return this.renderBody(width, 1);\n }\n\n invalidate(): void {\n this.state.transcriptComponent.invalidate();\n this.state.bodyViewport.invalidate();\n this.state.editor?.invalidate();\n }\n\n renderBody(width: number, budget: number): string[] {\n return renderChatSessionBody(this.state, width, budget);\n }\n\n renderPendingMessages(width: number): string[] {\n return renderChatSessionPendingMessages(this.state, width);\n }\n\n renderWorkingStatus(width: number): string[] {\n return renderChatSessionWorkingStatus(this.state, width);\n }\n\n renderUsage(width: number): string[] {\n return renderChatSessionUsage(this.state, width);\n }\n\n renderEditor(width: number): string[] {\n return renderChatSessionEditor(this.state, width, this.focused);\n }\n\n renderFooter(width: number): string[] {\n return renderChatSessionFooter(this.state, width);\n }\n\n handleScrollInput(data: string): boolean {\n return this.state.bodyViewport.handleInput(data);\n }\n\n handleInput(data: string): boolean {\n return handleChatSessionInput(this.state, data, this.editorCallbacks());\n }\n\n async interrupt(): Promise<void> {\n await interruptChatSession(this.state);\n }\n\n async submit(mode: \"auto\" | \"followUp\" = \"auto\", submittedText?: string): Promise<void> {\n await submitChatSession(this.state, mode, submittedText);\n }\n\n isStreaming(): boolean {\n return isChatSessionStreaming(this.state);\n }\n\n isBashRunning(): boolean {\n return isChatSessionBashRunning(this.state);\n }\n\n isEditingBashCommand(): boolean {\n return this.state.isBashMode;\n }\n\n isCompacting(): boolean {\n return this.state.compacting;\n }\n\n hasInputText(): boolean {\n return this.state.inputBuffer.length > 0;\n }\n\n hasAnimationTick(): boolean {\n return this.state.animationTimer !== undefined;\n }\n\n bodyScrollFromBottom(): number {\n return this.state.bodyViewport.getScrollFromBottom();\n }\n\n bodyMaxScroll(): number {\n return this.state.bodyViewport.getMaxScroll();\n }\n\n inputText(): string {\n return this.state.inputBuffer;\n }\n\n statusText(): string {\n return this.state.statusMessage;\n }\n\n scrollToBottom(): void {\n this.state.bodyViewport.scrollToBottom();\n }\n\n syncAnimationTick(): void {\n syncChatSessionAnimationTick(this.state);\n }\n\n clearBusyForTerminalWorkflowStage(): void {\n clearChatSessionBusyForTerminalWorkflowStage(this.state);\n }\n\n dispose(): void {\n disposeChatSession(this.state);\n }\n\n restoreQueuedMessagesToEditor(): boolean {\n return restoreQueuedMessagesToEditor(this.state);\n }\n\n private editorCallbacks(): {\n submit: (mode: \"auto\" | \"followUp\", submittedText?: string) => void | Promise<void>;\n restoreQueuedMessagesToEditor: () => boolean;\n abortCompaction: () => void | Promise<void>;\n interrupt: () => void | Promise<void>;\n abortBash: () => void | Promise<void>;\n } {\n return {\n submit: (mode, submittedText) => this.submit(mode, submittedText),\n restoreQueuedMessagesToEditor: () => this.restoreQueuedMessagesToEditor(),\n abortCompaction: () => abortChatSessionCompaction(this.state),\n interrupt: () => this.interrupt(),\n abortBash: () => abortChatSessionBash(this.state),\n };\n }\n}\n"]}
1
+ {"version":3,"file":"chat-session-host.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-session-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AA+BpE,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EACV,0BAA0B,EAC1B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAEtC,qBAAa,eAAe,CAAC,WAAW,SAAS,uBAAuB,GAAG,KAAK,CAC9E,YAAW,SAAS,EAAE,SAAS;IAE/B,OAAO,UAAQ;IAEf,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAE1D,YAAY,IAAI,EAAE,mBAAmB,CAAC,WAAW,CAAC,EAcjD;IAED,cAAc,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI,CAE9D;IAED,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAUrD;IAED,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAGzC;IAED,OAAO,IAAI,SAAS,oBAAoB,CAAC,WAAW,CAAC,EAAE,CAEtD;IAED,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAEjD;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9B;IAED,UAAU,IAAI,IAAI,CAIjB;IAED,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAElD;IAED,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE7C;IAED,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3C;IAED,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnC;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpC;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpC;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvC;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjC;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/B;IAEK,MAAM,CAAC,IAAI,GAAE,MAAM,GAAG,UAAmB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtF;IAED,WAAW,IAAI,OAAO,CAErB;IAED,aAAa,IAAI,OAAO,CAEvB;IAED,oBAAoB,IAAI,OAAO,CAE9B;IAED,YAAY,IAAI,OAAO,CAEtB;IAED,YAAY,IAAI,OAAO,CAEtB;IAED,gBAAgB,IAAI,OAAO,CAE1B;IAED,oBAAoB,IAAI,MAAM,CAE7B;IAED,aAAa,IAAI,MAAM,CAEtB;IAED,SAAS,IAAI,MAAM,CAElB;IAED,UAAU,IAAI,MAAM,CAEnB;IAED,cAAc,IAAI,IAAI,CAErB;IAED,iBAAiB,IAAI,IAAI,CAExB;IAED,iCAAiC,IAAI,IAAI,CAExC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,6BAA6B,IAAI,OAAO,CAEvC;IAED,OAAO,CAAC,eAAe;CAexB"}