@ai-agent-forge/agent-forge 0.88.1 → 0.88.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +1 -1
  3. package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
  4. package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
  5. package/bundled-plugins/coding-tools/agent-forge.json +1 -1
  6. package/bundled-plugins/coding-tools/plugin.json +1 -1
  7. package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
  8. package/bundled-plugins/compaction-policy/plugin.json +1 -1
  9. package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
  10. package/bundled-plugins/overflow-policy/plugin.json +1 -1
  11. package/bundled-plugins/provider-failover/agent-forge.json +1 -1
  12. package/bundled-plugins/provider-failover/plugin.json +1 -1
  13. package/bundled-plugins/retry-policy/agent-forge.json +1 -1
  14. package/bundled-plugins/retry-policy/plugin.json +1 -1
  15. package/dist/artifacts/paged-read.d.ts +6 -1
  16. package/dist/artifacts/paged-read.d.ts.map +1 -1
  17. package/dist/artifacts/paged-read.js.map +1 -1
  18. package/dist/bundle/.build-manifest.json +283 -263
  19. package/dist/bundle/chunks/{anthropic-messages-PLAKXR73.js → anthropic-messages-3FJHRAJL.js} +2 -2
  20. package/dist/bundle/chunks/anthropic.js +1 -1
  21. package/dist/bundle/chunks/{azure-openai-responses-OUWQ2AZD.js → azure-openai-responses-GCL47IDS.js} +1 -1
  22. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  23. package/dist/bundle/chunks/{chunk-Z72JWUZ4.js → chunk-32YDZI4J.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-AQLNTW2B.js → chunk-755VNWIF.js} +17 -16
  25. package/dist/bundle/chunks/{chunk-LZOEQITZ.js → chunk-B42Y2VME.js} +120 -104
  26. package/dist/bundle/chunks/{chunk-DRQDKNXA.js → chunk-BVVSHK6W.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-6R7UI4IY.js → chunk-QDLOMKF6.js} +1 -1
  28. package/dist/bundle/chunks/{chunk-D3ARGZFR.js → chunk-V3ACW7VD.js} +3 -3
  29. package/dist/bundle/chunks/{google-generative-ai-DLII6DAT.js → google-generative-ai-6BMXWA44.js} +1 -1
  30. package/dist/bundle/chunks/{google-vertex-G7BZL7GM.js → google-vertex-6H7NLRTK.js} +1 -1
  31. package/dist/bundle/chunks/image-resize-worker.js +3 -3
  32. package/dist/bundle/chunks/{mistral-conversations-JXUK24ID.js → mistral-conversations-IXUHSFSJ.js} +1 -1
  33. package/dist/bundle/chunks/{openai-codex-responses-5GSGFIPG.js → openai-codex-responses-YHUAEVCM.js} +1 -1
  34. package/dist/bundle/chunks/openai-codex.js +1 -1
  35. package/dist/bundle/chunks/{openai-completions-EI2I6DTG.js → openai-completions-ULQCFC72.js} +1 -1
  36. package/dist/bundle/chunks/openai-responses-NLLAJDPS.js +2 -0
  37. package/dist/bundle/chunks/{openrouter-images-G4GQRUSG.js → openrouter-images-GZZQZXMS.js} +1 -1
  38. package/dist/bundle/chunks/openrouter.js +1 -1
  39. package/dist/bundle/chunks/{pi-messages-PWU2VJMR.js → pi-messages-EJTI2EJ3.js} +1 -1
  40. package/dist/bundle/chunks/virtual-modules-TQWEGNNZ.js +5 -0
  41. package/dist/bundle/cli.js +1 -1
  42. package/dist/bundle/client.js +1 -1
  43. package/dist/bundle/index.js +1 -1
  44. package/dist/bundle/rpc-entry.js +1 -1
  45. package/dist/cli/args.d.ts +0 -1
  46. package/dist/cli/args.d.ts.map +1 -1
  47. package/dist/cli/args.js +1 -4
  48. package/dist/cli/args.js.map +1 -1
  49. package/dist/cli/config-selector.d.ts.map +1 -1
  50. package/dist/cli/config-selector.js +1 -1
  51. package/dist/cli/config-selector.js.map +1 -1
  52. package/dist/cli/experimental/cli.d.ts +3 -3
  53. package/dist/cli/experimental/cli.d.ts.map +1 -1
  54. package/dist/cli/experimental/cli.js +2 -2
  55. package/dist/cli/experimental/cli.js.map +1 -1
  56. package/dist/cli/experimental/commands/agent-forge.d.ts +15 -0
  57. package/dist/cli/experimental/commands/agent-forge.d.ts.map +1 -0
  58. package/dist/cli/experimental/commands/{pi.js → agent-forge.js} +4 -4
  59. package/dist/cli/experimental/commands/agent-forge.js.map +1 -0
  60. package/dist/cli/plugin-command.d.ts.map +1 -1
  61. package/dist/cli/plugin-command.js +8 -2
  62. package/dist/cli/plugin-command.js.map +1 -1
  63. package/dist/cli/startup-ui.d.ts.map +1 -1
  64. package/dist/cli/startup-ui.js +1 -1
  65. package/dist/cli/startup-ui.js.map +1 -1
  66. package/dist/config.d.ts +4 -4
  67. package/dist/config.d.ts.map +1 -1
  68. package/dist/config.js +7 -7
  69. package/dist/config.js.map +1 -1
  70. package/dist/core/agent-forge-manifest.d.ts +7 -0
  71. package/dist/core/agent-forge-manifest.d.ts.map +1 -0
  72. package/dist/core/{pi-manifest.js → agent-forge-manifest.js} +4 -4
  73. package/dist/core/agent-forge-manifest.js.map +1 -0
  74. package/dist/core/agent-session-compaction.d.ts +1 -1
  75. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  76. package/dist/core/agent-session-compaction.js +3 -3
  77. package/dist/core/agent-session-compaction.js.map +1 -1
  78. package/dist/core/agent-session-internal.d.ts +2 -0
  79. package/dist/core/agent-session-internal.d.ts.map +1 -1
  80. package/dist/core/agent-session-internal.js.map +1 -1
  81. package/dist/core/agent-session-lifecycle.d.ts.map +1 -1
  82. package/dist/core/agent-session-lifecycle.js +12 -1
  83. package/dist/core/agent-session-lifecycle.js.map +1 -1
  84. package/dist/core/agent-session-projection.d.ts.map +1 -1
  85. package/dist/core/agent-session-projection.js +3 -3
  86. package/dist/core/agent-session-projection.js.map +1 -1
  87. package/dist/core/agent-session-services.d.ts +3 -1
  88. package/dist/core/agent-session-services.d.ts.map +1 -1
  89. package/dist/core/agent-session-services.js +2 -1
  90. package/dist/core/agent-session-services.js.map +1 -1
  91. package/dist/core/agent-session-store.d.ts.map +1 -1
  92. package/dist/core/agent-session-store.js +6 -1
  93. package/dist/core/agent-session-store.js.map +1 -1
  94. package/dist/core/agent-session-tools.d.ts.map +1 -1
  95. package/dist/core/agent-session-tools.js +13 -0
  96. package/dist/core/agent-session-tools.js.map +1 -1
  97. package/dist/core/agent-session.d.ts +24 -0
  98. package/dist/core/agent-session.d.ts.map +1 -1
  99. package/dist/core/agent-session.js +58 -4
  100. package/dist/core/agent-session.js.map +1 -1
  101. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  102. package/dist/core/compaction/branch-summarization.js +1 -1
  103. package/dist/core/compaction/branch-summarization.js.map +1 -1
  104. package/dist/core/experimental.d.ts.map +1 -1
  105. package/dist/core/experimental.js +1 -3
  106. package/dist/core/experimental.js.map +1 -1
  107. package/dist/core/extensions/capability-runtime-store.d.ts +20 -1
  108. package/dist/core/extensions/capability-runtime-store.d.ts.map +1 -1
  109. package/dist/core/extensions/capability-runtime-store.js +67 -0
  110. package/dist/core/extensions/capability-runtime-store.js.map +1 -1
  111. package/dist/core/extensions/capability-runtime-types.d.ts +14 -0
  112. package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -1
  113. package/dist/core/extensions/capability-runtime-types.js +7 -1
  114. package/dist/core/extensions/capability-runtime-types.js.map +1 -1
  115. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  116. package/dist/core/extensions/capability-runtime.js +144 -42
  117. package/dist/core/extensions/capability-runtime.js.map +1 -1
  118. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  119. package/dist/core/extensions/virtual-modules.js +6 -1
  120. package/dist/core/extensions/virtual-modules.js.map +1 -1
  121. package/dist/core/facade/coding-agent-facade.d.ts +1 -1
  122. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  123. package/dist/core/facade/coding-agent-facade.js +1 -1
  124. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  125. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -1
  126. package/dist/core/i18n/locales/zh-cn/cli.js +2 -0
  127. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -1
  128. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +1 -1
  129. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -1
  130. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +3 -3
  131. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -1
  132. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -1
  133. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +1 -1
  134. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -1
  135. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
  136. package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -1
  137. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
  138. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -1
  139. package/dist/core/i18n/locales/zh-cn/index.js +2 -0
  140. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -1
  141. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -1
  142. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +5 -0
  143. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -1
  144. package/dist/core/i18n/locales/zh-cn/session-cleanup.d.ts +7 -0
  145. package/dist/core/i18n/locales/zh-cn/session-cleanup.d.ts.map +1 -0
  146. package/dist/core/i18n/locales/zh-cn/session-cleanup.js +15 -0
  147. package/dist/core/i18n/locales/zh-cn/session-cleanup.js.map +1 -0
  148. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -1
  149. package/dist/core/i18n/locales/zh-cn/slash-commands.js +1 -0
  150. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -1
  151. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -1
  152. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +2 -0
  153. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -1
  154. package/dist/core/model-resolver.d.ts +2 -0
  155. package/dist/core/model-resolver.d.ts.map +1 -1
  156. package/dist/core/model-resolver.js +4 -1
  157. package/dist/core/model-resolver.js.map +1 -1
  158. package/dist/core/package-resource-collection.d.ts.map +1 -1
  159. package/dist/core/package-resource-collection.js +5 -5
  160. package/dist/core/package-resource-collection.js.map +1 -1
  161. package/dist/core/provider-composer.d.ts.map +1 -1
  162. package/dist/core/provider-composer.js +3 -3
  163. package/dist/core/provider-composer.js.map +1 -1
  164. package/dist/core/resource-loader.d.ts.map +1 -1
  165. package/dist/core/resource-loader.js +1 -1
  166. package/dist/core/resource-loader.js.map +1 -1
  167. package/dist/core/sdk.d.ts +1 -1
  168. package/dist/core/sdk.d.ts.map +1 -1
  169. package/dist/core/sdk.js +30 -8
  170. package/dist/core/sdk.js.map +1 -1
  171. package/dist/core/session-cleanup.d.ts +49 -0
  172. package/dist/core/session-cleanup.d.ts.map +1 -0
  173. package/dist/core/session-cleanup.js +159 -0
  174. package/dist/core/session-cleanup.js.map +1 -0
  175. package/dist/core/session-index.d.ts +75 -0
  176. package/dist/core/session-index.d.ts.map +1 -0
  177. package/dist/core/session-index.js +455 -0
  178. package/dist/core/session-index.js.map +1 -0
  179. package/dist/core/session-manager.d.ts +9 -0
  180. package/dist/core/session-manager.d.ts.map +1 -1
  181. package/dist/core/session-manager.js +206 -51
  182. package/dist/core/session-manager.js.map +1 -1
  183. package/dist/core/settings-manager.d.ts.map +1 -1
  184. package/dist/core/settings-manager.js +5 -10
  185. package/dist/core/settings-manager.js.map +1 -1
  186. package/dist/core/slash-commands.d.ts.map +1 -1
  187. package/dist/core/slash-commands.js +5 -0
  188. package/dist/core/slash-commands.js.map +1 -1
  189. package/dist/core/system-prompt.d.ts.map +1 -1
  190. package/dist/core/system-prompt.js +12 -1
  191. package/dist/core/system-prompt.js.map +1 -1
  192. package/dist/core/timings.d.ts.map +1 -1
  193. package/dist/core/timings.js +1 -3
  194. package/dist/core/timings.js.map +1 -1
  195. package/dist/core/tools/capability-mount.d.ts +40 -0
  196. package/dist/core/tools/capability-mount.d.ts.map +1 -0
  197. package/dist/core/tools/capability-mount.js +112 -0
  198. package/dist/core/tools/capability-mount.js.map +1 -0
  199. package/dist/core/tools/render-utils.d.ts +1 -1
  200. package/dist/core/tools/render-utils.d.ts.map +1 -1
  201. package/dist/core/tools/render-utils.js.map +1 -1
  202. package/dist/core/tools/tool-definition.d.ts +1 -1
  203. package/dist/core/tools/tool-definition.d.ts.map +1 -1
  204. package/dist/core/tools/tool-definition.js.map +1 -1
  205. package/dist/core/trace-retention.d.ts +16 -1
  206. package/dist/core/trace-retention.d.ts.map +1 -1
  207. package/dist/core/trace-retention.js +43 -20
  208. package/dist/core/trace-retention.js.map +1 -1
  209. package/dist/export-html/ansi-to-html.d.ts.map +1 -0
  210. package/dist/export-html/ansi-to-html.js.map +1 -0
  211. package/dist/{core/export-html → export-html}/index.d.ts +1 -1
  212. package/dist/export-html/index.d.ts.map +1 -0
  213. package/dist/{core/export-html → export-html}/index.js +5 -5
  214. package/dist/export-html/index.js.map +1 -0
  215. package/dist/{core/export-html → export-html}/tool-renderer.d.ts +2 -2
  216. package/dist/export-html/tool-renderer.d.ts.map +1 -0
  217. package/dist/export-html/tool-renderer.js.map +1 -0
  218. package/dist/{modes/interactive → host}/model-catalog-refresh.d.ts +1 -1
  219. package/dist/host/model-catalog-refresh.d.ts.map +1 -0
  220. package/dist/{modes/interactive → host}/model-catalog-refresh.js +1 -1
  221. package/dist/host/model-catalog-refresh.js.map +1 -0
  222. package/dist/index.d.ts +5 -5
  223. package/dist/index.d.ts.map +1 -1
  224. package/dist/index.js +12 -12
  225. package/dist/index.js.map +1 -1
  226. package/dist/main.d.ts.map +1 -1
  227. package/dist/main.js +26 -14
  228. package/dist/main.js.map +1 -1
  229. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  230. package/dist/modes/interactive/components/agents-view.js +1 -1
  231. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  232. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  233. package/dist/modes/interactive/components/armin.js +1 -1
  234. package/dist/modes/interactive/components/armin.js.map +1 -1
  235. package/dist/modes/interactive/components/assistant-message.d.ts +6 -0
  236. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  237. package/dist/modes/interactive/components/assistant-message.js +108 -27
  238. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  239. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  240. package/dist/modes/interactive/components/bash-execution.js +1 -1
  241. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  242. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  243. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  244. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  245. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  246. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  247. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  248. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  250. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  251. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/config-selector.js +1 -1
  253. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  254. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/custom-entry.js +1 -1
  256. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  257. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/custom-message.js +1 -1
  259. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  260. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  261. package/dist/modes/interactive/components/daxnuts.js +1 -1
  262. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  263. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  264. package/dist/modes/interactive/components/dialog-editor.js +1 -1
  265. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  266. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  267. package/dist/modes/interactive/components/dialog-input.js +1 -1
  268. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  269. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  270. package/dist/modes/interactive/components/dialog-selector.js +1 -1
  271. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  272. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  273. package/dist/modes/interactive/components/diff.js +1 -1
  274. package/dist/modes/interactive/components/diff.js.map +1 -1
  275. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  276. package/dist/modes/interactive/components/dynamic-border.js +1 -1
  277. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  278. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
  279. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  281. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  282. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/footer.js +1 -1
  284. package/dist/modes/interactive/components/footer.js.map +1 -1
  285. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  286. package/dist/modes/interactive/components/keybinding-hints.js +1 -1
  287. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  288. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  289. package/dist/modes/interactive/components/login-dialog.js +1 -1
  290. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  291. package/dist/modes/interactive/components/mermaid.d.ts +1 -1
  292. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  293. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  294. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/model-selector.js +2 -2
  296. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  297. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  298. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  299. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  300. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  301. package/dist/modes/interactive/components/plugin-manager-entry.js +1 -1
  302. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  303. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  304. package/dist/modes/interactive/components/plugin-selection-entry.js +1 -1
  305. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  306. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -1
  307. package/dist/modes/interactive/components/queue-manager-selector.js +1 -1
  308. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -1
  309. package/dist/modes/interactive/components/render-types.d.ts +1 -1
  310. package/dist/modes/interactive/components/render-types.d.ts.map +1 -1
  311. package/dist/modes/interactive/components/render-types.js.map +1 -1
  312. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  313. package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  314. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  315. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/session-selector-search.js +5 -1
  317. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  318. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/session-selector.js +11 -2
  320. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  321. package/dist/modes/interactive/components/settings-selector.d.ts +1 -1
  322. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  323. package/dist/modes/interactive/components/settings-selector.js +1 -1
  324. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  325. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/settings-submenu.js +1 -1
  327. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  328. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  329. package/dist/modes/interactive/components/show-images-selector.js +1 -1
  330. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  331. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  332. package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  333. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  334. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  335. package/dist/modes/interactive/components/status-indicator.js +1 -1
  336. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  337. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  338. package/dist/modes/interactive/components/theme-selector.js +1 -1
  339. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  340. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  341. package/dist/modes/interactive/components/thinking-selector.js +1 -1
  342. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  343. package/dist/modes/interactive/components/tool-execution.d.ts +19 -0
  344. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  345. package/dist/modes/interactive/components/tool-execution.js +139 -4
  346. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  347. package/dist/modes/interactive/components/tool-run-group.d.ts +44 -0
  348. package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -0
  349. package/dist/modes/interactive/components/tool-run-group.js +121 -0
  350. package/dist/modes/interactive/components/tool-run-group.js.map +1 -0
  351. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  352. package/dist/modes/interactive/components/tree-list.js +1 -1
  353. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  354. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  355. package/dist/modes/interactive/components/tree-render.js +1 -1
  356. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  357. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  358. package/dist/modes/interactive/components/tree-selector.js +1 -1
  359. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  360. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  361. package/dist/modes/interactive/components/user-message-selector.js +1 -1
  362. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  363. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/user-message.js +1 -1
  365. package/dist/modes/interactive/components/user-message.js.map +1 -1
  366. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/workflow-view.js +1 -1
  368. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  369. package/dist/modes/interactive/interactive-auth.d.ts +1 -1
  370. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  371. package/dist/modes/interactive/interactive-auth.js +1 -1
  372. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  373. package/dist/modes/interactive/interactive-commands.d.ts +125 -6
  374. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  375. package/dist/modes/interactive/interactive-commands.js +698 -4
  376. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  377. package/dist/modes/interactive/interactive-events.d.ts +174 -0
  378. package/dist/modes/interactive/interactive-events.d.ts.map +1 -0
  379. package/dist/modes/interactive/interactive-events.js +704 -0
  380. package/dist/modes/interactive/interactive-events.js.map +1 -0
  381. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  382. package/dist/modes/interactive/interactive-format.js +1 -1
  383. package/dist/modes/interactive/interactive-format.js.map +1 -1
  384. package/dist/modes/interactive/interactive-lifecycle.d.ts +94 -0
  385. package/dist/modes/interactive/interactive-lifecycle.d.ts.map +1 -0
  386. package/dist/modes/interactive/interactive-lifecycle.js +177 -0
  387. package/dist/modes/interactive/interactive-lifecycle.js.map +1 -0
  388. package/dist/modes/interactive/interactive-mode.d.ts +254 -129
  389. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  390. package/dist/modes/interactive/interactive-mode.js +275 -2101
  391. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  392. package/dist/modes/interactive/interactive-queues.d.ts +96 -0
  393. package/dist/modes/interactive/interactive-queues.d.ts.map +1 -0
  394. package/dist/modes/interactive/interactive-queues.js +183 -0
  395. package/dist/modes/interactive/interactive-queues.js.map +1 -0
  396. package/dist/modes/interactive/interactive-selectors.d.ts +95 -5
  397. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  398. package/dist/modes/interactive/interactive-selectors.js +517 -6
  399. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  400. package/dist/modes/interactive/startup-services.d.ts +31 -0
  401. package/dist/modes/interactive/startup-services.d.ts.map +1 -0
  402. package/dist/modes/interactive/startup-services.js +123 -0
  403. package/dist/modes/interactive/startup-services.js.map +1 -0
  404. package/dist/modes/memory-preheat.d.ts +11 -0
  405. package/dist/modes/memory-preheat.d.ts.map +1 -0
  406. package/dist/modes/memory-preheat.js +20 -0
  407. package/dist/modes/memory-preheat.js.map +1 -0
  408. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  409. package/dist/modes/rpc/rpc-mode.js +3 -1
  410. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  411. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  412. package/dist/plugins/ecosystem/cli.js +6 -3
  413. package/dist/plugins/ecosystem/cli.js.map +1 -1
  414. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +7 -1
  415. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  416. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +50 -3
  417. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  418. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +28 -16
  419. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
  420. package/dist/plugins/ecosystem/plugin-bootstrap.js +35 -33
  421. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
  422. package/dist/profile/plugin-profiles.d.ts +1 -1
  423. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  424. package/dist/profile/plugin-profiles.js +18 -0
  425. package/dist/profile/plugin-profiles.js.map +1 -1
  426. package/dist/remote/server-assembly.d.ts.map +1 -1
  427. package/dist/remote/server-assembly.js +7 -2
  428. package/dist/remote/server-assembly.js.map +1 -1
  429. package/dist/{profiles → suites}/builtin-suites.d.ts +14 -4
  430. package/dist/suites/builtin-suites.d.ts.map +1 -0
  431. package/dist/{profiles → suites}/builtin-suites.js +20 -5
  432. package/dist/suites/builtin-suites.js.map +1 -0
  433. package/dist/suites/resolved-agent-profile.d.ts.map +1 -0
  434. package/dist/suites/resolved-agent-profile.js.map +1 -0
  435. package/dist/suites/suite-lifecycle.d.ts.map +1 -0
  436. package/dist/suites/suite-lifecycle.js.map +1 -0
  437. package/dist/suites/suite-loader.d.ts.map +1 -0
  438. package/dist/suites/suite-loader.js.map +1 -0
  439. package/dist/{modes/interactive/theme → theme}/dark.json +1 -1
  440. package/dist/{modes/interactive/theme → theme}/light.json +1 -1
  441. package/dist/{modes/interactive/theme → theme}/theme-controller.d.ts +1 -1
  442. package/dist/theme/theme-controller.d.ts.map +1 -0
  443. package/dist/{modes/interactive/theme → theme}/theme-controller.js +1 -1
  444. package/dist/theme/theme-controller.js.map +1 -0
  445. package/dist/{modes/interactive/theme → theme}/theme.d.ts +1 -1
  446. package/dist/theme/theme.d.ts.map +1 -0
  447. package/dist/{modes/interactive/theme → theme}/theme.js +5 -5
  448. package/dist/theme/theme.js.map +1 -0
  449. package/docs/compaction.md +7 -7
  450. package/docs/environment-variables.md +10 -4
  451. package/docs/keybindings.md +3 -3
  452. package/docs/models.md +17 -17
  453. package/docs/packages.md +1 -1
  454. package/docs/prompt-templates.md +1 -1
  455. package/docs/rpc.md +2 -2
  456. package/docs/sdk.md +5 -5
  457. package/docs/session-format.md +3 -3
  458. package/docs/settings.md +368 -354
  459. package/docs/shell-aliases.md +1 -1
  460. package/docs/skills.md +1 -1
  461. package/docs/terminal-setup.md +17 -17
  462. package/docs/themes.md +5 -5
  463. package/docs/tmux.md +4 -4
  464. package/docs/tui.md +1 -1
  465. package/docs/windows.md +1 -1
  466. package/examples/extensions/bash-spawn-hook/index.ts +1 -1
  467. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  468. package/examples/extensions/with-deps/package-lock.json +2 -2
  469. package/examples/extensions/with-deps/package.json +1 -6
  470. package/examples/extensions/with-deps/plugin.json +1 -1
  471. package/package.json +2 -2
  472. package/dist/bundle/chunks/openai-responses-AUJQ3NWT.js +0 -2
  473. package/dist/bundle/chunks/virtual-modules-WF6WRHP7.js +0 -5
  474. package/dist/cli/experimental/commands/pi.d.ts +0 -15
  475. package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
  476. package/dist/cli/experimental/commands/pi.js.map +0 -1
  477. package/dist/core/export-html/ansi-to-html.d.ts.map +0 -1
  478. package/dist/core/export-html/ansi-to-html.js.map +0 -1
  479. package/dist/core/export-html/index.d.ts.map +0 -1
  480. package/dist/core/export-html/index.js.map +0 -1
  481. package/dist/core/export-html/tool-renderer.d.ts.map +0 -1
  482. package/dist/core/export-html/tool-renderer.js.map +0 -1
  483. package/dist/core/pi-manifest.d.ts +0 -7
  484. package/dist/core/pi-manifest.d.ts.map +0 -1
  485. package/dist/core/pi-manifest.js.map +0 -1
  486. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +0 -1
  487. package/dist/modes/interactive/model-catalog-refresh.js.map +0 -1
  488. package/dist/modes/interactive/theme/theme-controller.d.ts.map +0 -1
  489. package/dist/modes/interactive/theme/theme-controller.js.map +0 -1
  490. package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
  491. package/dist/modes/interactive/theme/theme.js.map +0 -1
  492. package/dist/profiles/builtin-suites.d.ts.map +0 -1
  493. package/dist/profiles/builtin-suites.js.map +0 -1
  494. package/dist/profiles/resolved-agent-profile.d.ts.map +0 -1
  495. package/dist/profiles/resolved-agent-profile.js.map +0 -1
  496. package/dist/profiles/suite-lifecycle.d.ts.map +0 -1
  497. package/dist/profiles/suite-lifecycle.js.map +0 -1
  498. package/dist/profiles/suite-loader.d.ts.map +0 -1
  499. package/dist/profiles/suite-loader.js.map +0 -1
  500. package/dist/utils/deprecation.d.ts +0 -4
  501. package/dist/utils/deprecation.d.ts.map +0 -1
  502. package/dist/utils/deprecation.js +0 -13
  503. package/dist/utils/deprecation.js.map +0 -1
  504. /package/dist/{core/export-html → export-html}/ansi-to-html.d.ts +0 -0
  505. /package/dist/{core/export-html → export-html}/ansi-to-html.js +0 -0
  506. /package/dist/{core/export-html → export-html}/template.css +0 -0
  507. /package/dist/{core/export-html → export-html}/template.html +0 -0
  508. /package/dist/{core/export-html → export-html}/template.js +0 -0
  509. /package/dist/{core/export-html → export-html}/tool-renderer.js +0 -0
  510. /package/dist/{core/export-html → export-html}/vendor/highlight.min.js +0 -0
  511. /package/dist/{core/export-html → export-html}/vendor/marked.min.js +0 -0
  512. /package/dist/{profiles → suites}/resolved-agent-profile.d.ts +0 -0
  513. /package/dist/{profiles → suites}/resolved-agent-profile.js +0 -0
  514. /package/dist/{profiles → suites}/suite-lifecycle.d.ts +0 -0
  515. /package/dist/{profiles → suites}/suite-lifecycle.js +0 -0
  516. /package/dist/{profiles → suites}/suite-loader.d.ts +0 -0
  517. /package/dist/{profiles → suites}/suite-loader.js +0 -0
  518. /package/dist/{modes/interactive/theme → theme}/theme-schema.json +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-manager-entry.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-manager-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin installation/update entry for the config screen.\n *\n * This component deliberately projects the manager snapshot to a small UI\n * view. Registry sources, paths, signatures, package bytes, credentials and\n * host response text never participate in rendering or action selection.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginManagerControllerErrorCodeV1,\n\tPluginManagerControllerV1,\n\tPluginManagerEntryStatusV1,\n\tPluginManagerMutationResultV1,\n\tPluginManagerSnapshotV1,\n} from \"../../../cli/plugin-manager-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst MAX_PLUGIN_ENTRIES_V1 = 128;\nconst MAX_DISPLAY_CHARS_V1 = 256;\nconst MAX_DIAGNOSTIC_CODES_V1 = 8;\n\ntype PluginManagerActionV1 = \"install\" | \"update\" | \"remove\";\ntype PluginManagerViewStatusV1 = \"ready\" | \"error\";\n\ninterface PluginManagerViewEntryV1 {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly status: PluginManagerEntryStatusV1;\n\treadonly installedVersion?: string;\n\treadonly lifecycle?: \"installed\" | \"active\" | \"retained\";\n\treadonly diagnosticCodes: readonly string[];\n}\n\nexport interface PluginManagerEntryOptionsV1 {\n\treadonly controller: PluginManagerControllerV1;\n\treadonly snapshot?: PluginManagerSnapshotV1;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nexport interface PluginManagerEntryOpenContextV1 {\n\treadonly status: PluginManagerViewStatusV1;\n\treadonly entryCount: number;\n\treadonly truncated: boolean;\n\treadonly diagnosticCode?: PluginManagerControllerErrorCodeV1;\n}\n\nexport type PluginManagerEntryOpenResultV1 = PluginManagerEntryOpenContextV1;\n\nfunction safeDisplay(value: string): string {\n\t// Registry/state validators bound these values, but the UI remains\n\t// defensive because the component is also usable with injected test hosts.\n\treturn value\n\t\t.replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/gu, \"\")\n\t\t.replace(/[\\u0000-\\u001f\\u007f]/gu, \"�\")\n\t\t.slice(0, MAX_DISPLAY_CHARS_V1);\n}\n\nfunction projectSnapshot(snapshot: PluginManagerSnapshotV1): {\n\treadonly entries: readonly PluginManagerViewEntryV1[];\n\treadonly truncated: boolean;\n} {\n\tconst entries = snapshot.entries.slice(0, MAX_PLUGIN_ENTRIES_V1).map((entry) => {\n\t\t// Explicitly select only fields intended for this UI. In particular,\n\t\t// registrySource and signed are not read here.\n\t\treturn Object.freeze({\n\t\t\tpluginId: entry.pluginId,\n\t\t\tpluginVersion: entry.pluginVersion,\n\t\t\tstatus: entry.status,\n\t\t\t...(entry.installedVersion === undefined ? {} : { installedVersion: entry.installedVersion }),\n\t\t\t...(entry.lifecycle === undefined ? {} : { lifecycle: entry.lifecycle }),\n\t\t\tdiagnosticCodes: Object.freeze(\n\t\t\t\tentry.diagnosticCodes.slice(0, MAX_DIAGNOSTIC_CODES_V1).map((code) => safeDisplay(code)),\n\t\t\t),\n\t\t});\n\t});\n\treturn Object.freeze({\n\t\tentries: Object.freeze(entries),\n\t\ttruncated: snapshot.truncated || snapshot.entries.length > MAX_PLUGIN_ENTRIES_V1,\n\t});\n}\n\nfunction actionsFor(entry: PluginManagerViewEntryV1): readonly PluginManagerActionV1[] {\n\tswitch (entry.status) {\n\t\tcase \"available\":\n\t\t\treturn [\"install\"];\n\t\tcase \"update-available\":\n\t\t\treturn [\"update\", \"remove\"];\n\t\tcase \"installed\":\n\t\t\treturn [\"remove\"];\n\t\tcase \"unavailable\":\n\t\t\treturn [];\n\t}\n}\n\nfunction actionTargetVersion(entry: PluginManagerViewEntryV1, action: PluginManagerActionV1): string | undefined {\n\treturn action === \"remove\" ? (entry.installedVersion ?? entry.pluginVersion) : entry.pluginVersion;\n}\n\nfunction errorCode(result: PluginManagerMutationResultV1): PluginManagerControllerErrorCodeV1 {\n\treturn result.code ?? \"manager-operation-failed\";\n}\n\n/**\n * Focusable manager surface. The outer config selector owns navigation to this\n * entry; this surface owns confirmation and only emits stable host codes.\n */\nexport class PluginManagerEntryComponent implements Component, Focusable {\n\tprivate readonly controller: PluginManagerControllerV1;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate entries: readonly PluginManagerViewEntryV1[] = Object.freeze([]);\n\tprivate truncated = false;\n\tprivate selectedIndex = 0;\n\tprivate selectedActionIndex = 0;\n\tprivate confirmation: { readonly pluginId: string; readonly action: PluginManagerActionV1 } | undefined;\n\tprivate busy = false;\n\tprivate status: PluginManagerEntryOpenContextV1 = Object.freeze({\n\t\tstatus: \"error\",\n\t\tentryCount: 0,\n\t\ttruncated: false,\n\t});\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginManagerEntryOptionsV1) {\n\t\tthis.controller = options.controller;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tif (options.snapshot !== undefined) this.setSnapshot(options.snapshot);\n\t}\n\n\tprivate setSnapshot(snapshot: PluginManagerSnapshotV1): void {\n\t\tconst projected = projectSnapshot(snapshot);\n\t\tthis.entries = projected.entries;\n\t\tthis.truncated = projected.truncated;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.entries.length - 1));\n\t\tthis.selectedActionIndex = Math.min(this.selectedActionIndex, Math.max(0, this.currentActions().length - 1));\n\t\tthis.status = Object.freeze({\n\t\t\tstatus: \"ready\",\n\t\t\tentryCount: this.entries.length,\n\t\t\ttruncated: this.truncated,\n\t\t});\n\t}\n\n\tprivate currentEntry(): PluginManagerViewEntryV1 | undefined {\n\t\treturn this.entries[this.selectedIndex];\n\t}\n\n\tprivate currentActions(): readonly PluginManagerActionV1[] {\n\t\tconst entry = this.currentEntry();\n\t\treturn entry === undefined ? [] : actionsFor(entry);\n\t}\n\n\tprivate currentAction(): PluginManagerActionV1 | undefined {\n\t\treturn this.currentActions()[this.selectedActionIndex];\n\t}\n\n\tprivate request(): void {\n\t\tthis.requestRender?.();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this._focused) {\n\t\t\tconst state =\n\t\t\t\tthis.status.status === \"ready\"\n\t\t\t\t\t? t(\"catalog {count}\", { count: this.status.entryCount })\n\t\t\t\t\t: t(\"catalog unavailable\");\n\t\t\tconst bounded = this.truncated ? t(\", bounded\") : \"\";\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"muted\", ` ${t(\"Plugin manager · {state}{bounded} · Enter open\", { state, bounded })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tconst lines: string[] = [truncateToWidth(theme.bold(` ${t(\"Plugin manager\")}`), width, \"...\")];\n\t\tif (this.busy) {\n\t\t\tlines.push(truncateToWidth(theme.fg(\"accent\", ` ${t(\"Working…\")}`), width, \"...\"));\n\t\t} else if (this.confirmation !== undefined) {\n\t\t\tconst entry = this.currentEntry();\n\t\t\tconst action = this.currentAction();\n\t\t\tif (entry !== undefined && action !== undefined) {\n\t\t\t\tconst targetVersion = actionTargetVersion(entry, action) ?? entry.pluginVersion;\n\t\t\t\tlines.push(\n\t\t\t\t\ttruncateToWidth(\n\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\t` ${t(\"Confirm {action} {plugin}@{version}? Enter confirm · Esc cancel\", {\n\t\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\t\tplugin: safeDisplay(entry.pluginId),\n\t\t\t\t\t\t\t\tversion: safeDisplay(targetVersion),\n\t\t\t\t\t\t\t})}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\"...\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (this.status.status === \"error\" && this.status.diagnosticCode !== undefined) {\n\t\t\tlines.push(\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"error\", ` ${t(\"Error: {code}\", { code: this.status.diagnosticCode })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (this.entries.length === 0) {\n\t\t\tlines.push(theme.fg(\"dim\", ` ${t(\"No plugins available\")}`));\n\t\t} else {\n\t\t\tfor (const [index, entry] of this.entries.entries()) {\n\t\t\t\tconst selected = index === this.selectedIndex;\n\t\t\t\tconst cursor = selected ? \">\" : \" \";\n\t\t\t\tconst status = entry.status;\n\t\t\t\tconst installed =\n\t\t\t\t\tentry.installedVersion === undefined\n\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t: ` ${t(\"installed {version}\", { version: safeDisplay(entry.installedVersion) })}`;\n\t\t\t\tconst diagnostics = entry.diagnosticCodes.length === 0 ? \"\" : ` [${entry.diagnosticCodes.join(\", \")}]`;\n\t\t\t\tlines.push(\n\t\t\t\t\ttruncateToWidth(\n\t\t\t\t\t\t`${cursor} ${safeDisplay(entry.pluginId)}@${safeDisplay(entry.pluginVersion)} · ${status}${installed}${diagnostics}`,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\"...\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst actions = this.currentActions();\n\t\tif (actions.length > 0 && !this.busy) {\n\t\t\tconst action = this.currentAction();\n\t\t\tlines.push(\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\"muted\",\n\t\t\t\t\t\t` ${t(\"Action: {action} · Tab switch action · Enter confirm\", { action: action ?? \"install\" })}`,\n\t\t\t\t\t),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (this.entries.length > 0 && !this.busy) {\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Selected plugin is unavailable\")}`), width, \"...\"));\n\t\t}\n\t\tif (this.truncated) lines.push(theme.fg(\"dim\", ` ${t(\"(list bounded)\")}`));\n\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"↑↓ navigate · Esc close\")}`), width, \"...\"));\n\t\treturn lines;\n\t}\n\n\tprivate async refresh(): Promise<PluginManagerEntryOpenContextV1> {\n\t\ttry {\n\t\t\tconst result = await this.controller.getSnapshot();\n\t\t\tif (result.status === \"ok\") {\n\t\t\t\tthis.setSnapshot(result.snapshot);\n\t\t\t\tthis.request();\n\t\t\t\treturn this.status;\n\t\t\t}\n\t\t\tthis.status = Object.freeze({\n\t\t\t\tstatus: \"error\",\n\t\t\t\tentryCount: 0,\n\t\t\t\ttruncated: false,\n\t\t\t\tdiagnosticCode: result.code,\n\t\t\t});\n\t\t\tthis.entries = Object.freeze([]);\n\t\t\tthis.truncated = false;\n\t\t\tthis.request();\n\t\t\treturn this.status;\n\t\t} catch {\n\t\t\tthis.status = Object.freeze({\n\t\t\t\tstatus: \"error\",\n\t\t\t\tentryCount: 0,\n\t\t\t\ttruncated: false,\n\t\t\t\tdiagnosticCode: \"manager-operation-failed\",\n\t\t\t});\n\t\t\tthis.entries = Object.freeze([]);\n\t\t\tthis.truncated = false;\n\t\t\tthis.request();\n\t\t\treturn this.status;\n\t\t}\n\t}\n\n\tprivate async perform(action: PluginManagerActionV1): Promise<void> {\n\t\tconst entry = this.currentEntry();\n\t\tif (entry === undefined) return;\n\t\tthis.busy = true;\n\t\tthis.confirmation = undefined;\n\t\tthis.request();\n\t\tlet result: PluginManagerMutationResultV1;\n\t\ttry {\n\t\t\tconst input = {\n\t\t\t\tpluginId: entry.pluginId,\n\t\t\t\tpluginVersion: actionTargetVersion(entry, action),\n\t\t\t\tconfirmed: true as const,\n\t\t\t};\n\t\t\tresult = await this.controller[action](input);\n\t\t} catch {\n\t\t\tresult = { status: \"failed\", code: \"manager-operation-failed\" };\n\t\t}\n\t\tif (result.snapshot !== undefined) this.setSnapshot(result.snapshot);\n\t\tconst mutationCode = result.status === \"succeeded\" ? undefined : errorCode(result);\n\t\tconst refreshed = result.snapshot === undefined ? await this.refresh() : this.status;\n\t\tif (mutationCode !== undefined) {\n\t\t\tthis.status = Object.freeze({ ...refreshed, status: \"error\", diagnosticCode: mutationCode });\n\t\t}\n\t\tthis.busy = false;\n\t\tthis.selectedActionIndex = Math.min(this.selectedActionIndex, Math.max(0, this.currentActions().length - 1));\n\t\tthis.request();\n\t}\n\n\tasync openPluginManager(): Promise<PluginManagerEntryOpenResultV1> {\n\t\treturn await this.refresh();\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused) return;\n\t\tconst kb = getKeybindings();\n\t\tif (this.busy) return;\n\t\tif (this.confirmation !== undefined) {\n\t\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\tthis.confirmation = undefined;\n\t\t\t\tthis.request();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\t\tconst action = this.currentAction();\n\t\t\t\tif (action !== undefined) void this.perform(action);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.selectedActionIndex = 0;\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(Math.max(0, this.entries.length - 1), this.selectedIndex + 1);\n\t\t\tthis.selectedActionIndex = 0;\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.input.tab\")) {\n\t\t\tconst actions = this.currentActions();\n\t\t\tif (actions.length > 0) this.selectedActionIndex = (this.selectedActionIndex + 1) % actions.length;\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tconst entry = this.currentEntry();\n\t\t\tconst action = this.currentAction();\n\t\t\tif (entry !== undefined && action !== undefined) {\n\t\t\t\tthis.confirmation = { pluginId: entry.pluginId, action };\n\t\t\t\tthis.request();\n\t\t\t}\n\t\t}\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectedPluginId(): string | undefined {\n\t\treturn this.currentEntry()?.pluginId;\n\t}\n\n\tgetSelectedAction(): PluginManagerActionV1 | undefined {\n\t\treturn this.currentAction();\n\t}\n\n\tgetStatus(): PluginManagerEntryOpenContextV1 {\n\t\treturn this.status;\n\t}\n}\n"]}
