@ai-agent-forge/agent-forge 0.88.1 → 0.88.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 (518) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +1 -1
  3. package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
  4. package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
  5. package/bundled-plugins/coding-tools/agent-forge.json +1 -1
  6. package/bundled-plugins/coding-tools/plugin.json +1 -1
  7. package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
  8. package/bundled-plugins/compaction-policy/plugin.json +1 -1
  9. package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
  10. package/bundled-plugins/overflow-policy/plugin.json +1 -1
  11. package/bundled-plugins/provider-failover/agent-forge.json +1 -1
  12. package/bundled-plugins/provider-failover/plugin.json +1 -1
  13. package/bundled-plugins/retry-policy/agent-forge.json +1 -1
  14. package/bundled-plugins/retry-policy/plugin.json +1 -1
  15. package/dist/artifacts/paged-read.d.ts +6 -1
  16. package/dist/artifacts/paged-read.d.ts.map +1 -1
  17. package/dist/artifacts/paged-read.js.map +1 -1
  18. package/dist/bundle/.build-manifest.json +283 -263
  19. package/dist/bundle/chunks/{anthropic-messages-PLAKXR73.js → anthropic-messages-3FJHRAJL.js} +2 -2
  20. package/dist/bundle/chunks/anthropic.js +1 -1
  21. package/dist/bundle/chunks/{azure-openai-responses-OUWQ2AZD.js → azure-openai-responses-GCL47IDS.js} +1 -1
  22. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  23. package/dist/bundle/chunks/{chunk-Z72JWUZ4.js → chunk-32YDZI4J.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-AQLNTW2B.js → chunk-755VNWIF.js} +17 -16
  25. package/dist/bundle/chunks/{chunk-LZOEQITZ.js → chunk-B42Y2VME.js} +120 -104
  26. package/dist/bundle/chunks/{chunk-DRQDKNXA.js → chunk-BVVSHK6W.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-6R7UI4IY.js → chunk-QDLOMKF6.js} +1 -1
  28. package/dist/bundle/chunks/{chunk-D3ARGZFR.js → chunk-V3ACW7VD.js} +3 -3
  29. package/dist/bundle/chunks/{google-generative-ai-DLII6DAT.js → google-generative-ai-6BMXWA44.js} +1 -1
  30. package/dist/bundle/chunks/{google-vertex-G7BZL7GM.js → google-vertex-6H7NLRTK.js} +1 -1
  31. package/dist/bundle/chunks/image-resize-worker.js +3 -3
  32. package/dist/bundle/chunks/{mistral-conversations-JXUK24ID.js → mistral-conversations-IXUHSFSJ.js} +1 -1
  33. package/dist/bundle/chunks/{openai-codex-responses-5GSGFIPG.js → openai-codex-responses-YHUAEVCM.js} +1 -1
  34. package/dist/bundle/chunks/openai-codex.js +1 -1
  35. package/dist/bundle/chunks/{openai-completions-EI2I6DTG.js → openai-completions-ULQCFC72.js} +1 -1
  36. package/dist/bundle/chunks/openai-responses-NLLAJDPS.js +2 -0
  37. package/dist/bundle/chunks/{openrouter-images-G4GQRUSG.js → openrouter-images-GZZQZXMS.js} +1 -1
  38. package/dist/bundle/chunks/openrouter.js +1 -1
  39. package/dist/bundle/chunks/{pi-messages-PWU2VJMR.js → pi-messages-EJTI2EJ3.js} +1 -1
  40. package/dist/bundle/chunks/virtual-modules-TQWEGNNZ.js +5 -0
  41. package/dist/bundle/cli.js +1 -1
  42. package/dist/bundle/client.js +1 -1
  43. package/dist/bundle/index.js +1 -1
  44. package/dist/bundle/rpc-entry.js +1 -1
  45. package/dist/cli/args.d.ts +0 -1
  46. package/dist/cli/args.d.ts.map +1 -1
  47. package/dist/cli/args.js +1 -4
  48. package/dist/cli/args.js.map +1 -1
  49. package/dist/cli/config-selector.d.ts.map +1 -1
  50. package/dist/cli/config-selector.js +1 -1
  51. package/dist/cli/config-selector.js.map +1 -1
  52. package/dist/cli/experimental/cli.d.ts +3 -3
  53. package/dist/cli/experimental/cli.d.ts.map +1 -1
  54. package/dist/cli/experimental/cli.js +2 -2
  55. package/dist/cli/experimental/cli.js.map +1 -1
  56. package/dist/cli/experimental/commands/agent-forge.d.ts +15 -0
  57. package/dist/cli/experimental/commands/agent-forge.d.ts.map +1 -0
  58. package/dist/cli/experimental/commands/{pi.js → agent-forge.js} +4 -4
  59. package/dist/cli/experimental/commands/agent-forge.js.map +1 -0
  60. package/dist/cli/plugin-command.d.ts.map +1 -1
  61. package/dist/cli/plugin-command.js +8 -2
  62. package/dist/cli/plugin-command.js.map +1 -1
  63. package/dist/cli/startup-ui.d.ts.map +1 -1
  64. package/dist/cli/startup-ui.js +1 -1
  65. package/dist/cli/startup-ui.js.map +1 -1
  66. package/dist/config.d.ts +4 -4
  67. package/dist/config.d.ts.map +1 -1
  68. package/dist/config.js +7 -7
  69. package/dist/config.js.map +1 -1
  70. package/dist/core/agent-forge-manifest.d.ts +7 -0
  71. package/dist/core/agent-forge-manifest.d.ts.map +1 -0
  72. package/dist/core/{pi-manifest.js → agent-forge-manifest.js} +4 -4
  73. package/dist/core/agent-forge-manifest.js.map +1 -0
  74. package/dist/core/agent-session-compaction.d.ts +1 -1
  75. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  76. package/dist/core/agent-session-compaction.js +3 -3
  77. package/dist/core/agent-session-compaction.js.map +1 -1
  78. package/dist/core/agent-session-internal.d.ts +2 -0
  79. package/dist/core/agent-session-internal.d.ts.map +1 -1
  80. package/dist/core/agent-session-internal.js.map +1 -1
  81. package/dist/core/agent-session-lifecycle.d.ts.map +1 -1
  82. package/dist/core/agent-session-lifecycle.js +12 -1
  83. package/dist/core/agent-session-lifecycle.js.map +1 -1
  84. package/dist/core/agent-session-projection.d.ts.map +1 -1
  85. package/dist/core/agent-session-projection.js +3 -3
  86. package/dist/core/agent-session-projection.js.map +1 -1
  87. package/dist/core/agent-session-services.d.ts +3 -1
  88. package/dist/core/agent-session-services.d.ts.map +1 -1
  89. package/dist/core/agent-session-services.js +2 -1
  90. package/dist/core/agent-session-services.js.map +1 -1
  91. package/dist/core/agent-session-store.d.ts.map +1 -1
  92. package/dist/core/agent-session-store.js +6 -1
  93. package/dist/core/agent-session-store.js.map +1 -1
  94. package/dist/core/agent-session-tools.d.ts.map +1 -1
  95. package/dist/core/agent-session-tools.js +13 -0
  96. package/dist/core/agent-session-tools.js.map +1 -1
  97. package/dist/core/agent-session.d.ts +24 -0
  98. package/dist/core/agent-session.d.ts.map +1 -1
  99. package/dist/core/agent-session.js +58 -4
  100. package/dist/core/agent-session.js.map +1 -1
  101. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  102. package/dist/core/compaction/branch-summarization.js +1 -1
  103. package/dist/core/compaction/branch-summarization.js.map +1 -1
  104. package/dist/core/experimental.d.ts.map +1 -1
  105. package/dist/core/experimental.js +1 -3
  106. package/dist/core/experimental.js.map +1 -1
  107. package/dist/core/extensions/capability-runtime-store.d.ts +20 -1
  108. package/dist/core/extensions/capability-runtime-store.d.ts.map +1 -1
  109. package/dist/core/extensions/capability-runtime-store.js +67 -0
  110. package/dist/core/extensions/capability-runtime-store.js.map +1 -1
  111. package/dist/core/extensions/capability-runtime-types.d.ts +14 -0
  112. package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -1
  113. package/dist/core/extensions/capability-runtime-types.js +7 -1
  114. package/dist/core/extensions/capability-runtime-types.js.map +1 -1
  115. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  116. package/dist/core/extensions/capability-runtime.js +144 -42
  117. package/dist/core/extensions/capability-runtime.js.map +1 -1
  118. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  119. package/dist/core/extensions/virtual-modules.js +6 -1
  120. package/dist/core/extensions/virtual-modules.js.map +1 -1
  121. package/dist/core/facade/coding-agent-facade.d.ts +1 -1
  122. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  123. package/dist/core/facade/coding-agent-facade.js +1 -1
  124. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  125. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -1
  126. package/dist/core/i18n/locales/zh-cn/cli.js +2 -0
  127. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -1
  128. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +1 -1
  129. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -1
  130. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +3 -3
  131. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -1
  132. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -1
  133. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +1 -1
  134. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -1
  135. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
  136. package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -1
  137. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
  138. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -1
  139. package/dist/core/i18n/locales/zh-cn/index.js +2 -0
  140. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -1
  141. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -1
  142. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +5 -0
  143. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -1
  144. package/dist/core/i18n/locales/zh-cn/session-cleanup.d.ts +7 -0
  145. package/dist/core/i18n/locales/zh-cn/session-cleanup.d.ts.map +1 -0
  146. package/dist/core/i18n/locales/zh-cn/session-cleanup.js +15 -0
  147. package/dist/core/i18n/locales/zh-cn/session-cleanup.js.map +1 -0
  148. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -1
  149. package/dist/core/i18n/locales/zh-cn/slash-commands.js +1 -0
  150. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -1
  151. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -1
  152. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +2 -0
  153. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -1
  154. package/dist/core/model-resolver.d.ts +2 -0
  155. package/dist/core/model-resolver.d.ts.map +1 -1
  156. package/dist/core/model-resolver.js +4 -1
  157. package/dist/core/model-resolver.js.map +1 -1
  158. package/dist/core/package-resource-collection.d.ts.map +1 -1
  159. package/dist/core/package-resource-collection.js +5 -5
  160. package/dist/core/package-resource-collection.js.map +1 -1
  161. package/dist/core/provider-composer.d.ts.map +1 -1
  162. package/dist/core/provider-composer.js +3 -3
  163. package/dist/core/provider-composer.js.map +1 -1
  164. package/dist/core/resource-loader.d.ts.map +1 -1
  165. package/dist/core/resource-loader.js +1 -1
  166. package/dist/core/resource-loader.js.map +1 -1
  167. package/dist/core/sdk.d.ts +1 -1
  168. package/dist/core/sdk.d.ts.map +1 -1
  169. package/dist/core/sdk.js +30 -8
  170. package/dist/core/sdk.js.map +1 -1
  171. package/dist/core/session-cleanup.d.ts +49 -0
  172. package/dist/core/session-cleanup.d.ts.map +1 -0
  173. package/dist/core/session-cleanup.js +159 -0
  174. package/dist/core/session-cleanup.js.map +1 -0
  175. package/dist/core/session-index.d.ts +75 -0
  176. package/dist/core/session-index.d.ts.map +1 -0
  177. package/dist/core/session-index.js +455 -0
  178. package/dist/core/session-index.js.map +1 -0
  179. package/dist/core/session-manager.d.ts +9 -0
  180. package/dist/core/session-manager.d.ts.map +1 -1
  181. package/dist/core/session-manager.js +206 -51
  182. package/dist/core/session-manager.js.map +1 -1
  183. package/dist/core/settings-manager.d.ts.map +1 -1
  184. package/dist/core/settings-manager.js +5 -10
  185. package/dist/core/settings-manager.js.map +1 -1
  186. package/dist/core/slash-commands.d.ts.map +1 -1
  187. package/dist/core/slash-commands.js +5 -0
  188. package/dist/core/slash-commands.js.map +1 -1
  189. package/dist/core/system-prompt.d.ts.map +1 -1
  190. package/dist/core/system-prompt.js +12 -1
  191. package/dist/core/system-prompt.js.map +1 -1
  192. package/dist/core/timings.d.ts.map +1 -1
  193. package/dist/core/timings.js +1 -3
  194. package/dist/core/timings.js.map +1 -1
  195. package/dist/core/tools/capability-mount.d.ts +40 -0
  196. package/dist/core/tools/capability-mount.d.ts.map +1 -0
  197. package/dist/core/tools/capability-mount.js +112 -0
  198. package/dist/core/tools/capability-mount.js.map +1 -0
  199. package/dist/core/tools/render-utils.d.ts +1 -1
  200. package/dist/core/tools/render-utils.d.ts.map +1 -1
  201. package/dist/core/tools/render-utils.js.map +1 -1
  202. package/dist/core/tools/tool-definition.d.ts +1 -1
  203. package/dist/core/tools/tool-definition.d.ts.map +1 -1
  204. package/dist/core/tools/tool-definition.js.map +1 -1
  205. package/dist/core/trace-retention.d.ts +16 -1
  206. package/dist/core/trace-retention.d.ts.map +1 -1
  207. package/dist/core/trace-retention.js +43 -20
  208. package/dist/core/trace-retention.js.map +1 -1
  209. package/dist/export-html/ansi-to-html.d.ts.map +1 -0
  210. package/dist/export-html/ansi-to-html.js.map +1 -0
  211. package/dist/{core/export-html → export-html}/index.d.ts +1 -1
  212. package/dist/export-html/index.d.ts.map +1 -0
  213. package/dist/{core/export-html → export-html}/index.js +5 -5
  214. package/dist/export-html/index.js.map +1 -0
  215. package/dist/{core/export-html → export-html}/tool-renderer.d.ts +2 -2
  216. package/dist/export-html/tool-renderer.d.ts.map +1 -0
  217. package/dist/export-html/tool-renderer.js.map +1 -0
  218. package/dist/{modes/interactive → host}/model-catalog-refresh.d.ts +1 -1
  219. package/dist/host/model-catalog-refresh.d.ts.map +1 -0
  220. package/dist/{modes/interactive → host}/model-catalog-refresh.js +1 -1
  221. package/dist/host/model-catalog-refresh.js.map +1 -0
  222. package/dist/index.d.ts +5 -5
  223. package/dist/index.d.ts.map +1 -1
  224. package/dist/index.js +12 -12
  225. package/dist/index.js.map +1 -1
  226. package/dist/main.d.ts.map +1 -1
  227. package/dist/main.js +26 -14
  228. package/dist/main.js.map +1 -1
  229. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  230. package/dist/modes/interactive/components/agents-view.js +1 -1
  231. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  232. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  233. package/dist/modes/interactive/components/armin.js +1 -1
  234. package/dist/modes/interactive/components/armin.js.map +1 -1
  235. package/dist/modes/interactive/components/assistant-message.d.ts +6 -0
  236. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  237. package/dist/modes/interactive/components/assistant-message.js +108 -27
  238. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  239. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  240. package/dist/modes/interactive/components/bash-execution.js +1 -1
  241. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  242. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  243. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  244. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  245. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  246. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  247. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  248. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  250. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  251. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/config-selector.js +1 -1
  253. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  254. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/custom-entry.js +1 -1
  256. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  257. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/custom-message.js +1 -1
  259. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  260. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  261. package/dist/modes/interactive/components/daxnuts.js +1 -1
  262. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  263. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  264. package/dist/modes/interactive/components/dialog-editor.js +1 -1
  265. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  266. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  267. package/dist/modes/interactive/components/dialog-input.js +1 -1
  268. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  269. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  270. package/dist/modes/interactive/components/dialog-selector.js +1 -1
  271. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  272. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  273. package/dist/modes/interactive/components/diff.js +1 -1
  274. package/dist/modes/interactive/components/diff.js.map +1 -1
  275. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  276. package/dist/modes/interactive/components/dynamic-border.js +1 -1
  277. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  278. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
  279. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  281. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  282. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/footer.js +1 -1
  284. package/dist/modes/interactive/components/footer.js.map +1 -1
  285. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  286. package/dist/modes/interactive/components/keybinding-hints.js +1 -1
  287. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  288. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  289. package/dist/modes/interactive/components/login-dialog.js +1 -1
  290. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  291. package/dist/modes/interactive/components/mermaid.d.ts +1 -1
  292. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  293. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  294. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/model-selector.js +2 -2
  296. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  297. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  298. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  299. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  300. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  301. package/dist/modes/interactive/components/plugin-manager-entry.js +1 -1
  302. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  303. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  304. package/dist/modes/interactive/components/plugin-selection-entry.js +1 -1
  305. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  306. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -1
  307. package/dist/modes/interactive/components/queue-manager-selector.js +1 -1
  308. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -1
  309. package/dist/modes/interactive/components/render-types.d.ts +1 -1
  310. package/dist/modes/interactive/components/render-types.d.ts.map +1 -1
  311. package/dist/modes/interactive/components/render-types.js.map +1 -1
  312. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  313. package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  314. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  315. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/session-selector-search.js +5 -1
  317. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  318. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/session-selector.js +11 -2
  320. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  321. package/dist/modes/interactive/components/settings-selector.d.ts +1 -1
  322. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  323. package/dist/modes/interactive/components/settings-selector.js +1 -1
  324. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  325. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/settings-submenu.js +1 -1
  327. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  328. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  329. package/dist/modes/interactive/components/show-images-selector.js +1 -1
  330. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  331. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  332. package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  333. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  334. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  335. package/dist/modes/interactive/components/status-indicator.js +1 -1
  336. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  337. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  338. package/dist/modes/interactive/components/theme-selector.js +1 -1
  339. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  340. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  341. package/dist/modes/interactive/components/thinking-selector.js +1 -1
  342. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  343. package/dist/modes/interactive/components/tool-execution.d.ts +19 -0
  344. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  345. package/dist/modes/interactive/components/tool-execution.js +139 -4
  346. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  347. package/dist/modes/interactive/components/tool-run-group.d.ts +44 -0
  348. package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -0
  349. package/dist/modes/interactive/components/tool-run-group.js +121 -0
  350. package/dist/modes/interactive/components/tool-run-group.js.map +1 -0
  351. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  352. package/dist/modes/interactive/components/tree-list.js +1 -1
  353. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  354. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  355. package/dist/modes/interactive/components/tree-render.js +1 -1
  356. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  357. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  358. package/dist/modes/interactive/components/tree-selector.js +1 -1
  359. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  360. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  361. package/dist/modes/interactive/components/user-message-selector.js +1 -1
  362. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  363. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/user-message.js +1 -1
  365. package/dist/modes/interactive/components/user-message.js.map +1 -1
  366. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/workflow-view.js +1 -1
  368. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  369. package/dist/modes/interactive/interactive-auth.d.ts +1 -1
  370. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  371. package/dist/modes/interactive/interactive-auth.js +1 -1
  372. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  373. package/dist/modes/interactive/interactive-commands.d.ts +125 -6
  374. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  375. package/dist/modes/interactive/interactive-commands.js +698 -4
  376. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  377. package/dist/modes/interactive/interactive-events.d.ts +174 -0
  378. package/dist/modes/interactive/interactive-events.d.ts.map +1 -0
  379. package/dist/modes/interactive/interactive-events.js +704 -0
  380. package/dist/modes/interactive/interactive-events.js.map +1 -0
  381. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  382. package/dist/modes/interactive/interactive-format.js +1 -1
  383. package/dist/modes/interactive/interactive-format.js.map +1 -1
  384. package/dist/modes/interactive/interactive-lifecycle.d.ts +94 -0
  385. package/dist/modes/interactive/interactive-lifecycle.d.ts.map +1 -0
  386. package/dist/modes/interactive/interactive-lifecycle.js +177 -0
  387. package/dist/modes/interactive/interactive-lifecycle.js.map +1 -0
  388. package/dist/modes/interactive/interactive-mode.d.ts +254 -129
  389. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  390. package/dist/modes/interactive/interactive-mode.js +275 -2101
  391. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  392. package/dist/modes/interactive/interactive-queues.d.ts +96 -0
  393. package/dist/modes/interactive/interactive-queues.d.ts.map +1 -0
  394. package/dist/modes/interactive/interactive-queues.js +183 -0
  395. package/dist/modes/interactive/interactive-queues.js.map +1 -0
  396. package/dist/modes/interactive/interactive-selectors.d.ts +95 -5
  397. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  398. package/dist/modes/interactive/interactive-selectors.js +517 -6
  399. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  400. package/dist/modes/interactive/startup-services.d.ts +31 -0
  401. package/dist/modes/interactive/startup-services.d.ts.map +1 -0
  402. package/dist/modes/interactive/startup-services.js +123 -0
  403. package/dist/modes/interactive/startup-services.js.map +1 -0
  404. package/dist/modes/memory-preheat.d.ts +11 -0
  405. package/dist/modes/memory-preheat.d.ts.map +1 -0
  406. package/dist/modes/memory-preheat.js +20 -0
  407. package/dist/modes/memory-preheat.js.map +1 -0
  408. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  409. package/dist/modes/rpc/rpc-mode.js +3 -1
  410. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  411. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  412. package/dist/plugins/ecosystem/cli.js +6 -3
  413. package/dist/plugins/ecosystem/cli.js.map +1 -1
  414. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +7 -1
  415. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  416. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +50 -3
  417. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  418. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +28 -16
  419. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
  420. package/dist/plugins/ecosystem/plugin-bootstrap.js +35 -33
  421. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
  422. package/dist/profile/plugin-profiles.d.ts +1 -1
  423. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  424. package/dist/profile/plugin-profiles.js +18 -0
  425. package/dist/profile/plugin-profiles.js.map +1 -1
  426. package/dist/remote/server-assembly.d.ts.map +1 -1
  427. package/dist/remote/server-assembly.js +7 -2
  428. package/dist/remote/server-assembly.js.map +1 -1
  429. package/dist/{profiles → suites}/builtin-suites.d.ts +14 -4
  430. package/dist/suites/builtin-suites.d.ts.map +1 -0
  431. package/dist/{profiles → suites}/builtin-suites.js +20 -5
  432. package/dist/suites/builtin-suites.js.map +1 -0
  433. package/dist/suites/resolved-agent-profile.d.ts.map +1 -0
  434. package/dist/suites/resolved-agent-profile.js.map +1 -0
  435. package/dist/suites/suite-lifecycle.d.ts.map +1 -0
  436. package/dist/suites/suite-lifecycle.js.map +1 -0
  437. package/dist/suites/suite-loader.d.ts.map +1 -0
  438. package/dist/suites/suite-loader.js.map +1 -0
  439. package/dist/{modes/interactive/theme → theme}/dark.json +1 -1
  440. package/dist/{modes/interactive/theme → theme}/light.json +1 -1
  441. package/dist/{modes/interactive/theme → theme}/theme-controller.d.ts +1 -1
  442. package/dist/theme/theme-controller.d.ts.map +1 -0
  443. package/dist/{modes/interactive/theme → theme}/theme-controller.js +1 -1
  444. package/dist/theme/theme-controller.js.map +1 -0
  445. package/dist/{modes/interactive/theme → theme}/theme.d.ts +1 -1
  446. package/dist/theme/theme.d.ts.map +1 -0
  447. package/dist/{modes/interactive/theme → theme}/theme.js +5 -5
  448. package/dist/theme/theme.js.map +1 -0
  449. package/docs/compaction.md +7 -7
  450. package/docs/environment-variables.md +10 -4
  451. package/docs/keybindings.md +3 -3
  452. package/docs/models.md +17 -17
  453. package/docs/packages.md +1 -1
  454. package/docs/prompt-templates.md +1 -1
  455. package/docs/rpc.md +2 -2
  456. package/docs/sdk.md +5 -5
  457. package/docs/session-format.md +3 -3
  458. package/docs/settings.md +368 -354
  459. package/docs/shell-aliases.md +1 -1
  460. package/docs/skills.md +1 -1
  461. package/docs/terminal-setup.md +17 -17
  462. package/docs/themes.md +5 -5
  463. package/docs/tmux.md +4 -4
  464. package/docs/tui.md +1 -1
  465. package/docs/windows.md +1 -1
  466. package/examples/extensions/bash-spawn-hook/index.ts +1 -1
  467. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  468. package/examples/extensions/with-deps/package-lock.json +2 -2
  469. package/examples/extensions/with-deps/package.json +1 -6
  470. package/examples/extensions/with-deps/plugin.json +1 -1
  471. package/package.json +2 -2
  472. package/dist/bundle/chunks/openai-responses-AUJQ3NWT.js +0 -2
  473. package/dist/bundle/chunks/virtual-modules-WF6WRHP7.js +0 -5
  474. package/dist/cli/experimental/commands/pi.d.ts +0 -15
  475. package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
  476. package/dist/cli/experimental/commands/pi.js.map +0 -1
  477. package/dist/core/export-html/ansi-to-html.d.ts.map +0 -1
  478. package/dist/core/export-html/ansi-to-html.js.map +0 -1
  479. package/dist/core/export-html/index.d.ts.map +0 -1
  480. package/dist/core/export-html/index.js.map +0 -1
  481. package/dist/core/export-html/tool-renderer.d.ts.map +0 -1
  482. package/dist/core/export-html/tool-renderer.js.map +0 -1
  483. package/dist/core/pi-manifest.d.ts +0 -7
  484. package/dist/core/pi-manifest.d.ts.map +0 -1
  485. package/dist/core/pi-manifest.js.map +0 -1
  486. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +0 -1
  487. package/dist/modes/interactive/model-catalog-refresh.js.map +0 -1
  488. package/dist/modes/interactive/theme/theme-controller.d.ts.map +0 -1
  489. package/dist/modes/interactive/theme/theme-controller.js.map +0 -1
  490. package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
  491. package/dist/modes/interactive/theme/theme.js.map +0 -1
  492. package/dist/profiles/builtin-suites.d.ts.map +0 -1
  493. package/dist/profiles/builtin-suites.js.map +0 -1
  494. package/dist/profiles/resolved-agent-profile.d.ts.map +0 -1
  495. package/dist/profiles/resolved-agent-profile.js.map +0 -1
  496. package/dist/profiles/suite-lifecycle.d.ts.map +0 -1
  497. package/dist/profiles/suite-lifecycle.js.map +0 -1
  498. package/dist/profiles/suite-loader.d.ts.map +0 -1
  499. package/dist/profiles/suite-loader.js.map +0 -1
  500. package/dist/utils/deprecation.d.ts +0 -4
  501. package/dist/utils/deprecation.d.ts.map +0 -1
  502. package/dist/utils/deprecation.js +0 -13
  503. package/dist/utils/deprecation.js.map +0 -1
  504. /package/dist/{core/export-html → export-html}/ansi-to-html.d.ts +0 -0
  505. /package/dist/{core/export-html → export-html}/ansi-to-html.js +0 -0
  506. /package/dist/{core/export-html → export-html}/template.css +0 -0
  507. /package/dist/{core/export-html → export-html}/template.html +0 -0
  508. /package/dist/{core/export-html → export-html}/template.js +0 -0
  509. /package/dist/{core/export-html → export-html}/tool-renderer.js +0 -0
  510. /package/dist/{core/export-html → export-html}/vendor/highlight.min.js +0 -0
  511. /package/dist/{core/export-html → export-html}/vendor/marked.min.js +0 -0
  512. /package/dist/{profiles → suites}/resolved-agent-profile.d.ts +0 -0
  513. /package/dist/{profiles → suites}/resolved-agent-profile.js +0 -0
  514. /package/dist/{profiles → suites}/suite-lifecycle.d.ts +0 -0
  515. /package/dist/{profiles → suites}/suite-lifecycle.js +0 -0
  516. /package/dist/{profiles → suites}/suite-loader.d.ts +0 -0
  517. /package/dist/{profiles → suites}/suite-loader.js +0 -0
  518. /package/dist/{modes/interactive/theme → theme}/theme-schema.json +0 -0
