@caupulican/pi-adaptative 0.81.40 → 0.81.41

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 (406) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +1 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +1 -0
  6. package/dist/cli/args.d.ts +2 -0
  7. package/dist/cli/args.d.ts.map +1 -1
  8. package/dist/cli/args.js +22 -1
  9. package/dist/cli/args.js.map +1 -1
  10. package/dist/core/agent-paths.d.ts +6 -0
  11. package/dist/core/agent-paths.d.ts.map +1 -1
  12. package/dist/core/agent-paths.js +12 -0
  13. package/dist/core/agent-paths.js.map +1 -1
  14. package/dist/core/agent-session-contracts.d.ts +293 -0
  15. package/dist/core/agent-session-contracts.d.ts.map +1 -0
  16. package/dist/core/agent-session-contracts.js +26 -0
  17. package/dist/core/agent-session-contracts.js.map +1 -0
  18. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  19. package/dist/core/agent-session-runtime.js +3 -0
  20. package/dist/core/agent-session-runtime.js.map +1 -1
  21. package/dist/core/agent-session.d.ts +26 -405
  22. package/dist/core/agent-session.d.ts.map +1 -1
  23. package/dist/core/agent-session.js +86 -307
  24. package/dist/core/agent-session.js.map +1 -1
  25. package/dist/core/auth-storage.d.ts.map +1 -1
  26. package/dist/core/auth-storage.js +3 -1
  27. package/dist/core/auth-storage.js.map +1 -1
  28. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  29. package/dist/core/autonomy/lane-tool-surface.js +2 -1
  30. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  31. package/dist/core/background-lane-controller.d.ts +3 -1
  32. package/dist/core/background-lane-controller.d.ts.map +1 -1
  33. package/dist/core/background-lane-controller.js +1 -0
  34. package/dist/core/background-lane-controller.js.map +1 -1
  35. package/dist/core/bedrock-sso-login.d.ts +16 -0
  36. package/dist/core/bedrock-sso-login.d.ts.map +1 -0
  37. package/dist/core/bedrock-sso-login.js +98 -0
  38. package/dist/core/bedrock-sso-login.js.map +1 -0
  39. package/dist/core/compaction-controller.d.ts.map +1 -1
  40. package/dist/core/compaction-controller.js +1 -1
  41. package/dist/core/compaction-controller.js.map +1 -1
  42. package/dist/core/compaction-support.d.ts +3 -8
  43. package/dist/core/compaction-support.d.ts.map +1 -1
  44. package/dist/core/compaction-support.js +3 -3
  45. package/dist/core/compaction-support.js.map +1 -1
  46. package/dist/core/context-pipeline.d.ts +1 -1
  47. package/dist/core/context-pipeline.d.ts.map +1 -1
  48. package/dist/core/context-pipeline.js +7 -33
  49. package/dist/core/context-pipeline.js.map +1 -1
  50. package/dist/core/cost/cost-summary.d.ts.map +1 -1
  51. package/dist/core/cost/cost-summary.js +5 -3
  52. package/dist/core/cost/cost-summary.js.map +1 -1
  53. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  54. package/dist/core/cost/daily-usage.js +4 -5
  55. package/dist/core/cost/daily-usage.js.map +1 -1
  56. package/dist/core/default-tool-surface.d.ts.map +1 -1
  57. package/dist/core/default-tool-surface.js +1 -0
  58. package/dist/core/default-tool-surface.js.map +1 -1
  59. package/dist/core/extension-import-authority.d.ts +6 -0
  60. package/dist/core/extension-import-authority.d.ts.map +1 -0
  61. package/dist/core/extension-import-authority.js +10 -0
  62. package/dist/core/extension-import-authority.js.map +1 -0
  63. package/dist/core/extensions/loader.d.ts.map +1 -1
  64. package/dist/core/extensions/loader.js +2 -3
  65. package/dist/core/extensions/loader.js.map +1 -1
  66. package/dist/core/extensions/runner.d.ts +3 -0
  67. package/dist/core/extensions/runner.d.ts.map +1 -1
  68. package/dist/core/extensions/runner.js +14 -5
  69. package/dist/core/extensions/runner.js.map +1 -1
  70. package/dist/core/extensions/stale-context.d.ts +2 -0
  71. package/dist/core/extensions/stale-context.d.ts.map +1 -0
  72. package/dist/core/extensions/stale-context.js +2 -0
  73. package/dist/core/extensions/stale-context.js.map +1 -0
  74. package/dist/core/extensions/types.d.ts +8 -0
  75. package/dist/core/extensions/types.d.ts.map +1 -1
  76. package/dist/core/extensions/types.js.map +1 -1
  77. package/dist/core/foreground-recovery-controller.d.ts +1 -0
  78. package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
  79. package/dist/core/foreground-recovery-controller.js +13 -13
  80. package/dist/core/foreground-recovery-controller.js.map +1 -1
  81. package/dist/core/goal-loop-controller.d.ts +14 -9
  82. package/dist/core/goal-loop-controller.d.ts.map +1 -1
  83. package/dist/core/goal-loop-controller.js +47 -75
  84. package/dist/core/goal-loop-controller.js.map +1 -1
  85. package/dist/core/goals/compact-goal-context.d.ts +11 -0
  86. package/dist/core/goals/compact-goal-context.d.ts.map +1 -0
  87. package/dist/core/goals/compact-goal-context.js +59 -0
  88. package/dist/core/goals/compact-goal-context.js.map +1 -0
  89. package/dist/core/goals/goal-acceptance.d.ts.map +1 -1
  90. package/dist/core/goals/goal-acceptance.js +2 -0
  91. package/dist/core/goals/goal-acceptance.js.map +1 -1
  92. package/dist/core/goals/goal-auto-continue-controller.d.ts +2 -1
  93. package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
  94. package/dist/core/goals/goal-auto-continue-controller.js +5 -8
  95. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
  96. package/dist/core/goals/goal-continuation-controller.d.ts +2 -2
  97. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  98. package/dist/core/goals/goal-continuation-controller.js +42 -11
  99. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  100. package/dist/core/goals/goal-continuation-defaults.d.ts +4 -29
  101. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
  102. package/dist/core/goals/goal-continuation-defaults.js +4 -32
  103. package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
  104. package/dist/core/goals/goal-continuation-prompt.d.ts +8 -18
  105. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  106. package/dist/core/goals/goal-continuation-prompt.js +9 -179
  107. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  108. package/dist/core/goals/goal-lifecycle.d.ts +35 -12
  109. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
  110. package/dist/core/goals/goal-lifecycle.js +98 -13
  111. package/dist/core/goals/goal-lifecycle.js.map +1 -1
  112. package/dist/core/goals/goal-record.d.ts +17 -0
  113. package/dist/core/goals/goal-record.d.ts.map +1 -0
  114. package/dist/core/goals/goal-record.js +31 -0
  115. package/dist/core/goals/goal-record.js.map +1 -0
  116. package/dist/core/goals/goal-session-controller.d.ts +42 -0
  117. package/dist/core/goals/goal-session-controller.d.ts.map +1 -0
  118. package/dist/core/goals/goal-session-controller.js +128 -0
  119. package/dist/core/goals/goal-session-controller.js.map +1 -0
  120. package/dist/core/goals/goal-state.d.ts +45 -25
  121. package/dist/core/goals/goal-state.d.ts.map +1 -1
  122. package/dist/core/goals/goal-state.js +85 -15
  123. package/dist/core/goals/goal-state.js.map +1 -1
  124. package/dist/core/goals/goal-tool-core.d.ts +1 -4
  125. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  126. package/dist/core/goals/goal-tool-core.js +49 -34
  127. package/dist/core/goals/goal-tool-core.js.map +1 -1
  128. package/dist/core/goals/session-goal-state.d.ts +18 -8
  129. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  130. package/dist/core/goals/session-goal-state.js +134 -11
  131. package/dist/core/goals/session-goal-state.js.map +1 -1
  132. package/dist/core/human-input-controller.d.ts +47 -0
  133. package/dist/core/human-input-controller.d.ts.map +1 -0
  134. package/dist/core/human-input-controller.js +181 -0
  135. package/dist/core/human-input-controller.js.map +1 -0
  136. package/dist/core/local-runtime-controller.d.ts +1 -1
  137. package/dist/core/local-runtime-controller.d.ts.map +1 -1
  138. package/dist/core/local-runtime-controller.js.map +1 -1
  139. package/dist/core/model-capability.d.ts +0 -19
  140. package/dist/core/model-capability.d.ts.map +1 -1
  141. package/dist/core/model-capability.js +0 -19
  142. package/dist/core/model-capability.js.map +1 -1
  143. package/dist/core/model-registry.d.ts +6 -1
  144. package/dist/core/model-registry.d.ts.map +1 -1
  145. package/dist/core/model-registry.js +13 -5
  146. package/dist/core/model-registry.js.map +1 -1
  147. package/dist/core/model-resolver.d.ts +16 -1
  148. package/dist/core/model-resolver.d.ts.map +1 -1
  149. package/dist/core/model-resolver.js +32 -16
  150. package/dist/core/model-resolver.js.map +1 -1
  151. package/dist/core/model-router-controller.d.ts +1 -1
  152. package/dist/core/model-router-controller.d.ts.map +1 -1
  153. package/dist/core/model-router-controller.js.map +1 -1
  154. package/dist/core/model-selection-controller.d.ts +1 -1
  155. package/dist/core/model-selection-controller.d.ts.map +1 -1
  156. package/dist/core/model-selection-controller.js.map +1 -1
  157. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  158. package/dist/core/orchestration/delegation-ledger.js +3 -0
  159. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  160. package/dist/core/orchestration/work-state-projection.d.ts.map +1 -1
  161. package/dist/core/orchestration/work-state-projection.js +1 -1
  162. package/dist/core/orchestration/work-state-projection.js.map +1 -1
  163. package/dist/core/package-manager.d.ts.map +1 -1
  164. package/dist/core/package-manager.js +20 -3
  165. package/dist/core/package-manager.js.map +1 -1
  166. package/dist/core/profile-filter-controller.d.ts +8 -1
  167. package/dist/core/profile-filter-controller.d.ts.map +1 -1
  168. package/dist/core/profile-filter-controller.js +23 -5
  169. package/dist/core/profile-filter-controller.js.map +1 -1
  170. package/dist/core/prompt-templates.d.ts +1 -0
  171. package/dist/core/prompt-templates.d.ts.map +1 -1
  172. package/dist/core/prompt-templates.js +18 -29
  173. package/dist/core/prompt-templates.js.map +1 -1
  174. package/dist/core/reflection-controller.d.ts +1 -1
  175. package/dist/core/reflection-controller.d.ts.map +1 -1
  176. package/dist/core/reflection-controller.js +3 -1
  177. package/dist/core/reflection-controller.js.map +1 -1
  178. package/dist/core/request-auth.d.ts +7 -0
  179. package/dist/core/request-auth.d.ts.map +1 -0
  180. package/dist/core/request-auth.js +8 -0
  181. package/dist/core/request-auth.js.map +1 -0
  182. package/dist/core/resource-loader.d.ts.map +1 -1
  183. package/dist/core/resource-loader.js +16 -6
  184. package/dist/core/resource-loader.js.map +1 -1
  185. package/dist/core/risk-classifier.d.ts.map +1 -1
  186. package/dist/core/risk-classifier.js +8 -0
  187. package/dist/core/risk-classifier.js.map +1 -1
  188. package/dist/core/runtime-builder.d.ts +15 -3
  189. package/dist/core/runtime-builder.d.ts.map +1 -1
  190. package/dist/core/runtime-builder.js +132 -79
  191. package/dist/core/runtime-builder.js.map +1 -1
  192. package/dist/core/sdk.d.ts.map +1 -1
  193. package/dist/core/sdk.js +7 -1
  194. package/dist/core/sdk.js.map +1 -1
  195. package/dist/core/secrets/credential-exposure-guard.d.ts +9 -0
  196. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -0
  197. package/dist/core/secrets/credential-exposure-guard.js +241 -0
  198. package/dist/core/secrets/credential-exposure-guard.js.map +1 -0
  199. package/dist/core/secrets/secret-dotenv.d.ts +27 -0
  200. package/dist/core/secrets/secret-dotenv.d.ts.map +1 -0
  201. package/dist/core/secrets/secret-dotenv.js +183 -0
  202. package/dist/core/secrets/secret-dotenv.js.map +1 -0
  203. package/dist/core/secrets/secret-vault-format.d.ts +112 -0
  204. package/dist/core/secrets/secret-vault-format.d.ts.map +1 -0
  205. package/dist/core/secrets/secret-vault-format.js +397 -0
  206. package/dist/core/secrets/secret-vault-format.js.map +1 -0
  207. package/dist/core/secrets/secret-vault.d.ts +72 -0
  208. package/dist/core/secrets/secret-vault.d.ts.map +1 -0
  209. package/dist/core/secrets/secret-vault.js +671 -0
  210. package/dist/core/secrets/secret-vault.js.map +1 -0
  211. package/dist/core/session-analytics.d.ts +4 -23
  212. package/dist/core/session-analytics.d.ts.map +1 -1
  213. package/dist/core/session-analytics.js +39 -69
  214. package/dist/core/session-analytics.js.map +1 -1
  215. package/dist/core/session-role.d.ts +5 -0
  216. package/dist/core/session-role.d.ts.map +1 -1
  217. package/dist/core/session-role.js +14 -1
  218. package/dist/core/session-role.js.map +1 -1
  219. package/dist/core/session-tree-navigator.d.ts +4 -6
  220. package/dist/core/session-tree-navigator.d.ts.map +1 -1
  221. package/dist/core/session-tree-navigator.js +4 -1
  222. package/dist/core/session-tree-navigator.js.map +1 -1
  223. package/dist/core/settings-manager.d.ts +1 -1
  224. package/dist/core/settings-manager.d.ts.map +1 -1
  225. package/dist/core/settings-manager.js +1 -1
  226. package/dist/core/settings-manager.js.map +1 -1
  227. package/dist/core/slash-commands.d.ts.map +1 -1
  228. package/dist/core/slash-commands.js +2 -2
  229. package/dist/core/slash-commands.js.map +1 -1
  230. package/dist/core/tool-capability-policy.d.ts.map +1 -1
  231. package/dist/core/tool-capability-policy.js +1 -0
  232. package/dist/core/tool-capability-policy.js.map +1 -1
  233. package/dist/core/tool-gate-controller.d.ts.map +1 -1
  234. package/dist/core/tool-gate-controller.js +8 -2
  235. package/dist/core/tool-gate-controller.js.map +1 -1
  236. package/dist/core/tool-protocol-controller.d.ts +2 -4
  237. package/dist/core/tool-protocol-controller.d.ts.map +1 -1
  238. package/dist/core/tool-protocol-controller.js.map +1 -1
  239. package/dist/core/tool-recovery-stats.d.ts +21 -1
  240. package/dist/core/tool-recovery-stats.d.ts.map +1 -1
  241. package/dist/core/tool-recovery-stats.js.map +1 -1
  242. package/dist/core/tools/bash.d.ts +5 -0
  243. package/dist/core/tools/bash.d.ts.map +1 -1
  244. package/dist/core/tools/bash.js +59 -5
  245. package/dist/core/tools/bash.js.map +1 -1
  246. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  247. package/dist/core/tools/delegate-status.js +6 -7
  248. package/dist/core/tools/delegate-status.js.map +1 -1
  249. package/dist/core/tools/delegate.d.ts.map +1 -1
  250. package/dist/core/tools/delegate.js +6 -8
  251. package/dist/core/tools/delegate.js.map +1 -1
  252. package/dist/core/tools/git-filter.d.ts +1 -8
  253. package/dist/core/tools/git-filter.d.ts.map +1 -1
  254. package/dist/core/tools/git-filter.js +2 -63
  255. package/dist/core/tools/git-filter.js.map +1 -1
  256. package/dist/core/tools/goal.d.ts +5 -3
  257. package/dist/core/tools/goal.d.ts.map +1 -1
  258. package/dist/core/tools/goal.js +97 -19
  259. package/dist/core/tools/goal.js.map +1 -1
  260. package/dist/core/tools/index.d.ts +1 -0
  261. package/dist/core/tools/index.d.ts.map +1 -1
  262. package/dist/core/tools/index.js +1 -0
  263. package/dist/core/tools/index.js.map +1 -1
  264. package/dist/core/tools/orchestration-panel.d.ts +1 -4
  265. package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
  266. package/dist/core/tools/orchestration-panel.js +0 -44
  267. package/dist/core/tools/orchestration-panel.js.map +1 -1
  268. package/dist/core/tools/output-accumulator.d.ts +11 -0
  269. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  270. package/dist/core/tools/output-accumulator.js +36 -3
  271. package/dist/core/tools/output-accumulator.js.map +1 -1
  272. package/dist/core/tools/python.d.ts +2 -0
  273. package/dist/core/tools/python.d.ts.map +1 -1
  274. package/dist/core/tools/python.js +3 -1
  275. package/dist/core/tools/python.js.map +1 -1
  276. package/dist/core/tools/read.d.ts.map +1 -1
  277. package/dist/core/tools/read.js +1 -1
  278. package/dist/core/tools/read.js.map +1 -1
  279. package/dist/core/tools/search-command-guard.d.ts +14 -0
  280. package/dist/core/tools/search-command-guard.d.ts.map +1 -0
  281. package/dist/core/tools/search-command-guard.js +333 -0
  282. package/dist/core/tools/search-command-guard.js.map +1 -0
  283. package/dist/core/tools/secret-store.d.ts +38 -0
  284. package/dist/core/tools/secret-store.d.ts.map +1 -0
  285. package/dist/core/tools/secret-store.js +412 -0
  286. package/dist/core/tools/secret-store.js.map +1 -0
  287. package/dist/core/tools/shell-command-parser.d.ts +16 -0
  288. package/dist/core/tools/shell-command-parser.d.ts.map +1 -0
  289. package/dist/core/tools/shell-command-parser.js +113 -0
  290. package/dist/core/tools/shell-command-parser.js.map +1 -0
  291. package/dist/core/tools/task-steps.d.ts.map +1 -1
  292. package/dist/core/tools/task-steps.js +4 -7
  293. package/dist/core/tools/task-steps.js.map +1 -1
  294. package/dist/core/util/atomic-file.d.ts +6 -2
  295. package/dist/core/util/atomic-file.d.ts.map +1 -1
  296. package/dist/core/util/atomic-file.js +4 -4
  297. package/dist/core/util/atomic-file.js.map +1 -1
  298. package/dist/index.d.ts +3 -2
  299. package/dist/index.d.ts.map +1 -1
  300. package/dist/index.js +2 -1
  301. package/dist/index.js.map +1 -1
  302. package/dist/main.d.ts.map +1 -1
  303. package/dist/main.js +25 -11
  304. package/dist/main.js.map +1 -1
  305. package/dist/modes/interactive/auth-dialogs-controller.d.ts +4 -0
  306. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  307. package/dist/modes/interactive/auth-dialogs-controller.js +60 -1
  308. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  309. package/dist/modes/interactive/components/activity-lane.d.ts +55 -0
  310. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -0
  311. package/dist/modes/interactive/components/activity-lane.js +304 -0
  312. package/dist/modes/interactive/components/activity-lane.js.map +1 -0
  313. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  314. package/dist/modes/interactive/components/assistant-message.js +19 -10
  315. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  316. package/dist/modes/interactive/components/expandable-text.d.ts +12 -0
  317. package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -0
  318. package/dist/modes/interactive/components/expandable-text.js +17 -0
  319. package/dist/modes/interactive/components/expandable-text.js.map +1 -0
  320. package/dist/modes/interactive/components/extension-editor.d.ts +15 -1
  321. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  322. package/dist/modes/interactive/components/extension-editor.js +30 -21
  323. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  324. package/dist/modes/interactive/components/extension-input.d.ts +1 -0
  325. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/extension-input.js +6 -1
  327. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  328. package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
  329. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  330. package/dist/modes/interactive/components/scoped-models-selector.js +23 -14
  331. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  332. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  333. package/dist/modes/interactive/components/settings-selector.js +4 -4
  334. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  335. package/dist/modes/interactive/components/tool-execution.d.ts +19 -11
  336. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  337. package/dist/modes/interactive/components/tool-execution.js +53 -20
  338. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  339. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  340. package/dist/modes/interactive/components/tool-group.js +3 -0
  341. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  342. package/dist/modes/interactive/components/usage-action-selector.d.ts +16 -0
  343. package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -0
  344. package/dist/modes/interactive/components/usage-action-selector.js +46 -0
  345. package/dist/modes/interactive/components/usage-action-selector.js.map +1 -0
  346. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  347. package/dist/modes/interactive/extension-ui-host.js +1 -0
  348. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  349. package/dist/modes/interactive/external-editor.d.ts +15 -0
  350. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  351. package/dist/modes/interactive/external-editor.js +27 -19
  352. package/dist/modes/interactive/external-editor.js.map +1 -1
  353. package/dist/modes/interactive/history-reload-math.d.ts +6 -2
  354. package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
  355. package/dist/modes/interactive/history-reload-math.js +10 -5
  356. package/dist/modes/interactive/history-reload-math.js.map +1 -1
  357. package/dist/modes/interactive/interactive-event-controller.d.ts +74 -0
  358. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -0
  359. package/dist/modes/interactive/interactive-event-controller.js +328 -0
  360. package/dist/modes/interactive/interactive-event-controller.js.map +1 -0
  361. package/dist/modes/interactive/interactive-mode.d.ts +20 -25
  362. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  363. package/dist/modes/interactive/interactive-mode.js +196 -608
  364. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  365. package/dist/modes/interactive/loaded-resources-view.d.ts +20 -0
  366. package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -0
  367. package/dist/modes/interactive/loaded-resources-view.js +147 -0
  368. package/dist/modes/interactive/loaded-resources-view.js.map +1 -0
  369. package/dist/modes/interactive/resource-display.d.ts.map +1 -1
  370. package/dist/modes/interactive/resource-display.js +8 -2
  371. package/dist/modes/interactive/resource-display.js.map +1 -1
  372. package/dist/modes/interactive/resource-shell-commands.d.ts +1 -5
  373. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
  374. package/dist/modes/interactive/resource-shell-commands.js +0 -5
  375. package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
  376. package/dist/modes/interactive/session-flow-commands.d.ts +10 -6
  377. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  378. package/dist/modes/interactive/session-flow-commands.js +123 -70
  379. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  380. package/dist/modes/interactive/usage-commands.d.ts +34 -0
  381. package/dist/modes/interactive/usage-commands.d.ts.map +1 -0
  382. package/dist/modes/interactive/usage-commands.js +225 -0
  383. package/dist/modes/interactive/usage-commands.js.map +1 -0
  384. package/dist/utils/shell.d.ts.map +1 -1
  385. package/dist/utils/shell.js +5 -3
  386. package/dist/utils/shell.js.map +1 -1
  387. package/dist/utils/version-check.d.ts.map +1 -1
  388. package/dist/utils/version-check.js +3 -1
  389. package/dist/utils/version-check.js.map +1 -1
  390. package/docs/UI_POLISH_ORCHESTRATION.md +25 -31
  391. package/docs/UI_QUALITY_ORCHESTRATION.md +22 -24
  392. package/docs/providers.md +9 -1
  393. package/docs/ui-reference/README.md +6 -6
  394. package/docs/ui-reference/orchestration-after.txt +14 -7
  395. package/docs/ui-reference/orchestration-before.txt +12 -6
  396. package/docs/ui-reference/orchestration-reference.txt +15 -5
  397. package/docs/usage.md +9 -1
  398. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  399. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  400. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  401. package/examples/extensions/sandbox/package-lock.json +2 -2
  402. package/examples/extensions/sandbox/package.json +1 -1
  403. package/examples/extensions/with-deps/package-lock.json +2 -2
  404. package/examples/extensions/with-deps/package.json +1 -1
  405. package/npm-shrinkwrap.json +13 -13
  406. package/package.json +4 -4