1
+ {"version":3,"file":"plugin-manager-entry.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-manager-entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAkC,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQnG,OAAO,EAAE,CAAC,EAAE,MAAM,6BAA6B,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEhD,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAgClC,SAAS,WAAW,CAAC,KAAa,EAAU;IAC3C,mEAAmE;IACnE,2EAA2E;IAC3E,OAAO,KAAK;SACV,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC;SAC1C,OAAO,CAAC,yBAAyB,EAAE,KAAG,CAAC;SACvC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;AAAA,CACjC;AAED,SAAS,eAAe,CAAC,QAAiC,EAGxD;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/E,qEAAqE;QACrE,+CAA+C;QAC/C,OAAO,MAAM,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;YAC7F,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;YACxE,eAAe,EAAE,MAAM,CAAC,MAAM,CAC7B,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CACxF;SACD,CAAC,CAAC;IAAA,CACH,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAC/B,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,qBAAqB;KAChF,CAAC,CAAC;AAAA,CACH;AAED,SAAS,UAAU,CAAC,KAA+B,EAAoC;IACtF,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,WAAW;YACf,OAAO,CAAC,SAAS,CAAC,CAAC;QACpB,KAAK,kBAAkB;YACtB,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7B,KAAK,WAAW;YACf,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnB,KAAK,aAAa;YACjB,OAAO,EAAE,CAAC;IACZ,CAAC;AAAA,CACD;AAED,SAAS,mBAAmB,CAAC,KAA+B,EAAE,MAA6B,EAAsB;IAChH,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;AAAA,CACnG;AAED,SAAS,SAAS,CAAC,MAAqC,EAAsC;IAC7F,OAAO,MAAM,CAAC,IAAI,IAAI,0BAA0B,CAAC;AAAA,CACjD;AAED;;;GAGG;AACH,MAAM,OAAO,2BAA2B;IACtB,UAAU,CAA4B;IACtC,OAAO,CAAc;IACrB,aAAa,CAAc;IACpC,OAAO,GAAwC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjE,SAAS,GAAG,KAAK,CAAC;IAClB,aAAa,GAAG,CAAC,CAAC;IAClB,mBAAmB,GAAG,CAAC,CAAC;IACxB,YAAY,CAAoF;IAChG,IAAI,GAAG,KAAK,CAAC;IACb,MAAM,GAAoC,MAAM,CAAC,MAAM,CAAC;QAC/D,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,KAAK;KAChB,CAAC,CAAC;IACK,QAAQ,GAAG,KAAK,CAAC;IAEzB,IAAI,OAAO,GAAY;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC;IAAA,CACrB;IAED,IAAI,OAAO,CAAC,KAAc,EAAE;QAC3B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAAA,CACtB;IAED,YAAY,OAAoC,EAAE;QACjD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAAA,CACvE;IAEO,WAAW,CAAC,QAAiC,EAAQ;QAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7G,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,MAAM,EAAE,OAAO;YACf,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;SACzB,CAAC,CAAC;IAAA,CACH;IAEO,YAAY,GAAyC;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAAA,CACxC;IAEO,cAAc,GAAqC;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAAA,CACpD;IAEO,aAAa,GAAsC;QAC1D,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAAA,CACvD;IAEO,OAAO,GAAS;QACvB,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;IAAA,CACvB;IAED,MAAM,CAAC,KAAa,EAAY;QAC/B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,KAAK,GACV,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO;gBAC7B,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;gBACzD,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;YAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,OAAO;gBACN,eAAe,CACd,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kDAAgD,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EACjG,KAAK,EACL,KAAK,CACL;aACD,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAa,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QAChG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,YAAU,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACrF,CAAC;aAAM,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjD,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC;gBAChF,KAAK,CAAC,IAAI,CACT,eAAe,CACd,KAAK,CAAC,EAAE,CACP,OAAO,EACP,KAAK,CAAC,CAAC,kEAAiE,EAAE;oBACzE,MAAM;oBACN,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC;oBACnC,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC;iBACnC,CAAC,EAAE,CACJ,EACD,KAAK,EACL,KAAK,CACL,CACD,CAAC;YACH,CAAC;QACF,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACvF,KAAK,CAAC,IAAI,CACT,eAAe,CACd,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC,EAClF,KAAK,EACL,KAAK,CACL,CACD,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACP,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;gBACrD,MAAM,QAAQ,GAAG,KAAK,KAAK,IAAI,CAAC,aAAa,CAAC;gBAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBACpC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC5B,MAAM,SAAS,GACd,KAAK,CAAC,gBAAgB,KAAK,SAAS;oBACnC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,IAAI,CAAC,CAAC,qBAAqB,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC;gBACrF,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBACvG,KAAK,CAAC,IAAI,CACT,eAAe,CACd,GAAG,MAAM,IAAI,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,OAAM,MAAM,GAAG,SAAS,GAAG,WAAW,EAAE,EACpH,KAAK,EACL,KAAK,CACL,CACD,CAAC;YACH,CAAC;QACF,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CACT,eAAe,CACd,KAAK,CAAC,EAAE,CACP,OAAO,EACP,KAAK,CAAC,CAAC,wDAAsD,EAAE,EAAE,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC,EAAE,CACjG,EACD,KAAK,EACL,KAAK,CACL,CACD,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClD,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,gCAAgC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACxG,CAAC;QACD,IAAI,IAAI,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,8BAAyB,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QAChG,OAAO,KAAK,CAAC;IAAA,CACb;IAEO,KAAK,CAAC,OAAO,GAA6C;QACjE,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;YACnD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAClC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,OAAO,IAAI,CAAC,MAAM,CAAC;YACpB,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC3B,MAAM,EAAE,OAAO;gBACf,UAAU,EAAE,CAAC;gBACb,SAAS,EAAE,KAAK;gBAChB,cAAc,EAAE,MAAM,CAAC,IAAI;aAC3B,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,MAAM,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC3B,MAAM,EAAE,OAAO;gBACf,UAAU,EAAE,CAAC;gBACb,SAAS,EAAE,KAAK;gBAChB,cAAc,EAAE,0BAA0B;aAC1C,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,MAAM,CAAC;QACpB,CAAC;IAAA,CACD;IAEO,KAAK,CAAC,OAAO,CAAC,MAA6B,EAAiB;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,MAAqC,CAAC;QAC1C,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG;gBACb,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,aAAa,EAAE,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC;gBACjD,SAAS,EAAE,IAAa;aACxB,CAAC;YACF,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACR,MAAM,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;QACjE,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACrF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7G,IAAI,CAAC,OAAO,EAAE,CAAC;IAAA,CACf;IAED,KAAK,CAAC,iBAAiB,GAA4C;QAClE,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IAAA,CAC5B;IAED,WAAW,CAAC,IAAY,EAAQ;QAC/B,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QACtB,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACrC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;gBAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,OAAO;YACR,CAAC;YACD,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,CAAC;gBAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;gBACpC,IAAI,MAAM,KAAK,SAAS;oBAAE,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACpD,OAAO;YACR,CAAC;YACD,OAAO;QACR,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACR,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YACzD,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACR,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YAC5F,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACR,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,mBAAmB,GAAG,CAAC,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACnG,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACR,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjD,IAAI,CAAC,YAAY,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;gBACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,CAAC;QACF,CAAC;IAAA,CACD;IAED,UAAU,GAAS,EAAC,CAAC;IAErB,mBAAmB,GAAuB;QACzC,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,CAAC;IAAA,CACrC;IAED,iBAAiB,GAAsC;QACtD,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CAC5B;IAED,SAAS,GAAoC;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC;IAAA,CACnB;CACD","sourcesContent":["/**\n * Host-owned plugin installation/update entry for the config screen.\n *\n * This component deliberately projects the manager snapshot to a small UI\n * view. Registry sources, paths, signatures, package bytes, credentials and\n * host response text never participate in rendering or action selection.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginManagerControllerErrorCodeV1,\n\tPluginManagerControllerV1,\n\tPluginManagerEntryStatusV1,\n\tPluginManagerMutationResultV1,\n\tPluginManagerSnapshotV1,\n} from \"../../../cli/plugin-manager-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../../../theme/theme.ts\";\n\nconst MAX_PLUGIN_ENTRIES_V1 = 128;\nconst MAX_DISPLAY_CHARS_V1 = 256;\nconst MAX_DIAGNOSTIC_CODES_V1 = 8;\n\ntype PluginManagerActionV1 = \"install\" | \"update\" | \"remove\";\ntype PluginManagerViewStatusV1 = \"ready\" | \"error\";\n\ninterface PluginManagerViewEntryV1 {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly status: PluginManagerEntryStatusV1;\n\treadonly installedVersion?: string;\n\treadonly lifecycle?: \"installed\" | \"active\" | \"retained\";\n\treadonly diagnosticCodes: readonly string[];\n}\n\nexport interface PluginManagerEntryOptionsV1 {\n\treadonly controller: PluginManagerControllerV1;\n\treadonly snapshot?: PluginManagerSnapshotV1;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nexport interface PluginManagerEntryOpenContextV1 {\n\treadonly status: PluginManagerViewStatusV1;\n\treadonly entryCount: number;\n\treadonly truncated: boolean;\n\treadonly diagnosticCode?: PluginManagerControllerErrorCodeV1;\n}\n\nexport type PluginManagerEntryOpenResultV1 = PluginManagerEntryOpenContextV1;\n\nfunction safeDisplay(value: string): string {\n\t// Registry/state validators bound these values, but the UI remains\n\t// defensive because the component is also usable with injected test hosts.\n\treturn value\n\t\t.replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/gu, \"\")\n\t\t.replace(/[\\u0000-\\u001f\\u007f]/gu, \"�\")\n\t\t.slice(0, MAX_DISPLAY_CHARS_V1);\n}\n\nfunction projectSnapshot(snapshot: PluginManagerSnapshotV1): {\n\treadonly entries: readonly PluginManagerViewEntryV1[];\n\treadonly truncated: boolean;\n} {\n\tconst entries = snapshot.entries.slice(0, MAX_PLUGIN_ENTRIES_V1).map((entry) => {\n\t\t// Explicitly select only fields intended for this UI. In particular,\n\t\t// registrySource and signed are not read here.\n\t\treturn Object.freeze({\n\t\t\tpluginId: entry.pluginId,\n\t\t\tpluginVersion: entry.pluginVersion,\n\t\t\tstatus: entry.status,\n\t\t\t...(entry.installedVersion === undefined ? {} : { installedVersion: entry.installedVersion }),\n\t\t\t...(entry.lifecycle === undefined ? {} : { lifecycle: entry.lifecycle }),\n\t\t\tdiagnosticCodes: Object.freeze(\n\t\t\t\tentry.diagnosticCodes.slice(0, MAX_DIAGNOSTIC_CODES_V1).map((code) => safeDisplay(code)),\n\t\t\t),\n\t\t});\n\t});\n\treturn Object.freeze({\n\t\tentries: Object.freeze(entries),\n\t\ttruncated: snapshot.truncated || snapshot.entries.length > MAX_PLUGIN_ENTRIES_V1,\n\t});\n}\n\nfunction actionsFor(entry: PluginManagerViewEntryV1): readonly PluginManagerActionV1[] {\n\tswitch (entry.status) {\n\t\tcase \"available\":\n\t\t\treturn [\"install\"];\n\t\tcase \"update-available\":\n\t\t\treturn [\"update\", \"remove\"];\n\t\tcase \"installed\":\n\t\t\treturn [\"remove\"];\n\t\tcase \"unavailable\":\n\t\t\treturn [];\n\t}\n}\n\nfunction actionTargetVersion(entry: PluginManagerViewEntryV1, action: PluginManagerActionV1): string | undefined {\n\treturn action === \"remove\" ? (entry.installedVersion ?? entry.pluginVersion) : entry.pluginVersion;\n}\n\nfunction errorCode(result: PluginManagerMutationResultV1): PluginManagerControllerErrorCodeV1 {\n\treturn result.code ?? \"manager-operation-failed\";\n}\n\n/**\n * Focusable manager surface. The outer config selector owns navigation to this\n * entry; this surface owns confirmation and only emits stable host codes.\n */\nexport class PluginManagerEntryComponent implements Component, Focusable {\n\tprivate readonly controller: PluginManagerControllerV1;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate entries: readonly PluginManagerViewEntryV1[] = Object.freeze([]);\n\tprivate truncated = false;\n\tprivate selectedIndex = 0;\n\tprivate selectedActionIndex = 0;\n\tprivate confirmation: { readonly pluginId: string; readonly action: PluginManagerActionV1 } | undefined;\n\tprivate busy = false;\n\tprivate status: PluginManagerEntryOpenContextV1 = Object.freeze({\n\t\tstatus: \"error\",\n\t\tentryCount: 0,\n\t\ttruncated: false,\n\t});\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginManagerEntryOptionsV1) {\n\t\tthis.controller = options.controller;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tif (options.snapshot !== undefined) this.setSnapshot(options.snapshot);\n\t}\n\n\tprivate setSnapshot(snapshot: PluginManagerSnapshotV1): void {\n\t\tconst projected = projectSnapshot(snapshot);\n\t\tthis.entries = projected.entries;\n\t\tthis.truncated = projected.truncated;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.entries.length - 1));\n\t\tthis.selectedActionIndex = Math.min(this.selectedActionIndex, Math.max(0, this.currentActions().length - 1));\n\t\tthis.status = Object.freeze({\n\t\t\tstatus: \"ready\",\n\t\t\tentryCount: this.entries.length,\n\t\t\ttruncated: this.truncated,\n\t\t});\n\t}\n\n\tprivate currentEntry(): PluginManagerViewEntryV1 | undefined {\n\t\treturn this.entries[this.selectedIndex];\n\t}\n\n\tprivate currentActions(): readonly PluginManagerActionV1[] {\n\t\tconst entry = this.currentEntry();\n\t\treturn entry === undefined ? [] : actionsFor(entry);\n\t}\n\n\tprivate currentAction(): PluginManagerActionV1 | undefined {\n\t\treturn this.currentActions()[this.selectedActionIndex];\n\t}\n\n\tprivate request(): void {\n\t\tthis.requestRender?.();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this._focused) {\n\t\t\tconst state =\n\t\t\t\tthis.status.status === \"ready\"\n\t\t\t\t\t? t(\"catalog {count}\", { count: this.status.entryCount })\n\t\t\t\t\t: t(\"catalog unavailable\");\n\t\t\tconst bounded = this.truncated ? t(\", bounded\") : \"\";\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"muted\", ` ${t(\"Plugin manager · {state}{bounded} · Enter open\", { state, bounded })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tconst lines: string[] = [truncateToWidth(theme.bold(` ${t(\"Plugin manager\")}`), width, \"...\")];\n\t\tif (this.busy) {\n\t\t\tlines.push(truncateToWidth(theme.fg(\"accent\", ` ${t(\"Working…\")}`), width, \"...\"));\n\t\t} else if (this.confirmation !== undefined) {\n\t\t\tconst entry = this.currentEntry();\n\t\t\tconst action = this.currentAction();\n\t\t\tif (entry !== undefined && action !== undefined) {\n\t\t\t\tconst targetVersion = actionTargetVersion(entry, action) ?? entry.pluginVersion;\n\t\t\t\tlines.push(\n\t\t\t\t\ttruncateToWidth(\n\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\t` ${t(\"Confirm {action} {plugin}@{version}? Enter confirm · Esc cancel\", {\n\t\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\t\tplugin: safeDisplay(entry.pluginId),\n\t\t\t\t\t\t\t\tversion: safeDisplay(targetVersion),\n\t\t\t\t\t\t\t})}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\"...\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (this.status.status === \"error\" && this.status.diagnosticCode !== undefined) {\n\t\t\tlines.push(\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"error\", ` ${t(\"Error: {code}\", { code: this.status.diagnosticCode })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (this.entries.length === 0) {\n\t\t\tlines.push(theme.fg(\"dim\", ` ${t(\"No plugins available\")}`));\n\t\t} else {\n\t\t\tfor (const [index, entry] of this.entries.entries()) {\n\t\t\t\tconst selected = index === this.selectedIndex;\n\t\t\t\tconst cursor = selected ? \">\" : \" \";\n\t\t\t\tconst status = entry.status;\n\t\t\t\tconst installed =\n\t\t\t\t\tentry.installedVersion === undefined\n\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t: ` ${t(\"installed {version}\", { version: safeDisplay(entry.installedVersion) })}`;\n\t\t\t\tconst diagnostics = entry.diagnosticCodes.length === 0 ? \"\" : ` [${entry.diagnosticCodes.join(\", \")}]`;\n\t\t\t\tlines.push(\n\t\t\t\t\ttruncateToWidth(\n\t\t\t\t\t\t`${cursor} ${safeDisplay(entry.pluginId)}@${safeDisplay(entry.pluginVersion)} · ${status}${installed}${diagnostics}`,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\"...\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst actions = this.currentActions();\n\t\tif (actions.length > 0 && !this.busy) {\n\t\t\tconst action = this.currentAction();\n\t\t\tlines.push(\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\"muted\",\n\t\t\t\t\t\t` ${t(\"Action: {action} · Tab switch action · Enter confirm\", { action: action ?? \"install\" })}`,\n\t\t\t\t\t),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (this.entries.length > 0 && !this.busy) {\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Selected plugin is unavailable\")}`), width, \"...\"));\n\t\t}\n\t\tif (this.truncated) lines.push(theme.fg(\"dim\", ` ${t(\"(list bounded)\")}`));\n\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"↑↓ navigate · Esc close\")}`), width, \"...\"));\n\t\treturn lines;\n\t}\n\n\tprivate async refresh(): Promise<PluginManagerEntryOpenContextV1> {\n\t\ttry {\n\t\t\tconst result = await this.controller.getSnapshot();\n\t\t\tif (result.status === \"ok\") {\n\t\t\t\tthis.setSnapshot(result.snapshot);\n\t\t\t\tthis.request();\n\t\t\t\treturn this.status;\n\t\t\t}\n\t\t\tthis.status = Object.freeze({\n\t\t\t\tstatus: \"error\",\n\t\t\t\tentryCount: 0,\n\t\t\t\ttruncated: false,\n\t\t\t\tdiagnosticCode: result.code,\n\t\t\t});\n\t\t\tthis.entries = Object.freeze([]);\n\t\t\tthis.truncated = false;\n\t\t\tthis.request();\n\t\t\treturn this.status;\n\t\t} catch {\n\t\t\tthis.status = Object.freeze({\n\t\t\t\tstatus: \"error\",\n\t\t\t\tentryCount: 0,\n\t\t\t\ttruncated: false,\n\t\t\t\tdiagnosticCode: \"manager-operation-failed\",\n\t\t\t});\n\t\t\tthis.entries = Object.freeze([]);\n\t\t\tthis.truncated = false;\n\t\t\tthis.request();\n\t\t\treturn this.status;\n\t\t}\n\t}\n\n\tprivate async perform(action: PluginManagerActionV1): Promise<void> {\n\t\tconst entry = this.currentEntry();\n\t\tif (entry === undefined) return;\n\t\tthis.busy = true;\n\t\tthis.confirmation = undefined;\n\t\tthis.request();\n\t\tlet result: PluginManagerMutationResultV1;\n\t\ttry {\n\t\t\tconst input = {\n\t\t\t\tpluginId: entry.pluginId,\n\t\t\t\tpluginVersion: actionTargetVersion(entry, action),\n\t\t\t\tconfirmed: true as const,\n\t\t\t};\n\t\t\tresult = await this.controller[action](input);\n\t\t} catch {\n\t\t\tresult = { status: \"failed\", code: \"manager-operation-failed\" };\n\t\t}\n\t\tif (result.snapshot !== undefined) this.setSnapshot(result.snapshot);\n\t\tconst mutationCode = result.status === \"succeeded\" ? undefined : errorCode(result);\n\t\tconst refreshed = result.snapshot === undefined ? await this.refresh() : this.status;\n\t\tif (mutationCode !== undefined) {\n\t\t\tthis.status = Object.freeze({ ...refreshed, status: \"error\", diagnosticCode: mutationCode });\n\t\t}\n\t\tthis.busy = false;\n\t\tthis.selectedActionIndex = Math.min(this.selectedActionIndex, Math.max(0, this.currentActions().length - 1));\n\t\tthis.request();\n\t}\n\n\tasync openPluginManager(): Promise<PluginManagerEntryOpenResultV1> {\n\t\treturn await this.refresh();\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused) return;\n\t\tconst kb = getKeybindings();\n\t\tif (this.busy) return;\n\t\tif (this.confirmation !== undefined) {\n\t\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\tthis.confirmation = undefined;\n\t\t\t\tthis.request();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\t\tconst action = this.currentAction();\n\t\t\t\tif (action !== undefined) void this.perform(action);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.selectedActionIndex = 0;\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(Math.max(0, this.entries.length - 1), this.selectedIndex + 1);\n\t\t\tthis.selectedActionIndex = 0;\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.input.tab\")) {\n\t\t\tconst actions = this.currentActions();\n\t\t\tif (actions.length > 0) this.selectedActionIndex = (this.selectedActionIndex + 1) % actions.length;\n\t\t\tthis.request();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tconst entry = this.currentEntry();\n\t\t\tconst action = this.currentAction();\n\t\t\tif (entry !== undefined && action !== undefined) {\n\t\t\t\tthis.confirmation = { pluginId: entry.pluginId, action };\n\t\t\t\tthis.request();\n\t\t\t}\n\t\t}\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectedPluginId(): string | undefined {\n\t\treturn this.currentEntry()?.pluginId;\n\t}\n\n\tgetSelectedAction(): PluginManagerActionV1 | undefined {\n\t\treturn this.currentAction();\n\t}\n\n\tgetStatus(): PluginManagerEntryOpenContextV1 {\n\t\treturn this.status;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-selection-entry.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-selection-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin selection entry for the config screen.\n *\n * This component deliberately renders only counts and bounded status. The\n * catalog, selection IDs, adapters, paths, credentials, and plugin payloads\n * stay behind the injected host contract.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginSelectionControllerResultV1,\n\tPluginSelectionControllerV1,\n\tPluginSelectionUiPluginV1,\n\tPluginSelectionUiProfileV1,\n\tPluginSelectionUiSnapshotV1,\n} from \"../../../cli/plugin-selection-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport type { PluginCatalogSnapshotV1 } from \"../../../plugins/ecosystem/catalog.ts\";\nimport type { PluginSelectionV1 } from \"../../../plugins/ecosystem/selection.ts\";\nimport type {\n\tPluginSelectionStoreDiagnosticCodeV1,\n\tPluginSelectionStoreReadResultV1,\n\tPluginSelectionStoreV1,\n} from \"../../../plugins/ecosystem/selection-store.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst MAX_PROFILE_ID_CHARS = 128;\nconst MAX_SELECTION_IDS = 128;\nconst MAX_CATALOG_ENTRIES = 256;\nconst MAX_DIAGNOSTIC_CODES = 16;\n\nexport interface PluginSelectionSummaryV1 {\n\treadonly present: boolean;\n\treadonly selectedCount: number;\n\treadonly disabledCount: number;\n\treadonly truncated: boolean;\n}\n\nexport interface PluginCatalogSummaryV1 {\n\treadonly present: boolean;\n\treadonly entryCount: number;\n\treadonly readyCount: number;\n\treadonly unavailableCount: number;\n\treadonly truncated: boolean;\n}\n\nexport type PluginSelectionEntryStatusV1 = \"ready\" | \"missing\" | \"unsupported\" | \"invalid\" | \"cancelled\";\n\nexport interface PluginSelectionOpenContextV1 {\n\treadonly profileId: string;\n\treadonly status: PluginSelectionEntryStatusV1;\n\treadonly selection: PluginSelectionSummaryV1;\n\treadonly catalog: PluginCatalogSummaryV1;\n\treadonly diagnosticCodes: readonly PluginSelectionStoreDiagnosticCodeV1[];\n}\n\nexport type PluginSelectionEntryOpenResultV1 = PluginSelectionOpenContextV1;\n\nexport interface PluginSelectionEntryOptionsV1 {\n\treadonly profileId: string;\n\treadonly store?: PluginSelectionStoreV1;\n\treadonly selection?: PluginSelectionV1;\n\treadonly catalog?: PluginCatalogSnapshotV1;\n\treadonly controller?: PluginSelectionControllerV1;\n\treadonly snapshot?: PluginSelectionUiSnapshotV1;\n\t/** Host callback that opens the independent plugin selection surface. */\n\treadonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nfunction boundedCount(value: readonly unknown[] | undefined, maximum: number): { count: number; truncated: boolean } {\n\tif (value === undefined) return { count: 0, truncated: false };\n\treturn { count: Math.min(value.length, maximum), truncated: value.length > maximum };\n}\n\nexport function summarizePluginSelectionV1(selection: PluginSelectionV1 | undefined): PluginSelectionSummaryV1 {\n\tif (selection === undefined) {\n\t\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n\t}\n\tconst selected = boundedCount(selection.selectedPluginIds, MAX_SELECTION_IDS);\n\tconst disabled = boundedCount(selection.disabledPluginIds, MAX_SELECTION_IDS);\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tselectedCount: selected.count,\n\t\tdisabledCount: disabled.count,\n\t\ttruncated: selected.truncated || disabled.truncated,\n\t});\n}\n\nexport function summarizePluginCatalogV1(catalog: PluginCatalogSnapshotV1 | undefined): PluginCatalogSummaryV1 {\n\tif (catalog === undefined) {\n\t\treturn Object.freeze({ present: false, entryCount: 0, readyCount: 0, unavailableCount: 0, truncated: false });\n\t}\n\tconst entries = catalog.entries.slice(0, MAX_CATALOG_ENTRIES);\n\tconst readyCount = entries.filter((entry) => entry.resolution.status === \"installed-ready\").length;\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tentryCount: entries.length,\n\t\treadyCount,\n\t\tunavailableCount: entries.length - readyCount,\n\t\ttruncated: catalog.truncated || catalog.entries.length > MAX_CATALOG_ENTRIES,\n\t});\n}\n\nfunction validateProfileId(profileId: string): string {\n\tif (\n\t\ttypeof profileId !== \"string\" ||\n\t\tprofileId.trim().length === 0 ||\n\t\tprofileId.length > MAX_PROFILE_ID_CHARS ||\n\t\t/[\\u0000-\\u001f]/u.test(profileId)\n\t) {\n\t\tthrow new Error(t(\"invalid plugin selection profile ID\"));\n\t}\n\treturn profileId;\n}\n\nfunction emptySelectionSummary(): PluginSelectionSummaryV1 {\n\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n}\n\nfunction diagnosticCodes(result: PluginSelectionStoreReadResultV1): readonly PluginSelectionStoreDiagnosticCodeV1[] {\n\tif (result.status === \"ok\" || result.status === \"missing\") return Object.freeze([]);\n\treturn Object.freeze(result.diagnostics.slice(0, MAX_DIAGNOSTIC_CODES).map((item) => item.code));\n}\n\nfunction selectionForProfile(\n\tresult: Extract<PluginSelectionStoreReadResultV1, { readonly status: \"ok\" | \"missing\" }>,\n\tprofileId: string,\n): PluginSelectionV1 | undefined {\n\treturn result.snapshot.selections.find((selection) => selection.profileId === profileId);\n}\n\n/**\n * A non-focusable entry. The surrounding config selector can expose\n * `openPluginSelection()` to its host without assigning plugin actions to the\n * legacy resource list or inventing a new global key binding.\n */\nexport class PluginSelectionEntryComponent implements Component, Focusable {\n\tprivate readonly profileId: string;\n\tprivate readonly store?: PluginSelectionStoreV1;\n\tprivate readonly controller?: PluginSelectionControllerV1;\n\tprivate readonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate selection: PluginSelectionSummaryV1;\n\tprivate readonly catalog: PluginCatalogSummaryV1;\n\tprivate uiProfile?: PluginSelectionUiProfileV1;\n\tprivate uiPluginIndex = 0;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginSelectionEntryOptionsV1) {\n\t\tthis.profileId = validateProfileId(options.profileId);\n\t\tif (options.selection !== undefined && options.selection.profileId !== this.profileId) {\n\t\t\tthrow new Error(t(\"plugin selection profile does not match the entry profile\"));\n\t\t}\n\t\tthis.store = options.store;\n\t\tthis.controller = options.controller;\n\t\tthis.onOpen = options.onOpen;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tthis.selection = summarizePluginSelectionV1(options.selection);\n\t\tthis.catalog = summarizePluginCatalogV1(options.catalog);\n\t\tthis.uiProfile = options.snapshot?.profiles.find((profile) => profile.profileId === this.profileId);\n\t}\n\n\tprivate hasHostEntry(): boolean {\n\t\treturn this.store !== undefined || this.controller !== undefined || this.onOpen !== undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this.hasHostEntry()) {\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"dim\", ` ${t(\"Plugins: unsupported (host selection entry not injected)\")}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tif (this._focused && this.uiProfile !== undefined) {\n\t\t\tconst lines = [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.bold(` ${t(\"Plugins · {profile}\", { profile: this.uiProfile.profileId })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t\tfor (const [index, plugin] of this.uiProfile.plugins.entries()) {\n\t\t\t\tconst cursor = index === this.uiPluginIndex ? \">\" : \" \";\n\t\t\t\tconst state = plugin.state === \"selected\" ? \"on\" : plugin.state === \"disabled\" ? \"off\" : \"available\";\n\t\t\t\tconst availability = plugin.availability === \"ready\" ? \"ready\" : \"unavailable\";\n\t\t\t\tlines.push(truncateToWidth(` ${cursor} [${state}] ${plugin.pluginId} (${availability})`, width, \"...\"));\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Enter/Space toggle · Esc close\")}`), width, \"...\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selectionText = this.selection.present\n\t\t\t? t(\"selected {selected}, disabled {disabled}\", {\n\t\t\t\t\tselected: this.selection.selectedCount,\n\t\t\t\t\tdisabled: this.selection.disabledCount,\n\t\t\t\t}) + (this.selection.truncated ? t(\", bounded\") : \"\")\n\t\t\t: this.store === undefined\n\t\t\t\t? t(\"selection pending\")\n\t\t\t\t: t(\"selection not loaded\");\n\t\tconst catalogText = this.catalog.present\n\t\t\t? t(\"catalog {count} ({ready} ready, {unavailable} unavailable)\", {\n\t\t\t\t\tcount: this.catalog.entryCount,\n\t\t\t\t\tready: this.catalog.readyCount,\n\t\t\t\t\tunavailable: this.catalog.unavailableCount,\n\t\t\t\t}) + (this.catalog.truncated ? t(\", bounded\") : \"\")\n\t\t\t: t(\"catalog unavailable\");\n\t\tconst suffix = this.onOpen === undefined ? t(\"host store\") : t(\"open via host callback\");\n\t\treturn [\n\t\t\ttruncateToWidth(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t` ${t(\"Plugins: profile {profile} · {selection} · {catalog} · {suffix}\", {\n\t\t\t\t\t\tprofile: this.profileId,\n\t\t\t\t\t\tselection: selectionText,\n\t\t\t\t\t\tcatalog: catalogText,\n\t\t\t\t\t\tsuffix,\n\t\t\t\t\t})}`,\n\t\t\t\t),\n\t\t\t\twidth,\n\t\t\t\t\"...\",\n\t\t\t),\n\t\t];\n\t}\n\n\tprivate setUiSnapshot(result: PluginSelectionControllerResultV1): void {\n\t\tif (result.status !== \"ok\") return;\n\t\tthis.uiProfile = result.snapshot.profiles.find((profile) => profile.profileId === this.profileId);\n\t\tif (this.uiProfile !== undefined) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiPluginIndex, Math.max(0, this.uiProfile.plugins.length - 1));\n\t\t}\n\t}\n\n\tprivate currentUiPlugin(): PluginSelectionUiPluginV1 | undefined {\n\t\treturn this.uiProfile?.plugins[this.uiPluginIndex];\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused || this.uiProfile === undefined) return;\n\t\tconst keybindings = getKeybindings();\n\t\tif (keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.uiPluginIndex = Math.max(0, this.uiPluginIndex - 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiProfile.plugins.length - 1, this.uiPluginIndex + 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (!keybindings.matches(data, \"tui.select.confirm\") && data !== \" \") return;\n\t\tconst plugin = this.currentUiPlugin();\n\t\tif (\n\t\t\tplugin === undefined ||\n\t\t\tthis.controller === undefined ||\n\t\t\t(plugin.state === \"disabled\" && plugin.availability !== \"ready\")\n\t\t)\n\t\t\treturn;\n\t\tvoid this.controller\n\t\t\t.toggle({ profileId: this.profileId, pluginId: plugin.pluginId })\n\t\t\t.then((result) => {\n\t\t\t\tthis.setUiSnapshot(result);\n\t\t\t\tthis.requestRender?.();\n\t\t\t})\n\t\t\t.catch(() => this.requestRender?.());\n\t}\n\n\t/** Read the bounded selection DTO and invoke the host-owned entry callback. */\n\tasync openPluginSelection(): Promise<PluginSelectionEntryOpenResultV1> {\n\t\tlet controllerResult: PluginSelectionControllerResultV1 | undefined;\n\t\tif (this.controller !== undefined) {\n\t\t\tcontrollerResult = await this.controller.getSnapshot();\n\t\t\tthis.setUiSnapshot(controllerResult);\n\t\t}\n\t\tlet status: PluginSelectionEntryStatusV1 = this.hasHostEntry() ? \"ready\" : \"unsupported\";\n\t\tlet selection = this.selection;\n\t\tlet codes: readonly PluginSelectionStoreDiagnosticCodeV1[] = Object.freeze([]);\n\t\tif (controllerResult?.status === \"error\") {\n\t\t\tstatus = controllerResult.code === \"store-cancelled\" ? \"cancelled\" : \"invalid\";\n\t\t}\n\n\t\tif (this.store !== undefined) {\n\t\t\tconst result = await this.store.read();\n\t\t\tcodes = diagnosticCodes(result);\n\t\t\tif (result.status === \"ok\" || result.status === \"missing\") {\n\t\t\t\tconst storedSelection = selectionForProfile(result, this.profileId);\n\t\t\t\tselection = summarizePluginSelectionV1(storedSelection);\n\t\t\t\tstatus = result.status === \"ok\" ? \"ready\" : \"missing\";\n\t\t\t} else {\n\t\t\t\tselection = emptySelectionSummary();\n\t\t\t\tstatus = result.status;\n\t\t\t}\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tconst context: PluginSelectionOpenContextV1 = Object.freeze({\n\t\t\tprofileId: this.profileId,\n\t\t\tstatus,\n\t\t\tselection,\n\t\t\tcatalog: this.catalog,\n\t\t\tdiagnosticCodes: codes,\n\t\t});\n\t\tif (this.onOpen !== undefined) await this.onOpen(context);\n\t\treturn context;\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectionSummary(): PluginSelectionSummaryV1 {\n\t\treturn this.selection;\n\t}\n\n\tgetCatalogSummary(): PluginCatalogSummaryV1 {\n\t\treturn this.catalog;\n\t}\n}\n"]}
1
+ {"version":3,"file":"plugin-selection-entry.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-selection-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin selection entry for the config screen.\n *\n * This component deliberately renders only counts and bounded status. The\n * catalog, selection IDs, adapters, paths, credentials, and plugin payloads\n * stay behind the injected host contract.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginSelectionControllerResultV1,\n\tPluginSelectionControllerV1,\n\tPluginSelectionUiPluginV1,\n\tPluginSelectionUiProfileV1,\n\tPluginSelectionUiSnapshotV1,\n} from \"../../../cli/plugin-selection-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport type { PluginCatalogSnapshotV1 } from \"../../../plugins/ecosystem/catalog.ts\";\nimport type { PluginSelectionV1 } from \"../../../plugins/ecosystem/selection.ts\";\nimport type {\n\tPluginSelectionStoreDiagnosticCodeV1,\n\tPluginSelectionStoreReadResultV1,\n\tPluginSelectionStoreV1,\n} from \"../../../plugins/ecosystem/selection-store.ts\";\nimport { theme } from \"../../../theme/theme.ts\";\n\nconst MAX_PROFILE_ID_CHARS = 128;\nconst MAX_SELECTION_IDS = 128;\nconst MAX_CATALOG_ENTRIES = 256;\nconst MAX_DIAGNOSTIC_CODES = 16;\n\nexport interface PluginSelectionSummaryV1 {\n\treadonly present: boolean;\n\treadonly selectedCount: number;\n\treadonly disabledCount: number;\n\treadonly truncated: boolean;\n}\n\nexport interface PluginCatalogSummaryV1 {\n\treadonly present: boolean;\n\treadonly entryCount: number;\n\treadonly readyCount: number;\n\treadonly unavailableCount: number;\n\treadonly truncated: boolean;\n}\n\nexport type PluginSelectionEntryStatusV1 = \"ready\" | \"missing\" | \"unsupported\" | \"invalid\" | \"cancelled\";\n\nexport interface PluginSelectionOpenContextV1 {\n\treadonly profileId: string;\n\treadonly status: PluginSelectionEntryStatusV1;\n\treadonly selection: PluginSelectionSummaryV1;\n\treadonly catalog: PluginCatalogSummaryV1;\n\treadonly diagnosticCodes: readonly PluginSelectionStoreDiagnosticCodeV1[];\n}\n\nexport type PluginSelectionEntryOpenResultV1 = PluginSelectionOpenContextV1;\n\nexport interface PluginSelectionEntryOptionsV1 {\n\treadonly profileId: string;\n\treadonly store?: PluginSelectionStoreV1;\n\treadonly selection?: PluginSelectionV1;\n\treadonly catalog?: PluginCatalogSnapshotV1;\n\treadonly controller?: PluginSelectionControllerV1;\n\treadonly snapshot?: PluginSelectionUiSnapshotV1;\n\t/** Host callback that opens the independent plugin selection surface. */\n\treadonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nfunction boundedCount(value: readonly unknown[] | undefined, maximum: number): { count: number; truncated: boolean } {\n\tif (value === undefined) return { count: 0, truncated: false };\n\treturn { count: Math.min(value.length, maximum), truncated: value.length > maximum };\n}\n\nexport function summarizePluginSelectionV1(selection: PluginSelectionV1 | undefined): PluginSelectionSummaryV1 {\n\tif (selection === undefined) {\n\t\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n\t}\n\tconst selected = boundedCount(selection.selectedPluginIds, MAX_SELECTION_IDS);\n\tconst disabled = boundedCount(selection.disabledPluginIds, MAX_SELECTION_IDS);\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tselectedCount: selected.count,\n\t\tdisabledCount: disabled.count,\n\t\ttruncated: selected.truncated || disabled.truncated,\n\t});\n}\n\nexport function summarizePluginCatalogV1(catalog: PluginCatalogSnapshotV1 | undefined): PluginCatalogSummaryV1 {\n\tif (catalog === undefined) {\n\t\treturn Object.freeze({ present: false, entryCount: 0, readyCount: 0, unavailableCount: 0, truncated: false });\n\t}\n\tconst entries = catalog.entries.slice(0, MAX_CATALOG_ENTRIES);\n\tconst readyCount = entries.filter((entry) => entry.resolution.status === \"installed-ready\").length;\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tentryCount: entries.length,\n\t\treadyCount,\n\t\tunavailableCount: entries.length - readyCount,\n\t\ttruncated: catalog.truncated || catalog.entries.length > MAX_CATALOG_ENTRIES,\n\t});\n}\n\nfunction validateProfileId(profileId: string): string {\n\tif (\n\t\ttypeof profileId !== \"string\" ||\n\t\tprofileId.trim().length === 0 ||\n\t\tprofileId.length > MAX_PROFILE_ID_CHARS ||\n\t\t/[\\u0000-\\u001f]/u.test(profileId)\n\t) {\n\t\tthrow new Error(t(\"invalid plugin selection profile ID\"));\n\t}\n\treturn profileId;\n}\n\nfunction emptySelectionSummary(): PluginSelectionSummaryV1 {\n\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n}\n\nfunction diagnosticCodes(result: PluginSelectionStoreReadResultV1): readonly PluginSelectionStoreDiagnosticCodeV1[] {\n\tif (result.status === \"ok\" || result.status === \"missing\") return Object.freeze([]);\n\treturn Object.freeze(result.diagnostics.slice(0, MAX_DIAGNOSTIC_CODES).map((item) => item.code));\n}\n\nfunction selectionForProfile(\n\tresult: Extract<PluginSelectionStoreReadResultV1, { readonly status: \"ok\" | \"missing\" }>,\n\tprofileId: string,\n): PluginSelectionV1 | undefined {\n\treturn result.snapshot.selections.find((selection) => selection.profileId === profileId);\n}\n\n/**\n * A non-focusable entry. The surrounding config selector can expose\n * `openPluginSelection()` to its host without assigning plugin actions to the\n * legacy resource list or inventing a new global key binding.\n */\nexport class PluginSelectionEntryComponent implements Component, Focusable {\n\tprivate readonly profileId: string;\n\tprivate readonly store?: PluginSelectionStoreV1;\n\tprivate readonly controller?: PluginSelectionControllerV1;\n\tprivate readonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate selection: PluginSelectionSummaryV1;\n\tprivate readonly catalog: PluginCatalogSummaryV1;\n\tprivate uiProfile?: PluginSelectionUiProfileV1;\n\tprivate uiPluginIndex = 0;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginSelectionEntryOptionsV1) {\n\t\tthis.profileId = validateProfileId(options.profileId);\n\t\tif (options.selection !== undefined && options.selection.profileId !== this.profileId) {\n\t\t\tthrow new Error(t(\"plugin selection profile does not match the entry profile\"));\n\t\t}\n\t\tthis.store = options.store;\n\t\tthis.controller = options.controller;\n\t\tthis.onOpen = options.onOpen;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tthis.selection = summarizePluginSelectionV1(options.selection);\n\t\tthis.catalog = summarizePluginCatalogV1(options.catalog);\n\t\tthis.uiProfile = options.snapshot?.profiles.find((profile) => profile.profileId === this.profileId);\n\t}\n\n\tprivate hasHostEntry(): boolean {\n\t\treturn this.store !== undefined || this.controller !== undefined || this.onOpen !== undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this.hasHostEntry()) {\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"dim\", ` ${t(\"Plugins: unsupported (host selection entry not injected)\")}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tif (this._focused && this.uiProfile !== undefined) {\n\t\t\tconst lines = [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.bold(` ${t(\"Plugins · {profile}\", { profile: this.uiProfile.profileId })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t\tfor (const [index, plugin] of this.uiProfile.plugins.entries()) {\n\t\t\t\tconst cursor = index === this.uiPluginIndex ? \">\" : \" \";\n\t\t\t\tconst state = plugin.state === \"selected\" ? \"on\" : plugin.state === \"disabled\" ? \"off\" : \"available\";\n\t\t\t\tconst availability = plugin.availability === \"ready\" ? \"ready\" : \"unavailable\";\n\t\t\t\tlines.push(truncateToWidth(` ${cursor} [${state}] ${plugin.pluginId} (${availability})`, width, \"...\"));\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Enter/Space toggle · Esc close\")}`), width, \"...\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selectionText = this.selection.present\n\t\t\t? t(\"selected {selected}, disabled {disabled}\", {\n\t\t\t\t\tselected: this.selection.selectedCount,\n\t\t\t\t\tdisabled: this.selection.disabledCount,\n\t\t\t\t}) + (this.selection.truncated ? t(\", bounded\") : \"\")\n\t\t\t: this.store === undefined\n\t\t\t\t? t(\"selection pending\")\n\t\t\t\t: t(\"selection not loaded\");\n\t\tconst catalogText = this.catalog.present\n\t\t\t? t(\"catalog {count} ({ready} ready, {unavailable} unavailable)\", {\n\t\t\t\t\tcount: this.catalog.entryCount,\n\t\t\t\t\tready: this.catalog.readyCount,\n\t\t\t\t\tunavailable: this.catalog.unavailableCount,\n\t\t\t\t}) + (this.catalog.truncated ? t(\", bounded\") : \"\")\n\t\t\t: t(\"catalog unavailable\");\n\t\tconst suffix = this.onOpen === undefined ? t(\"host store\") : t(\"open via host callback\");\n\t\treturn [\n\t\t\ttruncateToWidth(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t` ${t(\"Plugins: profile {profile} · {selection} · {catalog} · {suffix}\", {\n\t\t\t\t\t\tprofile: this.profileId,\n\t\t\t\t\t\tselection: selectionText,\n\t\t\t\t\t\tcatalog: catalogText,\n\t\t\t\t\t\tsuffix,\n\t\t\t\t\t})}`,\n\t\t\t\t),\n\t\t\t\twidth,\n\t\t\t\t\"...\",\n\t\t\t),\n\t\t];\n\t}\n\n\tprivate setUiSnapshot(result: PluginSelectionControllerResultV1): void {\n\t\tif (result.status !== \"ok\") return;\n\t\tthis.uiProfile = result.snapshot.profiles.find((profile) => profile.profileId === this.profileId);\n\t\tif (this.uiProfile !== undefined) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiPluginIndex, Math.max(0, this.uiProfile.plugins.length - 1));\n\t\t}\n\t}\n\n\tprivate currentUiPlugin(): PluginSelectionUiPluginV1 | undefined {\n\t\treturn this.uiProfile?.plugins[this.uiPluginIndex];\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused || this.uiProfile === undefined) return;\n\t\tconst keybindings = getKeybindings();\n\t\tif (keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.uiPluginIndex = Math.max(0, this.uiPluginIndex - 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiProfile.plugins.length - 1, this.uiPluginIndex + 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (!keybindings.matches(data, \"tui.select.confirm\") && data !== \" \") return;\n\t\tconst plugin = this.currentUiPlugin();\n\t\tif (\n\t\t\tplugin === undefined ||\n\t\t\tthis.controller === undefined ||\n\t\t\t(plugin.state === \"disabled\" && plugin.availability !== \"ready\")\n\t\t)\n\t\t\treturn;\n\t\tvoid this.controller\n\t\t\t.toggle({ profileId: this.profileId, pluginId: plugin.pluginId })\n\t\t\t.then((result) => {\n\t\t\t\tthis.setUiSnapshot(result);\n\t\t\t\tthis.requestRender?.();\n\t\t\t})\n\t\t\t.catch(() => this.requestRender?.());\n\t}\n\n\t/** Read the bounded selection DTO and invoke the host-owned entry callback. */\n\tasync openPluginSelection(): Promise<PluginSelectionEntryOpenResultV1> {\n\t\tlet controllerResult: PluginSelectionControllerResultV1 | undefined;\n\t\tif (this.controller !== undefined) {\n\t\t\tcontrollerResult = await this.controller.getSnapshot();\n\t\t\tthis.setUiSnapshot(controllerResult);\n\t\t}\n\t\tlet status: PluginSelectionEntryStatusV1 = this.hasHostEntry() ? \"ready\" : \"unsupported\";\n\t\tlet selection = this.selection;\n\t\tlet codes: readonly PluginSelectionStoreDiagnosticCodeV1[] = Object.freeze([]);\n\t\tif (controllerResult?.status === \"error\") {\n\t\t\tstatus = controllerResult.code === \"store-cancelled\" ? \"cancelled\" : \"invalid\";\n\t\t}\n\n\t\tif (this.store !== undefined) {\n\t\t\tconst result = await this.store.read();\n\t\t\tcodes = diagnosticCodes(result);\n\t\t\tif (result.status === \"ok\" || result.status === \"missing\") {\n\t\t\t\tconst storedSelection = selectionForProfile(result, this.profileId);\n\t\t\t\tselection = summarizePluginSelectionV1(storedSelection);\n\t\t\t\tstatus = result.status === \"ok\" ? \"ready\" : \"missing\";\n\t\t\t} else {\n\t\t\t\tselection = emptySelectionSummary();\n\t\t\t\tstatus = result.status;\n\t\t\t}\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tconst context: PluginSelectionOpenContextV1 = Object.freeze({\n\t\t\tprofileId: this.profileId,\n\t\t\tstatus,\n\t\t\tselection,\n\t\t\tcatalog: this.catalog,\n\t\t\tdiagnosticCodes: codes,\n\t\t});\n\t\tif (this.onOpen !== undefined) await this.onOpen(context);\n\t\treturn context;\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectionSummary(): PluginSelectionSummaryV1 {\n\t\treturn this.selection;\n\t}\n\n\tgetCatalogSummary(): PluginCatalogSummaryV1 {\n\t\treturn this.catalog;\n\t}\n}\n"]}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { getKeybindings, truncateToWidth } from "@agent-forge/tui";
9
9
  import { t } from "../../../core/i18n/index.js";