@@ -1,6 +1,6 @@
1
1
  # Shell Aliases
2
2
 
3
- Pi runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
3
+ Agent Forge runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
4
4
 
5
5
  To enable your shell aliases, add to `~/.agent-forge/agent/settings.json`:
6
6
 
package/docs/skills.md CHANGED
@@ -29,7 +29,7 @@ Agent Forge loads skills from:
29
29
  - Project (only after the project is trusted):
30
30
  - `.agent-forge/skills/`
31
31
  - `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
32
- - Legacy packages: `skills/` directories or `pi.skills` entries in `package.json`; new plugins may coordinate Skills through their public capabilities.
32
+ - Legacy packages: `skills/` directories or `agent-forge.skills` entries in `package.json`; new plugins may coordinate Skills through their public capabilities.
33
33
  - Settings: `skills` array with files or directories
34
34
  - CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
35
35
 
@@ -1,16 +1,16 @@
1
1
  # Terminal Setup
2
2
 
3
- Pi uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
3
+ Agent Forge uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
4
4
 
5
5
  ## Capability Overrides
6
6
 
7
- Pi auto-detects OSC 8 hyperlinks, inline image protocols, and truecolor. If detection fails behind a terminal proxy or multiplexer, use these advanced overrides:
7
+ Agent Forge auto-detects OSC 8 hyperlinks, inline image protocols, and truecolor. If detection fails behind a terminal proxy or multiplexer, use these advanced overrides:
8
8
 
9
9
  | Capability | Environment variable | JSON setting |
10
10
  |------------|----------------------|--------------|
11
- | OSC 8 hyperlinks | `PI_HYPERLINKS=1\|0\|auto` | `terminal.hyperlinks: true\|false\|"auto"` |
12
- | Inline images | `PI_IMAGE_PROTOCOL=kitty\|iterm2\|none\|auto` | `terminal.images: "kitty"\|"iterm2"\|false\|"auto"` |
13
- | Truecolor | `PI_TRUE_COLOR=1\|0\|auto` | `terminal.trueColor: true\|false\|"auto"` |
11
+ | OSC 8 hyperlinks | `AGENT_FORGE_HYPERLINKS=1\|0\|auto` | `terminal.hyperlinks: true\|false\|"auto"` |
12
+ | Inline images | `AGENT_FORGE_IMAGE_PROTOCOL=kitty\|iterm2\|none\|auto` | `terminal.images: "kitty"\|"iterm2"\|false\|"auto"` |
13
+ | Truecolor | `AGENT_FORGE_TRUE_COLOR=1\|0\|auto` | `terminal.trueColor: true\|false\|"auto"` |
14
14
 
15
15
  Settings take precedence over environment variables; unset or `auto` preserves detection. Only force capabilities supported by the complete terminal path, since unsupported escape sequences can corrupt rendering.
16
16
 
@@ -26,7 +26,7 @@ Works out of the box.
26
26
 
27
27
  ### Fullscreen TUI mode
28
28
 
29
- Pi owns the viewport, so iTerm2 sends mouse-wheel reports instead of scrolling its native scrollback. With iTerm2's default fast-trackpad behavior, those reports can lose most of an accelerated wheel delta, making fullscreen scrolling much slower than regular scrolling.
29
+ Agent Forge owns the viewport, so iTerm2 sends mouse-wheel reports instead of scrolling its native scrollback. With iTerm2's default fast-trackpad behavior, those reports can lose most of an accelerated wheel delta, making fullscreen scrolling much slower than regular scrolling.
30
30
 
31
31
  If fast mouse-wheel gestures move only about one line at a time in fullscreen mode:
32
32
 
@@ -37,9 +37,9 @@ This is an iTerm2-wide workaround and may also change native trackpad scrolling.
37
37
 
38
38
  ## Apple Terminal
39
39
 
40
- Pi enables enhanced key reporting when available. If Terminal.app still sends plain Return for `Shift+Enter`, pi uses a local macOS modifier fallback to treat that Return as `Shift+Enter`.
40
+ Agent Forge enables enhanced key reporting when available. If Terminal.app still sends plain Return for `Shift+Enter`, it uses a local macOS modifier fallback to treat that Return as `Shift+Enter`.
41
41
 
42
- This fallback only works when pi runs on the same Mac as Terminal.app. It cannot detect the local keyboard over remote SSH.
42
+ This fallback only works when Agent Forge runs on the same Mac as Terminal.app. It cannot detect the local keyboard over remote SSH.
43
43
 
44
44
  ## Ghostty
45
45
 
@@ -55,15 +55,15 @@ Older Claude Code versions may have added this Ghostty mapping:
55
55
  keybind = shift+enter=text:\n
56
56
  ```
57
57
 
58
- That mapping sends a raw linefeed byte. Inside pi, that is indistinguishable from `Ctrl+J`, so tmux and pi no longer see a real `shift+enter` key event.
58
+ That mapping sends a raw linefeed byte. Inside Agent Forge, that is indistinguishable from `Ctrl+J`, so tmux and Agent Forge no longer see a real `shift+enter` key event.
59
59
 