@@ -0,0 +1,304 @@
1
+ import { truncateToWidth, visibleWidth } from "@caupulican/pi-tui";
2
+ import { isGoalUnfinishedStatus } from "../../../core/goals/goal-state.js";
3
+ const DEFAULT_TERMINAL_HOLD_MS = 2_000;
4
+ const MAX_ACTIVITY_LABEL_LENGTH = 240;
5
+ const MAX_SEEN_TERMINALS = 512;
6
+ const KIND_COLORS = {
7
+ runtime: "thinkingText",
8
+ tool: "mdLink",
9
+ task: "accent",
10
+ worker: "customMessageLabel",
11
+ goal: "mdHeading",
12
+ queue: "muted",
13
+ notice: "text",
14
+ };
15
+ const STATUS_COLORS = {
16
+ active: "muted",
17
+ waiting: "warning",
18
+ success: "success",
19
+ failure: "error",
20
+ neutral: "muted",
21
+ };
22
+ function boundedLabel(value) {
23
+ const normalized = value.replace(/\s+/g, " ").trim();
24
+ return normalized.length <= MAX_ACTIVITY_LABEL_LENGTH
25
+ ? normalized
26
+ : `${normalized.slice(0, MAX_ACTIVITY_LABEL_LENGTH - 1)}…`;
27
+ }
28
+ function taskLabel(step, state) {
29
+ const total = state.steps.length + state.archive.completed + state.archive.cancelled;
30
+ const activeIndex = state.steps.findIndex((candidate) => candidate.id === step.id);
31
+ const archived = state.archive.completed + state.archive.cancelled;
32
+ const position = Math.min(total, archived + Math.max(0, activeIndex) + 1);
33
+ const prefix = step.status === "blocked" ? "Blocked" : step.status === "pending" ? "Next" : "Step";
34
+ const content = step.status === "in_progress" ? (step.activeForm ?? step.content) : step.content;
35
+ return boundedLabel(`${prefix} ${position}/${total} · ${content}`);
36
+ }
37
+ function projectTaskState(state) {
38
+ if (!state)
39
+ return { active: [], terminal: [] };
40
+ const inProgress = state.steps.find((step) => step.status === "in_progress");
41
+ const blocked = state.steps.find((step) => step.status === "blocked");
42
+ const pending = state.steps.find((step) => step.status === "pending");
43
+ const current = inProgress ?? blocked ?? pending;
44
+ const active = current
45
+ ? [
46
+ {
47
+ id: `task:${current.id}`,
48
+ kind: "task",
49
+ label: taskLabel(current, state),
50
+ status: current.status === "blocked" ? "waiting" : "active",
51
+ },
52
+ ]
53
+ : [];
54
+ const terminal = state.steps
55
+ .filter((step) => step.status === "completed" || step.status === "cancelled")
56
+ .map((step) => ({
57
+ id: `terminal:task:${step.id}:${step.status}:${step.updatedAt}`,
58
+ kind: "task",
59
+ label: boundedLabel(step.status === "completed" ? `Completed · ${step.content}` : `Cancelled · ${step.content}`),
60
+ status: step.status === "completed" ? "success" : "neutral",
61
+ }));
62
+ return { active, terminal };
63
+ }
64
+ function projectGoalState(state) {
65
+ if (!state)
66
+ return { active: [], terminal: [] };
67
+ const satisfied = state.requirements.filter((requirement) => requirement.status === "satisfied").length;
68
+ const progress = state.requirements.length > 0 ? ` ${satisfied}/${state.requirements.length}` : "";
69
+ if (isGoalUnfinishedStatus(state.status)) {
70
+ const stopped = state.status === "active" ? "" : ` ${state.status.replace("_", " ")}`;
71
+ return {
72
+ active: [
73
+ {
74
+ id: `goal:${state.goalId}`,
75
+ kind: "goal",
76
+ label: boundedLabel(`Goal${stopped}${progress} · ${state.userGoal}`),
77
+ status: state.status === "active" ? "active" : "waiting",
78
+ },
79
+ ],
80
+ terminal: [],
81
+ };
82
+ }
83
+ return {
84
+ active: [],
85
+ terminal: [
86
+ {
87
+ id: `terminal:goal:${state.goalId}:${state.status}:${state.updatedAt}`,
88
+ kind: "goal",
89
+ label: state.status === "completed" ? "Goal achieved" : "Goal closed",
90
+ status: state.status === "completed" ? "success" : "neutral",
91
+ },
92
+ ],
93
+ };
94
+ }
95
+ function laneLabel(record) {
96
+ const runtime = record.type === "tmux-worker" ? "tmux" : "agent";
97
+ const label = record.label ?? record.laneId;
98
+ return boundedLabel(`${runtime} · ${label}`);
99
+ }
100
+ function projectLaneRecords(records) {
101
+ const workers = records.filter((record) => record.type === "worker" || record.type === "tmux-worker");
102
+ const active = workers
103
+ .filter((record) => record.status === "queued" || record.status === "running")
104
+ .map((record) => ({
105
+ id: `worker:${record.laneId}`,
106
+ kind: "worker",
107
+ label: laneLabel(record),
108
+ status: record.status === "queued" ? "waiting" : "active",
109
+ }));
110
+ const terminal = workers
111
+ .filter((record) => record.status === "succeeded" ||
112
+ record.status === "failed" ||
113
+ record.status === "timeout" ||
114
+ record.status === "budget_exhausted" ||
115
+ record.status === "canceled")
116
+ .map((record) => ({
117
+ id: `terminal:worker:${record.laneId}:${record.status}:${record.completedAt ?? "unknown"}`,
118
+ kind: "worker",
119
+ label: boundedLabel(`${record.status === "succeeded" ? "Finished" : record.status} · ${record.label ?? record.laneId}`),
120
+ status: record.status === "succeeded" ? "success" : record.status === "canceled" ? "neutral" : "failure",
121
+ }));
122
+ return { active, terminal };
123
+ }
124
+ export function projectActivityLane(snapshot) {
125
+ const task = projectTaskState(snapshot.taskState);
126
+ const lanes = projectLaneRecords(snapshot.laneRecords);
127
+ const goal = projectGoalState(snapshot.goalState);
128
+ return {
129
+ active: [...task.active, ...lanes.active, ...goal.active],
130
+ terminal: [...task.terminal, ...lanes.terminal, ...goal.terminal],
131
+ };
132
+ }
133
+ function renderItem(theme, item, maxWidth) {
134
+ const dot = theme.fg(STATUS_COLORS[item.status], "●");
135
+ const color = item.status === "success" || item.status === "failure" ? STATUS_COLORS[item.status] : KIND_COLORS[item.kind];
136
+ const labelWidth = Math.max(1, maxWidth - 2);
137
+ return `${dot} ${theme.fg(color, truncateToWidth(item.label, labelWidth, "…"))}`;
138
+ }
139
+ export function renderActivityLaneLine(theme, items, width) {
140
+ const safeWidth = Math.max(1, width);
141
+ if (items.length === 0 || safeWidth < 3)
142
+ return [];
143
+ const indent = " ";
144
+ const separator = theme.fg("dim", " · ");
145
+ const hiddenLabel = (count) => theme.fg("dim", `+${count}`);
146
+ const parts = [];
147
+ let used = visibleWidth(indent);
148
+ let hidden = 0;
149
+ for (let index = 0; index < items.length; index++) {
150
+ const item = items[index];
151
+ const gap = parts.length === 0 ? "" : separator;
152
+ const gapWidth = visibleWidth(gap);
153
+ const remainingItems = items.length - index - 1;
154
+ const reserve = remainingItems > 0 ? visibleWidth(separator) + visibleWidth(hiddenLabel(remainingItems)) : 0;
155
+ const available = safeWidth - used - gapWidth - reserve;
156
+ if (available < 5) {
157
+ hidden = items.length - index;
158
+ break;
159
+ }
160
+ const rendered = renderItem(theme, item, available);
161
+ parts.push(`${gap}${rendered}`);
162
+ used += gapWidth + visibleWidth(rendered);
163
+ if (visibleWidth(rendered) < Math.min(available, visibleWidth(renderItem(theme, item, safeWidth)))) {
164
+ hidden = remainingItems;
165
+ break;
166
+ }
167
+ }
168
+ if (hidden > 0) {
169
+ const suffix = `${separator}${hiddenLabel(hidden)}`;
170
+ if (used + visibleWidth(suffix) <= safeWidth)
171
+ parts.push(suffix);
172
+ }
173
+ return [truncateToWidth(`${indent}${parts.join("")}`, safeWidth, "")];
174
+ }
175
+ export class ActivityLaneComponent {
176
+ theme;
177
+ requestRender;
178
+ terminalHoldMs;
179
+ sessionKey;
180
+ canonical = new Map();
181
+ live = new Map();
182
+ transient = new Map();
183
+ transientTimers = new Map();
184
+ seenTerminalKeys = new Set();
185
+ transientSequence = 0;
186
+ constructor(theme, requestRender, terminalHoldMs = DEFAULT_TERMINAL_HOLD_MS) {
187
+ this.theme = theme;
188
+ this.requestRender = requestRender;
189
+ this.terminalHoldMs = terminalHoldMs;
190
+ }
191
+ rememberTerminal(key) {
192
+ this.seenTerminalKeys.add(key);
193
+ while (this.seenTerminalKeys.size > MAX_SEEN_TERMINALS) {
194
+ const oldest = this.seenTerminalKeys.values().next().value;
195
+ if (oldest === undefined)
196
+ break;
197
+ this.seenTerminalKeys.delete(oldest);
198
+ }
199
+ }
200
+ addTransient(item) {
201
+ const id = `${item.id}:${++this.transientSequence}`;
202
+ this.transient.set(id, { ...item, id });
203
+ const timer = setTimeout(() => {
204
+ this.transient.delete(id);
205
+ this.transientTimers.delete(id);
206
+ this.requestRender();
207
+ }, this.terminalHoldMs);
208
+ this.transientTimers.set(id, timer);
209
+ }
210
+ applyProjection(projection, showNewTerminals) {
211
+ this.canonical.clear();
212
+ for (const item of projection.active)
213
+ this.canonical.set(item.id, item);
214
+ for (const item of projection.terminal.slice(-MAX_SEEN_TERMINALS)) {
215
+ if (showNewTerminals && !this.seenTerminalKeys.has(item.id))
216
+ this.addTransient(item);
217
+ this.rememberTerminal(item.id);
218
+ }
219
+ this.requestRender();
220
+ }
221
+ replaceCanonical(sessionKey, snapshot) {
222
+ if (this.sessionKey !== sessionKey) {
223
+ this.clearTransient();
224
+ this.live.clear();
225
+ this.seenTerminalKeys.clear();
226
+ this.sessionKey = sessionKey;
227
+ }
228
+ this.applyProjection(projectActivityLane(snapshot), false);
229
+ }
230
+ updateCanonical(sessionKey, snapshot) {
231
+ if (this.sessionKey !== sessionKey) {
232
+ this.replaceCanonical(sessionKey, snapshot);
233
+ return;
234
+ }
235
+ this.applyProjection(projectActivityLane(snapshot), true);
236
+ }
237
+ start(item) {
238
+ this.live.set(item.id, { ...item, label: boundedLabel(item.label), status: "active" });
239
+ this.requestRender();
240
+ }
241
+ wait(item) {
242
+ this.live.set(item.id, { ...item, label: boundedLabel(item.label), status: "waiting" });
243
+ this.requestRender();
244
+ }
245
+ update(id, label) {
246
+ const current = this.live.get(id);
247
+ if (!current)
248
+ return;
249
+ this.live.set(id, { ...current, label: boundedLabel(label) });
250
+ this.requestRender();
251
+ }
252
+ remove(id) {
253
+ if (this.live.delete(id))
254
+ this.requestRender();
255
+ }
256
+ removeByPrefix(prefix) {
257
+ let removed = false;
258
+ for (const id of this.live.keys()) {
259
+ if (!id.startsWith(prefix))
260
+ continue;
261
+ this.live.delete(id);
262
+ removed = true;
263
+ }
264
+ if (removed)
265
+ this.requestRender();
266
+ }
267
+ finish(id, status, fallback) {
268
+ const current = this.live.get(id) ?? fallback;
269
+ this.live.delete(id);
270
+ if (current)
271
+ this.addTransient({ ...current, label: boundedLabel(current.label), status });
272
+ this.requestRender();
273
+ }
274
+ announce(label, status = "success") {
275
+ this.addTransient({ id: "notice", kind: "notice", label: boundedLabel(label), status });
276
+ this.requestRender();
277
+ }
278
+ clearTransient() {
279
+ for (const timer of this.transientTimers.values())
280
+ clearTimeout(timer);
281
+ this.transientTimers.clear();
282
+ this.transient.clear();
283
+ }
284
+ getItems() {
285
+ const transient = [...this.transient.values()];
286
+ const live = [...this.live.values()];
287
+ const hasSpecificLiveWork = live.some((item) => item.kind === "tool");
288
+ const visibleLive = hasSpecificLiveWork
289
+ ? live.filter((item) => !(item.kind === "runtime" && item.id === "runtime:turn"))
290
+ : live;
291
+ return [...transient, ...visibleLive, ...this.canonical.values()];
292
+ }
293
+ render(width) {
294
+ return renderActivityLaneLine(this.theme, this.getItems(), width);
295
+ }
296
+ invalidate() { }
297
+ dispose() {
298
+ this.clearTransient();
299
+ this.live.clear();
300
+ this.canonical.clear();
301
+ this.seenTerminalKeys.clear();
302
+ }
303
+ }
304
+ //# sourceMappingURL=activity-lane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-lane.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/activity-lane.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"@caupulican/pi-tui\";\nimport { truncateToWidth, visibleWidth } from \"@caupulican/pi-tui\";\nimport type { LaneRecord } from \"../../../core/autonomy/lane-tracker.ts\";\nimport { type GoalState, isGoalUnfinishedStatus } from \"../../../core/goals/goal-state.ts\";\nimport type { TaskStep, TaskStepsState } from \"../../../core/tasks/task-state.ts\";\nimport type { Theme, ThemeColor } from \"../theme/theme.ts\";\n\nexport type ActivityLaneKind = \"runtime\" | \"tool\" | \"task\" | \"worker\" | \"goal\" | \"queue\" | \"notice\";\nexport type ActivityLaneStatus = \"active\" | \"waiting\" | \"success\" | \"failure\" | \"neutral\";\n\nexport interface ActivityLaneItem {\n\tid: string;\n\tkind: ActivityLaneKind;\n\tlabel: string;\n\tstatus: ActivityLaneStatus;\n}\n\nexport interface ActivityLaneCanonicalSnapshot {\n\tgoalState?: GoalState;\n\ttaskState?: TaskStepsState;\n\tlaneRecords: readonly LaneRecord[];\n}\n\nexport interface ActivityLaneProjection {\n\tactive: ActivityLaneItem[];\n\tterminal: ActivityLaneItem[];\n}\n\nconst DEFAULT_TERMINAL_HOLD_MS = 2_000;\nconst MAX_ACTIVITY_LABEL_LENGTH = 240;\nconst MAX_SEEN_TERMINALS = 512;\n\nconst KIND_COLORS: Record<ActivityLaneKind, ThemeColor> = {\n\truntime: \"thinkingText\",\n\ttool: \"mdLink\",\n\ttask: \"accent\",\n\tworker: \"customMessageLabel\",\n\tgoal: \"mdHeading\",\n\tqueue: \"muted\",\n\tnotice: \"text\",\n};\n\nconst STATUS_COLORS: Record<ActivityLaneStatus, ThemeColor> = {\n\tactive: \"muted\",\n\twaiting: \"warning\",\n\tsuccess: \"success\",\n\tfailure: \"error\",\n\tneutral: \"muted\",\n};\n\nfunction boundedLabel(value: string): string {\n\tconst normalized = value.replace(/\\s+/g, \" \").trim();\n\treturn normalized.length <= MAX_ACTIVITY_LABEL_LENGTH\n\t\t? normalized\n\t\t: `${normalized.slice(0, MAX_ACTIVITY_LABEL_LENGTH - 1)}…`;\n}\n\nfunction taskLabel(step: TaskStep, state: TaskStepsState): string {\n\tconst total = state.steps.length + state.archive.completed + state.archive.cancelled;\n\tconst activeIndex = state.steps.findIndex((candidate) => candidate.id === step.id);\n\tconst archived = state.archive.completed + state.archive.cancelled;\n\tconst position = Math.min(total, archived + Math.max(0, activeIndex) + 1);\n\tconst prefix = step.status === \"blocked\" ? \"Blocked\" : step.status === \"pending\" ? \"Next\" : \"Step\";\n\tconst content = step.status === \"in_progress\" ? (step.activeForm ?? step.content) : step.content;\n\treturn boundedLabel(`${prefix} ${position}/${total} · ${content}`);\n}\n\nfunction projectTaskState(state: TaskStepsState | undefined): ActivityLaneProjection {\n\tif (!state) return { active: [], terminal: [] };\n\tconst inProgress = state.steps.find((step) => step.status === \"in_progress\");\n\tconst blocked = state.steps.find((step) => step.status === \"blocked\");\n\tconst pending = state.steps.find((step) => step.status === \"pending\");\n\tconst current = inProgress ?? blocked ?? pending;\n\tconst active = current\n\t\t? [\n\t\t\t\t{\n\t\t\t\t\tid: `task:${current.id}`,\n\t\t\t\t\tkind: \"task\" as const,\n\t\t\t\t\tlabel: taskLabel(current, state),\n\t\t\t\t\tstatus: current.status === \"blocked\" ? (\"waiting\" as const) : (\"active\" as const),\n\t\t\t\t},\n\t\t\t]\n\t\t: [];\n\tconst terminal = state.steps\n\t\t.filter((step) => step.status === \"completed\" || step.status === \"cancelled\")\n\t\t.map(\n\t\t\t(step): ActivityLaneItem => ({\n\t\t\t\tid: `terminal:task:${step.id}:${step.status}:${step.updatedAt}`,\n\t\t\t\tkind: \"task\",\n\t\t\t\tlabel: boundedLabel(\n\t\t\t\t\tstep.status === \"completed\" ? `Completed · ${step.content}` : `Cancelled · ${step.content}`,\n\t\t\t\t),\n\t\t\t\tstatus: step.status === \"completed\" ? \"success\" : \"neutral\",\n\t\t\t}),\n\t\t);\n\treturn { active, terminal };\n}\n\nfunction projectGoalState(state: GoalState | undefined): ActivityLaneProjection {\n\tif (!state) return { active: [], terminal: [] };\n\tconst satisfied = state.requirements.filter((requirement) => requirement.status === \"satisfied\").length;\n\tconst progress = state.requirements.length > 0 ? ` ${satisfied}/${state.requirements.length}` : \"\";\n\tif (isGoalUnfinishedStatus(state.status)) {\n\t\tconst stopped = state.status === \"active\" ? \"\" : ` ${state.status.replace(\"_\", \" \")}`;\n\t\treturn {\n\t\t\tactive: [\n\t\t\t\t{\n\t\t\t\t\tid: `goal:${state.goalId}`,\n\t\t\t\t\tkind: \"goal\",\n\t\t\t\t\tlabel: boundedLabel(`Goal${stopped}${progress} · ${state.userGoal}`),\n\t\t\t\t\tstatus: state.status === \"active\" ? \"active\" : \"waiting\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tterminal: [],\n\t\t};\n\t}\n\treturn {\n\t\tactive: [],\n\t\tterminal: [\n\t\t\t{\n\t\t\t\tid: `terminal:goal:${state.goalId}:${state.status}:${state.updatedAt}`,\n\t\t\t\tkind: \"goal\",\n\t\t\t\tlabel: state.status === \"completed\" ? \"Goal achieved\" : \"Goal closed\",\n\t\t\t\tstatus: state.status === \"completed\" ? \"success\" : \"neutral\",\n\t\t\t},\n\t\t],\n\t};\n}\n\nfunction laneLabel(record: LaneRecord): string {\n\tconst runtime = record.type === \"tmux-worker\" ? \"tmux\" : \"agent\";\n\tconst label = record.label ?? record.laneId;\n\treturn boundedLabel(`${runtime} · ${label}`);\n}\n\nfunction projectLaneRecords(records: readonly LaneRecord[]): ActivityLaneProjection {\n\tconst workers = records.filter((record) => record.type === \"worker\" || record.type === \"tmux-worker\");\n\tconst active = workers\n\t\t.filter((record) => record.status === \"queued\" || record.status === \"running\")\n\t\t.map(\n\t\t\t(record): ActivityLaneItem => ({\n\t\t\t\tid: `worker:${record.laneId}`,\n\t\t\t\tkind: \"worker\",\n\t\t\t\tlabel: laneLabel(record),\n\t\t\t\tstatus: record.status === \"queued\" ? \"waiting\" : \"active\",\n\t\t\t}),\n\t\t);\n\tconst terminal = workers\n\t\t.filter(\n\t\t\t(record) =>\n\t\t\t\trecord.status === \"succeeded\" ||\n\t\t\t\trecord.status === \"failed\" ||\n\t\t\t\trecord.status === \"timeout\" ||\n\t\t\t\trecord.status === \"budget_exhausted\" ||\n\t\t\t\trecord.status === \"canceled\",\n\t\t)\n\t\t.map(\n\t\t\t(record): ActivityLaneItem => ({\n\t\t\t\tid: `terminal:worker:${record.laneId}:${record.status}:${record.completedAt ?? \"unknown\"}`,\n\t\t\t\tkind: \"worker\",\n\t\t\t\tlabel: boundedLabel(\n\t\t\t\t\t`${record.status === \"succeeded\" ? \"Finished\" : record.status} · ${record.label ?? record.laneId}`,\n\t\t\t\t),\n\t\t\t\tstatus: record.status === \"succeeded\" ? \"success\" : record.status === \"canceled\" ? \"neutral\" : \"failure\",\n\t\t\t}),\n\t\t);\n\treturn { active, terminal };\n}\n\nexport function projectActivityLane(snapshot: ActivityLaneCanonicalSnapshot): ActivityLaneProjection {\n\tconst task = projectTaskState(snapshot.taskState);\n\tconst lanes = projectLaneRecords(snapshot.laneRecords);\n\tconst goal = projectGoalState(snapshot.goalState);\n\treturn {\n\t\tactive: [...task.active, ...lanes.active, ...goal.active],\n\t\tterminal: [...task.terminal, ...lanes.terminal, ...goal.terminal],\n\t};\n}\n\nfunction renderItem(theme: Theme, item: ActivityLaneItem, maxWidth: number): string {\n\tconst dot = theme.fg(STATUS_COLORS[item.status], \"●\");\n\tconst color =\n\t\titem.status === \"success\" || item.status === \"failure\" ? STATUS_COLORS[item.status] : KIND_COLORS[item.kind];\n\tconst labelWidth = Math.max(1, maxWidth - 2);\n\treturn `${dot} ${theme.fg(color, truncateToWidth(item.label, labelWidth, \"…\"))}`;\n}\n\nexport function renderActivityLaneLine(theme: Theme, items: readonly ActivityLaneItem[], width: number): string[] {\n\tconst safeWidth = Math.max(1, width);\n\tif (items.length === 0 || safeWidth < 3) return [];\n\tconst indent = \" \";\n\tconst separator = theme.fg(\"dim\", \" · \");\n\tconst hiddenLabel = (count: number) => theme.fg(\"dim\", `+${count}`);\n\tconst parts: string[] = [];\n\tlet used = visibleWidth(indent);\n\tlet hidden = 0;\n\n\tfor (let index = 0; index < items.length; index++) {\n\t\tconst item = items[index];\n\t\tconst gap = parts.length === 0 ? \"\" : separator;\n\t\tconst gapWidth = visibleWidth(gap);\n\t\tconst remainingItems = items.length - index - 1;\n\t\tconst reserve = remainingItems > 0 ? visibleWidth(separator) + visibleWidth(hiddenLabel(remainingItems)) : 0;\n\t\tconst available = safeWidth - used - gapWidth - reserve;\n\t\tif (available < 5) {\n\t\t\thidden = items.length - index;\n\t\t\tbreak;\n\t\t}\n\t\tconst rendered = renderItem(theme, item, available);\n\t\tparts.push(`${gap}${rendered}`);\n\t\tused += gapWidth + visibleWidth(rendered);\n\t\tif (visibleWidth(rendered) < Math.min(available, visibleWidth(renderItem(theme, item, safeWidth)))) {\n\t\t\thidden = remainingItems;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (hidden > 0) {\n\t\tconst suffix = `${separator}${hiddenLabel(hidden)}`;\n\t\tif (used + visibleWidth(suffix) <= safeWidth) parts.push(suffix);\n\t}\n\treturn [truncateToWidth(`${indent}${parts.join(\"\")}`, safeWidth, \"\")];\n}\n\nexport class ActivityLaneComponent implements Component {\n\tprivate readonly theme: Theme;\n\tprivate readonly requestRender: () => void;\n\tprivate readonly terminalHoldMs: number;\n\tprivate sessionKey: string | undefined;\n\tprivate readonly canonical = new Map<string, ActivityLaneItem>();\n\tprivate readonly live = new Map<string, ActivityLaneItem>();\n\tprivate readonly transient = new Map<string, ActivityLaneItem>();\n\tprivate readonly transientTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\tprivate readonly seenTerminalKeys = new Set<string>();\n\tprivate transientSequence = 0;\n\n\tconstructor(theme: Theme, requestRender: () => void, terminalHoldMs = DEFAULT_TERMINAL_HOLD_MS) {\n\t\tthis.theme = theme;\n\t\tthis.requestRender = requestRender;\n\t\tthis.terminalHoldMs = terminalHoldMs;\n\t}\n\n\tprivate rememberTerminal(key: string): void {\n\t\tthis.seenTerminalKeys.add(key);\n\t\twhile (this.seenTerminalKeys.size > MAX_SEEN_TERMINALS) {\n\t\t\tconst oldest = this.seenTerminalKeys.values().next().value;\n\t\t\tif (oldest === undefined) break;\n\t\t\tthis.seenTerminalKeys.delete(oldest);\n\t\t}\n\t}\n\n\tprivate addTransient(item: ActivityLaneItem): void {\n\t\tconst id = `${item.id}:${++this.transientSequence}`;\n\t\tthis.transient.set(id, { ...item, id });\n\t\tconst timer = setTimeout(() => {\n\t\t\tthis.transient.delete(id);\n\t\t\tthis.transientTimers.delete(id);\n\t\t\tthis.requestRender();\n\t\t}, this.terminalHoldMs);\n\t\tthis.transientTimers.set(id, timer);\n\t}\n\n\tprivate applyProjection(projection: ActivityLaneProjection, showNewTerminals: boolean): void {\n\t\tthis.canonical.clear();\n\t\tfor (const item of projection.active) this.canonical.set(item.id, item);\n\t\tfor (const item of projection.terminal.slice(-MAX_SEEN_TERMINALS)) {\n\t\t\tif (showNewTerminals && !this.seenTerminalKeys.has(item.id)) this.addTransient(item);\n\t\t\tthis.rememberTerminal(item.id);\n\t\t}\n\t\tthis.requestRender();\n\t}\n\n\treplaceCanonical(sessionKey: string, snapshot: ActivityLaneCanonicalSnapshot): void {\n\t\tif (this.sessionKey !== sessionKey) {\n\t\t\tthis.clearTransient();\n\t\t\tthis.live.clear();\n\t\t\tthis.seenTerminalKeys.clear();\n\t\t\tthis.sessionKey = sessionKey;\n\t\t}\n\t\tthis.applyProjection(projectActivityLane(snapshot), false);\n\t}\n\n\tupdateCanonical(sessionKey: string, snapshot: ActivityLaneCanonicalSnapshot): void {\n\t\tif (this.sessionKey !== sessionKey) {\n\t\t\tthis.replaceCanonical(sessionKey, snapshot);\n\t\t\treturn;\n\t\t}\n\t\tthis.applyProjection(projectActivityLane(snapshot), true);\n\t}\n\n\tstart(item: Omit<ActivityLaneItem, \"status\">): void {\n\t\tthis.live.set(item.id, { ...item, label: boundedLabel(item.label), status: \"active\" });\n\t\tthis.requestRender();\n\t}\n\n\twait(item: Omit<ActivityLaneItem, \"status\">): void {\n\t\tthis.live.set(item.id, { ...item, label: boundedLabel(item.label), status: \"waiting\" });\n\t\tthis.requestRender();\n\t}\n\n\tupdate(id: string, label: string): void {\n\t\tconst current = this.live.get(id);\n\t\tif (!current) return;\n\t\tthis.live.set(id, { ...current, label: boundedLabel(label) });\n\t\tthis.requestRender();\n\t}\n\n\tremove(id: string): void {\n\t\tif (this.live.delete(id)) this.requestRender();\n\t}\n\n\tremoveByPrefix(prefix: string): void {\n\t\tlet removed = false;\n\t\tfor (const id of this.live.keys()) {\n\t\t\tif (!id.startsWith(prefix)) continue;\n\t\t\tthis.live.delete(id);\n\t\t\tremoved = true;\n\t\t}\n\t\tif (removed) this.requestRender();\n\t}\n\n\tfinish(id: string, status: \"success\" | \"failure\" | \"neutral\", fallback?: Omit<ActivityLaneItem, \"status\">): void {\n\t\tconst current = this.live.get(id) ?? fallback;\n\t\tthis.live.delete(id);\n\t\tif (current) this.addTransient({ ...current, label: boundedLabel(current.label), status });\n\t\tthis.requestRender();\n\t}\n\n\tannounce(label: string, status: \"success\" | \"failure\" | \"neutral\" = \"success\"): void {\n\t\tthis.addTransient({ id: \"notice\", kind: \"notice\", label: boundedLabel(label), status });\n\t\tthis.requestRender();\n\t}\n\n\tprivate clearTransient(): void {\n\t\tfor (const timer of this.transientTimers.values()) clearTimeout(timer);\n\t\tthis.transientTimers.clear();\n\t\tthis.transient.clear();\n\t}\n\n\tgetItems(): ActivityLaneItem[] {\n\t\tconst transient = [...this.transient.values()];\n\t\tconst live = [...this.live.values()];\n\t\tconst hasSpecificLiveWork = live.some((item) => item.kind === \"tool\");\n\t\tconst visibleLive = hasSpecificLiveWork\n\t\t\t? live.filter((item) => !(item.kind === \"runtime\" && item.id === \"runtime:turn\"))\n\t\t\t: live;\n\t\treturn [...transient, ...visibleLive, ...this.canonical.values()];\n\t}\n\n\trender(width: number): string[] {\n\t\treturn renderActivityLaneLine(this.theme, this.getItems(), width);\n\t}\n\n\tinvalidate(): void {}\n\n\tdispose(): void {\n\t\tthis.clearTransient();\n\t\tthis.live.clear();\n\t\tthis.canonical.clear();\n\t\tthis.seenTerminalKeys.clear();\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AAO3F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EAenC;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAyE7C;CACD","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static thinking label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in thinkingText color, italic\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AAO3F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EAenC;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAgF7C;CACD","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\") {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") break;\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) thinkingBlocks.push(thinking);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t\tif (thinkingBlocks.length === 0) continue;\n\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show one static label for each adjacent run of thinking blocks.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Adjacent thinking blocks form one section instead of repeated visual chrome.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(thinkingBlocks.join(\"\\n\\n\"), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -68,28 +68,37 @@ export class AssistantMessageComponent extends Container {
68
68
  // Set paddingY=0 to avoid extra spacing before tool executions