10
- import { theme } from "../theme/theme.js";
10
+ import { theme } from "../../../theme/theme.js";
11
11
  const MAX_PROFILE_ID_CHARS = 128;
12
12
  const MAX_SELECTION_IDS = 128;
13
13
  const MAX_CATALOG_ENTRIES = 256;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-selection-entry.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-selection-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin selection entry for the config screen.\n *\n * This component deliberately renders only counts and bounded status. The\n * catalog, selection IDs, adapters, paths, credentials, and plugin payloads\n * stay behind the injected host contract.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginSelectionControllerResultV1,\n\tPluginSelectionControllerV1,\n\tPluginSelectionUiPluginV1,\n\tPluginSelectionUiProfileV1,\n\tPluginSelectionUiSnapshotV1,\n} from \"../../../cli/plugin-selection-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport type { PluginCatalogSnapshotV1 } from \"../../../plugins/ecosystem/catalog.ts\";\nimport type { PluginSelectionV1 } from \"../../../plugins/ecosystem/selection.ts\";\nimport type {\n\tPluginSelectionStoreDiagnosticCodeV1,\n\tPluginSelectionStoreReadResultV1,\n\tPluginSelectionStoreV1,\n} from \"../../../plugins/ecosystem/selection-store.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst MAX_PROFILE_ID_CHARS = 128;\nconst MAX_SELECTION_IDS = 128;\nconst MAX_CATALOG_ENTRIES = 256;\nconst MAX_DIAGNOSTIC_CODES = 16;\n\nexport interface PluginSelectionSummaryV1 {\n\treadonly present: boolean;\n\treadonly selectedCount: number;\n\treadonly disabledCount: number;\n\treadonly truncated: boolean;\n}\n\nexport interface PluginCatalogSummaryV1 {\n\treadonly present: boolean;\n\treadonly entryCount: number;\n\treadonly readyCount: number;\n\treadonly unavailableCount: number;\n\treadonly truncated: boolean;\n}\n\nexport type PluginSelectionEntryStatusV1 = \"ready\" | \"missing\" | \"unsupported\" | \"invalid\" | \"cancelled\";\n\nexport interface PluginSelectionOpenContextV1 {\n\treadonly profileId: string;\n\treadonly status: PluginSelectionEntryStatusV1;\n\treadonly selection: PluginSelectionSummaryV1;\n\treadonly catalog: PluginCatalogSummaryV1;\n\treadonly diagnosticCodes: readonly PluginSelectionStoreDiagnosticCodeV1[];\n}\n\nexport type PluginSelectionEntryOpenResultV1 = PluginSelectionOpenContextV1;\n\nexport interface PluginSelectionEntryOptionsV1 {\n\treadonly profileId: string;\n\treadonly store?: PluginSelectionStoreV1;\n\treadonly selection?: PluginSelectionV1;\n\treadonly catalog?: PluginCatalogSnapshotV1;\n\treadonly controller?: PluginSelectionControllerV1;\n\treadonly snapshot?: PluginSelectionUiSnapshotV1;\n\t/** Host callback that opens the independent plugin selection surface. */\n\treadonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nfunction boundedCount(value: readonly unknown[] | undefined, maximum: number): { count: number; truncated: boolean } {\n\tif (value === undefined) return { count: 0, truncated: false };\n\treturn { count: Math.min(value.length, maximum), truncated: value.length > maximum };\n}\n\nexport function summarizePluginSelectionV1(selection: PluginSelectionV1 | undefined): PluginSelectionSummaryV1 {\n\tif (selection === undefined) {\n\t\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n\t}\n\tconst selected = boundedCount(selection.selectedPluginIds, MAX_SELECTION_IDS);\n\tconst disabled = boundedCount(selection.disabledPluginIds, MAX_SELECTION_IDS);\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tselectedCount: selected.count,\n\t\tdisabledCount: disabled.count,\n\t\ttruncated: selected.truncated || disabled.truncated,\n\t});\n}\n\nexport function summarizePluginCatalogV1(catalog: PluginCatalogSnapshotV1 | undefined): PluginCatalogSummaryV1 {\n\tif (catalog === undefined) {\n\t\treturn Object.freeze({ present: false, entryCount: 0, readyCount: 0, unavailableCount: 0, truncated: false });\n\t}\n\tconst entries = catalog.entries.slice(0, MAX_CATALOG_ENTRIES);\n\tconst readyCount = entries.filter((entry) => entry.resolution.status === \"installed-ready\").length;\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tentryCount: entries.length,\n\t\treadyCount,\n\t\tunavailableCount: entries.length - readyCount,\n\t\ttruncated: catalog.truncated || catalog.entries.length > MAX_CATALOG_ENTRIES,\n\t});\n}\n\nfunction validateProfileId(profileId: string): string {\n\tif (\n\t\ttypeof profileId !== \"string\" ||\n\t\tprofileId.trim().length === 0 ||\n\t\tprofileId.length > MAX_PROFILE_ID_CHARS ||\n\t\t/[\\u0000-\\u001f]/u.test(profileId)\n\t) {\n\t\tthrow new Error(t(\"invalid plugin selection profile ID\"));\n\t}\n\treturn profileId;\n}\n\nfunction emptySelectionSummary(): PluginSelectionSummaryV1 {\n\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n}\n\nfunction diagnosticCodes(result: PluginSelectionStoreReadResultV1): readonly PluginSelectionStoreDiagnosticCodeV1[] {\n\tif (result.status === \"ok\" || result.status === \"missing\") return Object.freeze([]);\n\treturn Object.freeze(result.diagnostics.slice(0, MAX_DIAGNOSTIC_CODES).map((item) => item.code));\n}\n\nfunction selectionForProfile(\n\tresult: Extract<PluginSelectionStoreReadResultV1, { readonly status: \"ok\" | \"missing\" }>,\n\tprofileId: string,\n): PluginSelectionV1 | undefined {\n\treturn result.snapshot.selections.find((selection) => selection.profileId === profileId);\n}\n\n/**\n * A non-focusable entry. The surrounding config selector can expose\n * `openPluginSelection()` to its host without assigning plugin actions to the\n * legacy resource list or inventing a new global key binding.\n */\nexport class PluginSelectionEntryComponent implements Component, Focusable {\n\tprivate readonly profileId: string;\n\tprivate readonly store?: PluginSelectionStoreV1;\n\tprivate readonly controller?: PluginSelectionControllerV1;\n\tprivate readonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate selection: PluginSelectionSummaryV1;\n\tprivate readonly catalog: PluginCatalogSummaryV1;\n\tprivate uiProfile?: PluginSelectionUiProfileV1;\n\tprivate uiPluginIndex = 0;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginSelectionEntryOptionsV1) {\n\t\tthis.profileId = validateProfileId(options.profileId);\n\t\tif (options.selection !== undefined && options.selection.profileId !== this.profileId) {\n\t\t\tthrow new Error(t(\"plugin selection profile does not match the entry profile\"));\n\t\t}\n\t\tthis.store = options.store;\n\t\tthis.controller = options.controller;\n\t\tthis.onOpen = options.onOpen;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tthis.selection = summarizePluginSelectionV1(options.selection);\n\t\tthis.catalog = summarizePluginCatalogV1(options.catalog);\n\t\tthis.uiProfile = options.snapshot?.profiles.find((profile) => profile.profileId === this.profileId);\n\t}\n\n\tprivate hasHostEntry(): boolean {\n\t\treturn this.store !== undefined || this.controller !== undefined || this.onOpen !== undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this.hasHostEntry()) {\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"dim\", ` ${t(\"Plugins: unsupported (host selection entry not injected)\")}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tif (this._focused && this.uiProfile !== undefined) {\n\t\t\tconst lines = [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.bold(` ${t(\"Plugins · {profile}\", { profile: this.uiProfile.profileId })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t\tfor (const [index, plugin] of this.uiProfile.plugins.entries()) {\n\t\t\t\tconst cursor = index === this.uiPluginIndex ? \">\" : \" \";\n\t\t\t\tconst state = plugin.state === \"selected\" ? \"on\" : plugin.state === \"disabled\" ? \"off\" : \"available\";\n\t\t\t\tconst availability = plugin.availability === \"ready\" ? \"ready\" : \"unavailable\";\n\t\t\t\tlines.push(truncateToWidth(` ${cursor} [${state}] ${plugin.pluginId} (${availability})`, width, \"...\"));\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Enter/Space toggle · Esc close\")}`), width, \"...\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selectionText = this.selection.present\n\t\t\t? t(\"selected {selected}, disabled {disabled}\", {\n\t\t\t\t\tselected: this.selection.selectedCount,\n\t\t\t\t\tdisabled: this.selection.disabledCount,\n\t\t\t\t}) + (this.selection.truncated ? t(\", bounded\") : \"\")\n\t\t\t: this.store === undefined\n\t\t\t\t? t(\"selection pending\")\n\t\t\t\t: t(\"selection not loaded\");\n\t\tconst catalogText = this.catalog.present\n\t\t\t? t(\"catalog {count} ({ready} ready, {unavailable} unavailable)\", {\n\t\t\t\t\tcount: this.catalog.entryCount,\n\t\t\t\t\tready: this.catalog.readyCount,\n\t\t\t\t\tunavailable: this.catalog.unavailableCount,\n\t\t\t\t}) + (this.catalog.truncated ? t(\", bounded\") : \"\")\n\t\t\t: t(\"catalog unavailable\");\n\t\tconst suffix = this.onOpen === undefined ? t(\"host store\") : t(\"open via host callback\");\n\t\treturn [\n\t\t\ttruncateToWidth(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t` ${t(\"Plugins: profile {profile} · {selection} · {catalog} · {suffix}\", {\n\t\t\t\t\t\tprofile: this.profileId,\n\t\t\t\t\t\tselection: selectionText,\n\t\t\t\t\t\tcatalog: catalogText,\n\t\t\t\t\t\tsuffix,\n\t\t\t\t\t})}`,\n\t\t\t\t),\n\t\t\t\twidth,\n\t\t\t\t\"...\",\n\t\t\t),\n\t\t];\n\t}\n\n\tprivate setUiSnapshot(result: PluginSelectionControllerResultV1): void {\n\t\tif (result.status !== \"ok\") return;\n\t\tthis.uiProfile = result.snapshot.profiles.find((profile) => profile.profileId === this.profileId);\n\t\tif (this.uiProfile !== undefined) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiPluginIndex, Math.max(0, this.uiProfile.plugins.length - 1));\n\t\t}\n\t}\n\n\tprivate currentUiPlugin(): PluginSelectionUiPluginV1 | undefined {\n\t\treturn this.uiProfile?.plugins[this.uiPluginIndex];\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused || this.uiProfile === undefined) return;\n\t\tconst keybindings = getKeybindings();\n\t\tif (keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.uiPluginIndex = Math.max(0, this.uiPluginIndex - 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiProfile.plugins.length - 1, this.uiPluginIndex + 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (!keybindings.matches(data, \"tui.select.confirm\") && data !== \" \") return;\n\t\tconst plugin = this.currentUiPlugin();\n\t\tif (\n\t\t\tplugin === undefined ||\n\t\t\tthis.controller === undefined ||\n\t\t\t(plugin.state === \"disabled\" && plugin.availability !== \"ready\")\n\t\t)\n\t\t\treturn;\n\t\tvoid this.controller\n\t\t\t.toggle({ profileId: this.profileId, pluginId: plugin.pluginId })\n\t\t\t.then((result) => {\n\t\t\t\tthis.setUiSnapshot(result);\n\t\t\t\tthis.requestRender?.();\n\t\t\t})\n\t\t\t.catch(() => this.requestRender?.());\n\t}\n\n\t/** Read the bounded selection DTO and invoke the host-owned entry callback. */\n\tasync openPluginSelection(): Promise<PluginSelectionEntryOpenResultV1> {\n\t\tlet controllerResult: PluginSelectionControllerResultV1 | undefined;\n\t\tif (this.controller !== undefined) {\n\t\t\tcontrollerResult = await this.controller.getSnapshot();\n\t\t\tthis.setUiSnapshot(controllerResult);\n\t\t}\n\t\tlet status: PluginSelectionEntryStatusV1 = this.hasHostEntry() ? \"ready\" : \"unsupported\";\n\t\tlet selection = this.selection;\n\t\tlet codes: readonly PluginSelectionStoreDiagnosticCodeV1[] = Object.freeze([]);\n\t\tif (controllerResult?.status === \"error\") {\n\t\t\tstatus = controllerResult.code === \"store-cancelled\" ? \"cancelled\" : \"invalid\";\n\t\t}\n\n\t\tif (this.store !== undefined) {\n\t\t\tconst result = await this.store.read();\n\t\t\tcodes = diagnosticCodes(result);\n\t\t\tif (result.status === \"ok\" || result.status === \"missing\") {\n\t\t\t\tconst storedSelection = selectionForProfile(result, this.profileId);\n\t\t\t\tselection = summarizePluginSelectionV1(storedSelection);\n\t\t\t\tstatus = result.status === \"ok\" ? \"ready\" : \"missing\";\n\t\t\t} else {\n\t\t\t\tselection = emptySelectionSummary();\n\t\t\t\tstatus = result.status;\n\t\t\t}\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tconst context: PluginSelectionOpenContextV1 = Object.freeze({\n\t\t\tprofileId: this.profileId,\n\t\t\tstatus,\n\t\t\tselection,\n\t\t\tcatalog: this.catalog,\n\t\t\tdiagnosticCodes: codes,\n\t\t});\n\t\tif (this.onOpen !== undefined) await this.onOpen(context);\n\t\treturn context;\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectionSummary(): PluginSelectionSummaryV1 {\n\t\treturn this.selection;\n\t}\n\n\tgetCatalogSummary(): PluginCatalogSummaryV1 {\n\t\treturn this.catalog;\n\t}\n}\n"]}