60
60
  If Claude Code 2.x or newer is the only reason you added that mapping, you can remove it, unless you want to use Claude Code in tmux, where it still requires that Ghostty mapping.
61
61
 
62
- Pi binds `Ctrl+J` as a default newline alias, so `Shift+Enter` keeps working in tmux via that remap without extra pi configuration.
62
+ Agent Forge binds `Ctrl+J` as a default newline alias, so `Shift+Enter` keeps working in tmux via that remap without extra configuration.
63
63
 
64
64
  ### Fullscreen TUI mode
65
65
 
66
- In fullscreen mode, links remain clickable, but Ghostty does not show its hover underline or lower-left URL preview while pi captures mouse input. Hold `Shift+Command` on macOS or `Shift+Ctrl` on Linux to use Ghostty's native link handling.
66
+ In fullscreen mode, links remain clickable, but Ghostty does not show its hover underline or lower-left URL preview while Agent Forge captures mouse input. Hold `Shift+Command` on macOS or `Shift+Ctrl` on Linux to use Ghostty's native link handling.
67
67
 
68
68
  ## WezTerm
69
69
 
@@ -76,7 +76,7 @@ config.enable_kitty_keyboard = true
76
76
  return config
77
77
  ```
78
78
 
79
- On macOS, WezTerm binds `Option+Enter` to fullscreen by default. To use `Option+Enter` for pi follow-up queueing, add this key override:
79
+ On macOS, WezTerm binds `Option+Enter` to fullscreen by default. To use `Option+Enter` for Agent Forge follow-up queueing, add this key override:
80
80
 
81
81
  ```lua
82
82
  local wezterm = require 'wezterm'
@@ -93,11 +93,11 @@ return config
93
93
 
94
94
  If you already have a `config.keys` table, add the entry to it.
95
95
 
96
- On WSL, WezTerm may require a visible hardware cursor for IME candidate window positioning. If CJK IME candidates do not follow the text cursor, set `PI_HARDWARE_CURSOR=1` before running pi or set `showHardwareCursor` to `true` in settings.
96
+ On WSL, WezTerm may require a visible hardware cursor for IME candidate window positioning. If CJK IME candidates do not follow the text cursor, set `AGENT_FORGE_HARDWARE_CURSOR=1` before running Agent Forge or set `showHardwareCursor` to `true` in settings.
97
97
 
98
98
  ## Alacritty
99
99
 
100
- Alacritty usually works out of the box for `Shift+Enter`. On macOS, `Option+Enter` may arrive as plain `Enter`. To use `Option+Enter` for pi follow-up queueing, add to `~/.config/alacritty/alacritty.toml`:
100
+ Alacritty usually works out of the box for `Shift+Enter`. On macOS, `Option+Enter` may arrive as plain `Enter`. To use `Option+Enter` for Agent Forge follow-up queueing, add to `~/.config/alacritty/alacritty.toml`:
101
101
 
