@ai-agent-forge/agent-forge 0.88.2 → 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 (453) hide show
  1. package/CHANGELOG.md +27 -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 +240 -230
  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-6F5JWGKE.js → chunk-32YDZI4J.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-LSP24WNH.js → chunk-755VNWIF.js} +12 -12
  25. package/dist/bundle/chunks/{chunk-HTC5K5SM.js → chunk-B42Y2VME.js} +94 -89
  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-44I47ACN.js → chunk-V3ACW7VD.js} +1 -1
  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 +1 -1
  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/startup-ui.d.ts.map +1 -1
  61. package/dist/cli/startup-ui.js +1 -1
  62. package/dist/cli/startup-ui.js.map +1 -1
  63. package/dist/config.d.ts +4 -4
  64. package/dist/config.d.ts.map +1 -1
  65. package/dist/config.js +7 -7
  66. package/dist/config.js.map +1 -1
  67. package/dist/core/agent-forge-manifest.d.ts +7 -0
  68. package/dist/core/agent-forge-manifest.d.ts.map +1 -0
  69. package/dist/core/{pi-manifest.js → agent-forge-manifest.js} +4 -4
  70. package/dist/core/agent-forge-manifest.js.map +1 -0
  71. package/dist/core/agent-session-compaction.d.ts +1 -1
  72. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  73. package/dist/core/agent-session-compaction.js +3 -3
  74. package/dist/core/agent-session-compaction.js.map +1 -1
  75. package/dist/core/agent-session-lifecycle.d.ts.map +1 -1
  76. package/dist/core/agent-session-lifecycle.js +12 -1
  77. package/dist/core/agent-session-lifecycle.js.map +1 -1
  78. package/dist/core/agent-session-projection.d.ts.map +1 -1
  79. package/dist/core/agent-session-projection.js +3 -3
  80. package/dist/core/agent-session-projection.js.map +1 -1
  81. package/dist/core/agent-session-services.d.ts +1 -1
  82. package/dist/core/agent-session-services.d.ts.map +1 -1
  83. package/dist/core/agent-session-services.js +1 -1
  84. package/dist/core/agent-session-services.js.map +1 -1
  85. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  86. package/dist/core/compaction/branch-summarization.js +1 -1
  87. package/dist/core/compaction/branch-summarization.js.map +1 -1
  88. package/dist/core/experimental.d.ts.map +1 -1
  89. package/dist/core/experimental.js +1 -3
  90. package/dist/core/experimental.js.map +1 -1
  91. package/dist/core/extensions/capability-runtime-store.d.ts +20 -1
  92. package/dist/core/extensions/capability-runtime-store.d.ts.map +1 -1
  93. package/dist/core/extensions/capability-runtime-store.js +67 -0
  94. package/dist/core/extensions/capability-runtime-store.js.map +1 -1
  95. package/dist/core/extensions/capability-runtime-types.d.ts +14 -0
  96. package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -1
  97. package/dist/core/extensions/capability-runtime-types.js +7 -1
  98. package/dist/core/extensions/capability-runtime-types.js.map +1 -1
  99. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  100. package/dist/core/extensions/capability-runtime.js +144 -42
  101. package/dist/core/extensions/capability-runtime.js.map +1 -1
  102. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  103. package/dist/core/extensions/virtual-modules.js +6 -1
  104. package/dist/core/extensions/virtual-modules.js.map +1 -1
  105. package/dist/core/facade/coding-agent-facade.d.ts +1 -1
  106. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  107. package/dist/core/facade/coding-agent-facade.js +1 -1
  108. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  109. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +1 -1
  110. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -1
  111. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +3 -3
  112. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -1
  113. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -1
  114. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +1 -1
  115. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -1
  116. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
  117. package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -1
  118. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
  119. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -1
  120. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +2 -0
  121. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -1
  122. package/dist/core/model-resolver.d.ts +2 -0
  123. package/dist/core/model-resolver.d.ts.map +1 -1
  124. package/dist/core/model-resolver.js +4 -1
  125. package/dist/core/model-resolver.js.map +1 -1
  126. package/dist/core/package-resource-collection.d.ts.map +1 -1
  127. package/dist/core/package-resource-collection.js +5 -5
  128. package/dist/core/package-resource-collection.js.map +1 -1
  129. package/dist/core/provider-composer.d.ts.map +1 -1
  130. package/dist/core/provider-composer.js +3 -3
  131. package/dist/core/provider-composer.js.map +1 -1
  132. package/dist/core/resource-loader.d.ts.map +1 -1
  133. package/dist/core/resource-loader.js +1 -1
  134. package/dist/core/resource-loader.js.map +1 -1
  135. package/dist/core/sdk.d.ts +1 -1
  136. package/dist/core/sdk.d.ts.map +1 -1
  137. package/dist/core/sdk.js +6 -7
  138. package/dist/core/sdk.js.map +1 -1
  139. package/dist/core/session-manager.d.ts.map +1 -1
  140. package/dist/core/session-manager.js +4 -4
  141. package/dist/core/session-manager.js.map +1 -1
  142. package/dist/core/settings-manager.d.ts.map +1 -1
  143. package/dist/core/settings-manager.js +5 -10
  144. package/dist/core/settings-manager.js.map +1 -1
  145. package/dist/core/timings.d.ts.map +1 -1
  146. package/dist/core/timings.js +1 -3
  147. package/dist/core/timings.js.map +1 -1
  148. package/dist/core/tools/render-utils.d.ts +1 -1
  149. package/dist/core/tools/render-utils.d.ts.map +1 -1
  150. package/dist/core/tools/render-utils.js.map +1 -1
  151. package/dist/core/tools/tool-definition.d.ts +1 -1
  152. package/dist/core/tools/tool-definition.d.ts.map +1 -1
  153. package/dist/core/tools/tool-definition.js.map +1 -1
  154. package/dist/core/trace-retention.d.ts +16 -1
  155. package/dist/core/trace-retention.d.ts.map +1 -1
  156. package/dist/core/trace-retention.js +43 -20
  157. package/dist/core/trace-retention.js.map +1 -1
  158. package/dist/export-html/ansi-to-html.d.ts.map +1 -0
  159. package/dist/export-html/ansi-to-html.js.map +1 -0
  160. package/dist/{core/export-html → export-html}/index.d.ts +1 -1
  161. package/dist/export-html/index.d.ts.map +1 -0
  162. package/dist/{core/export-html → export-html}/index.js +5 -5
  163. package/dist/export-html/index.js.map +1 -0
  164. package/dist/{core/export-html → export-html}/tool-renderer.d.ts +2 -2
  165. package/dist/export-html/tool-renderer.d.ts.map +1 -0
  166. package/dist/export-html/tool-renderer.js.map +1 -0
  167. package/dist/{modes/interactive → host}/model-catalog-refresh.d.ts +1 -1
  168. package/dist/host/model-catalog-refresh.d.ts.map +1 -0
  169. package/dist/{modes/interactive → host}/model-catalog-refresh.js +1 -1
  170. package/dist/host/model-catalog-refresh.js.map +1 -0
  171. package/dist/index.d.ts +5 -5
  172. package/dist/index.d.ts.map +1 -1
  173. package/dist/index.js +12 -12
  174. package/dist/index.js.map +1 -1
  175. package/dist/main.d.ts.map +1 -1
  176. package/dist/main.js +25 -14
  177. package/dist/main.js.map +1 -1
  178. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  179. package/dist/modes/interactive/components/agents-view.js +1 -1
  180. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  181. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  182. package/dist/modes/interactive/components/armin.js +1 -1
  183. package/dist/modes/interactive/components/armin.js.map +1 -1
  184. package/dist/modes/interactive/components/assistant-message.d.ts +3 -0
  185. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/assistant-message.js +83 -24
  187. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  188. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  189. package/dist/modes/interactive/components/bash-execution.js +1 -1
  190. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  191. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  192. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  194. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  195. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  196. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  197. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  198. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  199. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  200. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  201. package/dist/modes/interactive/components/config-selector.js +1 -1
  202. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  203. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  204. package/dist/modes/interactive/components/custom-entry.js +1 -1
  205. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  206. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  207. package/dist/modes/interactive/components/custom-message.js +1 -1
  208. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  209. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/daxnuts.js +1 -1
  211. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  212. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  213. package/dist/modes/interactive/components/dialog-editor.js +1 -1
  214. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  215. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  216. package/dist/modes/interactive/components/dialog-input.js +1 -1
  217. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  218. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  219. package/dist/modes/interactive/components/dialog-selector.js +1 -1
  220. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  221. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  222. package/dist/modes/interactive/components/diff.js +1 -1
  223. package/dist/modes/interactive/components/diff.js.map +1 -1
  224. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  225. package/dist/modes/interactive/components/dynamic-border.js +1 -1
  226. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  227. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
  228. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  229. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  230. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  231. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  232. package/dist/modes/interactive/components/footer.js +1 -1
  233. package/dist/modes/interactive/components/footer.js.map +1 -1
  234. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  235. package/dist/modes/interactive/components/keybinding-hints.js +1 -1
  236. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  237. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  238. package/dist/modes/interactive/components/login-dialog.js +1 -1
  239. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  240. package/dist/modes/interactive/components/mermaid.d.ts +1 -1
  241. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  242. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  243. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  244. package/dist/modes/interactive/components/model-selector.js +2 -2
  245. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  246. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  247. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  248. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  249. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  250. package/dist/modes/interactive/components/plugin-manager-entry.js +1 -1
  251. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  252. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  253. package/dist/modes/interactive/components/plugin-selection-entry.js +1 -1
  254. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  255. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/queue-manager-selector.js +1 -1
  257. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -1
  258. package/dist/modes/interactive/components/render-types.d.ts +1 -1
  259. package/dist/modes/interactive/components/render-types.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/render-types.js.map +1 -1
  261. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  262. package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  263. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  264. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  265. package/dist/modes/interactive/components/session-selector.js +2 -2
  266. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  267. package/dist/modes/interactive/components/settings-selector.d.ts +1 -1
  268. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  269. package/dist/modes/interactive/components/settings-selector.js +1 -1
  270. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  271. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/settings-submenu.js +1 -1
  273. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  274. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  275. package/dist/modes/interactive/components/show-images-selector.js +1 -1
  276. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  277. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  278. package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  279. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  280. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  281. package/dist/modes/interactive/components/status-indicator.js +1 -1
  282. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  283. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  284. package/dist/modes/interactive/components/theme-selector.js +1 -1
  285. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  286. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  287. package/dist/modes/interactive/components/thinking-selector.js +1 -1
  288. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  289. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  290. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  291. package/dist/modes/interactive/components/tool-execution.js +96 -4
  292. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  293. package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -1
  294. package/dist/modes/interactive/components/tool-run-group.js +1 -1
  295. package/dist/modes/interactive/components/tool-run-group.js.map +1 -1
  296. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  297. package/dist/modes/interactive/components/tree-list.js +1 -1
  298. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  299. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  300. package/dist/modes/interactive/components/tree-render.js +1 -1
  301. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  302. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  303. package/dist/modes/interactive/components/tree-selector.js +1 -1
  304. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  305. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  306. package/dist/modes/interactive/components/user-message-selector.js +1 -1
  307. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  308. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  309. package/dist/modes/interactive/components/user-message.js +1 -1
  310. package/dist/modes/interactive/components/user-message.js.map +1 -1
  311. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  312. package/dist/modes/interactive/components/workflow-view.js +1 -1
  313. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  314. package/dist/modes/interactive/interactive-auth.d.ts +1 -1
  315. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  316. package/dist/modes/interactive/interactive-auth.js +1 -1
  317. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  318. package/dist/modes/interactive/interactive-commands.d.ts +123 -6
  319. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  320. package/dist/modes/interactive/interactive-commands.js +691 -4
  321. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  322. package/dist/modes/interactive/interactive-events.d.ts +174 -0
  323. package/dist/modes/interactive/interactive-events.d.ts.map +1 -0
  324. package/dist/modes/interactive/interactive-events.js +704 -0
  325. package/dist/modes/interactive/interactive-events.js.map +1 -0
  326. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  327. package/dist/modes/interactive/interactive-format.js +1 -1
  328. package/dist/modes/interactive/interactive-format.js.map +1 -1
  329. package/dist/modes/interactive/interactive-lifecycle.d.ts +94 -0
  330. package/dist/modes/interactive/interactive-lifecycle.d.ts.map +1 -0
  331. package/dist/modes/interactive/interactive-lifecycle.js +177 -0
  332. package/dist/modes/interactive/interactive-lifecycle.js.map +1 -0
  333. package/dist/modes/interactive/interactive-mode.d.ts +240 -133
  334. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  335. package/dist/modes/interactive/interactive-mode.js +251 -2159
  336. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  337. package/dist/modes/interactive/interactive-queues.d.ts +96 -0
  338. package/dist/modes/interactive/interactive-queues.d.ts.map +1 -0
  339. package/dist/modes/interactive/interactive-queues.js +183 -0
  340. package/dist/modes/interactive/interactive-queues.js.map +1 -0
  341. package/dist/modes/interactive/interactive-selectors.d.ts +95 -5
  342. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  343. package/dist/modes/interactive/interactive-selectors.js +517 -6
  344. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  345. package/dist/modes/interactive/startup-services.d.ts +31 -0
  346. package/dist/modes/interactive/startup-services.d.ts.map +1 -0
  347. package/dist/modes/interactive/startup-services.js +123 -0
  348. package/dist/modes/interactive/startup-services.js.map +1 -0
  349. package/dist/modes/memory-preheat.d.ts +11 -0
  350. package/dist/modes/memory-preheat.d.ts.map +1 -0
  351. package/dist/modes/memory-preheat.js +20 -0
  352. package/dist/modes/memory-preheat.js.map +1 -0
  353. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  354. package/dist/modes/rpc/rpc-mode.js +3 -1
  355. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  356. package/dist/remote/server-assembly.d.ts.map +1 -1
  357. package/dist/remote/server-assembly.js +7 -2
  358. package/dist/remote/server-assembly.js.map +1 -1
  359. package/dist/suites/builtin-suites.d.ts.map +1 -0
  360. package/dist/suites/builtin-suites.js.map +1 -0
  361. package/dist/suites/resolved-agent-profile.d.ts.map +1 -0
  362. package/dist/suites/resolved-agent-profile.js.map +1 -0
  363. package/dist/suites/suite-lifecycle.d.ts.map +1 -0
  364. package/dist/suites/suite-lifecycle.js.map +1 -0
  365. package/dist/suites/suite-loader.d.ts.map +1 -0
  366. package/dist/suites/suite-loader.js.map +1 -0
  367. package/dist/{modes/interactive/theme → theme}/dark.json +1 -1
  368. package/dist/{modes/interactive/theme → theme}/light.json +1 -1
  369. package/dist/{modes/interactive/theme → theme}/theme-controller.d.ts +1 -1
  370. package/dist/theme/theme-controller.d.ts.map +1 -0
  371. package/dist/{modes/interactive/theme → theme}/theme-controller.js +1 -1
  372. package/dist/theme/theme-controller.js.map +1 -0
  373. package/dist/{modes/interactive/theme → theme}/theme.d.ts +1 -1
  374. package/dist/theme/theme.d.ts.map +1 -0
  375. package/dist/{modes/interactive/theme → theme}/theme.js +5 -5
  376. package/dist/theme/theme.js.map +1 -0
  377. package/docs/compaction.md +7 -7
  378. package/docs/environment-variables.md +10 -4
  379. package/docs/keybindings.md +3 -3
  380. package/docs/models.md +17 -17
  381. package/docs/packages.md +1 -1
  382. package/docs/prompt-templates.md +1 -1
  383. package/docs/rpc.md +2 -2
  384. package/docs/sdk.md +5 -5
  385. package/docs/session-format.md +3 -3
  386. package/docs/settings.md +15 -1
  387. package/docs/shell-aliases.md +1 -1
  388. package/docs/skills.md +1 -1
  389. package/docs/terminal-setup.md +17 -17
  390. package/docs/themes.md +5 -5
  391. package/docs/tmux.md +4 -4
  392. package/docs/tui.md +1 -1
  393. package/docs/usage.md +292 -292
  394. package/docs/windows.md +1 -1
  395. package/examples/extensions/bash-spawn-hook/index.ts +1 -1
  396. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  397. package/examples/extensions/mcp-stdio/index.d.ts +64 -0
  398. package/examples/extensions/mcp-stdio/index.d.ts.map +1 -0
  399. package/examples/extensions/mcp-stdio/index.js +292 -0
  400. package/examples/extensions/mcp-stdio/index.js.map +1 -0
  401. package/examples/extensions/with-deps/package-lock.json +2 -2
  402. package/examples/extensions/with-deps/package.json +1 -6
  403. package/examples/extensions/with-deps/plugin.json +1 -1
  404. package/package.json +2 -2
  405. package/dist/bundle/chunks/openai-responses-AUJQ3NWT.js +0 -2
  406. package/dist/bundle/chunks/virtual-modules-MRXD3RWG.js +0 -5
  407. package/dist/cli/experimental/commands/pi.d.ts +0 -15
  408. package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
  409. package/dist/cli/experimental/commands/pi.js.map +0 -1
  410. package/dist/core/export-html/ansi-to-html.d.ts.map +0 -1
  411. package/dist/core/export-html/ansi-to-html.js.map +0 -1
  412. package/dist/core/export-html/index.d.ts.map +0 -1
  413. package/dist/core/export-html/index.js.map +0 -1
  414. package/dist/core/export-html/tool-renderer.d.ts.map +0 -1
  415. package/dist/core/export-html/tool-renderer.js.map +0 -1
  416. package/dist/core/pi-manifest.d.ts +0 -7
  417. package/dist/core/pi-manifest.d.ts.map +0 -1
  418. package/dist/core/pi-manifest.js.map +0 -1
  419. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +0 -1
  420. package/dist/modes/interactive/model-catalog-refresh.js.map +0 -1
  421. package/dist/modes/interactive/theme/theme-controller.d.ts.map +0 -1
  422. package/dist/modes/interactive/theme/theme-controller.js.map +0 -1
  423. package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
  424. package/dist/modes/interactive/theme/theme.js.map +0 -1
  425. package/dist/profiles/builtin-suites.d.ts.map +0 -1
  426. package/dist/profiles/builtin-suites.js.map +0 -1
  427. package/dist/profiles/resolved-agent-profile.d.ts.map +0 -1
  428. package/dist/profiles/resolved-agent-profile.js.map +0 -1
  429. package/dist/profiles/suite-lifecycle.d.ts.map +0 -1
  430. package/dist/profiles/suite-lifecycle.js.map +0 -1
  431. package/dist/profiles/suite-loader.d.ts.map +0 -1
  432. package/dist/profiles/suite-loader.js.map +0 -1
  433. package/dist/utils/deprecation.d.ts +0 -4
  434. package/dist/utils/deprecation.d.ts.map +0 -1
  435. package/dist/utils/deprecation.js +0 -13
  436. package/dist/utils/deprecation.js.map +0 -1
  437. /package/dist/{core/export-html → export-html}/ansi-to-html.d.ts +0 -0
  438. /package/dist/{core/export-html → export-html}/ansi-to-html.js +0 -0
  439. /package/dist/{core/export-html → export-html}/template.css +0 -0
  440. /package/dist/{core/export-html → export-html}/template.html +0 -0
  441. /package/dist/{core/export-html → export-html}/template.js +0 -0
  442. /package/dist/{core/export-html → export-html}/tool-renderer.js +0 -0
  443. /package/dist/{core/export-html → export-html}/vendor/highlight.min.js +0 -0
  444. /package/dist/{core/export-html → export-html}/vendor/marked.min.js +0 -0
  445. /package/dist/{profiles → suites}/builtin-suites.d.ts +0 -0
  446. /package/dist/{profiles → suites}/builtin-suites.js +0 -0
  447. /package/dist/{profiles → suites}/resolved-agent-profile.d.ts +0 -0
  448. /package/dist/{profiles → suites}/resolved-agent-profile.js +0 -0
  449. /package/dist/{profiles → suites}/suite-lifecycle.d.ts +0 -0
  450. /package/dist/{profiles → suites}/suite-lifecycle.js +0 -0
  451. /package/dist/{profiles → suites}/suite-loader.d.ts +0 -0
  452. /package/dist/{profiles → suites}/suite-loader.js +0 -0
  453. /package/dist/{modes/interactive/theme → theme}/theme-schema.json +0 -0