1
+ {"version":3,"file":"plugin-selection-entry.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-selection-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin selection entry for the config screen.\n *\n * This component deliberately renders only counts and bounded status. The\n * catalog, selection IDs, adapters, paths, credentials, and plugin payloads\n * stay behind the injected host contract.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginSelectionControllerResultV1,\n\tPluginSelectionControllerV1,\n\tPluginSelectionUiPluginV1,\n\tPluginSelectionUiProfileV1,\n\tPluginSelectionUiSnapshotV1,\n} from \"../../../cli/plugin-selection-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport type { PluginCatalogSnapshotV1 } from \"../../../plugins/ecosystem/catalog.ts\";\nimport type { PluginSelectionV1 } from \"../../../plugins/ecosystem/selection.ts\";\nimport type {\n\tPluginSelectionStoreDiagnosticCodeV1,\n\tPluginSelectionStoreReadResultV1,\n\tPluginSelectionStoreV1,\n} from \"../../../plugins/ecosystem/selection-store.ts\";\nimport { theme } from \"../../../theme/theme.ts\";\n\nconst MAX_PROFILE_ID_CHARS = 128;\nconst MAX_SELECTION_IDS = 128;\nconst MAX_CATALOG_ENTRIES = 256;\nconst MAX_DIAGNOSTIC_CODES = 16;\n\nexport interface PluginSelectionSummaryV1 {\n\treadonly present: boolean;\n\treadonly selectedCount: number;\n\treadonly disabledCount: number;\n\treadonly truncated: boolean;\n}\n\nexport interface PluginCatalogSummaryV1 {\n\treadonly present: boolean;\n\treadonly entryCount: number;\n\treadonly readyCount: number;\n\treadonly unavailableCount: number;\n\treadonly truncated: boolean;\n}\n\nexport type PluginSelectionEntryStatusV1 = \"ready\" | \"missing\" | \"unsupported\" | \"invalid\" | \"cancelled\";\n\nexport interface PluginSelectionOpenContextV1 {\n\treadonly profileId: string;\n\treadonly status: PluginSelectionEntryStatusV1;\n\treadonly selection: PluginSelectionSummaryV1;\n\treadonly catalog: PluginCatalogSummaryV1;\n\treadonly diagnosticCodes: readonly PluginSelectionStoreDiagnosticCodeV1[];\n}\n\nexport type PluginSelectionEntryOpenResultV1 = PluginSelectionOpenContextV1;\n\nexport interface PluginSelectionEntryOptionsV1 {\n\treadonly profileId: string;\n\treadonly store?: PluginSelectionStoreV1;\n\treadonly selection?: PluginSelectionV1;\n\treadonly catalog?: PluginCatalogSnapshotV1;\n\treadonly controller?: PluginSelectionControllerV1;\n\treadonly snapshot?: PluginSelectionUiSnapshotV1;\n\t/** Host callback that opens the independent plugin selection surface. */\n\treadonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nfunction boundedCount(value: readonly unknown[] | undefined, maximum: number): { count: number; truncated: boolean } {\n\tif (value === undefined) return { count: 0, truncated: false };\n\treturn { count: Math.min(value.length, maximum), truncated: value.length > maximum };\n}\n\nexport function summarizePluginSelectionV1(selection: PluginSelectionV1 | undefined): PluginSelectionSummaryV1 {\n\tif (selection === undefined) {\n\t\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n\t}\n\tconst selected = boundedCount(selection.selectedPluginIds, MAX_SELECTION_IDS);\n\tconst disabled = boundedCount(selection.disabledPluginIds, MAX_SELECTION_IDS);\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tselectedCount: selected.count,\n\t\tdisabledCount: disabled.count,\n\t\ttruncated: selected.truncated || disabled.truncated,\n\t});\n}\n\nexport function summarizePluginCatalogV1(catalog: PluginCatalogSnapshotV1 | undefined): PluginCatalogSummaryV1 {\n\tif (catalog === undefined) {\n\t\treturn Object.freeze({ present: false, entryCount: 0, readyCount: 0, unavailableCount: 0, truncated: false });\n\t}\n\tconst entries = catalog.entries.slice(0, MAX_CATALOG_ENTRIES);\n\tconst readyCount = entries.filter((entry) => entry.resolution.status === \"installed-ready\").length;\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tentryCount: entries.length,\n\t\treadyCount,\n\t\tunavailableCount: entries.length - readyCount,\n\t\ttruncated: catalog.truncated || catalog.entries.length > MAX_CATALOG_ENTRIES,\n\t});\n}\n\nfunction validateProfileId(profileId: string): string {\n\tif (\n\t\ttypeof profileId !== \"string\" ||\n\t\tprofileId.trim().length === 0 ||\n\t\tprofileId.length > MAX_PROFILE_ID_CHARS ||\n\t\t/[\\u0000-\\u001f]/u.test(profileId)\n\t) {\n\t\tthrow new Error(t(\"invalid plugin selection profile ID\"));\n\t}\n\treturn profileId;\n}\n\nfunction emptySelectionSummary(): PluginSelectionSummaryV1 {\n\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n}\n\nfunction diagnosticCodes(result: PluginSelectionStoreReadResultV1): readonly PluginSelectionStoreDiagnosticCodeV1[] {\n\tif (result.status === \"ok\" || result.status === \"missing\") return Object.freeze([]);\n\treturn Object.freeze(result.diagnostics.slice(0, MAX_DIAGNOSTIC_CODES).map((item) => item.code));\n}\n\nfunction selectionForProfile(\n\tresult: Extract<PluginSelectionStoreReadResultV1, { readonly status: \"ok\" | \"missing\" }>,\n\tprofileId: string,\n): PluginSelectionV1 | undefined {\n\treturn result.snapshot.selections.find((selection) => selection.profileId === profileId);\n}\n\n/**\n * A non-focusable entry. The surrounding config selector can expose\n * `openPluginSelection()` to its host without assigning plugin actions to the\n * legacy resource list or inventing a new global key binding.\n */\nexport class PluginSelectionEntryComponent implements Component, Focusable {\n\tprivate readonly profileId: string;\n\tprivate readonly store?: PluginSelectionStoreV1;\n\tprivate readonly controller?: PluginSelectionControllerV1;\n\tprivate readonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate selection: PluginSelectionSummaryV1;\n\tprivate readonly catalog: PluginCatalogSummaryV1;\n\tprivate uiProfile?: PluginSelectionUiProfileV1;\n\tprivate uiPluginIndex = 0;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginSelectionEntryOptionsV1) {\n\t\tthis.profileId = validateProfileId(options.profileId);\n\t\tif (options.selection !== undefined && options.selection.profileId !== this.profileId) {\n\t\t\tthrow new Error(t(\"plugin selection profile does not match the entry profile\"));\n\t\t}\n\t\tthis.store = options.store;\n\t\tthis.controller = options.controller;\n\t\tthis.onOpen = options.onOpen;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tthis.selection = summarizePluginSelectionV1(options.selection);\n\t\tthis.catalog = summarizePluginCatalogV1(options.catalog);\n\t\tthis.uiProfile = options.snapshot?.profiles.find((profile) => profile.profileId === this.profileId);\n\t}\n\n\tprivate hasHostEntry(): boolean {\n\t\treturn this.store !== undefined || this.controller !== undefined || this.onOpen !== undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this.hasHostEntry()) {\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"dim\", ` ${t(\"Plugins: unsupported (host selection entry not injected)\")}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tif (this._focused && this.uiProfile !== undefined) {\n\t\t\tconst lines = [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.bold(` ${t(\"Plugins · {profile}\", { profile: this.uiProfile.profileId })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t\tfor (const [index, plugin] of this.uiProfile.plugins.entries()) {\n\t\t\t\tconst cursor = index === this.uiPluginIndex ? \">\" : \" \";\n\t\t\t\tconst state = plugin.state === \"selected\" ? \"on\" : plugin.state === \"disabled\" ? \"off\" : \"available\";\n\t\t\t\tconst availability = plugin.availability === \"ready\" ? \"ready\" : \"unavailable\";\n\t\t\t\tlines.push(truncateToWidth(` ${cursor} [${state}] ${plugin.pluginId} (${availability})`, width, \"...\"));\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Enter/Space toggle · Esc close\")}`), width, \"...\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selectionText = this.selection.present\n\t\t\t? t(\"selected {selected}, disabled {disabled}\", {\n\t\t\t\t\tselected: this.selection.selectedCount,\n\t\t\t\t\tdisabled: this.selection.disabledCount,\n\t\t\t\t}) + (this.selection.truncated ? t(\", bounded\") : \"\")\n\t\t\t: this.store === undefined\n\t\t\t\t? t(\"selection pending\")\n\t\t\t\t: t(\"selection not loaded\");\n\t\tconst catalogText = this.catalog.present\n\t\t\t? t(\"catalog {count} ({ready} ready, {unavailable} unavailable)\", {\n\t\t\t\t\tcount: this.catalog.entryCount,\n\t\t\t\t\tready: this.catalog.readyCount,\n\t\t\t\t\tunavailable: this.catalog.unavailableCount,\n\t\t\t\t}) + (this.catalog.truncated ? t(\", bounded\") : \"\")\n\t\t\t: t(\"catalog unavailable\");\n\t\tconst suffix = this.onOpen === undefined ? t(\"host store\") : t(\"open via host callback\");\n\t\treturn [\n\t\t\ttruncateToWidth(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t` ${t(\"Plugins: profile {profile} · {selection} · {catalog} · {suffix}\", {\n\t\t\t\t\t\tprofile: this.profileId,\n\t\t\t\t\t\tselection: selectionText,\n\t\t\t\t\t\tcatalog: catalogText,\n\t\t\t\t\t\tsuffix,\n\t\t\t\t\t})}`,\n\t\t\t\t),\n\t\t\t\twidth,\n\t\t\t\t\"...\",\n\t\t\t),\n\t\t];\n\t}\n\n\tprivate setUiSnapshot(result: PluginSelectionControllerResultV1): void {\n\t\tif (result.status !== \"ok\") return;\n\t\tthis.uiProfile = result.snapshot.profiles.find((profile) => profile.profileId === this.profileId);\n\t\tif (this.uiProfile !== undefined) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiPluginIndex, Math.max(0, this.uiProfile.plugins.length - 1));\n\t\t}\n\t}\n\n\tprivate currentUiPlugin(): PluginSelectionUiPluginV1 | undefined {\n\t\treturn this.uiProfile?.plugins[this.uiPluginIndex];\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused || this.uiProfile === undefined) return;\n\t\tconst keybindings = getKeybindings();\n\t\tif (keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.uiPluginIndex = Math.max(0, this.uiPluginIndex - 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiProfile.plugins.length - 1, this.uiPluginIndex + 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (!keybindings.matches(data, \"tui.select.confirm\") && data !== \" \") return;\n\t\tconst plugin = this.currentUiPlugin();\n\t\tif (\n\t\t\tplugin === undefined ||\n\t\t\tthis.controller === undefined ||\n\t\t\t(plugin.state === \"disabled\" && plugin.availability !== \"ready\")\n\t\t)\n\t\t\treturn;\n\t\tvoid this.controller\n\t\t\t.toggle({ profileId: this.profileId, pluginId: plugin.pluginId })\n\t\t\t.then((result) => {\n\t\t\t\tthis.setUiSnapshot(result);\n\t\t\t\tthis.requestRender?.();\n\t\t\t})\n\t\t\t.catch(() => this.requestRender?.());\n\t}\n\n\t/** Read the bounded selection DTO and invoke the host-owned entry callback. */\n\tasync openPluginSelection(): Promise<PluginSelectionEntryOpenResultV1> {\n\t\tlet controllerResult: PluginSelectionControllerResultV1 | undefined;\n\t\tif (this.controller !== undefined) {\n\t\t\tcontrollerResult = await this.controller.getSnapshot();\n\t\t\tthis.setUiSnapshot(controllerResult);\n\t\t}\n\t\tlet status: PluginSelectionEntryStatusV1 = this.hasHostEntry() ? \"ready\" : \"unsupported\";\n\t\tlet selection = this.selection;\n\t\tlet codes: readonly PluginSelectionStoreDiagnosticCodeV1[] = Object.freeze([]);\n\t\tif (controllerResult?.status === \"error\") {\n\t\t\tstatus = controllerResult.code === \"store-cancelled\" ? \"cancelled\" : \"invalid\";\n\t\t}\n\n\t\tif (this.store !== undefined) {\n\t\t\tconst result = await this.store.read();\n\t\t\tcodes = diagnosticCodes(result);\n\t\t\tif (result.status === \"ok\" || result.status === \"missing\") {\n\t\t\t\tconst storedSelection = selectionForProfile(result, this.profileId);\n\t\t\t\tselection = summarizePluginSelectionV1(storedSelection);\n\t\t\t\tstatus = result.status === \"ok\" ? \"ready\" : \"missing\";\n\t\t\t} else {\n\t\t\t\tselection = emptySelectionSummary();\n\t\t\t\tstatus = result.status;\n\t\t\t}\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tconst context: PluginSelectionOpenContextV1 = Object.freeze({\n\t\t\tprofileId: this.profileId,\n\t\t\tstatus,\n\t\t\tselection,\n\t\t\tcatalog: this.catalog,\n\t\t\tdiagnosticCodes: codes,\n\t\t});\n\t\tif (this.onOpen !== undefined) await this.onOpen(context);\n\t\treturn context;\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectionSummary(): PluginSelectionSummaryV1 {\n\t\treturn this.selection;\n\t}\n\n\tgetCatalogSummary(): PluginCatalogSummaryV1 {\n\t\treturn this.catalog;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"queue-manager-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/queue-manager-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAiD,MAAM,kBAAkB,CAAC;AAK5G,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAE7C,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wFAAwF;AACxF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC,+EAA+E;IAC/E,OAAO,IAAI,qBAAqB,CAAC;IACjC,uFAAuF;IACvF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzD,kFAAkF;IAClF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACpD,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAAC;CAChB;AASD;;;GAGG;AACH,cAAM,gBAAiB,YAAW,SAAS;IAC1C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,YAAY,QAAQ,EAAE,qBAAqB,EAAE,SAAS,EAAE,qBAAqB,EAG5E;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB9B;IAED,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyDjC;IAED,0EAA0E;IAC1E,OAAO,CAAC,aAAa;IAOrB,0DAA0D;IAC1D,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,WAAW;CAGnB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,SAAS;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IAExC,YAAY,QAAQ,EAAE,qBAAqB,EAAE,SAAS,EAAE,qBAAqB,EAwB5E;IAED,cAAc,IAAI,gBAAgB,CAEjC;CACD","sourcesContent":["import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\n/** Which queue an entry belongs to; mirrors the session's queue names. */\nexport type QueueName = \"steer\" | \"followUp\";\n\n/** One row in the manager: the owning queue plus the queued text. */\nexport interface QueuedMessageEntry {\n\tqueue: QueueName;\n\ttext: string;\n}\n\n/** Queue snapshot shape the component consumes (same shape as the facade read view). */\nexport interface QueuedMessageSnapshot {\n\tsteering: string[];\n\tfollowUp: string[];\n}\n\n/**\n * Host surface the queue manager consumes. The component never touches the\n * facade: every mutation goes through these callbacks, so tests inject plain\n * functions and the host owns facade forwarding and the editor restore.\n */\nexport interface QueueManagerCallbacks {\n\t/** Re-read both queues after an operation; the component rebuilds its rows. */\n\trefresh(): QueuedMessageSnapshot;\n\t/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */\n\tonReorder(queue: QueueName, from: number, to: number): boolean;\n\t/** Remove the entry at group `index`; the removed text, or null when invalid. */\n\tonRemove(queue: QueueName, index: number): string | null;\n\t/** Remove the entry and put its text back into the editor; false when invalid. */\n\tonRestore(queue: QueueName, index: number): boolean;\n\t/** Close the manager (escape, restore, or both queues empty after a remove). */\n\tonClose(): void;\n}\n\nfunction flatten(snapshot: QueuedMessageSnapshot): QueuedMessageEntry[] {\n\treturn [\n\t\t...snapshot.steering.map((text): QueuedMessageEntry => ({ queue: \"steer\", text })),\n\t\t...snapshot.followUp.map((text): QueuedMessageEntry => ({ queue: \"followUp\", text })),\n\t];\n}\n\n/**\n * Flat queued-message list with selection, grouped steering-first. All key\n * handling goes through getKeybindings().matches — no hardcoded key values.\n */\nclass QueueManagerList implements Component {\n\tprivate entries: QueuedMessageEntry[] = [];\n\tprivate steeringCount = 0;\n\tprivate selectedIndex = 0;\n\tprivate readonly callbacks: QueueManagerCallbacks;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tthis.callbacks = callbacks;\n\t\tthis.applySnapshot(snapshot);\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tif (this.entries.length === 0) return lines;\n\n\t\tif (this.steeringCount > 0) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Steering\")}`));\n\t\t}\n\t\tfor (let i = 0; i < this.entries.length; i++) {\n\t\t\tconst entry = this.entries[i];\n\t\t\tconst opensFollowUpGroup = entry.queue === \"followUp\" && (i === 0 || this.entries[i - 1]?.queue === \"steer\");\n\t\t\tif (opensFollowUpGroup) {\n\t\t\t\tif (i > 0) lines.push(\"\");\n\t\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Follow-up\")}`));\n\t\t\t}\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\t\t\tconst normalized = entry.text.replace(/\\n/g, \" \").trim();\n\t\t\tconst truncated = truncateToWidth(normalized, width - 2);\n\t\t\tlines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));\n\t\t}\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up/down move the selection across the flat list, wrapping at the ends\n\t\t// (same semantics as UserMessageList).\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst moveUp = kb.matches(keyData, \"app.queue.moveUp\");\n\t\tconst moveDown = kb.matches(keyData, \"app.queue.moveDown\");\n\t\tif (moveUp || moveDown) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tconst target = index + (moveUp ? -1 : 1);\n\t\t\t// Reorder stays inside the selected entry's group (bounds guard\n\t\t\t// mirrors the scoped-models selector); the facade stays the final\n\t\t\t// authority — a stale snapshot returns false and nothing moves.\n\t\t\tif (target < 0 || target >= this.groupLength(queue)) return;\n\t\t\tif (this.callbacks.onReorder(queue, index, target)) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.queue.remove\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRemove(queue, index) !== null) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\t\t\tif (this.entries.length === 0) this.callbacks.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRestore(queue, index)) this.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** Rebuild rows from a fresh snapshot; steering entries stay in front. */\n\tprivate applySnapshot(snapshot: QueuedMessageSnapshot): void {\n\t\tthis.entries = flatten(snapshot);\n\t\tthis.steeringCount = snapshot.steering.length;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\tif (this.selectedIndex < 0) this.selectedIndex = 0;\n\t}\n\n\t/** Group and within-group index of the selected entry. */\n\tprivate selectedLocation(): { queue: QueueName; index: number | undefined } {\n\t\tconst entry = this.entries[this.selectedIndex];\n\t\tif (!entry) return { queue: \"steer\", index: undefined };\n\t\treturn {\n\t\t\tqueue: entry.queue,\n\t\t\tindex: entry.queue === \"steer\" ? this.selectedIndex : this.selectedIndex - this.steeringCount,\n\t\t};\n\t}\n\n\tprivate groupLength(queue: QueueName): number {\n\t\treturn this.entries.filter((entry) => entry.queue === queue).length;\n\t}\n}\n\n/**\n * Component that renders the queued-message manager (/queue-list): grouped\n * steering/follow-up entries with reorder, remove, and restore actions.\n */\nexport class QueueManagerSelectorComponent extends Container {\n\tprivate readonly list: QueueManagerList;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tsuper();\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.bold(t(\"Queued Messages\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.list = new QueueManagerList(snapshot, callbacks);\n\t\tthis.addChild(this.list);\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", t(\"alt+up/alt+down move · delete remove · enter restore · esc close\")), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Auto-close when mounted with both queues empty (the host gates the\n\t\t// open on non-empty queues; this covers the queue draining in between).\n\t\tif (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {\n\t\t\tsetTimeout(() => callbacks.onClose(), 100);\n\t\t}\n\t}\n\n\tgetMessageList(): QueueManagerList {\n\t\treturn this.list;\n\t}\n}\n"]}
1
+ {"version":3,"file":"queue-manager-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/queue-manager-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAiD,MAAM,kBAAkB,CAAC;AAK5G,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAE7C,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wFAAwF;AACxF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC,+EAA+E;IAC/E,OAAO,IAAI,qBAAqB,CAAC;IACjC,uFAAuF;IACvF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzD,kFAAkF;IAClF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACpD,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAAC;CAChB;AASD;;;GAGG;AACH,cAAM,gBAAiB,YAAW,SAAS;IAC1C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,YAAY,QAAQ,EAAE,qBAAqB,EAAE,SAAS,EAAE,qBAAqB,EAG5E;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB9B;IAED,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyDjC;IAED,0EAA0E;IAC1E,OAAO,CAAC,aAAa;IAOrB,0DAA0D;IAC1D,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,WAAW;CAGnB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,SAAS;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IAExC,YAAY,QAAQ,EAAE,qBAAqB,EAAE,SAAS,EAAE,qBAAqB,EAwB5E;IAED,cAAc,IAAI,gBAAgB,CAEjC;CACD","sourcesContent":["import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../../../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\n/** Which queue an entry belongs to; mirrors the session's queue names. */\nexport type QueueName = \"steer\" | \"followUp\";\n\n/** One row in the manager: the owning queue plus the queued text. */\nexport interface QueuedMessageEntry {\n\tqueue: QueueName;\n\ttext: string;\n}\n\n/** Queue snapshot shape the component consumes (same shape as the facade read view). */\nexport interface QueuedMessageSnapshot {\n\tsteering: string[];\n\tfollowUp: string[];\n}\n\n/**\n * Host surface the queue manager consumes. The component never touches the\n * facade: every mutation goes through these callbacks, so tests inject plain\n * functions and the host owns facade forwarding and the editor restore.\n */\nexport interface QueueManagerCallbacks {\n\t/** Re-read both queues after an operation; the component rebuilds its rows. */\n\trefresh(): QueuedMessageSnapshot;\n\t/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */\n\tonReorder(queue: QueueName, from: number, to: number): boolean;\n\t/** Remove the entry at group `index`; the removed text, or null when invalid. */\n\tonRemove(queue: QueueName, index: number): string | null;\n\t/** Remove the entry and put its text back into the editor; false when invalid. */\n\tonRestore(queue: QueueName, index: number): boolean;\n\t/** Close the manager (escape, restore, or both queues empty after a remove). */\n\tonClose(): void;\n}\n\nfunction flatten(snapshot: QueuedMessageSnapshot): QueuedMessageEntry[] {\n\treturn [\n\t\t...snapshot.steering.map((text): QueuedMessageEntry => ({ queue: \"steer\", text })),\n\t\t...snapshot.followUp.map((text): QueuedMessageEntry => ({ queue: \"followUp\", text })),\n\t];\n}\n\n/**\n * Flat queued-message list with selection, grouped steering-first. All key\n * handling goes through getKeybindings().matches — no hardcoded key values.\n */\nclass QueueManagerList implements Component {\n\tprivate entries: QueuedMessageEntry[] = [];\n\tprivate steeringCount = 0;\n\tprivate selectedIndex = 0;\n\tprivate readonly callbacks: QueueManagerCallbacks;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tthis.callbacks = callbacks;\n\t\tthis.applySnapshot(snapshot);\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tif (this.entries.length === 0) return lines;\n\n\t\tif (this.steeringCount > 0) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Steering\")}`));\n\t\t}\n\t\tfor (let i = 0; i < this.entries.length; i++) {\n\t\t\tconst entry = this.entries[i];\n\t\t\tconst opensFollowUpGroup = entry.queue === \"followUp\" && (i === 0 || this.entries[i - 1]?.queue === \"steer\");\n\t\t\tif (opensFollowUpGroup) {\n\t\t\t\tif (i > 0) lines.push(\"\");\n\t\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Follow-up\")}`));\n\t\t\t}\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\t\t\tconst normalized = entry.text.replace(/\\n/g, \" \").trim();\n\t\t\tconst truncated = truncateToWidth(normalized, width - 2);\n\t\t\tlines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));\n\t\t}\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up/down move the selection across the flat list, wrapping at the ends\n\t\t// (same semantics as UserMessageList).\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst moveUp = kb.matches(keyData, \"app.queue.moveUp\");\n\t\tconst moveDown = kb.matches(keyData, \"app.queue.moveDown\");\n\t\tif (moveUp || moveDown) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tconst target = index + (moveUp ? -1 : 1);\n\t\t\t// Reorder stays inside the selected entry's group (bounds guard\n\t\t\t// mirrors the scoped-models selector); the facade stays the final\n\t\t\t// authority — a stale snapshot returns false and nothing moves.\n\t\t\tif (target < 0 || target >= this.groupLength(queue)) return;\n\t\t\tif (this.callbacks.onReorder(queue, index, target)) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.queue.remove\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRemove(queue, index) !== null) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\t\t\tif (this.entries.length === 0) this.callbacks.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRestore(queue, index)) this.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** Rebuild rows from a fresh snapshot; steering entries stay in front. */\n\tprivate applySnapshot(snapshot: QueuedMessageSnapshot): void {\n\t\tthis.entries = flatten(snapshot);\n\t\tthis.steeringCount = snapshot.steering.length;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\tif (this.selectedIndex < 0) this.selectedIndex = 0;\n\t}\n\n\t/** Group and within-group index of the selected entry. */\n\tprivate selectedLocation(): { queue: QueueName; index: number | undefined } {\n\t\tconst entry = this.entries[this.selectedIndex];\n\t\tif (!entry) return { queue: \"steer\", index: undefined };\n\t\treturn {\n\t\t\tqueue: entry.queue,\n\t\t\tindex: entry.queue === \"steer\" ? this.selectedIndex : this.selectedIndex - this.steeringCount,\n\t\t};\n\t}\n\n\tprivate groupLength(queue: QueueName): number {\n\t\treturn this.entries.filter((entry) => entry.queue === queue).length;\n\t}\n}\n\n/**\n * Component that renders the queued-message manager (/queue-list): grouped\n * steering/follow-up entries with reorder, remove, and restore actions.\n */\nexport class QueueManagerSelectorComponent extends Container {\n\tprivate readonly list: QueueManagerList;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tsuper();\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.bold(t(\"Queued Messages\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.list = new QueueManagerList(snapshot, callbacks);\n\t\tthis.addChild(this.list);\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", t(\"alt+up/alt+down move · delete remove · enter restore · esc close\")), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Auto-close when mounted with both queues empty (the host gates the\n\t\t// open on non-empty queues; this covers the queue draining in between).\n\t\tif (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {\n\t\t\tsetTimeout(() => callbacks.onClose(), 100);\n\t\t}\n\t}\n\n\tgetMessageList(): QueueManagerList {\n\t\treturn this.list;\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { Container, getKeybindings, Spacer, Text, truncateToWidth } from "@agent-forge/tui";
2
2
  import { t } from "../../../core/i18n/index.js";
3
- import { theme } from "../theme/theme.js";
3
+ import { theme } from "../../../theme/theme.js";
4
4
  import { DynamicBorder } from "./dynamic-border.js";
5
5
  function flatten(snapshot) {
6
6
  return [
@@ -1 +1 @@
1
- {"version":3,"file":"queue-manager-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/queue-manager-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\n/** Which queue an entry belongs to; mirrors the session's queue names. */\nexport type QueueName = \"steer\" | \"followUp\";\n\n/** One row in the manager: the owning queue plus the queued text. */\nexport interface QueuedMessageEntry {\n\tqueue: QueueName;\n\ttext: string;\n}\n\n/** Queue snapshot shape the component consumes (same shape as the facade read view). */\nexport interface QueuedMessageSnapshot {\n\tsteering: string[];\n\tfollowUp: string[];\n}\n\n/**\n * Host surface the queue manager consumes. The component never touches the\n * facade: every mutation goes through these callbacks, so tests inject plain\n * functions and the host owns facade forwarding and the editor restore.\n */\nexport interface QueueManagerCallbacks {\n\t/** Re-read both queues after an operation; the component rebuilds its rows. */\n\trefresh(): QueuedMessageSnapshot;\n\t/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */\n\tonReorder(queue: QueueName, from: number, to: number): boolean;\n\t/** Remove the entry at group `index`; the removed text, or null when invalid. */\n\tonRemove(queue: QueueName, index: number): string | null;\n\t/** Remove the entry and put its text back into the editor; false when invalid. */\n\tonRestore(queue: QueueName, index: number): boolean;\n\t/** Close the manager (escape, restore, or both queues empty after a remove). */\n\tonClose(): void;\n}\n\nfunction flatten(snapshot: QueuedMessageSnapshot): QueuedMessageEntry[] {\n\treturn [\n\t\t...snapshot.steering.map((text): QueuedMessageEntry => ({ queue: \"steer\", text })),\n\t\t...snapshot.followUp.map((text): QueuedMessageEntry => ({ queue: \"followUp\", text })),\n\t];\n}\n\n/**\n * Flat queued-message list with selection, grouped steering-first. All key\n * handling goes through getKeybindings().matches — no hardcoded key values.\n */\nclass QueueManagerList implements Component {\n\tprivate entries: QueuedMessageEntry[] = [];\n\tprivate steeringCount = 0;\n\tprivate selectedIndex = 0;\n\tprivate readonly callbacks: QueueManagerCallbacks;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tthis.callbacks = callbacks;\n\t\tthis.applySnapshot(snapshot);\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tif (this.entries.length === 0) return lines;\n\n\t\tif (this.steeringCount > 0) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Steering\")}`));\n\t\t}\n\t\tfor (let i = 0; i < this.entries.length; i++) {\n\t\t\tconst entry = this.entries[i];\n\t\t\tconst opensFollowUpGroup = entry.queue === \"followUp\" && (i === 0 || this.entries[i - 1]?.queue === \"steer\");\n\t\t\tif (opensFollowUpGroup) {\n\t\t\t\tif (i > 0) lines.push(\"\");\n\t\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Follow-up\")}`));\n\t\t\t}\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\t\t\tconst normalized = entry.text.replace(/\\n/g, \" \").trim();\n\t\t\tconst truncated = truncateToWidth(normalized, width - 2);\n\t\t\tlines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));\n\t\t}\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up/down move the selection across the flat list, wrapping at the ends\n\t\t// (same semantics as UserMessageList).\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst moveUp = kb.matches(keyData, \"app.queue.moveUp\");\n\t\tconst moveDown = kb.matches(keyData, \"app.queue.moveDown\");\n\t\tif (moveUp || moveDown) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tconst target = index + (moveUp ? -1 : 1);\n\t\t\t// Reorder stays inside the selected entry's group (bounds guard\n\t\t\t// mirrors the scoped-models selector); the facade stays the final\n\t\t\t// authority — a stale snapshot returns false and nothing moves.\n\t\t\tif (target < 0 || target >= this.groupLength(queue)) return;\n\t\t\tif (this.callbacks.onReorder(queue, index, target)) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.queue.remove\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRemove(queue, index) !== null) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\t\t\tif (this.entries.length === 0) this.callbacks.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRestore(queue, index)) this.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** Rebuild rows from a fresh snapshot; steering entries stay in front. */\n\tprivate applySnapshot(snapshot: QueuedMessageSnapshot): void {\n\t\tthis.entries = flatten(snapshot);\n\t\tthis.steeringCount = snapshot.steering.length;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\tif (this.selectedIndex < 0) this.selectedIndex = 0;\n\t}\n\n\t/** Group and within-group index of the selected entry. */\n\tprivate selectedLocation(): { queue: QueueName; index: number | undefined } {\n\t\tconst entry = this.entries[this.selectedIndex];\n\t\tif (!entry) return { queue: \"steer\", index: undefined };\n\t\treturn {\n\t\t\tqueue: entry.queue,\n\t\t\tindex: entry.queue === \"steer\" ? this.selectedIndex : this.selectedIndex - this.steeringCount,\n\t\t};\n\t}\n\n\tprivate groupLength(queue: QueueName): number {\n\t\treturn this.entries.filter((entry) => entry.queue === queue).length;\n\t}\n}\n\n/**\n * Component that renders the queued-message manager (/queue-list): grouped\n * steering/follow-up entries with reorder, remove, and restore actions.\n */\nexport class QueueManagerSelectorComponent extends Container {\n\tprivate readonly list: QueueManagerList;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tsuper();\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.bold(t(\"Queued Messages\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.list = new QueueManagerList(snapshot, callbacks);\n\t\tthis.addChild(this.list);\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", t(\"alt+up/alt+down move · delete remove · enter restore · esc close\")), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Auto-close when mounted with both queues empty (the host gates the\n\t\t// open on non-empty queues; this covers the queue draining in between).\n\t\tif (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {\n\t\t\tsetTimeout(() => callbacks.onClose(), 100);\n\t\t}\n\t}\n\n\tgetMessageList(): QueueManagerList {\n\t\treturn this.list;\n\t}\n}\n"]}
1
+ {"version":3,"file":"queue-manager-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/queue-manager-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../../../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\n/** Which queue an entry belongs to; mirrors the session's queue names. */\nexport type QueueName = \"steer\" | \"followUp\";\n\n/** One row in the manager: the owning queue plus the queued text. */\nexport interface QueuedMessageEntry {\n\tqueue: QueueName;\n\ttext: string;\n}\n\n/** Queue snapshot shape the component consumes (same shape as the facade read view). */\nexport interface QueuedMessageSnapshot {\n\tsteering: string[];\n\tfollowUp: string[];\n}\n\n/**\n * Host surface the queue manager consumes. The component never touches the\n * facade: every mutation goes through these callbacks, so tests inject plain\n * functions and the host owns facade forwarding and the editor restore.\n */\nexport interface QueueManagerCallbacks {\n\t/** Re-read both queues after an operation; the component rebuilds its rows. */\n\trefresh(): QueuedMessageSnapshot;\n\t/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */\n\tonReorder(queue: QueueName, from: number, to: number): boolean;\n\t/** Remove the entry at group `index`; the removed text, or null when invalid. */\n\tonRemove(queue: QueueName, index: number): string | null;\n\t/** Remove the entry and put its text back into the editor; false when invalid. */\n\tonRestore(queue: QueueName, index: number): boolean;\n\t/** Close the manager (escape, restore, or both queues empty after a remove). */\n\tonClose(): void;\n}\n\nfunction flatten(snapshot: QueuedMessageSnapshot): QueuedMessageEntry[] {\n\treturn [\n\t\t...snapshot.steering.map((text): QueuedMessageEntry => ({ queue: \"steer\", text })),\n\t\t...snapshot.followUp.map((text): QueuedMessageEntry => ({ queue: \"followUp\", text })),\n\t];\n}\n\n/**\n * Flat queued-message list with selection, grouped steering-first. All key\n * handling goes through getKeybindings().matches — no hardcoded key values.\n */\nclass QueueManagerList implements Component {\n\tprivate entries: QueuedMessageEntry[] = [];\n\tprivate steeringCount = 0;\n\tprivate selectedIndex = 0;\n\tprivate readonly callbacks: QueueManagerCallbacks;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tthis.callbacks = callbacks;\n\t\tthis.applySnapshot(snapshot);\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tif (this.entries.length === 0) return lines;\n\n\t\tif (this.steeringCount > 0) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Steering\")}`));\n\t\t}\n\t\tfor (let i = 0; i < this.entries.length; i++) {\n\t\t\tconst entry = this.entries[i];\n\t\t\tconst opensFollowUpGroup = entry.queue === \"followUp\" && (i === 0 || this.entries[i - 1]?.queue === \"steer\");\n\t\t\tif (opensFollowUpGroup) {\n\t\t\t\tif (i > 0) lines.push(\"\");\n\t\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Follow-up\")}`));\n\t\t\t}\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\t\t\tconst normalized = entry.text.replace(/\\n/g, \" \").trim();\n\t\t\tconst truncated = truncateToWidth(normalized, width - 2);\n\t\t\tlines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));\n\t\t}\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up/down move the selection across the flat list, wrapping at the ends\n\t\t// (same semantics as UserMessageList).\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst moveUp = kb.matches(keyData, \"app.queue.moveUp\");\n\t\tconst moveDown = kb.matches(keyData, \"app.queue.moveDown\");\n\t\tif (moveUp || moveDown) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tconst target = index + (moveUp ? -1 : 1);\n\t\t\t// Reorder stays inside the selected entry's group (bounds guard\n\t\t\t// mirrors the scoped-models selector); the facade stays the final\n\t\t\t// authority — a stale snapshot returns false and nothing moves.\n\t\t\tif (target < 0 || target >= this.groupLength(queue)) return;\n\t\t\tif (this.callbacks.onReorder(queue, index, target)) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.queue.remove\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRemove(queue, index) !== null) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\t\t\tif (this.entries.length === 0) this.callbacks.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRestore(queue, index)) this.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** Rebuild rows from a fresh snapshot; steering entries stay in front. */\n\tprivate applySnapshot(snapshot: QueuedMessageSnapshot): void {\n\t\tthis.entries = flatten(snapshot);\n\t\tthis.steeringCount = snapshot.steering.length;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\tif (this.selectedIndex < 0) this.selectedIndex = 0;\n\t}\n\n\t/** Group and within-group index of the selected entry. */\n\tprivate selectedLocation(): { queue: QueueName; index: number | undefined } {\n\t\tconst entry = this.entries[this.selectedIndex];\n\t\tif (!entry) return { queue: \"steer\", index: undefined };\n\t\treturn {\n\t\t\tqueue: entry.queue,\n\t\t\tindex: entry.queue === \"steer\" ? this.selectedIndex : this.selectedIndex - this.steeringCount,\n\t\t};\n\t}\n\n\tprivate groupLength(queue: QueueName): number {\n\t\treturn this.entries.filter((entry) => entry.queue === queue).length;\n\t}\n}\n\n/**\n * Component that renders the queued-message manager (/queue-list): grouped\n * steering/follow-up entries with reorder, remove, and restore actions.\n */\nexport class QueueManagerSelectorComponent extends Container {\n\tprivate readonly list: QueueManagerList;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tsuper();\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.bold(t(\"Queued Messages\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.list = new QueueManagerList(snapshot, callbacks);\n\t\tthis.addChild(this.list);\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", t(\"alt+up/alt+down move · delete remove · enter restore · esc close\")), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Auto-close when mounted with both queues empty (the host gates the\n\t\t// open on non-empty queues; this covers the queue draining in between).\n\t\tif (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {\n\t\t\tsetTimeout(() => callbacks.onClose(), 100);\n\t\t}\n\t}\n\n\tgetMessageList(): QueueManagerList {\n\t\treturn this.list;\n\t}\n}\n"]}
@@ -6,7 +6,7 @@
6
6
  import type { Component } from "@agent-forge/tui";
7
7
  import type { CustomMessage } from "../../../core/messages.ts";
8
8
  import type { CustomEntry } from "../../../core/session-manager.ts";
9
- import type { Theme } from "../theme/theme.ts";
9
+ import type { Theme } from "../../../theme/theme.ts";
10
10
  export interface MessageRenderOptions {
11
11
  expanded: boolean;
12
12
  /** Horizontal padding configured by the outputPad setting. */
@@ -1 +1 @@
1
- {"version":3,"file":"render-types.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/render-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACxC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,oBAAoB,CAAC;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,KAAK,MAAM,CAAC;AAElG,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,OAAO,IAAI,CAC1C,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,KAAK,KACR,SAAS,GAAG,SAAS,CAAC;AAE3B,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,CACxC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EACrB,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,KAAK,KACR,SAAS,GAAG,SAAS,CAAC","sourcesContent":["/**\n * Message/entry rendering contracts for the interactive transcript (D-052:\n * TUI domain). These describe how the interactive mode renders custom messages\n * and entries; producers are the TUI itself (mermaid) and hosts, not plugins.\n */\n\nimport type { Component } from \"@agent-forge/tui\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport type { CustomEntry } from \"../../../core/session-manager.ts\";\nimport type { Theme } from \"../theme/theme.ts\";\n\nexport interface MessageRenderOptions {\n\texpanded: boolean;\n\t/** Horizontal padding configured by the outputPad setting. */\n\toutputPad: number;\n}\n\nexport interface MarkdownTransformContext {\n\tmessageType: \"user\" | \"assistant\" | \"assistant-thinking\";\n\tisStreaming: boolean;\n\tavailableWidth: number;\n}\n\nexport type MarkdownTransformer = (markdown: string, context: MarkdownTransformContext) => string;\n\nexport interface EntryRenderOptions {\n\texpanded: boolean;\n}\n\nexport type MessageRenderer<T = unknown> = (\n\tmessage: CustomMessage<T>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n\nexport type EntryRenderer<T = unknown> = (\n\tentry: CustomEntry<T>,\n\toptions: EntryRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n"]}
1
+ {"version":3,"file":"render-types.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/render-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACxC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,oBAAoB,CAAC;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,KAAK,MAAM,CAAC;AAElG,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,OAAO,IAAI,CAC1C,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,KAAK,KACR,SAAS,GAAG,SAAS,CAAC;AAE3B,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,CACxC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EACrB,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,KAAK,KACR,SAAS,GAAG,SAAS,CAAC","sourcesContent":["/**\n * Message/entry rendering contracts for the interactive transcript (D-052:\n * TUI domain). These describe how the interactive mode renders custom messages\n * and entries; producers are the TUI itself (mermaid) and hosts, not plugins.\n */\n\nimport type { Component } from \"@agent-forge/tui\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport type { CustomEntry } from \"../../../core/session-manager.ts\";\nimport type { Theme } from \"../../../theme/theme.ts\";\n\nexport interface MessageRenderOptions {\n\texpanded: boolean;\n\t/** Horizontal padding configured by the outputPad setting. */\n\toutputPad: number;\n}\n\nexport interface MarkdownTransformContext {\n\tmessageType: \"user\" | \"assistant\" | \"assistant-thinking\";\n\tisStreaming: boolean;\n\tavailableWidth: number;\n}\n\nexport type MarkdownTransformer = (markdown: string, context: MarkdownTransformContext) => string;\n\nexport interface EntryRenderOptions {\n\texpanded: boolean;\n}\n\nexport type MessageRenderer<T = unknown> = (\n\tmessage: CustomMessage<T>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n\nexport type EntryRenderer<T = unknown> = (\n\tentry: CustomEntry<T>,\n\toptions: EntryRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"render-types.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/render-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/**\n * Message/entry rendering contracts for the interactive transcript (D-052:\n * TUI domain). These describe how the interactive mode renders custom messages\n * and entries; producers are the TUI itself (mermaid) and hosts, not plugins.\n */\n\nimport type { Component } from \"@agent-forge/tui\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport type { CustomEntry } from \"../../../core/session-manager.ts\";\nimport type { Theme } from \"../theme/theme.ts\";\n\nexport interface MessageRenderOptions {\n\texpanded: boolean;\n\t/** Horizontal padding configured by the outputPad setting. */\n\toutputPad: number;\n}\n\nexport interface MarkdownTransformContext {\n\tmessageType: \"user\" | \"assistant\" | \"assistant-thinking\";\n\tisStreaming: boolean;\n\tavailableWidth: number;\n}\n\nexport type MarkdownTransformer = (markdown: string, context: MarkdownTransformContext) => string;\n\nexport interface EntryRenderOptions {\n\texpanded: boolean;\n}\n\nexport type MessageRenderer<T = unknown> = (\n\tmessage: CustomMessage<T>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n\nexport type EntryRenderer<T = unknown> = (\n\tentry: CustomEntry<T>,\n\toptions: EntryRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n"]}
1
+ {"version":3,"file":"render-types.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/render-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/**\n * Message/entry rendering contracts for the interactive transcript (D-052:\n * TUI domain). These describe how the interactive mode renders custom messages\n * and entries; producers are the TUI itself (mermaid) and hosts, not plugins.\n */\n\nimport type { Component } from \"@agent-forge/tui\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport type { CustomEntry } from \"../../../core/session-manager.ts\";\nimport type { Theme } from \"../../../theme/theme.ts\";\n\nexport interface MessageRenderOptions {\n\texpanded: boolean;\n\t/** Horizontal padding configured by the outputPad setting. */\n\toutputPad: number;\n}\n\nexport interface MarkdownTransformContext {\n\tmessageType: \"user\" | \"assistant\" | \"assistant-thinking\";\n\tisStreaming: boolean;\n\tavailableWidth: number;\n}\n\nexport type MarkdownTransformer = (markdown: string, context: MarkdownTransformContext) => string;\n\nexport interface EntryRenderOptions {\n\texpanded: boolean;\n}\n\nexport type MessageRenderer<T = unknown> = (\n\tmessage: CustomMessage<T>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n\nexport type EntryRenderer<T = unknown> = (\n\tentry: CustomEntry<T>,\n\toptions: EntryRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n"]}