102
102
  ```toml
103
103
  [[keyboard.bindings]]
@@ -147,11 +147,11 @@ Add these key bindings to your Zed `keymap.json`:
147
147
 
148
148
  ## Windows Terminal
149
149
 
150
- Pi uses Windows-style keybindings when running natively on Windows or in WSL:
150
+ Agent Forge uses Windows-style keybindings when running natively on Windows or in WSL:
151
151
 
152
152
  - `Alt+V` pastes an image or clipboard text.
153
153
  - `Ctrl+F` searches the transcript in fullscreen mode, and `Ctrl+Up`/`Ctrl+Down` jump between marked messages.
154
- - `Ctrl+Z` undoes editing on native Windows; WSL uses `Alt+Z` so `Ctrl+Z` can suspend pi.
154
+ - `Ctrl+Z` undoes editing on native Windows; WSL uses `Alt+Z` so `Ctrl+Z` can suspend Agent Forge.
155
155
  - Follow-up queueing and dequeue are command-only by default (`/queue`, `/dequeue`); model/thinking cycling likewise (`/model`, `/thinking`). All of them can be re-bound in `keybindings.json` (see [Keybindings](keybindings.md)).
156
156
 
157
157
  Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward `Shift+Enter` for inserting a new line:
@@ -186,6 +186,6 @@ For the best experience, use a terminal that supports the Kitty keyboard protoco
186
186
 
187
187
  The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal.
188
188
 
189
- If you want the hardware cursor visible, set `PI_HARDWARE_CURSOR=1` before running pi (disabled by default for compatibility).
189
+ If you want the hardware cursor visible, set `AGENT_FORGE_HARDWARE_CURSOR=1` before running Agent Forge (disabled by default for compatibility).
190
190
 
191
191
  Consider using a dedicated terminal emulator for the best experience.
package/docs/themes.md CHANGED
@@ -21,7 +21,7 @@ Agent Forge loads themes from:
21
21
  - Built-in: `dark`, `light`
22
22
  - Global: `~/.agent-forge/agent/themes/*.json`
23
23
  - Project: `.agent-forge/themes/*.json` (only after the project is trusted)
24
- - Legacy packages: `themes/` directories or `pi.themes` entries in `package.json`
24
+ - Legacy packages: `themes/` directories or `agent-forge.themes` entries in `package.json`
25
25
  - Settings: `themes` array with files or directories
26
26
  - CLI: `--theme <path>` (repeatable)
27
27
 
@@ -69,7 +69,7 @@ vim ~/.agent-forge/agent/themes/my-theme.json
69
69
 
70
70
  ```json
71
71
  {
72
- "$schema": "https://raw.githubusercontent.com/agent-forge/agent-forge/main/packages/agent-forge/src/modes/interactive/theme/theme-schema.json",
72
+ "$schema": "https://raw.githubusercontent.com/agent-forge/agent-forge/main/packages/agent-forge/src/theme/theme-schema.json",
73
73
  "name": "my-theme",
74
74
  "vars": {
75
75
  "primary": "#00aaff",
@@ -143,7 +143,7 @@ vim ~/.agent-forge/agent/themes/my-theme.json
143
143
 
144
144
  ```json
145
145
  {
146
- "$schema": "https://raw.githubusercontent.com/agent-forge/agent-forge/main/packages/agent-forge/src/modes/interactive/theme/theme-schema.json",
146
+ "$schema": "https://raw.githubusercontent.com/agent-forge/agent-forge/main/packages/agent-forge/src/theme/theme-schema.json",
147
147
  "name": "my-theme",
148
148
  "vars": {
149
149
  "blue": "#0066cc",
@@ -316,5 +316,5 @@ echo $COLORTERM # Should output "truecolor" or "24bit"
316
316
  ## Examples
317
317
 
318
318
  See the built-in themes:
319
- - [dark.json](../src/modes/interactive/theme/dark.json)
320
- - [light.json](../src/modes/interactive/theme/light.json)
319
+ - [dark.json](../src/theme/dark.json)
320
+ - [light.json](../src/theme/light.json)
package/docs/tmux.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tmux Setup
2
2
 
3
- Pi works inside tmux, but tmux strips modifier information from certain keys by default. Without configuration, `Shift+Enter` and `Ctrl+Enter` are usually indistinguishable from plain `Enter`.
3
+ Agent Forge works inside tmux, but tmux strips modifier information from certain keys by default. Without configuration, `Shift+Enter` and `Ctrl+Enter` are usually indistinguishable from plain `Enter`.
4
4
 
5
5
  ## Recommended Configuration
6
6
 
@@ -18,7 +18,7 @@ tmux kill-server
18
18
  tmux
19
19
  ```
20
20
 
21
- Pi requests extended key reporting automatically when Kitty keyboard protocol is not available. With `extended-keys-format csi-u`, tmux forwards modified keys in CSI-u format, which is the most reliable configuration. The `extended-keys-format` option requires tmux 3.5 or later.
21
+ Agent Forge requests extended key reporting automatically when Kitty keyboard protocol is not available. With `extended-keys-format csi-u`, tmux forwards modified keys in CSI-u format, which is the most reliable configuration. The `extended-keys-format` option requires tmux 3.5 or later.
22
22
 
23
23
  ## Why `csi-u` Is Recommended
24
24
 
@@ -40,7 +40,7 @@ With `extended-keys-format csi-u`, the same keys are forwarded as:
40
40
  - `Ctrl+D` → `\x1b[100;5u`
41
41
  - `Ctrl+Enter` → `\x1b[13;5u`
42
42
 
43
- Pi supports both formats, but `csi-u` is the recommended tmux setup.
43
+ Agent Forge supports both formats, but `csi-u` is the recommended tmux setup.
44
44
 
45
45
  ## What This Fixes
46
46
 
@@ -60,4 +60,4 @@ This affects the default keybindings (`Enter` to submit, `Shift+Enter` for newli
60
60
  - tmux 3.5 or later for `extended-keys-format csi-u` (run `tmux -V` to check)
61
61
  - A terminal emulator that supports extended keys (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminal)
62
62
 
63
- With tmux 3.2 through 3.4, omit `extended-keys-format csi-u`; Pi still supports tmux's default xterm `modifyOtherKeys` format.
63
+ With tmux 3.2 through 3.4, omit `extended-keys-format csi-u`; Agent Forge still supports tmux's default xterm `modifyOtherKeys` format.
package/docs/tui.md CHANGED
@@ -52,7 +52,7 @@ When a `Focusable` component has focus, TUI:
52
52
  3. Positions the hardware terminal cursor at that location
53
53
  4. Shows the hardware cursor only when `showHardwareCursor` is enabled
54
54
 
55
- The cursor remains hidden by default. This keeps the fake cursor rendering, while still positioning the hardware cursor for terminals that track IME candidate windows with hidden cursors. Some terminals require a visible hardware cursor for IME positioning; enable it with `showHardwareCursor`, `setShowHardwareCursor(true)`, or `PI_HARDWARE_CURSOR=1`. The `Editor` and `Input` built-in components already implement this interface.
55
+ The cursor remains hidden by default. This keeps the fake cursor rendering, while still positioning the hardware cursor for terminals that track IME candidate windows with hidden cursors. Some terminals require a visible hardware cursor for IME positioning; enable it with `showHardwareCursor`, `setShowHardwareCursor(true)`, or `AGENT_FORGE_HARDWARE_CURSOR=1`. The `Editor` and `Input` built-in components already implement this interface.
56
56
 
57
57
  ### Container Components with Embedded Inputs
58
58
 
package/docs/windows.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Windows Setup
2
2
 
3
- Pi uses Git Bash by default on Windows. Checked locations (in order):
3
+ Agent Forge uses Git Bash by default on Windows. Checked locations (in order):
4
4
 
5
5
  1. Custom path from `~/.agent-forge/agent/settings.json`
6
6
  2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
@@ -23,7 +23,7 @@ export default function (api: CapabilityAPI) {
23
23
  spawnHook: ({ command, cwd, env }) => ({
24
24
  command: `source ~/.profile\n${command}`,
25
25
  cwd,
26
- env: { ...env, PI_SPAWN_HOOK: "1" },
26
+ env: { ...env, AGENT_FORGE_SPAWN_HOOK: "1" },
27
27
  }),
28
28
  });
29
29
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/agent-forge/agent-forge/main/packages/agent-forge/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/agent-forge/agent-forge/main/packages/agent-forge/src/theme/theme-schema.json",
3
3
  "name": "dynamic-resources",
4
4
  "vars": {
5
5
  "cyan": "#00d7ff",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "agent-forge-extension-with-deps",
3
- "version": "0.87.1",
3
+ "version": "0.88.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "agent-forge-extension-with-deps",
9
- "version": "0.87.1",
9
+ "version": "0.88.3",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,18 +1,13 @@
1
1
  {
2
2
  "name": "agent-forge-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.87.1",
4
+ "version": "0.88.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
8
8
  "build": "echo 'nothing to build'",
9
9
  "check": "echo 'nothing to check'"
10
10
  },
11
- "pi": {
12
- "extensions": [
13
- "./index.ts"
14
- ]
15
- },
16
11
  "dependencies": {
17
12
  "ms": "2.1.3"
18
13
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "agent-forge.example.with-deps",
3
- "version": "0.87.1",
3
+ "version": "0.88.3",
4
4
  "hostVersion": ">=0.84.0",
5
5
  "apiVersion": "1-draft",
6
6
  "entry": "./index.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-agent-forge/agent-forge",
3
- "version": "0.88.1",
3
+ "version": "0.88.3",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "agentForgeConfig": {
@@ -41,7 +41,7 @@
41
41
  "clean": "shx rm -rf dist",
42
42
  "build": "npm run build:unbundled && node ../../scripts/build-agent-forge-bundle.mjs",
43
43
  "build:unbundled": "npm run clean && tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
44
- "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
44
+ "copy-assets": "shx mkdir -p dist/theme && shx cp src/theme/*.json dist/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/export-html/template.html src/export-html/template.css src/export-html/template.js dist/export-html/ && shx cp src/export-html/vendor/*.js dist/export-html/vendor/",
45
45
  "test": "vitest --run",
46
46
  "shrinkwrap": "node ../../scripts/generate-agent-forge-shrinkwrap.mjs",
47
47
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap",
@@ -1,2 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{convertResponsesMessages,convertResponsesTools,processResponsesStream}from"./chunk-HTEVUY7F.js";import{clampOpenAIPromptCacheKey}from"./chunk-PRRNXB7S.js";import{OpenAI}from"./chunk-OO6DJ3CL.js";import{formatProviderError,normalizeProviderError}from"./chunk-TEPMHNKQ.js";import"./chunk-PJACZCIR.js";import{splitDeferredTools}from"./chunk-GMWCTUPB.js";import{buildCopilotDynamicHeaders,hasCopilotVisionInput}from"./chunk-PGXDEOVV.js";import{retryProviderRequest}from"./chunk-WW3LMV3F.js";import"./chunk-EWXX34QG.js";import{buildBaseOptions,createGrammarToolInputProperties,getPiUserAgent}from"./chunk-TBPTHASB.js";import"./chunk-L2ZPNLYD.js";import{headersToRecord}from"./chunk-6R7UI4IY.js";import{getProviderEnvValue}from"./chunk-DRQDKNXA.js";import"./chunk-TRDNDS6A.js";import{clampThinkingLevel}from"./chunk-HV64ASMT.js";import{AssistantMessageEventStream}from"./chunk-A3JYRWB6.js";import"./chunk-4L3WN2XY.js";var OPENAI_TOOL_CALL_PROVIDERS=new Set(["openai","openai-codex","opencode"]),OPENAI_RESPONSES_MIN_OUTPUT_TOKENS=16;function hasHeader(headers,name){if(!headers)return!1;let expected=name.toLowerCase();for(let[key,value]of Object.entries(headers))if(key.toLowerCase()===expected&&value!==null&&value.trim().length>0)return!0;return!1}function getClientApiKey(provider,apiKey,headers){if(apiKey)return apiKey;if(hasHeader(headers,"authorization")||hasHeader(headers,"cf-aig-authorization"))return"unused";throw new Error(`No API key for provider: ${provider}`)}function detectSessionAffinityFormat(model){return model.provider==="openrouter"||model.baseUrl.includes("openrouter.ai")?"openrouter":"openai"}function resolveCacheRetention(cacheRetention,env){return cacheRetention||(getProviderEnvValue("AGENT_FORGE_CACHE_RETENTION",env)==="long"?"long":"short")}function getCompat(model){return{supportsDeveloperRole:model.compat?.supportsDeveloperRole??!0,sessionAffinityFormat:model.compat?.sessionAffinityFormat??detectSessionAffinityFormat(model),supportsLongCacheRetention:model.compat?.supportsLongCacheRetention??!0,supportsStrictMode:model.compat?.supportsStrictMode??!1,supportsOpenAIGrammarTools:model.compat?.supportsOpenAIGrammarTools??!1,supportsAdditionalTools:model.compat?.supportsAdditionalTools??!1,supportsToolSearch:model.compat?.supportsToolSearch??!1,supportsExplicitPromptCacheMode:model.compat?.supportsExplicitPromptCacheMode??!1,supportsMaxOutputTokens:model.compat?.supportsMaxOutputTokens??!0}}function getPromptCacheRetention(compat,cacheRetention){return cacheRetention==="long"&&compat.supportsLongCacheRetention&&!compat.supportsExplicitPromptCacheMode?"24h":void 0}function getPromptCacheOptions(compat,cacheRetention){if(compat.supportsExplicitPromptCacheMode){if(cacheRetention==="none")return{mode:"explicit"};if(cacheRetention==="long"&&compat.supportsLongCacheRetention)return{ttl:"30m"}}}var stream=(model,context,options)=>{let stream2=new AssistantMessageEventStream;return(async()=>{let output={role:"assistant",content:[],api:model.api,provider:model.provider,model:model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};try{let apiKey=getClientApiKey(model.provider,options?.apiKey,options?.headers),cacheSessionId=resolveCacheRetention(options?.cacheRetention,options?.env)==="none"?void 0:options?.sessionId,compat=getCompat(model),grammarToolInputProperties=createGrammarToolInputProperties(context.tools,compat.supportsOpenAIGrammarTools),client=createClient(model,context,apiKey,options?.headers,options?.fetch,cacheSessionId),params=buildParams(model,context,options,compat,grammarToolInputProperties),nextParams=await options?.onPayload?.(params,model);nextParams!==void 0&&(params=nextParams);let requestOptions={...options?.signal?{signal:options.signal}:{},...options?.timeoutMs!==void 0?{timeout:options.timeoutMs}:{},maxRetries:0},{data:openaiStream,response}=await retryProviderRequest(()=>client.responses.create(params,requestOptions).withResponse(),{maxRetries:options?.maxRetries,maxRetryDelayMs:options?.maxRetryDelayMs,signal:options?.signal});if(await options?.onResponse?.({status:response.status,headers:headersToRecord(response.headers)},model),stream2.push({type:"start",partial:output}),await processResponsesStream(openaiStream,output,stream2,model,{serviceTier:options?.serviceTier,grammarToolInputProperties,applyServiceTierPricing:(usage,serviceTier)=>applyServiceTierPricing(usage,serviceTier,model)}),options?.signal?.aborted)throw new Error("Request was aborted");if(output.stopReason==="pending")throw new Error("OpenAI Responses stream ended without a stop reason");if(output.stopReason==="aborted"||output.stopReason==="error")throw new Error(output.errorMessage||"An unknown error occurred");stream2.push({type:"done",reason:output.stopReason,message:output}),stream2.end()}catch(error){for(let block of output.content)delete block.index,delete block.partialJson,delete block.customInput;output.stopReason=options?.signal?.aborted?"aborted":"error",output.errorMessage=formatProviderError(normalizeProviderError(error),`${model.provider==="openai"?"OpenAI":model.provider} API error`),stream2.push({type:"error",reason:output.stopReason,error:output}),stream2.end()}})(),stream2},streamSimple=(model,context,options)=>{getClientApiKey(model.provider,options?.apiKey,options?.headers);let base={...buildBaseOptions(model,context,options,options?.apiKey),toolChoice:options?.toolChoice},clampedReasoning=options?.reasoning?clampThinkingLevel(model,options.reasoning):void 0;return stream(model,context,{...base,reasoningEffort:clampedReasoning==="off"?void 0:clampedReasoning})};function createClient(model,context,apiKey,optionsHeaders,fetch,sessionId){let compat=getCompat(model),headers={"User-Agent":getPiUserAgent(),...model.headers};if(model.provider==="github-copilot"){let hasImages=hasCopilotVisionInput(context.messages),copilotHeaders=buildCopilotDynamicHeaders({messages:context.messages,hasImages});Object.assign(headers,copilotHeaders)}return sessionId&&(compat.sessionAffinityFormat==="openrouter"?headers["x-session-id"]=sessionId:(compat.sessionAffinityFormat==="openai"&&(headers.session_id=sessionId),headers["x-client-request-id"]=sessionId)),optionsHeaders&&Object.assign(headers,optionsHeaders),new OpenAI({apiKey,baseURL:model.baseUrl,dangerouslyAllowBrowser:!0,fetch,defaultHeaders:headers})}function buildParams(model,context,options,compat=getCompat(model),grammarToolInputProperties=createGrammarToolInputProperties(context.tools,compat.supportsOpenAIGrammarTools)){let deferredToolsMode=compat.supportsAdditionalTools?"additional-tools":compat.supportsToolSearch?"tool-search":void 0,toolPlacement=splitDeferredTools(context,deferredToolsMode!==void 0),messages=convertResponsesMessages(model,context,OPENAI_TOOL_CALL_PROVIDERS,{grammarToolInputProperties,deferredTools:toolPlacement.deferred,deferredToolsMode,toolOptions:{supportsStrictMode:compat.supportsStrictMode,supportsOpenAIGrammarTools:compat.supportsOpenAIGrammarTools}}),cacheRetention=resolveCacheRetention(options?.cacheRetention,options?.env),params={model:model.id,input:messages,stream:!0,prompt_cache_key:cacheRetention==="none"?void 0:clampOpenAIPromptCacheKey(options?.sessionId),prompt_cache_retention:getPromptCacheRetention(compat,cacheRetention),prompt_cache_options:getPromptCacheOptions(compat,cacheRetention),store:!1};if(options?.maxTokens&&compat.supportsMaxOutputTokens&&(params.max_output_tokens=Math.max(options.maxTokens,OPENAI_RESPONSES_MIN_OUTPUT_TOKENS)),options?.temperature!==void 0&&(params.temperature=options?.temperature),options?.serviceTier!==void 0&&(params.service_tier=options.serviceTier),toolPlacement.immediate.length>0&&(params.tools=convertResponsesTools(toolPlacement.immediate,{supportsStrictMode:compat.supportsStrictMode,supportsOpenAIGrammarTools:compat.supportsOpenAIGrammarTools})),options?.toolChoice!==void 0&&(params.tool_choice=options.toolChoice),model.reasoning){if(options?.reasoningEffort||options?.reasoningSummary){let effort=options?.reasoningEffort?model.thinkingLevelMap?.[options.reasoningEffort]??options.reasoningEffort:"medium";params.reasoning={effort,summary:options?.reasoningSummary||"auto"},params.include=["reasoning.encrypted_content"]}else model.provider!=="github-copilot"&&model.thinkingLevelMap?.off!==null&&(params.reasoning={effort:model.thinkingLevelMap?.off??"none"});model.provider==="xai"&&(params.include=["reasoning.encrypted_content"])}return Object.assign(params,model.samplingParams,options?.samplingParams),params}function getServiceTierCostMultiplier(model,serviceTier){switch(serviceTier){case"flex":return .5;case"priority":case"fast":return model.id==="gpt-5.5"?2.5:2;default:return 1}}function applyServiceTierPricing(usage,serviceTier,model){let multiplier=getServiceTierCostMultiplier(model,serviceTier);multiplier!==1&&(usage.cost.input*=multiplier,usage.cost.output*=multiplier,usage.cost.cacheRead*=multiplier,usage.cost.cacheWrite*=multiplier,usage.cost.total=usage.cost.input+usage.cost.output+usage.cost.cacheRead+usage.cost.cacheWrite)}export{stream,streamSimple};
@@ -1,5 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{diff_exports}from"./chunk-Z72JWUZ4.js";import{DEFAULT_MAX_BYTES,DEFAULT_MAX_LINES,ansi_exports,bash_operations_exports,build_exports,child_process_exports,compaction_exports,compat_exports,dist_exports,dist_exports2,edit_diff_exports,file_mutation_queue_exports,image_process_exports,keybinding_hints_exports,mime_exports,path_utils_exports,paths_exports,readme_path_exports,render_utils_exports,require_undici,session_lineage_exports,shell_exports,subagent_exports,text_exports,theme_exports,tool_definition_exports,tools_manager_exports,truncateTail,truncate_exports,value_exports,visual_truncate_exports}from"./chunk-AQLNTW2B.js";import"./chunk-JUUC5AZY.js";import"./chunk-XDUWOHPL.js";import{i18n_exports,t}from"./chunk-D3ARGZFR.js";import"./chunk-DRQDKNXA.js";import"./chunk-TRDNDS6A.js";import"./chunk-HV64ASMT.js";import"./chunk-A3JYRWB6.js";import{__export,__toESM}from"./chunk-4L3WN2XY.js";var undici=__toESM(require_undici(),1);var output_accumulator_exports={};__export(output_accumulator_exports,{OutputAccumulator:()=>OutputAccumulator});import{randomBytes}from"node:crypto";import{createWriteStream}from"node:fs";import{tmpdir}from"node:os";import{join}from"node:path";function defaultTempFilePath(prefix){let id=randomBytes(8).toString("hex");return join(tmpdir(),`${prefix}-${id}.log`)}function byteLength(text){return Buffer.byteLength(text,"utf-8")}var OutputAccumulator=class{maxLines;maxBytes;maxRollingBytes;tempFilePrefix;decoder=new TextDecoder;rawChunks=[];tailText="";tailBytes=0;tailStartsAtLineBoundary=!0;totalRawBytes=0;totalDecodedBytes=0;completedLines=0;totalLines=0;currentLineBytes=0;hasOpenLine=!1;finished=!1;tempFilePath;tempFileStream;constructor(options={}){this.maxLines=options.maxLines??2e3,this.maxBytes=options.maxBytes??51200,this.maxRollingBytes=Math.max(this.maxBytes*2,1),this.tempFilePrefix=options.tempFilePrefix??"agent-forge-output"}append(data){if(this.finished)throw new Error(t("Cannot append to a finished output accumulator"));this.totalRawBytes+=data.length,this.appendDecodedText(this.decoder.decode(data,{stream:!0})),this.tempFileStream||this.shouldUseTempFile()?(this.ensureTempFile(),this.tempFileStream?.write(data)):data.length>0&&this.rawChunks.push(data)}finish(){this.finished||(this.finished=!0,this.appendDecodedText(this.decoder.decode()),this.shouldUseTempFile()&&this.ensureTempFile())}snapshot(options={}){let tailTruncation=truncateTail(this.getSnapshotText(),{maxLines:this.maxLines,maxBytes:this.maxBytes}),truncated=this.totalLines>this.maxLines||this.totalDecodedBytes>this.maxBytes,truncatedBy=truncated?tailTruncation.truncatedBy??(this.totalDecodedBytes>this.maxBytes?"bytes":"lines"):null,truncation={...tailTruncation,truncated,truncatedBy,totalLines:this.totalLines,totalBytes:this.totalDecodedBytes,maxLines:this.maxLines,maxBytes:this.maxBytes};return options.persistIfTruncated&&truncation.truncated&&this.ensureTempFile(),{content:truncation.content,truncation,fullOutputPath:this.tempFilePath}}async closeTempFile(){if(!this.tempFileStream)return;let stream=this.tempFileStream;this.tempFileStream=void 0,await new Promise((resolve,reject)=>{let onError=error=>{stream.off("finish",onFinish),reject(error)},onFinish=()=>{stream.off("error",onError),resolve()};stream.once("error",onError),stream.once("finish",onFinish),stream.end()})}getLastLineBytes(){return this.currentLineBytes}appendDecodedText(text){if(text.length===0)return;let bytes=byteLength(text);this.totalDecodedBytes+=bytes,this.tailText+=text,this.tailBytes+=bytes,this.tailBytes>this.maxRollingBytes*2&&this.trimTail();let newlines=0,lastNewline=-1;for(let i=text.indexOf(`
3
- `);i!==-1;i=text.indexOf(`
4
- `,i+1))newlines++,lastNewline=i;if(newlines===0)this.currentLineBytes+=bytes,this.hasOpenLine=!0;else{this.completedLines+=newlines;let tail=text.slice(lastNewline+1);this.currentLineBytes=byteLength(tail),this.hasOpenLine=tail.length>0}this.totalLines=this.completedLines+(this.hasOpenLine?1:0)}trimTail(){let buffer=Buffer.from(this.tailText,"utf-8");if(buffer.length<=this.maxRollingBytes){this.tailBytes=buffer.length;return}let start=buffer.length-this.maxRollingBytes;for(;start<buffer.length&&(buffer[start]&192)===128;)start++;this.tailStartsAtLineBoundary=start===0?this.tailStartsAtLineBoundary:buffer[start-1]===10,this.tailText=buffer.subarray(start).toString("utf-8"),this.tailBytes=byteLength(this.tailText)}getSnapshotText(){if(this.tailStartsAtLineBoundary)return this.tailText;let firstNewline=this.tailText.indexOf(`
5
- `);return firstNewline===-1?this.tailText:this.tailText.slice(firstNewline+1)}shouldUseTempFile(){return this.totalRawBytes>this.maxBytes||this.totalDecodedBytes>this.maxBytes||this.totalLines>this.maxLines}ensureTempFile(){if(!this.tempFilePath){this.tempFilePath=defaultTempFilePath(this.tempFilePrefix),this.tempFileStream=createWriteStream(this.tempFilePath);for(let chunk of this.rawChunks)this.tempFileStream.write(chunk);this.rawChunks=[]}}};var VIRTUAL_MODULES={"@agent-forge/plugin-sdk":dist_exports2,"@agent-forge/plugin-sdk/session-lineage":session_lineage_exports,"@agent-forge/protocol/subagent":subagent_exports,typebox:build_exports,"typebox/value":value_exports,undici,"@agent-forge/tui":{...dist_exports},"@agent-forge/ai/compat":{...compat_exports},"@agent-forge/host/compaction":{...compaction_exports},"@agent-forge/host/i18n":{...i18n_exports},"@agent-forge/host/theme":{...theme_exports},"@agent-forge/host/keybinding-hints":{...keybinding_hints_exports},"@agent-forge/host/visual-truncate":{...visual_truncate_exports},"@agent-forge/host/diff":{...diff_exports},"@agent-forge/host/render-utils":{...render_utils_exports},"@agent-forge/host/tool-definition":{...tool_definition_exports},"@agent-forge/host/truncate":{...truncate_exports},"@agent-forge/host/edit-diff":{...edit_diff_exports},"@agent-forge/host/file-mutation-queue":{...file_mutation_queue_exports},"@agent-forge/host/output-accumulator":{...output_accumulator_exports},"@agent-forge/host/path-utils":{...path_utils_exports},"@agent-forge/host/readme-path":{...readme_path_exports},"@agent-forge/host/paths":{...paths_exports},"@agent-forge/host/shell":{...shell_exports},"@agent-forge/host/text":{...text_exports},"@agent-forge/host/ansi":{...ansi_exports},"@agent-forge/host/mime":{...mime_exports},"@agent-forge/host/image-process":{...image_process_exports},"@agent-forge/host/child-process":{...child_process_exports},"@agent-forge/host/tools-manager":{...tools_manager_exports},"@agent-forge/host/bash-operations":{...bash_operations_exports}};export{VIRTUAL_MODULES};
@@ -1,15 +0,0 @@
1
- import type { Args } from "../../args.ts";
2
- import type { AuthInput } from "../auth.ts";
3
- import { Command } from "../command.ts";
4
- import type { TransportAddress } from "../transport-address.ts";
5
- export interface PiCommand {
6
- readonly command: "pi";
7
- readonly auth?: AuthInput;
8
- readonly options: Args;
9
- readonly listen?: readonly TransportAddress[];
10
- }
11
- export interface PiCommandContext {
12
- runPi(command: PiCommand): void | Promise<void>;
13
- }
14
- export declare const piCommand: Command<PiCommand, PiCommandContext, PiCommand>;
15
- //# sourceMappingURL=pi.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../../../src/cli/experimental/commands/pi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAQxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAID,eAAO,MAAM,SAAS,iDAoBgC,CAAC","sourcesContent":["import type { Args } from \"../../args.ts\";\nimport type { AuthInput } from \"../auth.ts\";\nimport { Command } from \"../command.ts\";\nimport {\n\tauthTokenFileOption,\n\tauthTokenOption,\n\tparseAuth,\n\tparseLegacyOptions,\n\ttransportOption,\n} from \"../command-options.ts\";\nimport type { TransportAddress } from \"../transport-address.ts\";\n\nexport interface PiCommand {\n\treadonly command: \"pi\";\n\treadonly auth?: AuthInput;\n\treadonly options: Args;\n\treadonly listen?: readonly TransportAddress[];\n}\n\nexport interface PiCommandContext {\n\trunPi(command: PiCommand): void | Promise<void>;\n}\n\nconst listenOption = transportOption(\"--listen\");\n\nexport const piCommand = new Command<PiCommand, PiCommandContext>(\"pi\")\n\t.option(listenOption)\n\t.option(authTokenOption)\n\t.option(authTokenFileOption)\n\t.build((input) => {\n\t\tconst { auth, errors: authErrors } = parseAuth(input);\n\t\tconst listen = input.values(listenOption);\n\t\tconst { options, errors: optionErrors } = parseLegacyOptions(input);\n\t\tconst errors = [...authErrors, ...optionErrors];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\treturn {\n\t\t\tok: true,\n\t\t\tcommand: {\n\t\t\t\tcommand: \"pi\",\n\t\t\t\toptions,\n\t\t\t\t...(auth === undefined ? {} : { auth }),\n\t\t\t\t...(listen.length === 0 ? {} : { listen }),\n\t\t\t},\n\t\t};\n\t})\n\t.action((command, context) => context.runPi(command));\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.js","sourceRoot":"","sources":["../../../../src/cli/experimental/commands/pi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,kBAAkB,EAClB,eAAe,GACf,MAAM,uBAAuB,CAAC;AAc/B,MAAM,YAAY,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;AAEjD,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAA8B,IAAI,CAAC;KACrE,MAAM,CAAC,YAAY,CAAC;KACpB,MAAM,CAAC,eAAe,CAAC;KACvB,MAAM,CAAC,mBAAmB,CAAC;KAC3B,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;IACjB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACpD,OAAO;QACN,EAAE,EAAE,IAAI;QACR,OAAO,EAAE;YACR,OAAO,EAAE,IAAI;YACb,OAAO;YACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACvC,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;SAC1C;KACD,CAAC;AAAA,CACF,CAAC;KACD,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC","sourcesContent":["import type { Args } from \"../../args.ts\";\nimport type { AuthInput } from \"../auth.ts\";\nimport { Command } from \"../command.ts\";\nimport {\n\tauthTokenFileOption,\n\tauthTokenOption,\n\tparseAuth,\n\tparseLegacyOptions,\n\ttransportOption,\n} from \"../command-options.ts\";\nimport type { TransportAddress } from \"../transport-address.ts\";\n\nexport interface PiCommand {\n\treadonly command: \"pi\";\n\treadonly auth?: AuthInput;\n\treadonly options: Args;\n\treadonly listen?: readonly TransportAddress[];\n}\n\nexport interface PiCommandContext {\n\trunPi(command: PiCommand): void | Promise<void>;\n}\n\nconst listenOption = transportOption(\"--listen\");\n\nexport const piCommand = new Command<PiCommand, PiCommandContext>(\"pi\")\n\t.option(listenOption)\n\t.option(authTokenOption)\n\t.option(authTokenFileOption)\n\t.build((input) => {\n\t\tconst { auth, errors: authErrors } = parseAuth(input);\n\t\tconst listen = input.values(listenOption);\n\t\tconst { options, errors: optionErrors } = parseLegacyOptions(input);\n\t\tconst errors = [...authErrors, ...optionErrors];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\treturn {\n\t\t\tok: true,\n\t\t\tcommand: {\n\t\t\t\tcommand: \"pi\",\n\t\t\t\toptions,\n\t\t\t\t...(auth === undefined ? {} : { auth }),\n\t\t\t\t...(listen.length === 0 ? {} : { listen }),\n\t\t\t},\n\t\t};\n\t})\n\t.action((command, context) => context.runPi(command));\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ansi-to-html.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/ansi-to-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAuLH;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoD/C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvD","sourcesContent":["/**\n * ANSI escape code to HTML converter.\n *\n * Converts terminal ANSI color/style codes to HTML with inline styles.\n * Supports:\n * - Standard foreground colors (30-37) and bright variants (90-97)\n * - Standard background colors (40-47) and bright variants (100-107)\n * - 256-color palette (38;5;N and 48;5;N)\n * - RGB true color (38;2;R;G;B and 48;2;R;G;B)\n * - Text styles: bold (1), dim (2), italic (3), underline (4)\n * - Reset (0)\n */\n\n// Standard ANSI color palette (0-15)\nconst ANSI_COLORS = [\n\t\"#000000\", // 0: black\n\t\"#800000\", // 1: red\n\t\"#008000\", // 2: green\n\t\"#808000\", // 3: yellow\n\t\"#000080\", // 4: blue\n\t\"#800080\", // 5: magenta\n\t\"#008080\", // 6: cyan\n\t\"#c0c0c0\", // 7: white\n\t\"#808080\", // 8: bright black\n\t\"#ff0000\", // 9: bright red\n\t\"#00ff00\", // 10: bright green\n\t\"#ffff00\", // 11: bright yellow\n\t\"#0000ff\", // 12: bright blue\n\t\"#ff00ff\", // 13: bright magenta\n\t\"#00ffff\", // 14: bright cyan\n\t\"#ffffff\", // 15: bright white\n];\n\n/**\n * Convert 256-color index to hex.\n */\nfunction color256ToHex(index: number): string {\n\t// Standard colors (0-15)\n\tif (index < 16) {\n\t\treturn ANSI_COLORS[index];\n\t}\n\n\t// Color cube (16-231): 6x6x6 = 216 colors\n\tif (index < 232) {\n\t\tconst cubeIndex = index - 16;\n\t\tconst r = Math.floor(cubeIndex / 36);\n\t\tconst g = Math.floor((cubeIndex % 36) / 6);\n\t\tconst b = cubeIndex % 6;\n\t\tconst toComponent = (n: number) => (n === 0 ? 0 : 55 + n * 40);\n\t\tconst toHex = (n: number) => toComponent(n).toString(16).padStart(2, \"0\");\n\t\treturn `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n\t}\n\n\t// Grayscale (232-255): 24 shades\n\tconst gray = 8 + (index - 232) * 10;\n\tconst grayHex = gray.toString(16).padStart(2, \"0\");\n\treturn `#${grayHex}${grayHex}${grayHex}`;\n}\n\n/**\n * Escape HTML special characters.\n */\nfunction escapeHtml(text: string): string {\n\treturn text\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&#039;\");\n}\n\ninterface TextStyle {\n\tfg: string | null;\n\tbg: string | null;\n\tbold: boolean;\n\tdim: boolean;\n\titalic: boolean;\n\tunderline: boolean;\n}\n\nfunction createEmptyStyle(): TextStyle {\n\treturn {\n\t\tfg: null,\n\t\tbg: null,\n\t\tbold: false,\n\t\tdim: false,\n\t\titalic: false,\n\t\tunderline: false,\n\t};\n}\n\nfunction styleToInlineCSS(style: TextStyle): string {\n\tconst parts: string[] = [];\n\tif (style.fg) parts.push(`color:${style.fg}`);\n\tif (style.bg) parts.push(`background-color:${style.bg}`);\n\tif (style.bold) parts.push(\"font-weight:bold\");\n\tif (style.dim) parts.push(\"opacity:0.6\");\n\tif (style.italic) parts.push(\"font-style:italic\");\n\tif (style.underline) parts.push(\"text-decoration:underline\");\n\treturn parts.join(\";\");\n}\n\nfunction hasStyle(style: TextStyle): boolean {\n\treturn style.fg !== null || style.bg !== null || style.bold || style.dim || style.italic || style.underline;\n}\n\n/**\n * Parse ANSI SGR (Select Graphic Rendition) codes and update style.\n */\nfunction applySgrCode(params: number[], style: TextStyle): void {\n\tlet i = 0;\n\twhile (i < params.length) {\n\t\tconst code = params[i];\n\n\t\tif (code === 0) {\n\t\t\t// Reset all\n\t\t\tstyle.fg = null;\n\t\t\tstyle.bg = null;\n\t\t\tstyle.bold = false;\n\t\t\tstyle.dim = false;\n\t\t\tstyle.italic = false;\n\t\t\tstyle.underline = false;\n\t\t} else if (code === 1) {\n\t\t\tstyle.bold = true;\n\t\t} else if (code === 2) {\n\t\t\tstyle.dim = true;\n\t\t} else if (code === 3) {\n\t\t\tstyle.italic = true;\n\t\t} else if (code === 4) {\n\t\t\tstyle.underline = true;\n\t\t} else if (code === 22) {\n\t\t\t// Reset bold/dim\n\t\t\tstyle.bold = false;\n\t\t\tstyle.dim = false;\n\t\t} else if (code === 23) {\n\t\t\tstyle.italic = false;\n\t\t} else if (code === 24) {\n\t\t\tstyle.underline = false;\n\t\t} else if (code >= 30 && code <= 37) {\n\t\t\t// Standard foreground colors\n\t\t\tstyle.fg = ANSI_COLORS[code - 30];\n\t\t} else if (code === 38) {\n\t\t\t// Extended foreground color\n\t\t\tif (params[i + 1] === 5 && params.length > i + 2) {\n\t\t\t\t// 256-color: 38;5;N\n\t\t\t\tstyle.fg = color256ToHex(params[i + 2]);\n\t\t\t\ti += 2;\n\t\t\t} else if (params[i + 1] === 2 && params.length > i + 4) {\n\t\t\t\t// RGB: 38;2;R;G;B\n\t\t\t\tconst r = params[i + 2];\n\t\t\t\tconst g = params[i + 3];\n\t\t\t\tconst b = params[i + 4];\n\t\t\t\tstyle.fg = `rgb(${r},${g},${b})`;\n\t\t\t\ti += 4;\n\t\t\t}\n\t\t} else if (code === 39) {\n\t\t\t// Default foreground\n\t\t\tstyle.fg = null;\n\t\t} else if (code >= 40 && code <= 47) {\n\t\t\t// Standard background colors\n\t\t\tstyle.bg = ANSI_COLORS[code - 40];\n\t\t} else if (code === 48) {\n\t\t\t// Extended background color\n\t\t\tif (params[i + 1] === 5 && params.length > i + 2) {\n\t\t\t\t// 256-color: 48;5;N\n\t\t\t\tstyle.bg = color256ToHex(params[i + 2]);\n\t\t\t\ti += 2;\n\t\t\t} else if (params[i + 1] === 2 && params.length > i + 4) {\n\t\t\t\t// RGB: 48;2;R;G;B\n\t\t\t\tconst r = params[i + 2];\n\t\t\t\tconst g = params[i + 3];\n\t\t\t\tconst b = params[i + 4];\n\t\t\t\tstyle.bg = `rgb(${r},${g},${b})`;\n\t\t\t\ti += 4;\n\t\t\t}\n\t\t} else if (code === 49) {\n\t\t\t// Default background\n\t\t\tstyle.bg = null;\n\t\t} else if (code >= 90 && code <= 97) {\n\t\t\t// Bright foreground colors\n\t\t\tstyle.fg = ANSI_COLORS[code - 90 + 8];\n\t\t} else if (code >= 100 && code <= 107) {\n\t\t\t// Bright background colors\n\t\t\tstyle.bg = ANSI_COLORS[code - 100 + 8];\n\t\t}\n\t\t// Ignore unrecognized codes\n\n\t\ti++;\n\t}\n}\n\n// Match ANSI escape sequences: ESC[ followed by params and ending with 'm'\nconst ANSI_REGEX = /\\x1b\\[([\\d;]*)m/g;\n\n/**\n * Convert ANSI-escaped text to HTML with inline styles.\n */\nexport function ansiToHtml(text: string): string {\n\tconst style = createEmptyStyle();\n\tlet result = \"\";\n\tlet lastIndex = 0;\n\tlet inSpan = false;\n\n\t// Reset regex state\n\tANSI_REGEX.lastIndex = 0;\n\n\tlet match = ANSI_REGEX.exec(text);\n\twhile (match !== null) {\n\t\t// Add text before this escape sequence\n\t\tconst beforeText = text.slice(lastIndex, match.index);\n\t\tif (beforeText) {\n\t\t\tresult += escapeHtml(beforeText);\n\t\t}\n\n\t\t// Parse SGR parameters\n\t\tconst paramStr = match[1];\n\t\tconst params = paramStr ? paramStr.split(\";\").map((p) => parseInt(p, 10) || 0) : [0];\n\n\t\t// Close existing span if we have one\n\t\tif (inSpan) {\n\t\t\tresult += \"</span>\";\n\t\t\tinSpan = false;\n\t\t}\n\n\t\t// Apply the codes\n\t\tapplySgrCode(params, style);\n\n\t\t// Open new span if we have any styling\n\t\tif (hasStyle(style)) {\n\t\t\tresult += `<span style=\"${styleToInlineCSS(style)}\">`;\n\t\t\tinSpan = true;\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t\tmatch = ANSI_REGEX.exec(text);\n\t}\n\n\t// Add remaining text\n\tconst remainingText = text.slice(lastIndex);\n\tif (remainingText) {\n\t\tresult += escapeHtml(remainingText);\n\t}\n\n\t// Close any open span\n\tif (inSpan) {\n\t\tresult += \"</span>\";\n\t}\n\n\treturn result;\n}\n\n/**\n * Convert array of ANSI-escaped lines to HTML.\n * Each line is wrapped in a div element.\n */\nexport function ansiLinesToHtml(lines: string[]): string {\n\treturn lines.map((line) => `<div class=\"ansi-line\">${ansiToHtml(line) || \"&nbsp;\"}</div>`).join(\"\");\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ansi-to-html.js","sourceRoot":"","sources":["../../../src/core/export-html/ansi-to-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qCAAqC;AACrC,MAAM,WAAW,GAAG;IACnB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,YAAY;IACvB,SAAS,EAAE,UAAU;IACrB,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,UAAU;IACrB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,gBAAgB;IAC3B,SAAS,EAAE,mBAAmB;IAC9B,SAAS,EAAE,oBAAoB;IAC/B,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,qBAAqB;IAChC,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,mBAAmB;CAC9B,CAAC;AAEF;;GAEG;AACH,SAAS,aAAa,CAAC,KAAa,EAAU;IAC7C,yBAAyB;IACzB,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QAChB,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,0CAA0C;IAC1C,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,KAAK,GAAG,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;QACxB,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1E,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,CAAC;IAED,iCAAiC;IACjC,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE,CAAC;AAAA,CACzC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY,EAAU;IACzC,OAAO,IAAI;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,CAC1B;AAWD,SAAS,gBAAgB,GAAc;IACtC,OAAO;QACN,EAAE,EAAE,IAAI;QACR,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,KAAK;QACV,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,KAAK;KAChB,CAAC;AAAA,CACF;AAED,SAAS,gBAAgB,CAAC,KAAgB,EAAU;IACnD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9C,IAAI,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,oBAAoB,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClD,IAAI,KAAK,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAAA,CACvB;AAED,SAAS,QAAQ,CAAC,KAAgB,EAAW;IAC5C,OAAO,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC;AAAA,CAC5G;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,MAAgB,EAAE,KAAgB,EAAQ;IAC/D,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAEvB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YAChB,YAAY;YACZ,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;YACnB,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC;YAClB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;YACrB,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;QAClB,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,iBAAiB;YACjB,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;YACnB,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC;QACnB,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;QACtB,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;YACrC,6BAA6B;YAC7B,KAAK,CAAC,EAAE,GAAG,WAAW,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,4BAA4B;YAC5B,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClD,oBAAoB;gBACpB,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACxC,CAAC,IAAI,CAAC,CAAC;YACR,CAAC;iBAAM,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzD,kBAAkB;gBAClB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxB,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBACjC,CAAC,IAAI,CAAC,CAAC;YACR,CAAC;QACF,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,qBAAqB;YACrB,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;YACrC,6BAA6B;YAC7B,KAAK,CAAC,EAAE,GAAG,WAAW,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,4BAA4B;YAC5B,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClD,oBAAoB;gBACpB,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACxC,CAAC,IAAI,CAAC,CAAC;YACR,CAAC;iBAAM,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzD,kBAAkB;gBAClB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxB,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBACjC,CAAC,IAAI,CAAC,CAAC;YACR,CAAC;QACF,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxB,qBAAqB;YACrB,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;YACrC,2BAA2B;YAC3B,KAAK,CAAC,EAAE,GAAG,WAAW,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;YACvC,2BAA2B;YAC3B,KAAK,CAAC,EAAE,GAAG,WAAW,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;QACxC,CAAC;QACD,4BAA4B;QAE5B,CAAC,EAAE,CAAC;IACL,CAAC;AAAA,CACD;AAED,2EAA2E;AAC3E,MAAM,UAAU,GAAG,kBAAkB,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAU;IAChD,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,oBAAoB;IACpB,UAAU,CAAC,SAAS,GAAG,CAAC,CAAC;IAEzB,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;QACvB,uCAAuC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QAED,uBAAuB;QACvB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAErF,qCAAqC;QACrC,IAAI,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,SAAS,CAAC;YACpB,MAAM,GAAG,KAAK,CAAC;QAChB,CAAC;QAED,kBAAkB;QAClB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAE5B,uCAAuC;QACvC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,gBAAgB,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;YACtD,MAAM,GAAG,IAAI,CAAC;QACf,CAAC;QAED,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1C,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,qBAAqB;IACrB,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,sBAAsB;IACtB,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC;AAAA,CACd;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAe,EAAU;IACxD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,0BAA0B,UAAU,CAAC,IAAI,CAAC,IAAI,QAAQ,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAAA,CACpG","sourcesContent":["/**\n * ANSI escape code to HTML converter.\n *\n * Converts terminal ANSI color/style codes to HTML with inline styles.\n * Supports:\n * - Standard foreground colors (30-37) and bright variants (90-97)\n * - Standard background colors (40-47) and bright variants (100-107)\n * - 256-color palette (38;5;N and 48;5;N)\n * - RGB true color (38;2;R;G;B and 48;2;R;G;B)\n * - Text styles: bold (1), dim (2), italic (3), underline (4)\n * - Reset (0)\n */\n\n// Standard ANSI color palette (0-15)\nconst ANSI_COLORS = [\n\t\"#000000\", // 0: black\n\t\"#800000\", // 1: red\n\t\"#008000\", // 2: green\n\t\"#808000\", // 3: yellow\n\t\"#000080\", // 4: blue\n\t\"#800080\", // 5: magenta\n\t\"#008080\", // 6: cyan\n\t\"#c0c0c0\", // 7: white\n\t\"#808080\", // 8: bright black\n\t\"#ff0000\", // 9: bright red\n\t\"#00ff00\", // 10: bright green\n\t\"#ffff00\", // 11: bright yellow\n\t\"#0000ff\", // 12: bright blue\n\t\"#ff00ff\", // 13: bright magenta\n\t\"#00ffff\", // 14: bright cyan\n\t\"#ffffff\", // 15: bright white\n];\n\n/**\n * Convert 256-color index to hex.\n */\nfunction color256ToHex(index: number): string {\n\t// Standard colors (0-15)\n\tif (index < 16) {\n\t\treturn ANSI_COLORS[index];\n\t}\n\n\t// Color cube (16-231): 6x6x6 = 216 colors\n\tif (index < 232) {\n\t\tconst cubeIndex = index - 16;\n\t\tconst r = Math.floor(cubeIndex / 36);\n\t\tconst g = Math.floor((cubeIndex % 36) / 6);\n\t\tconst b = cubeIndex % 6;\n\t\tconst toComponent = (n: number) => (n === 0 ? 0 : 55 + n * 40);\n\t\tconst toHex = (n: number) => toComponent(n).toString(16).padStart(2, \"0\");\n\t\treturn `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n\t}\n\n\t// Grayscale (232-255): 24 shades\n\tconst gray = 8 + (index - 232) * 10;\n\tconst grayHex = gray.toString(16).padStart(2, \"0\");\n\treturn `#${grayHex}${grayHex}${grayHex}`;\n}\n\n/**\n * Escape HTML special characters.\n */\nfunction escapeHtml(text: string): string {\n\treturn text\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&#039;\");\n}\n\ninterface TextStyle {\n\tfg: string | null;\n\tbg: string | null;\n\tbold: boolean;\n\tdim: boolean;\n\titalic: boolean;\n\tunderline: boolean;\n}\n\nfunction createEmptyStyle(): TextStyle {\n\treturn {\n\t\tfg: null,\n\t\tbg: null,\n\t\tbold: false,\n\t\tdim: false,\n\t\titalic: false,\n\t\tunderline: false,\n\t};\n}\n\nfunction styleToInlineCSS(style: TextStyle): string {\n\tconst parts: string[] = [];\n\tif (style.fg) parts.push(`color:${style.fg}`);\n\tif (style.bg) parts.push(`background-color:${style.bg}`);\n\tif (style.bold) parts.push(\"font-weight:bold\");\n\tif (style.dim) parts.push(\"opacity:0.6\");\n\tif (style.italic) parts.push(\"font-style:italic\");\n\tif (style.underline) parts.push(\"text-decoration:underline\");\n\treturn parts.join(\";\");\n}\n\nfunction hasStyle(style: TextStyle): boolean {\n\treturn style.fg !== null || style.bg !== null || style.bold || style.dim || style.italic || style.underline;\n}\n\n/**\n * Parse ANSI SGR (Select Graphic Rendition) codes and update style.\n */\nfunction applySgrCode(params: number[], style: TextStyle): void {\n\tlet i = 0;\n\twhile (i < params.length) {\n\t\tconst code = params[i];\n\n\t\tif (code === 0) {\n\t\t\t// Reset all\n\t\t\tstyle.fg = null;\n\t\t\tstyle.bg = null;\n\t\t\tstyle.bold = false;\n\t\t\tstyle.dim = false;\n\t\t\tstyle.italic = false;\n\t\t\tstyle.underline = false;\n\t\t} else if (code === 1) {\n\t\t\tstyle.bold = true;\n\t\t} else if (code === 2) {\n\t\t\tstyle.dim = true;\n\t\t} else if (code === 3) {\n\t\t\tstyle.italic = true;\n\t\t} else if (code === 4) {\n\t\t\tstyle.underline = true;\n\t\t} else if (code === 22) {\n\t\t\t// Reset bold/dim\n\t\t\tstyle.bold = false;\n\t\t\tstyle.dim = false;\n\t\t} else if (code === 23) {\n\t\t\tstyle.italic = false;\n\t\t} else if (code === 24) {\n\t\t\tstyle.underline = false;\n\t\t} else if (code >= 30 && code <= 37) {\n\t\t\t// Standard foreground colors\n\t\t\tstyle.fg = ANSI_COLORS[code - 30];\n\t\t} else if (code === 38) {\n\t\t\t// Extended foreground color\n\t\t\tif (params[i + 1] === 5 && params.length > i + 2) {\n\t\t\t\t// 256-color: 38;5;N\n\t\t\t\tstyle.fg = color256ToHex(params[i + 2]);\n\t\t\t\ti += 2;\n\t\t\t} else if (params[i + 1] === 2 && params.length > i + 4) {\n\t\t\t\t// RGB: 38;2;R;G;B\n\t\t\t\tconst r = params[i + 2];\n\t\t\t\tconst g = params[i + 3];\n\t\t\t\tconst b = params[i + 4];\n\t\t\t\tstyle.fg = `rgb(${r},${g},${b})`;\n\t\t\t\ti += 4;\n\t\t\t}\n\t\t} else if (code === 39) {\n\t\t\t// Default foreground\n\t\t\tstyle.fg = null;\n\t\t} else if (code >= 40 && code <= 47) {\n\t\t\t// Standard background colors\n\t\t\tstyle.bg = ANSI_COLORS[code - 40];\n\t\t} else if (code === 48) {\n\t\t\t// Extended background color\n\t\t\tif (params[i + 1] === 5 && params.length > i + 2) {\n\t\t\t\t// 256-color: 48;5;N\n\t\t\t\tstyle.bg = color256ToHex(params[i + 2]);\n\t\t\t\ti += 2;\n\t\t\t} else if (params[i + 1] === 2 && params.length > i + 4) {\n\t\t\t\t// RGB: 48;2;R;G;B\n\t\t\t\tconst r = params[i + 2];\n\t\t\t\tconst g = params[i + 3];\n\t\t\t\tconst b = params[i + 4];\n\t\t\t\tstyle.bg = `rgb(${r},${g},${b})`;\n\t\t\t\ti += 4;\n\t\t\t}\n\t\t} else if (code === 49) {\n\t\t\t// Default background\n\t\t\tstyle.bg = null;\n\t\t} else if (code >= 90 && code <= 97) {\n\t\t\t// Bright foreground colors\n\t\t\tstyle.fg = ANSI_COLORS[code - 90 + 8];\n\t\t} else if (code >= 100 && code <= 107) {\n\t\t\t// Bright background colors\n\t\t\tstyle.bg = ANSI_COLORS[code - 100 + 8];\n\t\t}\n\t\t// Ignore unrecognized codes\n\n\t\ti++;\n\t}\n}\n\n// Match ANSI escape sequences: ESC[ followed by params and ending with 'm'\nconst ANSI_REGEX = /\\x1b\\[([\\d;]*)m/g;\n\n/**\n * Convert ANSI-escaped text to HTML with inline styles.\n */\nexport function ansiToHtml(text: string): string {\n\tconst style = createEmptyStyle();\n\tlet result = \"\";\n\tlet lastIndex = 0;\n\tlet inSpan = false;\n\n\t// Reset regex state\n\tANSI_REGEX.lastIndex = 0;\n\n\tlet match = ANSI_REGEX.exec(text);\n\twhile (match !== null) {\n\t\t// Add text before this escape sequence\n\t\tconst beforeText = text.slice(lastIndex, match.index);\n\t\tif (beforeText) {\n\t\t\tresult += escapeHtml(beforeText);\n\t\t}\n\n\t\t// Parse SGR parameters\n\t\tconst paramStr = match[1];\n\t\tconst params = paramStr ? paramStr.split(\";\").map((p) => parseInt(p, 10) || 0) : [0];\n\n\t\t// Close existing span if we have one\n\t\tif (inSpan) {\n\t\t\tresult += \"</span>\";\n\t\t\tinSpan = false;\n\t\t}\n\n\t\t// Apply the codes\n\t\tapplySgrCode(params, style);\n\n\t\t// Open new span if we have any styling\n\t\tif (hasStyle(style)) {\n\t\t\tresult += `<span style=\"${styleToInlineCSS(style)}\">`;\n\t\t\tinSpan = true;\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t\tmatch = ANSI_REGEX.exec(text);\n\t}\n\n\t// Add remaining text\n\tconst remainingText = text.slice(lastIndex);\n\tif (remainingText) {\n\t\tresult += escapeHtml(remainingText);\n\t}\n\n\t// Close any open span\n\tif (inSpan) {\n\t\tresult += \"</span>\";\n\t}\n\n\treturn result;\n}\n\n/**\n * Convert array of ANSI-escaped lines to HTML.\n * Each line is wrapped in a div element.\n */\nexport function ansiLinesToHtml(lines: string[]): string {\n\treturn lines.map((line) => `<div class=\"ansi-line\">${ansiToHtml(line) || \"&nbsp;\"}</div>`).join(\"\");\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAQ1D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,4GAA4G;IAC5G,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AASD,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAgMD;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,cAAc,EAClB,KAAK,CAAC,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAC9B,OAAO,CAAC,MAAM,CAAC,CA8CjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BzG","sourcesContent":["import type { AgentState } from \"@agent-forge/agent-core\";\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { basename, join } from \"path\";\nimport { APP_NAME, getExportTemplateDir } from \"../../config.ts\";\nimport { getResolvedThemeColors, getThemeExportColors } from \"../../modes/interactive/theme/theme.ts\";\nimport { normalizePath, resolvePath } from \"../../utils/paths.ts\";\nimport { t } from \"../i18n/index.ts\";\nimport type { SessionEntry } from \"../session-manager.ts\";\nimport { SessionManager } from \"../session-manager.ts\";\nimport type { ToolDefinition } from \"../tools/tool-definition.ts\";\n\n/**\n * Interface for rendering custom tools to HTML.\n * Used by agent-session to pre-render extension tool output.\n */\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to HTML. Returns collapsed/expanded or undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/** Pre-rendered HTML for a custom tool call and result */\ninterface RenderedToolHtml {\n\tcallHtml?: string;\n\tresultHtmlCollapsed?: string;\n\tresultHtmlExpanded?: string;\n}\n\nexport interface ExportOptions {\n\toutputPath?: string;\n\tthemeName?: string;\n\t/** Optional tool renderer for custom tools */\n\ttoolRenderer?: ToolHtmlRenderer;\n}\n\n/** Parse a color string to RGB values. Supports hex (#RRGGBB) and rgb(r,g,b) formats. */\nfunction parseColor(color: string): { r: number; g: number; b: number } | undefined {\n\tconst hexMatch = color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);\n\tif (hexMatch) {\n\t\treturn {\n\t\t\tr: Number.parseInt(hexMatch[1], 16),\n\t\t\tg: Number.parseInt(hexMatch[2], 16),\n\t\t\tb: Number.parseInt(hexMatch[3], 16),\n\t\t};\n\t}\n\tconst rgbMatch = color.match(/^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/);\n\tif (rgbMatch) {\n\t\treturn {\n\t\t\tr: Number.parseInt(rgbMatch[1], 10),\n\t\t\tg: Number.parseInt(rgbMatch[2], 10),\n\t\t\tb: Number.parseInt(rgbMatch[3], 10),\n\t\t};\n\t}\n\treturn undefined;\n}\n\n/** Calculate relative luminance of a color (0-1, higher = lighter). */\nfunction getLuminance(r: number, g: number, b: number): number {\n\tconst toLinear = (c: number) => {\n\t\tconst s = c / 255;\n\t\treturn s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n\t};\n\treturn 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\n}\n\n/** Adjust color brightness. Factor > 1 lightens, < 1 darkens. */\nfunction adjustBrightness(color: string, factor: number): string {\n\tconst parsed = parseColor(color);\n\tif (!parsed) return color;\n\tconst adjust = (c: number) => Math.min(255, Math.max(0, Math.round(c * factor)));\n\treturn `rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`;\n}\n\n/** Derive export background colors from a base color (e.g., userMessageBg). */\nfunction deriveExportColors(baseColor: string): { pageBg: string; cardBg: string; infoBg: string } {\n\tconst parsed = parseColor(baseColor);\n\tif (!parsed) {\n\t\treturn {\n\t\t\tpageBg: \"rgb(24, 24, 30)\",\n\t\t\tcardBg: \"rgb(30, 30, 36)\",\n\t\t\tinfoBg: \"rgb(60, 55, 40)\",\n\t\t};\n\t}\n\n\tconst luminance = getLuminance(parsed.r, parsed.g, parsed.b);\n\tconst isLight = luminance > 0.5;\n\n\tif (isLight) {\n\t\treturn {\n\t\t\tpageBg: adjustBrightness(baseColor, 0.96),\n\t\t\tcardBg: baseColor,\n\t\t\tinfoBg: `rgb(${Math.min(255, parsed.r + 10)}, ${Math.min(255, parsed.g + 5)}, ${Math.max(0, parsed.b - 20)})`,\n\t\t};\n\t}\n\treturn {\n\t\tpageBg: adjustBrightness(baseColor, 0.7),\n\t\tcardBg: adjustBrightness(baseColor, 0.85),\n\t\tinfoBg: `rgb(${Math.min(255, parsed.r + 20)}, ${Math.min(255, parsed.g + 15)}, ${parsed.b})`,\n\t};\n}\n\n/**\n * Generate CSS custom property declarations from theme colors.\n */\nfunction generateThemeVars(themeName?: string): string {\n\tconst colors = getResolvedThemeColors(themeName);\n\tconst lines: string[] = [];\n\tfor (const [key, value] of Object.entries(colors)) {\n\t\tlines.push(`--${key}: ${value};`);\n\t}\n\n\t// Use explicit theme export colors if available, otherwise derive from userMessageBg\n\tconst themeExport = getThemeExportColors(themeName);\n\tconst userMessageBg = colors.userMessageBg || \"#343541\";\n\tconst derivedColors = deriveExportColors(userMessageBg);\n\n\tlines.push(`--exportPageBg: ${themeExport.pageBg ?? derivedColors.pageBg};`);\n\tlines.push(`--exportCardBg: ${themeExport.cardBg ?? derivedColors.cardBg};`);\n\tlines.push(`--exportInfoBg: ${themeExport.infoBg ?? derivedColors.infoBg};`);\n\n\treturn lines.join(\"\\n \");\n}\n\ninterface SessionData {\n\theader: ReturnType<SessionManager[\"getHeader\"]>;\n\tentries: ReturnType<SessionManager[\"getEntries\"]>;\n\tleafId: string | null;\n\tsystemPrompt?: string;\n\ttools?: Array<Pick<ToolDefinition, \"name\" | \"description\" | \"parameters\">>;\n\t/** Pre-rendered HTML for custom tool calls/results, keyed by tool call ID */\n\trenderedTools?: Record<string, RenderedToolHtml>;\n}\n\n/**\n * Core HTML generation logic shared by both export functions.\n */\nfunction generateHtml(sessionData: SessionData, themeName?: string): string {\n\tconst templateDir = getExportTemplateDir();\n\tconst template = readFileSync(join(templateDir, \"template.html\"), \"utf-8\");\n\tconst templateCss = readFileSync(join(templateDir, \"template.css\"), \"utf-8\");\n\tconst templateJs = readFileSync(join(templateDir, \"template.js\"), \"utf-8\");\n\tconst markedJs = readFileSync(join(templateDir, \"vendor\", \"marked.min.js\"), \"utf-8\");\n\tconst hljsJs = readFileSync(join(templateDir, \"vendor\", \"highlight.min.js\"), \"utf-8\");\n\n\tconst themeVars = generateThemeVars(themeName);\n\tconst colors = getResolvedThemeColors(themeName);\n\tconst themeExport = getThemeExportColors(themeName);\n\tconst derivedExportColors = deriveExportColors(colors.userMessageBg || \"#343541\");\n\tconst bodyBg = themeExport.pageBg ?? derivedExportColors.pageBg;\n\tconst containerBg = themeExport.cardBg ?? derivedExportColors.cardBg;\n\tconst infoBg = themeExport.infoBg ?? derivedExportColors.infoBg;\n\n\t// Base64 encode session data to avoid escaping issues\n\tconst sessionDataBase64 = Buffer.from(JSON.stringify(sessionData)).toString(\"base64\");\n\n\t// Build the CSS with theme variables injected\n\tconst css = templateCss\n\t\t.replace(\"{{THEME_VARS}}\", themeVars)\n\t\t.replace(\"{{BODY_BG}}\", bodyBg)\n\t\t.replace(\"{{CONTAINER_BG}}\", containerBg)\n\t\t.replace(\"{{INFO_BG}}\", infoBg);\n\n\treturn template\n\t\t.replace(\"{{CSS}}\", css)\n\t\t.replace(\"{{JS}}\", templateJs)\n\t\t.replace(\"{{SESSION_DATA}}\", sessionDataBase64)\n\t\t.replace(\"{{MARKED_JS}}\", markedJs)\n\t\t.replace(\"{{HIGHLIGHT_JS}}\", hljsJs);\n}\n\n/** Tools rendered directly by the HTML template (not pre-rendered via TUI→ANSI→HTML pipeline) */\nconst TEMPLATE_RENDERED_TOOLS = new Set([\"bash\", \"read\", \"write\", \"edit\", \"ls\"]);\n\n/**\n * Pre-render custom tools to HTML using their TUI renderers.\n */\nfunction preRenderCustomTools(\n\tentries: SessionEntry[],\n\ttoolRenderer: ToolHtmlRenderer,\n): Record<string, RenderedToolHtml> {\n\tconst renderedTools: Record<string, RenderedToolHtml> = {};\n\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst msg = entry.message;\n\n\t\t// Find tool calls in assistant messages\n\t\tif (msg.role === \"assistant\" && Array.isArray(msg.content)) {\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"toolCall\" && !TEMPLATE_RENDERED_TOOLS.has(block.name)) {\n\t\t\t\t\tconst callHtml = toolRenderer.renderCall(block.id, block.name, block.arguments);\n\t\t\t\t\tif (callHtml) {\n\t\t\t\t\t\trenderedTools[block.id] = { callHtml };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Find tool results\n\t\tif (msg.role === \"toolResult\" && msg.toolCallId) {\n\t\t\tconst toolName = msg.toolName || \"\";\n\t\t\t// Only render if we have a pre-rendered call OR it's not template-rendered\n\t\t\tconst existing = renderedTools[msg.toolCallId];\n\t\t\tif (existing || !TEMPLATE_RENDERED_TOOLS.has(toolName)) {\n\t\t\t\tconst rendered = toolRenderer.renderResult(\n\t\t\t\t\tmsg.toolCallId,\n\t\t\t\t\ttoolName,\n\t\t\t\t\tmsg.content,\n\t\t\t\t\tmsg.details,\n\t\t\t\t\tmsg.isError || false,\n\t\t\t\t);\n\t\t\t\tif (rendered) {\n\t\t\t\t\trenderedTools[msg.toolCallId] = {\n\t\t\t\t\t\t...existing,\n\t\t\t\t\t\tresultHtmlCollapsed: rendered.collapsed,\n\t\t\t\t\t\tresultHtmlExpanded: rendered.expanded,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn renderedTools;\n}\n\n/**\n * Export session to HTML using SessionManager and AgentState.\n * Used by TUI's /export command.\n */\nexport async function exportSessionToHtml(\n\tsm: SessionManager,\n\tstate?: AgentState,\n\toptions?: ExportOptions | string,\n): Promise<string> {\n\tconst opts: ExportOptions = typeof options === \"string\" ? { outputPath: options } : options || {};\n\n\tconst sessionFile = sm.getSessionFile();\n\tif (!sessionFile) {\n\t\tthrow new Error(t(\"Cannot export in-memory session to HTML\"));\n\t}\n\tif (!existsSync(sessionFile)) {\n\t\tthrow new Error(t(\"Nothing to export yet - start a conversation first\"));\n\t}\n\n\tconst entries = sm.getEntries();\n\n\t// Pre-render custom tools if a tool renderer is provided\n\tlet renderedTools: Record<string, RenderedToolHtml> | undefined;\n\tif (opts.toolRenderer) {\n\t\trenderedTools = preRenderCustomTools(entries, opts.toolRenderer);\n\t\t// Only include if we actually rendered something\n\t\tif (Object.keys(renderedTools).length === 0) {\n\t\t\trenderedTools = undefined;\n\t\t}\n\t}\n\n\tconst sessionData: SessionData = {\n\t\theader: sm.getHeader(),\n\t\tentries,\n\t\tleafId: sm.getLeafId(),\n\t\tsystemPrompt: state?.systemPrompt,\n\t\ttools: state?.tools?.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.parameters,\n\t\t})),\n\t\trenderedTools,\n\t};\n\n\tconst html = generateHtml(sessionData, opts.themeName);\n\n\tlet outputPath = opts.outputPath ? normalizePath(opts.outputPath) : undefined;\n\tif (!outputPath) {\n\t\tconst sessionBasename = basename(sessionFile, \".jsonl\");\n\t\toutputPath = `${APP_NAME}-session-${sessionBasename}.html`;\n\t}\n\n\twriteFileSync(outputPath, html, \"utf8\");\n\treturn outputPath;\n}\n\n/**\n * Export session file to HTML (standalone, without AgentState).\n * Used by CLI for exporting arbitrary session files.\n */\nexport async function exportFromFile(inputPath: string, options?: ExportOptions | string): Promise<string> {\n\tconst opts: ExportOptions = typeof options === \"string\" ? { outputPath: options } : options || {};\n\tconst resolvedInputPath = resolvePath(inputPath);\n\n\tif (!existsSync(resolvedInputPath)) {\n\t\tthrow new Error(t(\"File not found: {path}\", { path: resolvedInputPath }));\n\t}\n\n\tconst sm = SessionManager.open(resolvedInputPath);\n\n\tconst sessionData: SessionData = {\n\t\theader: sm.getHeader(),\n\t\tentries: sm.getEntries(),\n\t\tleafId: sm.getLeafId(),\n\t\tsystemPrompt: undefined,\n\t\ttools: undefined,\n\t};\n\n\tconst html = generateHtml(sessionData, opts.themeName);\n\n\tlet outputPath = opts.outputPath ? normalizePath(opts.outputPath) : undefined;\n\tif (!outputPath) {\n\t\tconst inputBasename = basename(resolvedInputPath, \".jsonl\");\n\t\toutputPath = `${APP_NAME}-session-${inputBasename}.html`;\n\t}\n\n\twriteFileSync(outputPath, html, \"utf8\");\n\treturn outputPath;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/export-html/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentState } from \"@agent-forge/agent-core\";\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { basename, join } from \"path\";\nimport { APP_NAME, getExportTemplateDir } from \"../../config.ts\";\nimport { getResolvedThemeColors, getThemeExportColors } from \"../../modes/interactive/theme/theme.ts\";\nimport { normalizePath, resolvePath } from \"../../utils/paths.ts\";\nimport { t } from \"../i18n/index.ts\";\nimport type { SessionEntry } from \"../session-manager.ts\";\nimport { SessionManager } from \"../session-manager.ts\";\nimport type { ToolDefinition } from \"../tools/tool-definition.ts\";\n\n/**\n * Interface for rendering custom tools to HTML.\n * Used by agent-session to pre-render extension tool output.\n */\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to HTML. Returns collapsed/expanded or undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/** Pre-rendered HTML for a custom tool call and result */\ninterface RenderedToolHtml {\n\tcallHtml?: string;\n\tresultHtmlCollapsed?: string;\n\tresultHtmlExpanded?: string;\n}\n\nexport interface ExportOptions {\n\toutputPath?: string;\n\tthemeName?: string;\n\t/** Optional tool renderer for custom tools */\n\ttoolRenderer?: ToolHtmlRenderer;\n}\n\n/** Parse a color string to RGB values. Supports hex (#RRGGBB) and rgb(r,g,b) formats. */\nfunction parseColor(color: string): { r: number; g: number; b: number } | undefined {\n\tconst hexMatch = color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);\n\tif (hexMatch) {\n\t\treturn {\n\t\t\tr: Number.parseInt(hexMatch[1], 16),\n\t\t\tg: Number.parseInt(hexMatch[2], 16),\n\t\t\tb: Number.parseInt(hexMatch[3], 16),\n\t\t};\n\t}\n\tconst rgbMatch = color.match(/^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/);\n\tif (rgbMatch) {\n\t\treturn {\n\t\t\tr: Number.parseInt(rgbMatch[1], 10),\n\t\t\tg: Number.parseInt(rgbMatch[2], 10),\n\t\t\tb: Number.parseInt(rgbMatch[3], 10),\n\t\t};\n\t}\n\treturn undefined;\n}\n\n/** Calculate relative luminance of a color (0-1, higher = lighter). */\nfunction getLuminance(r: number, g: number, b: number): number {\n\tconst toLinear = (c: number) => {\n\t\tconst s = c / 255;\n\t\treturn s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n\t};\n\treturn 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\n}\n\n/** Adjust color brightness. Factor > 1 lightens, < 1 darkens. */\nfunction adjustBrightness(color: string, factor: number): string {\n\tconst parsed = parseColor(color);\n\tif (!parsed) return color;\n\tconst adjust = (c: number) => Math.min(255, Math.max(0, Math.round(c * factor)));\n\treturn `rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`;\n}\n\n/** Derive export background colors from a base color (e.g., userMessageBg). */\nfunction deriveExportColors(baseColor: string): { pageBg: string; cardBg: string; infoBg: string } {\n\tconst parsed = parseColor(baseColor);\n\tif (!parsed) {\n\t\treturn {\n\t\t\tpageBg: \"rgb(24, 24, 30)\",\n\t\t\tcardBg: \"rgb(30, 30, 36)\",\n\t\t\tinfoBg: \"rgb(60, 55, 40)\",\n\t\t};\n\t}\n\n\tconst luminance = getLuminance(parsed.r, parsed.g, parsed.b);\n\tconst isLight = luminance > 0.5;\n\n\tif (isLight) {\n\t\treturn {\n\t\t\tpageBg: adjustBrightness(baseColor, 0.96),\n\t\t\tcardBg: baseColor,\n\t\t\tinfoBg: `rgb(${Math.min(255, parsed.r + 10)}, ${Math.min(255, parsed.g + 5)}, ${Math.max(0, parsed.b - 20)})`,\n\t\t};\n\t}\n\treturn {\n\t\tpageBg: adjustBrightness(baseColor, 0.7),\n\t\tcardBg: adjustBrightness(baseColor, 0.85),\n\t\tinfoBg: `rgb(${Math.min(255, parsed.r + 20)}, ${Math.min(255, parsed.g + 15)}, ${parsed.b})`,\n\t};\n}\n\n/**\n * Generate CSS custom property declarations from theme colors.\n */\nfunction generateThemeVars(themeName?: string): string {\n\tconst colors = getResolvedThemeColors(themeName);\n\tconst lines: string[] = [];\n\tfor (const [key, value] of Object.entries(colors)) {\n\t\tlines.push(`--${key}: ${value};`);\n\t}\n\n\t// Use explicit theme export colors if available, otherwise derive from userMessageBg\n\tconst themeExport = getThemeExportColors(themeName);\n\tconst userMessageBg = colors.userMessageBg || \"#343541\";\n\tconst derivedColors = deriveExportColors(userMessageBg);\n\n\tlines.push(`--exportPageBg: ${themeExport.pageBg ?? derivedColors.pageBg};`);\n\tlines.push(`--exportCardBg: ${themeExport.cardBg ?? derivedColors.cardBg};`);\n\tlines.push(`--exportInfoBg: ${themeExport.infoBg ?? derivedColors.infoBg};`);\n\n\treturn lines.join(\"\\n \");\n}\n\ninterface SessionData {\n\theader: ReturnType<SessionManager[\"getHeader\"]>;\n\tentries: ReturnType<SessionManager[\"getEntries\"]>;\n\tleafId: string | null;\n\tsystemPrompt?: string;\n\ttools?: Array<Pick<ToolDefinition, \"name\" | \"description\" | \"parameters\">>;\n\t/** Pre-rendered HTML for custom tool calls/results, keyed by tool call ID */\n\trenderedTools?: Record<string, RenderedToolHtml>;\n}\n\n/**\n * Core HTML generation logic shared by both export functions.\n */\nfunction generateHtml(sessionData: SessionData, themeName?: string): string {\n\tconst templateDir = getExportTemplateDir();\n\tconst template = readFileSync(join(templateDir, \"template.html\"), \"utf-8\");\n\tconst templateCss = readFileSync(join(templateDir, \"template.css\"), \"utf-8\");\n\tconst templateJs = readFileSync(join(templateDir, \"template.js\"), \"utf-8\");\n\tconst markedJs = readFileSync(join(templateDir, \"vendor\", \"marked.min.js\"), \"utf-8\");\n\tconst hljsJs = readFileSync(join(templateDir, \"vendor\", \"highlight.min.js\"), \"utf-8\");\n\n\tconst themeVars = generateThemeVars(themeName);\n\tconst colors = getResolvedThemeColors(themeName);\n\tconst themeExport = getThemeExportColors(themeName);\n\tconst derivedExportColors = deriveExportColors(colors.userMessageBg || \"#343541\");\n\tconst bodyBg = themeExport.pageBg ?? derivedExportColors.pageBg;\n\tconst containerBg = themeExport.cardBg ?? derivedExportColors.cardBg;\n\tconst infoBg = themeExport.infoBg ?? derivedExportColors.infoBg;\n\n\t// Base64 encode session data to avoid escaping issues\n\tconst sessionDataBase64 = Buffer.from(JSON.stringify(sessionData)).toString(\"base64\");\n\n\t// Build the CSS with theme variables injected\n\tconst css = templateCss\n\t\t.replace(\"{{THEME_VARS}}\", themeVars)\n\t\t.replace(\"{{BODY_BG}}\", bodyBg)\n\t\t.replace(\"{{CONTAINER_BG}}\", containerBg)\n\t\t.replace(\"{{INFO_BG}}\", infoBg);\n\n\treturn template\n\t\t.replace(\"{{CSS}}\", css)\n\t\t.replace(\"{{JS}}\", templateJs)\n\t\t.replace(\"{{SESSION_DATA}}\", sessionDataBase64)\n\t\t.replace(\"{{MARKED_JS}}\", markedJs)\n\t\t.replace(\"{{HIGHLIGHT_JS}}\", hljsJs);\n}\n\n/** Tools rendered directly by the HTML template (not pre-rendered via TUI→ANSI→HTML pipeline) */\nconst TEMPLATE_RENDERED_TOOLS = new Set([\"bash\", \"read\", \"write\", \"edit\", \"ls\"]);\n\n/**\n * Pre-render custom tools to HTML using their TUI renderers.\n */\nfunction preRenderCustomTools(\n\tentries: SessionEntry[],\n\ttoolRenderer: ToolHtmlRenderer,\n): Record<string, RenderedToolHtml> {\n\tconst renderedTools: Record<string, RenderedToolHtml> = {};\n\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst msg = entry.message;\n\n\t\t// Find tool calls in assistant messages\n\t\tif (msg.role === \"assistant\" && Array.isArray(msg.content)) {\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"toolCall\" && !TEMPLATE_RENDERED_TOOLS.has(block.name)) {\n\t\t\t\t\tconst callHtml = toolRenderer.renderCall(block.id, block.name, block.arguments);\n\t\t\t\t\tif (callHtml) {\n\t\t\t\t\t\trenderedTools[block.id] = { callHtml };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Find tool results\n\t\tif (msg.role === \"toolResult\" && msg.toolCallId) {\n\t\t\tconst toolName = msg.toolName || \"\";\n\t\t\t// Only render if we have a pre-rendered call OR it's not template-rendered\n\t\t\tconst existing = renderedTools[msg.toolCallId];\n\t\t\tif (existing || !TEMPLATE_RENDERED_TOOLS.has(toolName)) {\n\t\t\t\tconst rendered = toolRenderer.renderResult(\n\t\t\t\t\tmsg.toolCallId,\n\t\t\t\t\ttoolName,\n\t\t\t\t\tmsg.content,\n\t\t\t\t\tmsg.details,\n\t\t\t\t\tmsg.isError || false,\n\t\t\t\t);\n\t\t\t\tif (rendered) {\n\t\t\t\t\trenderedTools[msg.toolCallId] = {\n\t\t\t\t\t\t...existing,\n\t\t\t\t\t\tresultHtmlCollapsed: rendered.collapsed,\n\t\t\t\t\t\tresultHtmlExpanded: rendered.expanded,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn renderedTools;\n}\n\n/**\n * Export session to HTML using SessionManager and AgentState.\n * Used by TUI's /export command.\n */\nexport async function exportSessionToHtml(\n\tsm: SessionManager,\n\tstate?: AgentState,\n\toptions?: ExportOptions | string,\n): Promise<string> {\n\tconst opts: ExportOptions = typeof options === \"string\" ? { outputPath: options } : options || {};\n\n\tconst sessionFile = sm.getSessionFile();\n\tif (!sessionFile) {\n\t\tthrow new Error(t(\"Cannot export in-memory session to HTML\"));\n\t}\n\tif (!existsSync(sessionFile)) {\n\t\tthrow new Error(t(\"Nothing to export yet - start a conversation first\"));\n\t}\n\n\tconst entries = sm.getEntries();\n\n\t// Pre-render custom tools if a tool renderer is provided\n\tlet renderedTools: Record<string, RenderedToolHtml> | undefined;\n\tif (opts.toolRenderer) {\n\t\trenderedTools = preRenderCustomTools(entries, opts.toolRenderer);\n\t\t// Only include if we actually rendered something\n\t\tif (Object.keys(renderedTools).length === 0) {\n\t\t\trenderedTools = undefined;\n\t\t}\n\t}\n\n\tconst sessionData: SessionData = {\n\t\theader: sm.getHeader(),\n\t\tentries,\n\t\tleafId: sm.getLeafId(),\n\t\tsystemPrompt: state?.systemPrompt,\n\t\ttools: state?.tools?.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.parameters,\n\t\t})),\n\t\trenderedTools,\n\t};\n\n\tconst html = generateHtml(sessionData, opts.themeName);\n\n\tlet outputPath = opts.outputPath ? normalizePath(opts.outputPath) : undefined;\n\tif (!outputPath) {\n\t\tconst sessionBasename = basename(sessionFile, \".jsonl\");\n\t\toutputPath = `${APP_NAME}-session-${sessionBasename}.html`;\n\t}\n\n\twriteFileSync(outputPath, html, \"utf8\");\n\treturn outputPath;\n}\n\n/**\n * Export session file to HTML (standalone, without AgentState).\n * Used by CLI for exporting arbitrary session files.\n */\nexport async function exportFromFile(inputPath: string, options?: ExportOptions | string): Promise<string> {\n\tconst opts: ExportOptions = typeof options === \"string\" ? { outputPath: options } : options || {};\n\tconst resolvedInputPath = resolvePath(inputPath);\n\n\tif (!existsSync(resolvedInputPath)) {\n\t\tthrow new Error(t(\"File not found: {path}\", { path: resolvedInputPath }));\n\t}\n\n\tconst sm = SessionManager.open(resolvedInputPath);\n\n\tconst sessionData: SessionData = {\n\t\theader: sm.getHeader(),\n\t\tentries: sm.getEntries(),\n\t\tleafId: sm.getLeafId(),\n\t\tsystemPrompt: undefined,\n\t\ttools: undefined,\n\t};\n\n\tconst html = generateHtml(sessionData, opts.themeName);\n\n\tlet outputPath = opts.outputPath ? normalizePath(opts.outputPath) : undefined;\n\tif (!outputPath) {\n\t\tconst inputBasename = basename(resolvedInputPath, \".jsonl\");\n\t\toutputPath = `${APP_NAME}-session-${inputBasename}.html`;\n\t}\n\n\twriteFileSync(outputPath, html, \"utf8\");\n\treturn outputPath;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,6BAA6B,CAAC;AAGrF,MAAM,WAAW,oBAAoB;IACpC,kDAAkD;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IAChE,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,yGAAyG;IACzG,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAkHnF","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@agent-forge/ai\";\nimport type { Component } from \"@agent-forge/tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolDefinition, ToolRenderContext } from \"../tools/tool-definition.ts\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.ts\";\n\nexport interface ToolHtmlRendererDeps {\n\t/** Function to look up tool definition by name */\n\tgetToolDefinition: (name: string) => ToolDefinition | undefined;\n\t/** Theme for styling */\n\ttheme: Theme;\n\t/** Working directory for render context */\n\tcwd: string;\n\t/** Terminal width for rendering (default: 100) */\n\twidth?: number;\n}\n\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to collapsed/expanded HTML. Returns undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[\\d;]*m/g;\n\nfunction isBlankRenderedLine(line: string): boolean {\n\treturn line.replace(ANSI_ESCAPE_REGEX, \"\").trim().length === 0;\n}\n\nfunction trimRenderedResultLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && isBlankRenderedLine(lines[start])) start++;\n\twhile (end > start && isBlankRenderedLine(lines[end - 1])) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function createToolHtmlRenderer(deps: ToolHtmlRendererDeps): ToolHtmlRenderer {\n\tconst { getToolDefinition, theme, cwd, width = 100 } = deps;\n\n\tconst renderedCallComponents = new Map<string, Component>();\n\tconst renderedResultComponents = new Map<string, Component>();\n\tconst renderedStates = new Map<string, Record<string, unknown>>();\n\tconst renderedArgs = new Map<string, unknown>();\n\n\tconst getState = (toolCallId: string): Record<string, unknown> => {\n\t\tlet state = renderedStates.get(toolCallId);\n\t\tif (!state) {\n\t\t\tstate = {};\n\t\t\trenderedStates.set(toolCallId, state);\n\t\t}\n\t\treturn state;\n\t};\n\n\tconst createRenderContext = (\n\t\ttoolCallId: string,\n\t\tlastComponent: Component | undefined,\n\t\texpanded: boolean,\n\t\tisPartial: boolean,\n\t\tisError: boolean,\n\t): ToolRenderContext => {\n\t\treturn {\n\t\t\targs: renderedArgs.get(toolCallId),\n\t\t\ttoolCallId,\n\t\t\tinvalidate: () => {},\n\t\t\tlastComponent,\n\t\t\tstate: getState(toolCallId),\n\t\t\tcwd,\n\t\t\texecutionStarted: true,\n\t\t\targsComplete: true,\n\t\t\tisPartial,\n\t\t\texpanded,\n\t\t\tshowImages: false,\n\t\t\tisError,\n\t\t};\n\t};\n\n\treturn {\n\t\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined {\n\t\t\ttry {\n\t\t\t\trenderedArgs.set(toolCallId, args);\n\t\t\t\tconst toolDef = getToolDefinition(toolName);\n\t\t\t\tif (!toolDef?.renderCall) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst component = toolDef.renderCall(\n\t\t\t\t\targs,\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedCallComponents.get(toolCallId), false, true, false),\n\t\t\t\t);\n\t\t\t\trenderedCallComponents.set(toolCallId, component);\n\t\t\t\tconst lines = component.render(width);\n\t\t\t\treturn ansiLinesToHtml(lines);\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\trenderResult(\n\t\t\ttoolCallId: string,\n\t\t\ttoolName: string,\n\t\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\t\tdetails: unknown,\n\t\t\tisError: boolean,\n\t\t): { collapsed?: string; expanded?: string } | undefined {\n\t\t\ttry {\n\t\t\t\tconst toolDef = getToolDefinition(toolName);\n\t\t\t\tif (!toolDef?.renderResult) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build AgentToolResult from content array\n\t\t\t\t// Cast content since session storage uses generic object types\n\t\t\t\tconst agentToolResult = {\n\t\t\t\t\tcontent: result as (TextContent | ImageContent)[],\n\t\t\t\t\tdetails,\n\t\t\t\t\tisError,\n\t\t\t\t};\n\n\t\t\t\t// Render collapsed\n\t\t\t\tconst collapsedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: false, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), false, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, collapsedComponent);\n\t\t\t\tconst collapsed = ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width)));\n\n\t\t\t\t// Render expanded\n\t\t\t\tconst expandedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: true, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), true, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, expandedComponent);\n\t\t\t\tconst expanded = ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(collapsed && collapsed !== expanded ? { collapsed } : {}),\n\t\t\t\t\texpanded,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@agent-forge/ai\";\nimport type { Component } from \"@agent-forge/tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolDefinition, ToolRenderContext } from \"../tools/tool-definition.ts\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.ts\";\n\nexport interface ToolHtmlRendererDeps {\n\t/** Function to look up tool definition by name */\n\tgetToolDefinition: (name: string) => ToolDefinition | undefined;\n\t/** Theme for styling */\n\ttheme: Theme;\n\t/** Working directory for render context */\n\tcwd: string;\n\t/** Terminal width for rendering (default: 100) */\n\twidth?: number;\n}\n\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to collapsed/expanded HTML. Returns undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[\\d;]*m/g;\n\nfunction isBlankRenderedLine(line: string): boolean {\n\treturn line.replace(ANSI_ESCAPE_REGEX, \"\").trim().length === 0;\n}\n\nfunction trimRenderedResultLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && isBlankRenderedLine(lines[start])) start++;\n\twhile (end > start && isBlankRenderedLine(lines[end - 1])) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function createToolHtmlRenderer(deps: ToolHtmlRendererDeps): ToolHtmlRenderer {\n\tconst { getToolDefinition, theme, cwd, width = 100 } = deps;\n\n\tconst renderedCallComponents = new Map<string, Component>();\n\tconst renderedResultComponents = new Map<string, Component>();\n\tconst renderedStates = new Map<string, Record<string, unknown>>();\n\tconst renderedArgs = new Map<string, unknown>();\n\n\tconst getState = (toolCallId: string): Record<string, unknown> => {\n\t\tlet state = renderedStates.get(toolCallId);\n\t\tif (!state) {\n\t\t\tstate = {};\n\t\t\trenderedStates.set(toolCallId, state);\n\t\t}\n\t\treturn state;\n\t};\n\n\tconst createRenderContext = (\n\t\ttoolCallId: string,\n\t\tlastComponent: Component | undefined,\n\t\texpanded: boolean,\n\t\tisPartial: boolean,\n\t\tisError: boolean,\n\t): ToolRenderContext => {\n\t\treturn {\n\t\t\targs: renderedArgs.get(toolCallId),\n\t\t\ttoolCallId,\n\t\t\tinvalidate: () => {},\n\t\t\tlastComponent,\n\t\t\tstate: getState(toolCallId),\n\t\t\tcwd,\n\t\t\texecutionStarted: true,\n\t\t\targsComplete: true,\n\t\t\tisPartial,\n\t\t\texpanded,\n\t\t\tshowImages: false,\n\t\t\tisError,\n\t\t};\n\t};\n\n\treturn {\n\t\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined {\n\t\t\ttry {\n\t\t\t\trenderedArgs.set(toolCallId, args);\n\t\t\t\tconst toolDef = getToolDefinition(toolName);\n\t\t\t\tif (!toolDef?.renderCall) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst component = toolDef.renderCall(\n\t\t\t\t\targs,\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedCallComponents.get(toolCallId), false, true, false),\n\t\t\t\t);\n\t\t\t\trenderedCallComponents.set(toolCallId, component);\n\t\t\t\tconst lines = component.render(width);\n\t\t\t\treturn ansiLinesToHtml(lines);\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\trenderResult(\n\t\t\ttoolCallId: string,\n\t\t\ttoolName: string,\n\t\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\t\tdetails: unknown,\n\t\t\tisError: boolean,\n\t\t): { collapsed?: string; expanded?: string } | undefined {\n\t\t\ttry {\n\t\t\t\tconst toolDef = getToolDefinition(toolName);\n\t\t\t\tif (!toolDef?.renderResult) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build AgentToolResult from content array\n\t\t\t\t// Cast content since session storage uses generic object types\n\t\t\t\tconst agentToolResult = {\n\t\t\t\t\tcontent: result as (TextContent | ImageContent)[],\n\t\t\t\t\tdetails,\n\t\t\t\t\tisError,\n\t\t\t\t};\n\n\t\t\t\t// Render collapsed\n\t\t\t\tconst collapsedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: false, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), false, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, collapsedComponent);\n\t\t\t\tconst collapsed = ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width)));\n\n\t\t\t\t// Render expanded\n\t\t\t\tconst expandedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: true, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), true, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, expandedComponent);\n\t\t\t\tconst expanded = ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(collapsed && collapsed !== expanded ? { collapsed } : {}),\n\t\t\t\t\texpanded,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -1,7 +0,0 @@
1
- export interface PiManifest {
2
- skills?: string[];
3
- prompts?: string[];
4
- themes?: string[];
5
- }
6
- export declare function readPiManifest(packageJsonPath: string): PiManifest | null;
7
- //# sourceMappingURL=pi-manifest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi-manifest.d.ts","sourceRoot":"","sources":["../../src/core/pi-manifest.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAQD,wBAAgB,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAkBzE","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { stripBom } from \"../utils/text.ts\";\n\nexport interface PiManifest {\n\tskills?: string[];\n\tprompts?: string[];\n\tthemes?: string[];\n}\n\nconst RESOURCE_FIELDS = [\"skills\", \"prompts\", \"themes\"] as const;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function readPiManifest(packageJsonPath: string): PiManifest | null {\n\ttry {\n\t\tconst pkg: unknown = JSON.parse(stripBom(readFileSync(packageJsonPath, \"utf-8\")));\n\t\tif (!isObject(pkg) || !isObject(pkg.pi)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst manifest: PiManifest = {};\n\t\tfor (const field of RESOURCE_FIELDS) {\n\t\t\tconst entries = pkg.pi[field];\n\t\t\tif (Array.isArray(entries) && entries.every((entry) => typeof entry === \"string\")) {\n\t\t\t\tmanifest[field] = entries;\n\t\t\t}\n\t\t}\n\t\treturn manifest;\n\t} catch {\n\t\treturn null;\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi-manifest.js","sourceRoot":"","sources":["../../src/core/pi-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAQ5C,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAC;AAEjE,SAAS,QAAQ,CAAC,KAAc,EAAoC;IACnE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAAA,CAC5E;AAED,MAAM,UAAU,cAAc,CAAC,eAAuB,EAAqB;IAC1E,IAAI,CAAC;QACJ,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,QAAQ,GAAe,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACnF,QAAQ,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;YAC3B,CAAC;QACF,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AAAA,CACD","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { stripBom } from \"../utils/text.ts\";\n\nexport interface PiManifest {\n\tskills?: string[];\n\tprompts?: string[];\n\tthemes?: string[];\n}\n\nconst RESOURCE_FIELDS = [\"skills\", \"prompts\", \"themes\"] as const;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function readPiManifest(packageJsonPath: string): PiManifest | null {\n\ttry {\n\t\tconst pkg: unknown = JSON.parse(stripBom(readFileSync(packageJsonPath, \"utf-8\")));\n\t\tif (!isObject(pkg) || !isObject(pkg.pi)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst manifest: PiManifest = {};\n\t\tfor (const field of RESOURCE_FIELDS) {\n\t\t\tconst entries = pkg.pi[field];\n\t\t\tif (Array.isArray(entries) && entries.every((entry) => typeof entry === \"string\")) {\n\t\t\t\tmanifest[field] = entries;\n\t\t\t}\n\t\t}\n\t\treturn manifest;\n\t} catch {\n\t\treturn null;\n\t}\n}\n"]}