@@ -0,0 +1,64 @@
1
+ /**
2
+ * MCP-like JSON-RPC 2.0 stdio bridge.
3
+ *
4
+ * This is intentionally an external capability plugin. It discovers tools
5
+ * from one explicitly configured process and exposes them through the public
6
+ * CapabilityAPI; policy, approval, and server selection remain host-owned.
7
+ */
8
+ import type { CapabilityAPI, CapabilityPluginFactory } from "@agent-forge/coding-agent";
9
+ export type McpErrorReason = "spawn" | "exit" | "malformed" | "protocol" | "remote" | "aborted" | "timed_out";
10
+ export interface McpErrorDetails {
11
+ method?: string;
12
+ requestId?: number;
13
+ stdout?: string;
14
+ stderr?: string;
15
+ exitCode?: number | null;
16
+ data?: unknown;
17
+ }
18
+ export declare class McpStdioError extends Error {
19
+ readonly reason: McpErrorReason;
20
+ readonly details: McpErrorDetails;
21
+ constructor(message: string, reason: McpErrorReason, details?: McpErrorDetails);
22
+ }
23
+ export interface McpRequestOptions {
24
+ signal?: AbortSignal;
25
+ timeoutMs?: number;
26
+ }
27
+ export interface McpStdioTransport {
28
+ request(method: string, params?: unknown, options?: McpRequestOptions): Promise<unknown>;
29
+ notify(method: string, params?: unknown): Promise<void> | void;
30
+ close(): Promise<void> | void;
31
+ readonly stderr?: string;
32
+ }
33
+ export interface McpStdioTransportConfig {
34
+ command: string;
35
+ args: readonly string[];
36
+ cwd?: string;
37
+ env?: NodeJS.ProcessEnv;
38
+ onStderr?: (text: string) => void;
39
+ }
40
+ export type McpStdioTransportFactory = (config: McpStdioTransportConfig) => McpStdioTransport | Promise<McpStdioTransport>;
41
+ export interface McpStdioPluginOptions {
42
+ command: string;
43
+ args?: readonly string[];
44
+ cwd?: string;
45
+ env?: NodeJS.ProcessEnv;
46
+ timeoutMs?: number;
47
+ transportFactory?: McpStdioTransportFactory;
48
+ onStderr?: (text: string) => void;
49
+ protocolVersion?: string;
50
+ clientInfo?: {
51
+ name: string;
52
+ version: string;
53
+ };
54
+ }
55
+ /** Default line-delimited stdio transport. The command is never passed to a shell. */
56
+ export declare function spawnMcpTransport(config: McpStdioTransportConfig): McpStdioTransport;
57
+ /** Create an asynchronously discovering MCP stdio capability plugin. */
58
+ export declare function createMcpStdioPlugin(options: McpStdioPluginOptions): CapabilityPluginFactory;
59
+ /**
60
+ * Template entry only. A working MCP transport needs a user-selected command,
61
+ * arguments, and timeout; never launch an unconfigured child process.
62
+ */
63
+ export default function mcpStdioExample(_api: CapabilityAPI): never;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EACX,aAAa,EACb,uBAAuB,EAGvB,MAAM,2BAA2B,CAAC;AAGnC,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAE9G,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,aAAc,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAElC,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,eAAoB,EAKjF;CACD;AAED,MAAM,WAAW,iBAAiB;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,MAAM,wBAAwB,GAAG,CACtC,MAAM,EAAE,uBAAuB,KAC3B,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,wBAAwB,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AA+CD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,iBAAiB,CAQpF;AAmLD,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,uBAAuB,CA0D5F;AAED;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,KAAK,CAIlE","sourcesContent":["/**\n * MCP-like JSON-RPC 2.0 stdio bridge.\n *\n * This is intentionally an external capability plugin. It discovers tools\n * from one explicitly configured process and exposes them through the public\n * CapabilityAPI; policy, approval, and server selection remain host-owned.\n */\n\nimport type { ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { spawn } from \"node:child_process\";\nimport type { AgentToolResult } from \"@agent-forge/agent-core\";\nimport type {\n\tCapabilityAPI,\n\tCapabilityPluginFactory,\n\tExtensionContext,\n\tToolDefinition,\n} from \"@agent-forge/coding-agent\";\nimport { Type } from \"typebox\";\n\nexport type McpErrorReason = \"spawn\" | \"exit\" | \"malformed\" | \"protocol\" | \"remote\" | \"aborted\" | \"timed_out\";\n\nexport interface McpErrorDetails {\n\tmethod?: string;\n\trequestId?: number;\n\tstdout?: string;\n\tstderr?: string;\n\texitCode?: number | null;\n\tdata?: unknown;\n}\n\nexport class McpStdioError extends Error {\n\treadonly reason: McpErrorReason;\n\treadonly details: McpErrorDetails;\n\n\tconstructor(message: string, reason: McpErrorReason, details: McpErrorDetails = {}) {\n\t\tsuper(message);\n\t\tthis.name = \"McpStdioError\";\n\t\tthis.reason = reason;\n\t\tthis.details = details;\n\t}\n}\n\nexport interface McpRequestOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n}\n\nexport interface McpStdioTransport {\n\trequest(method: string, params?: unknown, options?: McpRequestOptions): Promise<unknown>;\n\tnotify(method: string, params?: unknown): Promise<void> | void;\n\tclose(): Promise<void> | void;\n\treadonly stderr?: string;\n}\n\nexport interface McpStdioTransportConfig {\n\tcommand: string;\n\targs: readonly string[];\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tonStderr?: (text: string) => void;\n}\n\nexport type McpStdioTransportFactory = (\n\tconfig: McpStdioTransportConfig,\n) => McpStdioTransport | Promise<McpStdioTransport>;\n\nexport interface McpStdioPluginOptions {\n\tcommand: string;\n\targs?: readonly string[];\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\ttimeoutMs?: number;\n\ttransportFactory?: McpStdioTransportFactory;\n\tonStderr?: (text: string) => void;\n\tprotocolVersion?: string;\n\tclientInfo?: { name: string; version: string };\n}\n\ninterface JsonRpcResponse {\n\tjsonrpc?: unknown;\n\tid?: unknown;\n\tmethod?: unknown;\n\tresult?: unknown;\n\terror?: { code?: unknown; message?: unknown; data?: unknown };\n}\n\nconst noResult = (): AgentToolResult<unknown> => ({ content: [{ type: \"text\", text: \"\" }], details: undefined });\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new McpStdioError(`${label} must be an object`, \"malformed\", { data: value });\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction validateToolList(value: unknown): readonly Record<string, unknown>[] {\n\tconst object = asRecord(value, \"MCP tools/list result\");\n\tif (!Array.isArray(object.tools)) {\n\t\tthrow new McpStdioError(\"MCP tools/list result must contain tools[]\", \"malformed\", { data: value });\n\t}\n\treturn object.tools.map((tool, index) => {\n\t\tconst record = asRecord(tool, `MCP tool at index ${index}`);\n\t\tif (typeof record.name !== \"string\" || !record.name.trim()) {\n\t\t\tthrow new McpStdioError(`MCP tool at index ${index} requires a non-empty name`, \"malformed\", { data: tool });\n\t\t}\n\t\tif (record.inputSchema !== undefined && (typeof record.inputSchema !== \"object\" || record.inputSchema === null)) {\n\t\t\tthrow new McpStdioError(`MCP tool has an invalid inputSchema: ${record.name}`, \"malformed\", { data: tool });\n\t\t}\n\t\treturn record;\n\t});\n}\n\nfunction normalizeToolResult(value: unknown): AgentToolResult<unknown> {\n\tif (value && typeof value === \"object\" && Array.isArray((value as { content?: unknown }).content)) {\n\t\treturn value as AgentToolResult<unknown>;\n\t}\n\tif (value === undefined) return noResult();\n\treturn {\n\t\tcontent: [{ type: \"text\", text: typeof value === \"string\" ? value : JSON.stringify(value) }],\n\t\tdetails: undefined,\n\t};\n}\n\n/** Default line-delimited stdio transport. The command is never passed to a shell. */\nexport function spawnMcpTransport(config: McpStdioTransportConfig): McpStdioTransport {\n\tconst child = spawn(config.command, [...config.args], {\n\t\tcwd: config.cwd,\n\t\tenv: config.env,\n\t\tshell: false,\n\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t});\n\treturn createJsonRpcTransport(child, config.onStderr);\n}\n\nfunction createJsonRpcTransport(\n\tchild: ChildProcessWithoutNullStreams,\n\tonStderr?: (text: string) => void,\n): McpStdioTransport {\n\tlet nextId = 1;\n\tlet closed = false;\n\tlet stdout = \"\";\n\tlet stderr = \"\";\n\tlet closeRequested = false;\n\tconst pending = new Map<\n\t\tnumber,\n\t\t{ method: string; resolve: (value: unknown) => void; reject: (error: unknown) => void }\n\t>();\n\tconst ignored = new Set<number>();\n\tlet fatalError: McpStdioError | undefined;\n\n\tconst failAll = (error: McpStdioError): void => {\n\t\tif (fatalError) return;\n\t\tfatalError = error;\n\t\tclosed = true;\n\t\tfor (const request of pending.values()) request.reject(error);\n\t\tpending.clear();\n\t};\n\n\tchild.stdout.setEncoding(\"utf8\");\n\tchild.stdout.on(\"data\", (chunk: string) => {\n\t\tstdout += chunk;\n\t\tconst lines = stdout.split(/\\r?\\n/);\n\t\tstdout = lines.pop() ?? \"\";\n\t\tfor (const line of lines) {\n\t\t\tif (!line.trim()) continue;\n\t\t\tlet parsed: JsonRpcResponse;\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(line) as JsonRpcResponse;\n\t\t\t} catch {\n\t\t\t\tfailAll(new McpStdioError(\"Malformed JSON-RPC response\", \"malformed\", { stdout: line, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (parsed.jsonrpc !== \"2.0\") {\n\t\t\t\tfailAll(new McpStdioError(\"Invalid JSON-RPC response envelope\", \"protocol\", { data: parsed, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (parsed.id === undefined) {\n\t\t\t\tif (typeof parsed.method === \"string\") continue;\n\t\t\t\tfailAll(new McpStdioError(\"JSON-RPC response is missing an id\", \"protocol\", { data: parsed, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (typeof parsed.id !== \"number\" && parsed.id !== null) {\n\t\t\t\tfailAll(new McpStdioError(\"Invalid JSON-RPC response id\", \"protocol\", { data: parsed, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (parsed.id === null) continue;\n\t\t\tconst responseId = parsed.id as number;\n\t\t\tif (ignored.delete(responseId)) continue;\n\t\t\tconst request = pending.get(responseId);\n\t\t\tif (!request) {\n\t\t\t\tfailAll(\n\t\t\t\t\tnew McpStdioError(`Unknown JSON-RPC response id: ${responseId}`, \"protocol\", { data: parsed, stderr }),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending.delete(responseId);\n\t\t\tif (parsed.error) {\n\t\t\t\tconst message = typeof parsed.error.message === \"string\" ? parsed.error.message : \"MCP request failed\";\n\t\t\t\trequest.reject(\n\t\t\t\t\tnew McpStdioError(message, \"remote\", {\n\t\t\t\t\t\tmethod: request.method,\n\t\t\t\t\t\trequestId: responseId,\n\t\t\t\t\t\tdata: parsed.error,\n\t\t\t\t\t\tstderr,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else if (!(\"result\" in parsed)) {\n\t\t\t\trequest.reject(\n\t\t\t\t\tnew McpStdioError(\"JSON-RPC response has neither result nor error\", \"protocol\", {\n\t\t\t\t\t\tmethod: request.method,\n\t\t\t\t\t\trequestId: responseId,\n\t\t\t\t\t\tdata: parsed,\n\t\t\t\t\t\tstderr,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\trequest.resolve(parsed.result);\n\t\t\t}\n\t\t}\n\t});\n\tchild.stderr.setEncoding(\"utf8\");\n\tchild.stderr.on(\"data\", (chunk: string) => {\n\t\tstderr += chunk;\n\t\tonStderr?.(chunk);\n\t});\n\tchild.once(\"error\", (error) => {\n\t\tfailAll(new McpStdioError(`Failed to spawn MCP process: ${error.message}`, \"spawn\", { stdout, stderr }));\n\t});\n\tchild.once(\"close\", (exitCode) => {\n\t\tif (closed) return;\n\t\tfailAll(\n\t\t\tnew McpStdioError(`MCP process exited with code ${exitCode ?? \"unknown\"}`, \"exit\", {\n\t\t\t\tstdout,\n\t\t\t\tstderr,\n\t\t\t\texitCode,\n\t\t\t}),\n\t\t);\n\t});\n\n\tconst request = (method: string, params?: unknown, options: McpRequestOptions = {}): Promise<unknown> => {\n\t\tif (fatalError || closed)\n\t\t\treturn Promise.reject(fatalError ?? new McpStdioError(\"MCP transport is closed\", \"exit\", { stderr }));\n\t\tif (options.signal?.aborted)\n\t\t\treturn Promise.reject(new McpStdioError(\"MCP request aborted\", \"aborted\", { method, stderr }));\n\t\tconst id = nextId++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timeout: NodeJS.Timeout | undefined;\n\t\t\tconst abort = (): void => {\n\t\t\t\tif (!pending.delete(id)) return;\n\t\t\t\tignored.add(id);\n\t\t\t\tif (timeout) clearTimeout(timeout);\n\t\t\t\treject(new McpStdioError(\"MCP request aborted\", \"aborted\", { method, requestId: id, stderr }));\n\t\t\t};\n\t\t\tpending.set(id, {\n\t\t\t\tmethod,\n\t\t\t\tresolve: (result) => {\n\t\t\t\t\tif (timeout) clearTimeout(timeout);\n\t\t\t\t\toptions.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\t\tresolve(result);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tif (timeout) clearTimeout(timeout);\n\t\t\t\t\toptions.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t});\n\t\t\toptions.signal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tif (options.timeoutMs !== undefined) {\n\t\t\t\ttimeout = setTimeout(() => {\n\t\t\t\t\tif (!pending.delete(id)) return;\n\t\t\t\t\tignored.add(id);\n\t\t\t\t\toptions.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\t\treject(new McpStdioError(\"MCP request timed out\", \"timed_out\", { method, requestId: id, stderr }));\n\t\t\t\t}, options.timeoutMs);\n\t\t\t}\n\t\t\tchild.stdin.write(\n\t\t\t\t`${JSON.stringify({ jsonrpc: \"2.0\", id, method, ...(params === undefined ? {} : { params }) })}\\n`,\n\t\t\t);\n\t\t});\n\t};\n\treturn {\n\t\trequest,\n\t\tnotify(method, params) {\n\t\t\tif (fatalError || closed) throw fatalError ?? new McpStdioError(\"MCP transport is closed\", \"exit\", { stderr });\n\t\t\tchild.stdin.write(\n\t\t\t\t`${JSON.stringify({ jsonrpc: \"2.0\", method, ...(params === undefined ? {} : { params }) })}\\n`,\n\t\t\t);\n\t\t},\n\t\tclose() {\n\t\t\tif (closeRequested) return;\n\t\t\tcloseRequested = true;\n\t\t\tclosed = true;\n\t\t\tfor (const request of pending.values())\n\t\t\t\trequest.reject(new McpStdioError(\"MCP transport closed\", \"exit\", { stdout, stderr }));\n\t\t\tpending.clear();\n\t\t\tchild.stdin.end();\n\t\t\tif (!child.killed) child.kill();\n\t\t},\n\t\tget stderr() {\n\t\t\treturn stderr;\n\t\t},\n\t};\n}\n\nfunction validateOptions(options: McpStdioPluginOptions): void {\n\tif (!options.command.trim()) throw new Error(\"MCP stdio command requires a non-empty command\");\n\tif (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)) {\n\t\tthrow new Error(\"MCP stdio timeoutMs must be a positive number\");\n\t}\n}\n\n/** Create an asynchronously discovering MCP stdio capability plugin. */\nexport function createMcpStdioPlugin(options: McpStdioPluginOptions): CapabilityPluginFactory {\n\tvalidateOptions(options);\n\tconst factory = options.transportFactory ?? spawnMcpTransport;\n\treturn async (api: CapabilityAPI) => {\n\t\tconst transport = await factory({\n\t\t\tcommand: options.command,\n\t\t\targs: options.args ?? [],\n\t\t\tcwd: options.cwd,\n\t\t\tenv: options.env,\n\t\t\tonStderr: options.onStderr,\n\t\t});\n\t\ttry {\n\t\t\tasRecord(\n\t\t\t\tawait transport.request(\n\t\t\t\t\t\"initialize\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocolVersion: options.protocolVersion ?? \"2024-11-05\",\n\t\t\t\t\t\tcapabilities: {},\n\t\t\t\t\t\tclientInfo: options.clientInfo ?? { name: \"agent-forge-mcp-stdio\", version: \"0.1.0\" },\n\t\t\t\t\t},\n\t\t\t\t\t{ timeoutMs: options.timeoutMs },\n\t\t\t\t),\n\t\t\t\t\"MCP initialize result\",\n\t\t\t);\n\t\t\tawait transport.notify(\"notifications/initialized\");\n\t\t\tconst discovered = validateToolList(\n\t\t\t\tawait transport.request(\"tools/list\", undefined, { timeoutMs: options.timeoutMs }),\n\t\t\t);\n\t\t\tfor (const remote of discovered) {\n\t\t\t\tconst name = remote.name as string;\n\t\t\t\tconst schema = (remote.inputSchema ?? Type.Object({})) as ToolDefinition[\"parameters\"];\n\t\t\t\tconst definition: ToolDefinition = {\n\t\t\t\t\tname,\n\t\t\t\t\tlabel: name,\n\t\t\t\t\tdescription: typeof remote.description === \"string\" ? remote.description : `MCP tool: ${name}`,\n\t\t\t\t\tparameters: schema,\n\t\t\t\t\tasync execute(toolCallId, params, signal, _onUpdate, _ctx: ExtensionContext) {\n\t\t\t\t\t\tconst input = params === undefined && typeof toolCallId !== \"string\" ? toolCallId : params;\n\t\t\t\t\t\tconst result = await transport.request(\n\t\t\t\t\t\t\t\"tools/call\",\n\t\t\t\t\t\t\t{ name, arguments: input ?? {} },\n\t\t\t\t\t\t\t{ signal, timeoutMs: options.timeoutMs },\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn normalizeToolResult(result);\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tapi.registerTool(definition);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tdispose: async () => {\n\t\t\t\t\tawait transport.close();\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait transport.close();\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Template entry only. A working MCP transport needs a user-selected command,\n * arguments, and timeout; never launch an unconfigured child process.\n */\nexport default function mcpStdioExample(_api: CapabilityAPI): never {\n\tthrow new Error(\n\t\t\"Configure createMcpStdioPlugin({ command, args, timeoutMs }) before installing this MCP stdio example.\",\n\t);\n}\n"]}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * MCP-like JSON-RPC 2.0 stdio bridge.
3
+ *
4
+ * This is intentionally an external capability plugin. It discovers tools
5
+ * from one explicitly configured process and exposes them through the public
6
+ * CapabilityAPI; policy, approval, and server selection remain host-owned.
7
+ */
8
+ import { spawn } from "node:child_process";
9
+ import { Type } from "typebox";
10
+ export class McpStdioError extends Error {
11
+ reason;
12
+ details;
13
+ constructor(message, reason, details = {}) {
14
+ super(message);
15
+ this.name = "McpStdioError";
16
+ this.reason = reason;
17
+ this.details = details;
18
+ }
19
+ }
20
+ const noResult = () => ({ content: [{ type: "text", text: "" }], details: undefined });
21
+ function asRecord(value, label) {
22
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
23
+ throw new McpStdioError(`${label} must be an object`, "malformed", { data: value });
24
+ }
25
+ return value;
26
+ }
27
+ function validateToolList(value) {
28
+ const object = asRecord(value, "MCP tools/list result");
29
+ if (!Array.isArray(object.tools)) {
30
+ throw new McpStdioError("MCP tools/list result must contain tools[]", "malformed", { data: value });
31
+ }
32
+ return object.tools.map((tool, index) => {
33
+ const record = asRecord(tool, `MCP tool at index ${index}`);
34
+ if (typeof record.name !== "string" || !record.name.trim()) {
35
+ throw new McpStdioError(`MCP tool at index ${index} requires a non-empty name`, "malformed", { data: tool });
36
+ }
37
+ if (record.inputSchema !== undefined && (typeof record.inputSchema !== "object" || record.inputSchema === null)) {
38
+ throw new McpStdioError(`MCP tool has an invalid inputSchema: ${record.name}`, "malformed", { data: tool });
39
+ }
40
+ return record;
41
+ });
42
+ }
43
+ function normalizeToolResult(value) {
44
+ if (value && typeof value === "object" && Array.isArray(value.content)) {
45
+ return value;
46
+ }
47
+ if (value === undefined)
48
+ return noResult();
49
+ return {
50
+ content: [{ type: "text", text: typeof value === "string" ? value : JSON.stringify(value) }],
51
+ details: undefined,
52
+ };
53
+ }
54
+ /** Default line-delimited stdio transport. The command is never passed to a shell. */
55
+ export function spawnMcpTransport(config) {
56
+ const child = spawn(config.command, [...config.args], {
57
+ cwd: config.cwd,
58
+ env: config.env,
59
+ shell: false,
60
+ stdio: ["pipe", "pipe", "pipe"],
61
+ });
62
+ return createJsonRpcTransport(child, config.onStderr);
63
+ }
64
+ function createJsonRpcTransport(child, onStderr) {
65
+ let nextId = 1;
66
+ let closed = false;
67
+ let stdout = "";
68
+ let stderr = "";
69
+ let closeRequested = false;
70
+ const pending = new Map();
71
+ const ignored = new Set();
72
+ let fatalError;
73
+ const failAll = (error) => {
74
+ if (fatalError)
75
+ return;
76
+ fatalError = error;
77
+ closed = true;
78
+ for (const request of pending.values())
79
+ request.reject(error);
80
+ pending.clear();
81
+ };
82
+ child.stdout.setEncoding("utf8");
83
+ child.stdout.on("data", (chunk) => {
84
+ stdout += chunk;
85
+ const lines = stdout.split(/\r?\n/);
86
+ stdout = lines.pop() ?? "";
87
+ for (const line of lines) {
88
+ if (!line.trim())
89
+ continue;
90
+ let parsed;
91
+ try {
92
+ parsed = JSON.parse(line);
93
+ }
94
+ catch {
95
+ failAll(new McpStdioError("Malformed JSON-RPC response", "malformed", { stdout: line, stderr }));
96
+ return;
97
+ }
98
+ if (parsed.jsonrpc !== "2.0") {
99
+ failAll(new McpStdioError("Invalid JSON-RPC response envelope", "protocol", { data: parsed, stderr }));
100
+ return;
101
+ }
102
+ if (parsed.id === undefined) {
103
+ if (typeof parsed.method === "string")
104
+ continue;
105
+ failAll(new McpStdioError("JSON-RPC response is missing an id", "protocol", { data: parsed, stderr }));
106
+ return;
107
+ }
108
+ if (typeof parsed.id !== "number" && parsed.id !== null) {
109
+ failAll(new McpStdioError("Invalid JSON-RPC response id", "protocol", { data: parsed, stderr }));
110
+ return;
111
+ }
112
+ if (parsed.id === null)
113
+ continue;
114
+ const responseId = parsed.id;
115
+ if (ignored.delete(responseId))
116
+ continue;
117
+ const request = pending.get(responseId);
118
+ if (!request) {
119
+ failAll(new McpStdioError(`Unknown JSON-RPC response id: ${responseId}`, "protocol", { data: parsed, stderr }));
120
+ return;
121
+ }
122
+ pending.delete(responseId);
123
+ if (parsed.error) {
124
+ const message = typeof parsed.error.message === "string" ? parsed.error.message : "MCP request failed";
125
+ request.reject(new McpStdioError(message, "remote", {
126
+ method: request.method,
127
+ requestId: responseId,
128
+ data: parsed.error,
129
+ stderr,
130
+ }));
131
+ }
132
+ else if (!("result" in parsed)) {
133
+ request.reject(new McpStdioError("JSON-RPC response has neither result nor error", "protocol", {
134
+ method: request.method,
135
+ requestId: responseId,
136
+ data: parsed,
137
+ stderr,
138
+ }));
139
+ }
140
+ else {
141
+ request.resolve(parsed.result);
142
+ }
143
+ }
144
+ });
145
+ child.stderr.setEncoding("utf8");
146
+ child.stderr.on("data", (chunk) => {
147
+ stderr += chunk;
148
+ onStderr?.(chunk);
149
+ });
150
+ child.once("error", (error) => {
151
+ failAll(new McpStdioError(`Failed to spawn MCP process: ${error.message}`, "spawn", { stdout, stderr }));
152
+ });
153
+ child.once("close", (exitCode) => {
154
+ if (closed)
155
+ return;
156
+ failAll(new McpStdioError(`MCP process exited with code ${exitCode ?? "unknown"}`, "exit", {
157
+ stdout,
158
+ stderr,
159
+ exitCode,
160
+ }));
161
+ });
162
+ const request = (method, params, options = {}) => {
163
+ if (fatalError || closed)
164
+ return Promise.reject(fatalError ?? new McpStdioError("MCP transport is closed", "exit", { stderr }));
165
+ if (options.signal?.aborted)
166
+ return Promise.reject(new McpStdioError("MCP request aborted", "aborted", { method, stderr }));
167
+ const id = nextId++;
168
+ return new Promise((resolve, reject) => {
169
+ let timeout;
170
+ const abort = () => {
171
+ if (!pending.delete(id))
172
+ return;
173
+ ignored.add(id);
174
+ if (timeout)
175
+ clearTimeout(timeout);
176
+ reject(new McpStdioError("MCP request aborted", "aborted", { method, requestId: id, stderr }));
177
+ };
178
+ pending.set(id, {
179
+ method,
180
+ resolve: (result) => {
181
+ if (timeout)
182
+ clearTimeout(timeout);
183
+ options.signal?.removeEventListener("abort", abort);
184
+ resolve(result);
185
+ },
186
+ reject: (error) => {
187
+ if (timeout)
188
+ clearTimeout(timeout);
189
+ options.signal?.removeEventListener("abort", abort);
190
+ reject(error);
191
+ },
192
+ });
193
+ options.signal?.addEventListener("abort", abort, { once: true });
194
+ if (options.timeoutMs !== undefined) {
195
+ timeout = setTimeout(() => {
196
+ if (!pending.delete(id))
197
+ return;
198
+ ignored.add(id);
199
+ options.signal?.removeEventListener("abort", abort);
200
+ reject(new McpStdioError("MCP request timed out", "timed_out", { method, requestId: id, stderr }));
201
+ }, options.timeoutMs);
202
+ }
203
+ child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, ...(params === undefined ? {} : { params }) })}\n`);
204
+ });
205
+ };
206
+ return {
207
+ request,
208
+ notify(method, params) {
209
+ if (fatalError || closed)
210
+ throw fatalError ?? new McpStdioError("MCP transport is closed", "exit", { stderr });
211
+ child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", method, ...(params === undefined ? {} : { params }) })}\n`);
212
+ },
213
+ close() {
214
+ if (closeRequested)
215
+ return;
216
+ closeRequested = true;
217
+ closed = true;
218
+ for (const request of pending.values())
219
+ request.reject(new McpStdioError("MCP transport closed", "exit", { stdout, stderr }));
220
+ pending.clear();
221
+ child.stdin.end();
222
+ if (!child.killed)
223
+ child.kill();
224
+ },
225
+ get stderr() {
226
+ return stderr;
227
+ },
228
+ };
229
+ }
230
+ function validateOptions(options) {
231
+ if (!options.command.trim())
232
+ throw new Error("MCP stdio command requires a non-empty command");
233
+ if (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)) {
234
+ throw new Error("MCP stdio timeoutMs must be a positive number");
235
+ }
236
+ }
237
+ /** Create an asynchronously discovering MCP stdio capability plugin. */
238
+ export function createMcpStdioPlugin(options) {
239
+ validateOptions(options);
240
+ const factory = options.transportFactory ?? spawnMcpTransport;
241
+ return async (api) => {
242
+ const transport = await factory({
243
+ command: options.command,
244
+ args: options.args ?? [],
245
+ cwd: options.cwd,
246
+ env: options.env,
247
+ onStderr: options.onStderr,
248
+ });
249
+ try {
250
+ asRecord(await transport.request("initialize", {
251
+ protocolVersion: options.protocolVersion ?? "2024-11-05",
252
+ capabilities: {},
253
+ clientInfo: options.clientInfo ?? { name: "agent-forge-mcp-stdio", version: "0.1.0" },
254
+ }, { timeoutMs: options.timeoutMs }), "MCP initialize result");
255
+ await transport.notify("notifications/initialized");
256
+ const discovered = validateToolList(await transport.request("tools/list", undefined, { timeoutMs: options.timeoutMs }));
257
+ for (const remote of discovered) {
258
+ const name = remote.name;
259
+ const schema = (remote.inputSchema ?? Type.Object({}));
260
+ const definition = {
261
+ name,
262
+ label: name,
263
+ description: typeof remote.description === "string" ? remote.description : `MCP tool: ${name}`,
264
+ parameters: schema,
265
+ async execute(toolCallId, params, signal, _onUpdate, _ctx) {
266
+ const input = params === undefined && typeof toolCallId !== "string" ? toolCallId : params;
267
+ const result = await transport.request("tools/call", { name, arguments: input ?? {} }, { signal, timeoutMs: options.timeoutMs });
268
+ return normalizeToolResult(result);
269
+ },
270
+ };
271
+ api.registerTool(definition);
272
+ }
273
+ return {
274
+ dispose: async () => {
275
+ await transport.close();
276
+ },
277
+ };
278
+ }
279
+ catch (error) {
280
+ await transport.close();
281
+ throw error;
282
+ }
283
+ };
284
+ }
285
+ /**
286
+ * Template entry only. A working MCP transport needs a user-selected command,
287
+ * arguments, and timeout; never launch an unconfigured child process.
288
+ */
289
+ export default function mcpStdioExample(_api) {
290
+ throw new Error("Configure createMcpStdioPlugin({ command, args, timeoutMs }) before installing this MCP stdio example.");
291
+ }
292
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP-like JSON-RPC 2.0 stdio bridge.\n *\n * This is intentionally an external capability plugin. It discovers tools\n * from one explicitly configured process and exposes them through the public\n * CapabilityAPI; policy, approval, and server selection remain host-owned.\n */\n\nimport type { ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { spawn } from \"node:child_process\";\nimport type { AgentToolResult } from \"@agent-forge/agent-core\";\nimport type {\n\tCapabilityAPI,\n\tCapabilityPluginFactory,\n\tExtensionContext,\n\tToolDefinition,\n} from \"@agent-forge/coding-agent\";\nimport { Type } from \"typebox\";\n\nexport type McpErrorReason = \"spawn\" | \"exit\" | \"malformed\" | \"protocol\" | \"remote\" | \"aborted\" | \"timed_out\";\n\nexport interface McpErrorDetails {\n\tmethod?: string;\n\trequestId?: number;\n\tstdout?: string;\n\tstderr?: string;\n\texitCode?: number | null;\n\tdata?: unknown;\n}\n\nexport class McpStdioError extends Error {\n\treadonly reason: McpErrorReason;\n\treadonly details: McpErrorDetails;\n\n\tconstructor(message: string, reason: McpErrorReason, details: McpErrorDetails = {}) {\n\t\tsuper(message);\n\t\tthis.name = \"McpStdioError\";\n\t\tthis.reason = reason;\n\t\tthis.details = details;\n\t}\n}\n\nexport interface McpRequestOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n}\n\nexport interface McpStdioTransport {\n\trequest(method: string, params?: unknown, options?: McpRequestOptions): Promise<unknown>;\n\tnotify(method: string, params?: unknown): Promise<void> | void;\n\tclose(): Promise<void> | void;\n\treadonly stderr?: string;\n}\n\nexport interface McpStdioTransportConfig {\n\tcommand: string;\n\targs: readonly string[];\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tonStderr?: (text: string) => void;\n}\n\nexport type McpStdioTransportFactory = (\n\tconfig: McpStdioTransportConfig,\n) => McpStdioTransport | Promise<McpStdioTransport>;\n\nexport interface McpStdioPluginOptions {\n\tcommand: string;\n\targs?: readonly string[];\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\ttimeoutMs?: number;\n\ttransportFactory?: McpStdioTransportFactory;\n\tonStderr?: (text: string) => void;\n\tprotocolVersion?: string;\n\tclientInfo?: { name: string; version: string };\n}\n\ninterface JsonRpcResponse {\n\tjsonrpc?: unknown;\n\tid?: unknown;\n\tmethod?: unknown;\n\tresult?: unknown;\n\terror?: { code?: unknown; message?: unknown; data?: unknown };\n}\n\nconst noResult = (): AgentToolResult<unknown> => ({ content: [{ type: \"text\", text: \"\" }], details: undefined });\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new McpStdioError(`${label} must be an object`, \"malformed\", { data: value });\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction validateToolList(value: unknown): readonly Record<string, unknown>[] {\n\tconst object = asRecord(value, \"MCP tools/list result\");\n\tif (!Array.isArray(object.tools)) {\n\t\tthrow new McpStdioError(\"MCP tools/list result must contain tools[]\", \"malformed\", { data: value });\n\t}\n\treturn object.tools.map((tool, index) => {\n\t\tconst record = asRecord(tool, `MCP tool at index ${index}`);\n\t\tif (typeof record.name !== \"string\" || !record.name.trim()) {\n\t\t\tthrow new McpStdioError(`MCP tool at index ${index} requires a non-empty name`, \"malformed\", { data: tool });\n\t\t}\n\t\tif (record.inputSchema !== undefined && (typeof record.inputSchema !== \"object\" || record.inputSchema === null)) {\n\t\t\tthrow new McpStdioError(`MCP tool has an invalid inputSchema: ${record.name}`, \"malformed\", { data: tool });\n\t\t}\n\t\treturn record;\n\t});\n}\n\nfunction normalizeToolResult(value: unknown): AgentToolResult<unknown> {\n\tif (value && typeof value === \"object\" && Array.isArray((value as { content?: unknown }).content)) {\n\t\treturn value as AgentToolResult<unknown>;\n\t}\n\tif (value === undefined) return noResult();\n\treturn {\n\t\tcontent: [{ type: \"text\", text: typeof value === \"string\" ? value : JSON.stringify(value) }],\n\t\tdetails: undefined,\n\t};\n}\n\n/** Default line-delimited stdio transport. The command is never passed to a shell. */\nexport function spawnMcpTransport(config: McpStdioTransportConfig): McpStdioTransport {\n\tconst child = spawn(config.command, [...config.args], {\n\t\tcwd: config.cwd,\n\t\tenv: config.env,\n\t\tshell: false,\n\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t});\n\treturn createJsonRpcTransport(child, config.onStderr);\n}\n\nfunction createJsonRpcTransport(\n\tchild: ChildProcessWithoutNullStreams,\n\tonStderr?: (text: string) => void,\n): McpStdioTransport {\n\tlet nextId = 1;\n\tlet closed = false;\n\tlet stdout = \"\";\n\tlet stderr = \"\";\n\tlet closeRequested = false;\n\tconst pending = new Map<\n\t\tnumber,\n\t\t{ method: string; resolve: (value: unknown) => void; reject: (error: unknown) => void }\n\t>();\n\tconst ignored = new Set<number>();\n\tlet fatalError: McpStdioError | undefined;\n\n\tconst failAll = (error: McpStdioError): void => {\n\t\tif (fatalError) return;\n\t\tfatalError = error;\n\t\tclosed = true;\n\t\tfor (const request of pending.values()) request.reject(error);\n\t\tpending.clear();\n\t};\n\n\tchild.stdout.setEncoding(\"utf8\");\n\tchild.stdout.on(\"data\", (chunk: string) => {\n\t\tstdout += chunk;\n\t\tconst lines = stdout.split(/\\r?\\n/);\n\t\tstdout = lines.pop() ?? \"\";\n\t\tfor (const line of lines) {\n\t\t\tif (!line.trim()) continue;\n\t\t\tlet parsed: JsonRpcResponse;\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(line) as JsonRpcResponse;\n\t\t\t} catch {\n\t\t\t\tfailAll(new McpStdioError(\"Malformed JSON-RPC response\", \"malformed\", { stdout: line, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (parsed.jsonrpc !== \"2.0\") {\n\t\t\t\tfailAll(new McpStdioError(\"Invalid JSON-RPC response envelope\", \"protocol\", { data: parsed, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (parsed.id === undefined) {\n\t\t\t\tif (typeof parsed.method === \"string\") continue;\n\t\t\t\tfailAll(new McpStdioError(\"JSON-RPC response is missing an id\", \"protocol\", { data: parsed, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (typeof parsed.id !== \"number\" && parsed.id !== null) {\n\t\t\t\tfailAll(new McpStdioError(\"Invalid JSON-RPC response id\", \"protocol\", { data: parsed, stderr }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (parsed.id === null) continue;\n\t\t\tconst responseId = parsed.id as number;\n\t\t\tif (ignored.delete(responseId)) continue;\n\t\t\tconst request = pending.get(responseId);\n\t\t\tif (!request) {\n\t\t\t\tfailAll(\n\t\t\t\t\tnew McpStdioError(`Unknown JSON-RPC response id: ${responseId}`, \"protocol\", { data: parsed, stderr }),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending.delete(responseId);\n\t\t\tif (parsed.error) {\n\t\t\t\tconst message = typeof parsed.error.message === \"string\" ? parsed.error.message : \"MCP request failed\";\n\t\t\t\trequest.reject(\n\t\t\t\t\tnew McpStdioError(message, \"remote\", {\n\t\t\t\t\t\tmethod: request.method,\n\t\t\t\t\t\trequestId: responseId,\n\t\t\t\t\t\tdata: parsed.error,\n\t\t\t\t\t\tstderr,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else if (!(\"result\" in parsed)) {\n\t\t\t\trequest.reject(\n\t\t\t\t\tnew McpStdioError(\"JSON-RPC response has neither result nor error\", \"protocol\", {\n\t\t\t\t\t\tmethod: request.method,\n\t\t\t\t\t\trequestId: responseId,\n\t\t\t\t\t\tdata: parsed,\n\t\t\t\t\t\tstderr,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\trequest.resolve(parsed.result);\n\t\t\t}\n\t\t}\n\t});\n\tchild.stderr.setEncoding(\"utf8\");\n\tchild.stderr.on(\"data\", (chunk: string) => {\n\t\tstderr += chunk;\n\t\tonStderr?.(chunk);\n\t});\n\tchild.once(\"error\", (error) => {\n\t\tfailAll(new McpStdioError(`Failed to spawn MCP process: ${error.message}`, \"spawn\", { stdout, stderr }));\n\t});\n\tchild.once(\"close\", (exitCode) => {\n\t\tif (closed) return;\n\t\tfailAll(\n\t\t\tnew McpStdioError(`MCP process exited with code ${exitCode ?? \"unknown\"}`, \"exit\", {\n\t\t\t\tstdout,\n\t\t\t\tstderr,\n\t\t\t\texitCode,\n\t\t\t}),\n\t\t);\n\t});\n\n\tconst request = (method: string, params?: unknown, options: McpRequestOptions = {}): Promise<unknown> => {\n\t\tif (fatalError || closed)\n\t\t\treturn Promise.reject(fatalError ?? new McpStdioError(\"MCP transport is closed\", \"exit\", { stderr }));\n\t\tif (options.signal?.aborted)\n\t\t\treturn Promise.reject(new McpStdioError(\"MCP request aborted\", \"aborted\", { method, stderr }));\n\t\tconst id = nextId++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timeout: NodeJS.Timeout | undefined;\n\t\t\tconst abort = (): void => {\n\t\t\t\tif (!pending.delete(id)) return;\n\t\t\t\tignored.add(id);\n\t\t\t\tif (timeout) clearTimeout(timeout);\n\t\t\t\treject(new McpStdioError(\"MCP request aborted\", \"aborted\", { method, requestId: id, stderr }));\n\t\t\t};\n\t\t\tpending.set(id, {\n\t\t\t\tmethod,\n\t\t\t\tresolve: (result) => {\n\t\t\t\t\tif (timeout) clearTimeout(timeout);\n\t\t\t\t\toptions.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\t\tresolve(result);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tif (timeout) clearTimeout(timeout);\n\t\t\t\t\toptions.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t});\n\t\t\toptions.signal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tif (options.timeoutMs !== undefined) {\n\t\t\t\ttimeout = setTimeout(() => {\n\t\t\t\t\tif (!pending.delete(id)) return;\n\t\t\t\t\tignored.add(id);\n\t\t\t\t\toptions.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\t\treject(new McpStdioError(\"MCP request timed out\", \"timed_out\", { method, requestId: id, stderr }));\n\t\t\t\t}, options.timeoutMs);\n\t\t\t}\n\t\t\tchild.stdin.write(\n\t\t\t\t`${JSON.stringify({ jsonrpc: \"2.0\", id, method, ...(params === undefined ? {} : { params }) })}\\n`,\n\t\t\t);\n\t\t});\n\t};\n\treturn {\n\t\trequest,\n\t\tnotify(method, params) {\n\t\t\tif (fatalError || closed) throw fatalError ?? new McpStdioError(\"MCP transport is closed\", \"exit\", { stderr });\n\t\t\tchild.stdin.write(\n\t\t\t\t`${JSON.stringify({ jsonrpc: \"2.0\", method, ...(params === undefined ? {} : { params }) })}\\n`,\n\t\t\t);\n\t\t},\n\t\tclose() {\n\t\t\tif (closeRequested) return;\n\t\t\tcloseRequested = true;\n\t\t\tclosed = true;\n\t\t\tfor (const request of pending.values())\n\t\t\t\trequest.reject(new McpStdioError(\"MCP transport closed\", \"exit\", { stdout, stderr }));\n\t\t\tpending.clear();\n\t\t\tchild.stdin.end();\n\t\t\tif (!child.killed) child.kill();\n\t\t},\n\t\tget stderr() {\n\t\t\treturn stderr;\n\t\t},\n\t};\n}\n\nfunction validateOptions(options: McpStdioPluginOptions): void {\n\tif (!options.command.trim()) throw new Error(\"MCP stdio command requires a non-empty command\");\n\tif (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)) {\n\t\tthrow new Error(\"MCP stdio timeoutMs must be a positive number\");\n\t}\n}\n\n/** Create an asynchronously discovering MCP stdio capability plugin. */\nexport function createMcpStdioPlugin(options: McpStdioPluginOptions): CapabilityPluginFactory {\n\tvalidateOptions(options);\n\tconst factory = options.transportFactory ?? spawnMcpTransport;\n\treturn async (api: CapabilityAPI) => {\n\t\tconst transport = await factory({\n\t\t\tcommand: options.command,\n\t\t\targs: options.args ?? [],\n\t\t\tcwd: options.cwd,\n\t\t\tenv: options.env,\n\t\t\tonStderr: options.onStderr,\n\t\t});\n\t\ttry {\n\t\t\tasRecord(\n\t\t\t\tawait transport.request(\n\t\t\t\t\t\"initialize\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocolVersion: options.protocolVersion ?? \"2024-11-05\",\n\t\t\t\t\t\tcapabilities: {},\n\t\t\t\t\t\tclientInfo: options.clientInfo ?? { name: \"agent-forge-mcp-stdio\", version: \"0.1.0\" },\n\t\t\t\t\t},\n\t\t\t\t\t{ timeoutMs: options.timeoutMs },\n\t\t\t\t),\n\t\t\t\t\"MCP initialize result\",\n\t\t\t);\n\t\t\tawait transport.notify(\"notifications/initialized\");\n\t\t\tconst discovered = validateToolList(\n\t\t\t\tawait transport.request(\"tools/list\", undefined, { timeoutMs: options.timeoutMs }),\n\t\t\t);\n\t\t\tfor (const remote of discovered) {\n\t\t\t\tconst name = remote.name as string;\n\t\t\t\tconst schema = (remote.inputSchema ?? Type.Object({})) as ToolDefinition[\"parameters\"];\n\t\t\t\tconst definition: ToolDefinition = {\n\t\t\t\t\tname,\n\t\t\t\t\tlabel: name,\n\t\t\t\t\tdescription: typeof remote.description === \"string\" ? remote.description : `MCP tool: ${name}`,\n\t\t\t\t\tparameters: schema,\n\t\t\t\t\tasync execute(toolCallId, params, signal, _onUpdate, _ctx: ExtensionContext) {\n\t\t\t\t\t\tconst input = params === undefined && typeof toolCallId !== \"string\" ? toolCallId : params;\n\t\t\t\t\t\tconst result = await transport.request(\n\t\t\t\t\t\t\t\"tools/call\",\n\t\t\t\t\t\t\t{ name, arguments: input ?? {} },\n\t\t\t\t\t\t\t{ signal, timeoutMs: options.timeoutMs },\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn normalizeToolResult(result);\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tapi.registerTool(definition);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tdispose: async () => {\n\t\t\t\t\tawait transport.close();\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait transport.close();\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Template entry only. A working MCP transport needs a user-selected command,\n * arguments, and timeout; never launch an unconfigured child process.\n */\nexport default function mcpStdioExample(_api: CapabilityAPI): never {\n\tthrow new Error(\n\t\t\"Configure createMcpStdioPlugin({ command, args, timeoutMs }) before installing this MCP stdio example.\",\n\t);\n}\n"]}
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "agent-forge-extension-with-deps",
3
- "version": "0.87.2",
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.2",
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.2",
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.2",
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.2",
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-6F5JWGKE.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-LSP24WNH.js";import"./chunk-JUUC5AZY.js";import"./chunk-XDUWOHPL.js";import{i18n_exports,t}from"./chunk-44I47ACN.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"]}