69
69
  this.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));
70
70
  }
71
- else if (content.type === "thinking" && content.thinking.trim()) {
71
+ else if (content.type === "thinking") {
72
+ const thinkingBlocks = [];
73
+ for (; i < message.content.length; i++) {
74
+ const thinkingContent = message.content[i];
75
+ if (thinkingContent.type !== "thinking")
76
+ break;
77
+ const thinking = thinkingContent.thinking.trim();
78
+ if (thinking)
79
+ thinkingBlocks.push(thinking);
80
+ }
81
+ i--;
82
+ if (thinkingBlocks.length === 0)
83
+ continue;
72
84
  // Add spacing only when another visible assistant content block follows.
73
85
  // This avoids a superfluous blank line before separately-rendered tool execution blocks.
74
86
  const hasVisibleContentAfter = message.content
75
87
  .slice(i + 1)
76
88
  .some((c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()));
77
89
  if (this.hideThinkingBlock) {
78
- // Show static thinking label when hidden
90
+ // Show one static label for each adjacent run of thinking blocks.
79
91
  this.contentContainer.addChild(new Text(theme.italic(theme.fg("thinkingText", this.hiddenThinkingLabel)), 1, 0));
80
- if (hasVisibleContentAfter) {
81
- this.contentContainer.addChild(new Spacer(1));
82
- }
83
92
  }
84
93
  else {
85
- // Thinking traces in thinkingText color, italic
86
- this.contentContainer.addChild(new Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {
94
+ // Adjacent thinking blocks form one section instead of repeated visual chrome.
95
+ this.contentContainer.addChild(new Markdown(thinkingBlocks.join("\n\n"), 1, 0, this.markdownTheme, {
87
96
  color: (text) => theme.fg("thinkingText", text),
88
97
  italic: true,
89
98
  }));
90
- if (hasVisibleContentAfter) {
91
- this.contentContainer.addChild(new Spacer(1));
92
- }
99
+ }
100
+ if (hasVisibleContentAfter) {
101
+ this.contentContainer.addChild(new Spacer(1));
93
102
  }
94
103
  }
95
104
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static thinking label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in thinkingText color, italic\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\") {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") break;\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) thinkingBlocks.push(thinking);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t\tif (thinkingBlocks.length === 0) continue;\n\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show one static label for each adjacent run of thinking blocks.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Adjacent thinking blocks form one section instead of repeated visual chrome.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(thinkingBlocks.join(\"\\n\\n\"), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { Text } from "@caupulican/pi-tui";
2
+ export interface Expandable {
3
+ setExpanded(expanded: boolean): void;
4
+ }
5
+ export declare function isExpandable(value: unknown): value is Expandable;
6
+ export declare class ExpandableText extends Text implements Expandable {
7
+ private readonly getCollapsedText;
8
+ private readonly getExpandedText;
9
+ constructor(getCollapsedText: () => string, getExpandedText: () => string, expanded?: boolean, paddingX?: number, paddingY?: number);
10
+ setExpanded(expanded: boolean): void;
11
+ }
12
+ //# sourceMappingURL=expandable-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expandable-text.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/expandable-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,WAAW,UAAU;IAC1B,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAIhE;AAED,qBAAa,cAAe,SAAQ,IAAK,YAAW,UAAU;IAC7D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAe;IAChD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAE/C,YACC,gBAAgB,EAAE,MAAM,MAAM,EAC9B,eAAe,EAAE,MAAM,MAAM,EAC7B,QAAQ,UAAQ,EAChB,QAAQ,SAAI,EACZ,QAAQ,SAAI,EAKZ;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAEnC;CACD","sourcesContent":["import { Text } from \"@caupulican/pi-tui\";\n\nexport interface Expandable {\n\tsetExpanded(expanded: boolean): void;\n}\n\nexport function isExpandable(value: unknown): value is Expandable {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && \"setExpanded\" in value && typeof value.setExpanded === \"function\"\n\t);\n}\n\nexport class ExpandableText extends Text implements Expandable {\n\tprivate readonly getCollapsedText: () => string;\n\tprivate readonly getExpandedText: () => string;\n\n\tconstructor(\n\t\tgetCollapsedText: () => string,\n\t\tgetExpandedText: () => string,\n\t\texpanded = false,\n\t\tpaddingX = 0,\n\t\tpaddingY = 0,\n\t) {\n\t\tsuper(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);\n\t\tthis.getCollapsedText = getCollapsedText;\n\t\tthis.getExpandedText = getExpandedText;\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.setText(expanded ? this.getExpandedText() : this.getCollapsedText());\n\t}\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { Text } from "@caupulican/pi-tui";
2
+ export function isExpandable(value) {
3
+ return (typeof value === "object" && value !== null && "setExpanded" in value && typeof value.setExpanded === "function");
4
+ }
5
+ export class ExpandableText extends Text {
6
+ getCollapsedText;
7
+ getExpandedText;
8
+ constructor(getCollapsedText, getExpandedText, expanded = false, paddingX = 0, paddingY = 0) {
9
+ super(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);
10
+ this.getCollapsedText = getCollapsedText;
11
+ this.getExpandedText = getExpandedText;
12
+ }
13
+ setExpanded(expanded) {
14
+ this.setText(expanded ? this.getExpandedText() : this.getCollapsedText());
15
+ }
16
+ }
17
+ //# sourceMappingURL=expandable-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expandable-text.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/expandable-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAM1C,MAAM,UAAU,YAAY,CAAC,KAAc,EAAuB;IACjE,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,aAAa,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,UAAU,CAChH,CAAC;AAAA,CACF;AAED,MAAM,OAAO,cAAe,SAAQ,IAAI;IACtB,gBAAgB,CAAe;IAC/B,eAAe,CAAe;IAE/C,YACC,gBAA8B,EAC9B,eAA6B,EAC7B,QAAQ,GAAG,KAAK,EAChB,QAAQ,GAAG,CAAC,EACZ,QAAQ,GAAG,CAAC,EACX;QACD,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7E,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IAAA,CACvC;IAED,WAAW,CAAC,QAAiB,EAAQ;QACpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAAA,CAC1E;CACD","sourcesContent":["import { Text } from \"@caupulican/pi-tui\";\n\nexport interface Expandable {\n\tsetExpanded(expanded: boolean): void;\n}\n\nexport function isExpandable(value: unknown): value is Expandable {\n\treturn (\n\t\ttypeof value === \"object\" && value !== null && \"setExpanded\" in value && typeof value.setExpanded === \"function\"\n\t);\n}\n\nexport class ExpandableText extends Text implements Expandable {\n\tprivate readonly getCollapsedText: () => string;\n\tprivate readonly getExpandedText: () => string;\n\n\tconstructor(\n\t\tgetCollapsedText: () => string,\n\t\tgetExpandedText: () => string,\n\t\texpanded = false,\n\t\tpaddingX = 0,\n\t\tpaddingY = 0,\n\t) {\n\t\tsuper(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);\n\t\tthis.getCollapsedText = getCollapsedText;\n\t\tthis.getExpandedText = getExpandedText;\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.setText(expanded ? this.getExpandedText() : this.getCollapsedText());\n\t}\n}\n"]}
@@ -4,17 +4,31 @@
4
4
  */
5
5
  import { Container, type EditorOptions, type Focusable, type TUI } from "@caupulican/pi-tui";
6
6
  import type { KeybindingsManager } from "../../../core/keybindings.ts";
7
+ export interface ExtensionEditorOptions extends EditorOptions {
8
+ /** Visible owner-only content that must not enter editor history, autocomplete, or external files. */
9
+ privateContent?: boolean;
10
+ /** Muted reassurance/instruction shown immediately above the editor. */
11
+ notice?: string;
12
+ /** External editors create plaintext temporary files, so private editors always disable this. */
13
+ allowExternalEditor?: boolean;
14
+ /** Programmatic cancellation for tool-owned dialogs. */
15
+ signal?: AbortSignal;
16
+ }
7
17
  export declare class ExtensionEditorComponent extends Container implements Focusable {
8
18
  private editor;
9
19
  private onSubmitCallback;
10
20
  private onCancelCallback;
11
21
  private tui;
12
22
  private keybindings;
23
+ private readonly allowExternalEditor;
24
+ private readonly signal;
25
+ private readonly onAbort;
13
26
  private _focused;
14
27
  get focused(): boolean;
15
28
  set focused(value: boolean);
16
- constructor(tui: TUI, keybindings: KeybindingsManager, title: string, prefill: string | undefined, onSubmit: (value: string) => void, onCancel: () => void, options?: EditorOptions);
29
+ constructor(tui: TUI, keybindings: KeybindingsManager, title: string, prefill: string | undefined, onSubmit: (value: string) => void, onCancel: () => void, options?: ExtensionEditorOptions);
17
30
  handleInput(keyData: string): void;
18
31
  private openExternalEditor;
32
+ dispose(): void;
19
33
  }
20
34
  //# sourceMappingURL=extension-editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension-editor.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/extension-editor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACN,SAAS,EAET,KAAK,aAAa,EAClB,KAAK,SAAS,EAId,KAAK,GAAG,EACR,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAOvE,qBAAa,wBAAyB,SAAQ,SAAU,YAAW,SAAS;IAC3E,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,WAAW,CAAqB;IAExC,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,YACC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,QAAQ,EAAE,MAAM,IAAI,EACpB,OAAO,CAAC,EAAE,aAAa,EA6CvB;IAED,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAgBjC;YAEa,kBAAkB;CAkChC","sourcesContent":["/**\n * Multi-line editor component for extensions.\n * Supports Ctrl+G for external editor.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n\tContainer,\n\tEditor,\n\ttype EditorOptions,\n\ttype Focusable,\n\tgetKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@caupulican/pi-tui\";\nimport { getAgentDir } from \"../../../config.ts\";\nimport type { KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { runExternalEditor } from \"../../../utils/external-editor-command.ts\";\nimport { getProcessWorkRun } from \"../../../utils/work-directory.ts\";\nimport { getEditorTheme, theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\nexport class ExtensionEditorComponent extends Container implements Focusable {\n\tprivate editor: Editor;\n\tprivate onSubmitCallback: (value: string) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate tui: TUI;\n\tprivate keybindings: KeybindingsManager;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.editor.focused = value;\n\t}\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tkeybindings: KeybindingsManager,\n\t\ttitle: string,\n\t\tprefill: string | undefined,\n\t\tonSubmit: (value: string) => void,\n\t\tonCancel: () => void,\n\t\toptions?: EditorOptions,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.keybindings = keybindings;\n\t\tthis.onSubmitCallback = onSubmit;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add title\n\t\tthis.addChild(new Text(theme.fg(\"accent\", title), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create editor\n\t\tthis.editor = new Editor(tui, getEditorTheme(), options);\n\t\tif (prefill) {\n\t\t\tthis.editor.setText(prefill);\n\t\t}\n\t\t// Wire up Enter to submit (Shift+Enter for newlines, like the main editor)\n\t\tthis.editor.onSubmit = (text: string) => {\n\t\t\tthis.onSubmitCallback(text);\n\t\t};\n\t\tthis.addChild(this.editor);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add hint\n\t\tconst hasExternalEditor = !!(process.env.VISUAL || process.env.EDITOR);\n\t\tconst hint =\n\t\t\tkeyHint(\"tui.select.confirm\", \"submit\") +\n\t\t\t\" \" +\n\t\t\tkeyHint(\"tui.input.newLine\", \"newline\") +\n\t\t\t\" \" +\n\t\t\tkeyHint(\"tui.select.cancel\", \"cancel\") +\n\t\t\t(hasExternalEditor ? ` ${keyHint(\"app.editor.external\", \"external editor\")}` : \"\");\n\t\tthis.addChild(new Text(hint, 1, 0));\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Escape or Ctrl+C to cancel\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\t// External editor (app keybinding)\n\t\tif (this.keybindings.matches(keyData, \"app.editor.external\")) {\n\t\t\tthis.openExternalEditor();\n\t\t\treturn;\n\t\t}\n\n\t\t// Forward to editor\n\t\tthis.editor.handleInput(keyData);\n\t}\n\n\tprivate async openExternalEditor(): Promise<void> {\n\t\tconst editorCmd = process.env.VISUAL || process.env.EDITOR;\n\t\tif (!editorCmd) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentText = this.editor.getText();\n\t\tconst tmpFile = path.join(\n\t\t\tgetProcessWorkRun(getAgentDir(), \"editors\", \"extensions\").path,\n\t\t\t`pi-extension-editor-${randomUUID()}.md`,\n\t\t);\n\n\t\ttry {\n\t\t\tfs.writeFileSync(tmpFile, currentText, \"utf-8\");\n\t\t\tthis.tui.stop();\n\n\t\t\tprocess.stdout.write(`Launching external editor: ${editorCmd}\\nPi will resume when the editor exits.\\n`);\n\t\t\tconst status = await runExternalEditor(editorCmd, tmpFile);\n\n\t\t\tif (status === 0) {\n\t\t\t\tconst newContent = fs.readFileSync(tmpFile, \"utf-8\").replace(/\\n$/, \"\");\n\t\t\t\tthis.editor.setText(newContent);\n\t\t\t}\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tfs.unlinkSync(tmpFile);\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup errors\n\t\t\t}\n\t\t\tthis.tui.start();\n\t\t\t// Force full re-render since external editor uses alternate screen\n\t\t\tthis.tui.requestRender(true);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"extension-editor.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/extension-editor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,SAAS,EAET,KAAK,aAAa,EAClB,KAAK,SAAS,EAId,KAAK,GAAG,EACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAMvE,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC5D,sGAAsG;IACtG,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wDAAwD;IACxD,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,qBAAa,wBAAyB,SAAQ,SAAU,YAAW,SAAS;IAC3E,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAEnD,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,YACC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,QAAQ,EAAE,MAAM,IAAI,EACpB,OAAO,CAAC,EAAE,sBAAsB,EA0DhC;IAED,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAgBjC;YAEa,kBAAkB;IAsBhC,OAAO,IAAI,IAAI,CAGd;CACD","sourcesContent":["/**\n * Multi-line editor component for extensions.\n * Supports Ctrl+G for external editor.\n */\n\nimport {\n\tContainer,\n\tEditor,\n\ttype EditorOptions,\n\ttype Focusable,\n\tgetKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@caupulican/pi-tui\";\nimport type { KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { editInExternalEditor } from \"../external-editor.ts\";\nimport { getEditorTheme, theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\nexport interface ExtensionEditorOptions extends EditorOptions {\n\t/** Visible owner-only content that must not enter editor history, autocomplete, or external files. */\n\tprivateContent?: boolean;\n\t/** Muted reassurance/instruction shown immediately above the editor. */\n\tnotice?: string;\n\t/** External editors create plaintext temporary files, so private editors always disable this. */\n\tallowExternalEditor?: boolean;\n\t/** Programmatic cancellation for tool-owned dialogs. */\n\tsignal?: AbortSignal;\n}\n\nexport class ExtensionEditorComponent extends Container implements Focusable {\n\tprivate editor: Editor;\n\tprivate onSubmitCallback: (value: string) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate tui: TUI;\n\tprivate keybindings: KeybindingsManager;\n\tprivate readonly allowExternalEditor: boolean;\n\tprivate readonly signal: AbortSignal | undefined;\n\tprivate readonly onAbort: (() => void) | undefined;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.editor.focused = value;\n\t}\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tkeybindings: KeybindingsManager,\n\t\ttitle: string,\n\t\tprefill: string | undefined,\n\t\tonSubmit: (value: string) => void,\n\t\tonCancel: () => void,\n\t\toptions?: ExtensionEditorOptions,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.keybindings = keybindings;\n\t\tthis.onSubmitCallback = onSubmit;\n\t\tthis.onCancelCallback = onCancel;\n\t\tthis.allowExternalEditor = options?.privateContent ? false : (options?.allowExternalEditor ?? true);\n\t\tthis.signal = options?.signal;\n\t\tthis.onAbort = this.signal ? () => this.onCancelCallback() : undefined;\n\t\tif (this.onAbort) this.signal?.addEventListener(\"abort\", this.onAbort, { once: true });\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add title\n\t\tthis.addChild(new Text(theme.fg(\"accent\", title), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tconst notice =\n\t\t\toptions?.notice ??\n\t\t\t(options?.privateContent\n\t\t\t\t? \"Private editor · visible only in this terminal · not sent to the model\"\n\t\t\t\t: undefined);\n\t\tif (notice) {\n\t\t\tthis.addChild(new Text(theme.fg(\"muted\", notice), 1, 0));\n\t\t\tthis.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Create editor\n\t\tthis.editor = new Editor(tui, getEditorTheme(), options);\n\t\tif (prefill) {\n\t\t\tthis.editor.setText(prefill);\n\t\t}\n\t\t// Wire up Enter to submit (Shift+Enter for newlines, like the main editor)\n\t\tthis.editor.onSubmit = (text: string) => {\n\t\t\tthis.onSubmitCallback(text);\n\t\t};\n\t\tthis.addChild(this.editor);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add hint\n\t\tconst hasExternalEditor = this.allowExternalEditor && !!(process.env.VISUAL || process.env.EDITOR);\n\t\tconst hint =\n\t\t\tkeyHint(\"tui.select.confirm\", \"submit\") +\n\t\t\t\" \" +\n\t\t\tkeyHint(\"tui.input.newLine\", \"newline\") +\n\t\t\t\" \" +\n\t\t\tkeyHint(\"tui.select.cancel\", \"cancel\") +\n\t\t\t(hasExternalEditor ? ` ${keyHint(\"app.editor.external\", \"external editor\")}` : \"\");\n\t\tthis.addChild(new Text(hint, 1, 0));\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Escape or Ctrl+C to cancel\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\t// External editor (app keybinding)\n\t\tif (this.keybindings.matches(keyData, \"app.editor.external\")) {\n\t\t\tif (this.allowExternalEditor) this.openExternalEditor();\n\t\t\treturn;\n\t\t}\n\n\t\t// Forward to editor\n\t\tthis.editor.handleInput(keyData);\n\t}\n\n\tprivate async openExternalEditor(): Promise<void> {\n\t\tif (!this.allowExternalEditor) return;\n\t\tconst editorCmd = process.env.VISUAL || process.env.EDITOR;\n\t\tif (!editorCmd) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentText = this.editor.getText();\n\n\t\ttry {\n\t\t\tthis.tui.stop();\n\t\t\tconst result = await editInExternalEditor({ command: editorCmd, content: currentText });\n\t\t\tif (result.status === \"complete\") {\n\t\t\t\tthis.editor.setText(result.content);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.tui.start();\n\t\t\t// Force full re-render since external editor uses alternate screen\n\t\t\tthis.tui.requestRender(true);\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tif (this.onAbort) this.signal?.removeEventListener(\"abort\", this.onAbort);\n\t\tthis.editor.clear();\n\t}\n}\n"]}