@adecore/agents-react 0.31.12 → 0.32.0

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 (402) hide show
  1. package/dist/agents/AccountDot.js +57 -6
  2. package/dist/agents/AgentIcon.js +88 -12
  3. package/dist/agents/ModelOptionControl.js +153 -18
  4. package/dist/agents/ProviderLogo.js +49 -4
  5. package/dist/agents/account-limits.js +17 -14
  6. package/dist/agents/accounts.js +99 -67
  7. package/dist/agents/agent-marks.js +5 -3
  8. package/dist/agents/model-name.js +42 -31
  9. package/dist/agents/model-options.js +8 -8
  10. package/dist/agents/model-requirement.js +17 -14
  11. package/dist/agents/option-words.d.ts +7 -0
  12. package/dist/agents/option-words.js +35 -0
  13. package/dist/agents/provider-paths.js +6 -6
  14. package/dist/agents/status-look.js +32 -12
  15. package/dist/chat/account-choice.d.ts +13 -0
  16. package/dist/chat/account-choice.js +90 -20
  17. package/dist/chat/actions.js +126 -59
  18. package/dist/chat/activity.js +5 -5
  19. package/dist/chat/attachments.js +74 -53
  20. package/dist/chat/bookmarks.js +58 -48
  21. package/dist/chat/chat-client.js +344 -263
  22. package/dist/chat/chat-references.js +3 -3
  23. package/dist/chat/composer-effort.d.ts +5 -0
  24. package/dist/chat/composer-effort.js +26 -0
  25. package/dist/chat/composer-send.js +13 -13
  26. package/dist/chat/drafts.js +115 -79
  27. package/dist/chat/forks.js +81 -24
  28. package/dist/chat/guards.js +15 -43
  29. package/dist/chat/index.d.ts +3 -1
  30. package/dist/chat/index.js +3 -2
  31. package/dist/chat/logic/ansi.js +170 -167
  32. package/dist/chat/logic/answers.js +2 -2
  33. package/dist/chat/logic/bookmarks.js +19 -19
  34. package/dist/chat/logic/command-looks.js +138 -96
  35. package/dist/chat/logic/context-usage.js +13 -9
  36. package/dist/chat/logic/continue-after-stop.js +15 -19
  37. package/dist/chat/logic/effort.d.ts +14 -0
  38. package/dist/chat/logic/effort.js +34 -0
  39. package/dist/chat/logic/embedded-code.js +387 -326
  40. package/dist/chat/logic/fork.js +134 -110
  41. package/dist/chat/logic/generated-image.js +54 -23
  42. package/dist/chat/logic/goal.js +28 -20
  43. package/dist/chat/logic/handback.js +6 -6
  44. package/dist/chat/logic/json.js +2 -2
  45. package/dist/chat/logic/limit.js +46 -30
  46. package/dist/chat/logic/picker-entries.d.ts +5 -3
  47. package/dist/chat/logic/picker-entries.js +83 -43
  48. package/dist/chat/logic/resume-compaction.d.ts +14 -1
  49. package/dist/chat/logic/resume-compaction.js +93 -24
  50. package/dist/chat/logic/scrubber.js +188 -136
  51. package/dist/chat/logic/thought.js +13 -16
  52. package/dist/chat/logic/thread-cards.js +60 -48
  53. package/dist/chat/logic/timeline-copy.js +30 -38
  54. package/dist/chat/logic/timeline-target.js +92 -63
  55. package/dist/chat/logic/timeline.js +499 -355
  56. package/dist/chat/logic/tool-catalog.js +54 -34
  57. package/dist/chat/logic/tools.js +106 -82
  58. package/dist/chat/logic/visual-height.js +18 -18
  59. package/dist/chat/logic/visual-viewport.js +6 -3
  60. package/dist/chat/logic/welcome.js +9 -9
  61. package/dist/chat/logic/workflow.js +45 -34
  62. package/dist/chat/mentions.js +149 -109
  63. package/dist/chat/persisted-json.js +51 -54
  64. package/dist/chat/preferences.d.ts +4 -0
  65. package/dist/chat/preferences.js +162 -84
  66. package/dist/chat/prompt-hold.js +9 -9
  67. package/dist/chat/quote.js +21 -30
  68. package/dist/chat/reading-width.js +12 -10
  69. package/dist/chat/recent-messages.js +34 -21
  70. package/dist/chat/resume-compaction-dismissals.js +25 -5
  71. package/dist/chat/runtime-modes.js +3 -3
  72. package/dist/chat/send-key.js +11 -7
  73. package/dist/chat/stash.js +89 -69
  74. package/dist/chat/subagent-conversation.js +181 -139
  75. package/dist/chat/subagent-list.js +65 -67
  76. package/dist/chat/subagent-support.js +12 -7
  77. package/dist/chat/subagent-view.js +132 -44
  78. package/dist/chat/thumbnails.js +88 -60
  79. package/dist/chat/timeline-flash.js +24 -12
  80. package/dist/chat/timeline-scroll.js +116 -86
  81. package/dist/chat/ui/AccountPill.js +126 -15
  82. package/dist/chat/ui/AnsiOutput.js +62 -6
  83. package/dist/chat/ui/BookmarkMarker.js +231 -41
  84. package/dist/chat/ui/BookmarkSubmenu.js +165 -18
  85. package/dist/chat/ui/ChatActivity.js +649 -70
  86. package/dist/chat/ui/ChatReferenceChip.js +104 -9
  87. package/dist/chat/ui/CodeBlock.js +132 -58
  88. package/dist/chat/ui/Composer.js +866 -132
  89. package/dist/chat/ui/ComposerInput.js +309 -120
  90. package/dist/chat/ui/DiffPool.js +75 -14
  91. package/dist/chat/ui/EditDiff.js +160 -21
  92. package/dist/chat/ui/FadingWords.js +32 -3
  93. package/dist/chat/ui/GoalDock.js +235 -42
  94. package/dist/chat/ui/ImageView.js +617 -61
  95. package/dist/chat/ui/LimitState.js +446 -72
  96. package/dist/chat/ui/Markdown.js +991 -173
  97. package/dist/chat/ui/MermaidBlock.js +238 -68
  98. package/dist/chat/ui/MessageActions.js +251 -39
  99. package/dist/chat/ui/ModelMarks.js +55 -5
  100. package/dist/chat/ui/Pickers.js +664 -113
  101. package/dist/chat/ui/PromptComposer.js +281 -51
  102. package/dist/chat/ui/QuoteButton.js +151 -57
  103. package/dist/chat/ui/ResumeCompactionDock.d.ts +6 -2
  104. package/dist/chat/ui/ResumeCompactionDock.js +141 -6
  105. package/dist/chat/ui/RowTime.js +59 -5
  106. package/dist/chat/ui/RunSettings.js +1744 -154
  107. package/dist/chat/ui/Scrubber.js +517 -88
  108. package/dist/chat/ui/ShellCommand.js +183 -107
  109. package/dist/chat/ui/SubagentControls.js +212 -24
  110. package/dist/chat/ui/SubagentInfo.js +170 -13
  111. package/dist/chat/ui/SubagentStopButton.js +115 -24
  112. package/dist/chat/ui/SubagentTimeline.js +357 -91
  113. package/dist/chat/ui/Timeline.js +988 -476
  114. package/dist/chat/ui/TimelineMenu.js +552 -37
  115. package/dist/chat/ui/UnifiedDiff.js +234 -27
  116. package/dist/chat/ui/UploadThumb.js +37 -7
  117. package/dist/chat/ui/VisualDialogs.js +251 -20
  118. package/dist/chat/ui/VisualFrame.js +321 -95
  119. package/dist/chat/ui/Welcome.js +72 -7
  120. package/dist/chat/ui/chips.js +1 -1
  121. package/dist/chat/ui/code-lines.js +36 -36
  122. package/dist/chat/ui/code-streaming.js +1 -1
  123. package/dist/chat/ui/code-theme.js +7 -7
  124. package/dist/chat/ui/composer/ComposerControls.js +329 -21
  125. package/dist/chat/ui/composer/ComposerMenu.js +358 -30
  126. package/dist/chat/ui/composer/DraftParts.js +185 -11
  127. package/dist/chat/ui/composer/QueuedMessages.js +138 -13
  128. package/dist/chat/ui/composer/chips.js +29 -19
  129. package/dist/chat/ui/composer/editor.js +79 -63
  130. package/dist/chat/ui/composer/insert.js +26 -12
  131. package/dist/chat/ui/composer/key-handler.js +180 -127
  132. package/dist/chat/ui/composer/keys.js +90 -73
  133. package/dist/chat/ui/composer/menu-aria.js +18 -9
  134. package/dist/chat/ui/composer/placeholder.js +78 -31
  135. package/dist/chat/ui/composer/surface.js +13 -37
  136. package/dist/chat/ui/composer/use-chat-controls.js +230 -90
  137. package/dist/chat/ui/composer/use-compaction-offer.js +50 -18
  138. package/dist/chat/ui/composer/use-composer-draft.js +65 -34
  139. package/dist/chat/ui/composer/use-composer-menus.js +478 -193
  140. package/dist/chat/ui/composer/use-composer-submit.js +251 -109
  141. package/dist/chat/ui/composer/use-continuable-turn.js +33 -6
  142. package/dist/chat/ui/composer/use-draft-files.js +245 -93
  143. package/dist/chat/ui/composer/use-effort-stepper.d.ts +13 -0
  144. package/dist/chat/ui/composer/use-effort-stepper.js +88 -0
  145. package/dist/chat/ui/composer/use-notice.js +61 -16
  146. package/dist/chat/ui/composer/use-pending-requests.js +38 -17
  147. package/dist/chat/ui/composer/use-prompt-history.js +117 -45
  148. package/dist/chat/ui/composer/use-prompt-hold.js +119 -35
  149. package/dist/chat/ui/composer/use-take-back.js +94 -72
  150. package/dist/chat/ui/diff/ApprovalReview.js +101 -23
  151. package/dist/chat/ui/diff/DiffFallbackBoundary.js +21 -13
  152. package/dist/chat/ui/diff/DiffOmitted.js +56 -6
  153. package/dist/chat/ui/diff/DiffStack.js +92 -8
  154. package/dist/chat/ui/diff/DiffUnavailable.js +56 -6
  155. package/dist/chat/ui/diff/EditorEditDiff.js +263 -51
  156. package/dist/chat/ui/diff/EditorPatchDiff.js +39 -14
  157. package/dist/chat/ui/diff/LegacyDiffPool.js +27 -10
  158. package/dist/chat/ui/diff/LegacyEditDiff.js +97 -20
  159. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +172 -42
  160. package/dist/chat/ui/diff/RawDiff.js +65 -5
  161. package/dist/chat/ui/diff/ReviewDiff.js +77 -5
  162. package/dist/chat/ui/diff/diff-props.js +1 -1
  163. package/dist/chat/ui/diff/diff-source-budget.js +46 -35
  164. package/dist/chat/ui/diff/editor-edit-model.js +18 -14
  165. package/dist/chat/ui/diff/review-plan.js +63 -40
  166. package/dist/chat/ui/diff/review-settle.js +24 -9
  167. package/dist/chat/ui/diff/syntax-runtime.js +236 -201
  168. package/dist/chat/ui/diff/use-review-stack.js +146 -25
  169. package/dist/chat/ui/diff-syntax.js +70 -58
  170. package/dist/chat/ui/diff-theme.js +31 -12
  171. package/dist/chat/ui/file-links.js +39 -10
  172. package/dist/chat/ui/find-reveal.js +29 -8
  173. package/dist/chat/ui/full-diff.js +17 -12
  174. package/dist/chat/ui/highlighter.js +143 -113
  175. package/dist/chat/ui/icons.js +16 -7
  176. package/dist/chat/ui/index.js +1 -1
  177. package/dist/chat/ui/intelligent-ui/UiBlockFrame.js +556 -82
  178. package/dist/chat/ui/intelligent-ui/UiFallbackPart.js +73 -5
  179. package/dist/chat/ui/intelligent-ui/UiReply.js +666 -262
  180. package/dist/chat/ui/intelligent-ui/block-local.js +59 -31
  181. package/dist/chat/ui/intelligent-ui/chart-data.js +77 -67
  182. package/dist/chat/ui/intelligent-ui/node-text.js +77 -91
  183. package/dist/chat/ui/intelligent-ui/registry.js +46 -46
  184. package/dist/chat/ui/intelligent-ui/render-context.js +1 -1
  185. package/dist/chat/ui/intelligent-ui/renderers/base-land.js +1 -1
  186. package/dist/chat/ui/intelligent-ui/renderers/binding.js +3 -3
  187. package/dist/chat/ui/intelligent-ui/renderers/chart.js +1223 -123
  188. package/dist/chat/ui/intelligent-ui/renderers/choices.js +312 -34
  189. package/dist/chat/ui/intelligent-ui/renderers/content.js +1241 -86
  190. package/dist/chat/ui/intelligent-ui/renderers/data.js +619 -54
  191. package/dist/chat/ui/intelligent-ui/renderers/inputs.js +868 -67
  192. package/dist/chat/ui/intelligent-ui/renderers/links.js +366 -62
  193. package/dist/chat/ui/intelligent-ui/renderers/map-slots.js +118 -60
  194. package/dist/chat/ui/intelligent-ui/renderers/map-style.js +85 -78
  195. package/dist/chat/ui/intelligent-ui/renderers/map-view.js +282 -217
  196. package/dist/chat/ui/intelligent-ui/renderers/map.js +621 -69
  197. package/dist/chat/ui/intelligent-ui/renderers/place-point.js +15 -8
  198. package/dist/chat/ui/intelligent-ui/renderers/structure.js +262 -20
  199. package/dist/chat/ui/intelligent-ui/renderers/text.js +674 -49
  200. package/dist/chat/ui/intelligent-ui/reply-parts.js +24 -15
  201. package/dist/chat/ui/intelligent-ui/table-data.js +97 -57
  202. package/dist/chat/ui/intelligent-ui/tones.js +31 -31
  203. package/dist/chat/ui/intelligent-ui/use-in-view.js +30 -12
  204. package/dist/chat/ui/intelligent-ui/use-later.js +28 -13
  205. package/dist/chat/ui/intelligent-ui/use-truncated.js +45 -21
  206. package/dist/chat/ui/intelligent-ui/use-ui-links.js +296 -109
  207. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +256 -246
  208. package/dist/chat/ui/markdown-blocks.js +296 -262
  209. package/dist/chat/ui/mermaid.js +60 -72
  210. package/dist/chat/ui/quote-selection.js +32 -29
  211. package/dist/chat/ui/rehype-chips.js +35 -23
  212. package/dist/chat/ui/rehype-fade.js +28 -17
  213. package/dist/chat/ui/remark-html-as-text.js +22 -15
  214. package/dist/chat/ui/reply-context.js +1 -1
  215. package/dist/chat/ui/reveal.js +161 -72
  216. package/dist/chat/ui/rows/ForksRow.js +226 -24
  217. package/dist/chat/ui/rows/GeneratedImageRow.js +541 -87
  218. package/dist/chat/ui/rows/MessageRows.js +1706 -159
  219. package/dist/chat/ui/rows/RowContainer.js +57 -7
  220. package/dist/chat/ui/rows/Rows.js +463 -54
  221. package/dist/chat/ui/rows/SubagentRow.js +577 -60
  222. package/dist/chat/ui/rows/TaskRow.js +359 -40
  223. package/dist/chat/ui/rows/VisualRow.js +233 -11
  224. package/dist/chat/ui/rows/WorkRows.js +1945 -164
  225. package/dist/chat/ui/rows/WorkflowRow.js +293 -34
  226. package/dist/chat/ui/rows/row-rhythm.js +27 -17
  227. package/dist/chat/ui/theme-watch.js +26 -23
  228. package/dist/chat/ui/timestamp-format.js +4 -1
  229. package/dist/chat/ui/use-diff-source-tokens.js +70 -34
  230. package/dist/chat/ui/useToggleSet.js +51 -19
  231. package/dist/chat/ui/visual-theme.js +153 -128
  232. package/dist/chat/visual-bridge.js +123 -123
  233. package/dist/chat/visual-viewport.js +94 -83
  234. package/dist/chat/visuals.js +13 -5
  235. package/dist/host-hooks.d.ts +29 -0
  236. package/dist/host-hooks.js +78 -0
  237. package/dist/host.js +120 -48
  238. package/dist/index.js +1 -1
  239. package/dist/lazy.js +38 -32
  240. package/dist/locales/en/agent-chat.d.ts +34 -0
  241. package/dist/locales/en/agent-chat.js +747 -713
  242. package/dist/locales/en/agent-prompts.js +42 -42
  243. package/dist/locales/en/agent-providers.d.ts +1 -0
  244. package/dist/locales/en/agent-providers.js +166 -165
  245. package/dist/locales/en/agent-usage.d.ts +6 -0
  246. package/dist/locales/en/agent-usage.js +129 -123
  247. package/dist/locales/nl/agent-chat.d.ts +34 -0
  248. package/dist/locales/nl/agent-chat.js +747 -713
  249. package/dist/locales/nl/agent-prompts.js +42 -42
  250. package/dist/locales/nl/agent-providers.d.ts +1 -0
  251. package/dist/locales/nl/agent-providers.js +166 -165
  252. package/dist/locales/nl/agent-usage.d.ts +6 -0
  253. package/dist/locales/nl/agent-usage.js +129 -123
  254. package/dist/locales.js +14 -14
  255. package/dist/mounted-registry.js +31 -30
  256. package/dist/port-transport.js +122 -111
  257. package/dist/prompts/index.js +1 -1
  258. package/dist/prompts/logic/focus.js +15 -14
  259. package/dist/prompts/logic/keys.js +93 -59
  260. package/dist/prompts/logic/prompts.js +27 -14
  261. package/dist/prompts/logic/subjects.js +60 -46
  262. package/dist/prompts/logic/useFocusAfterAnswer.js +60 -20
  263. package/dist/prompts/logic/usePromptSession.js +88 -77
  264. package/dist/prompts/ui/ApprovalBody.js +246 -27
  265. package/dist/prompts/ui/PromptActions.js +215 -9
  266. package/dist/prompts/ui/PromptCard.js +215 -36
  267. package/dist/prompts/ui/PromptView.js +372 -34
  268. package/dist/prompts/ui/QuestionBody.js +269 -73
  269. package/dist/providers/AccountColors.js +36 -5
  270. package/dist/providers/AccountDetail.js +683 -50
  271. package/dist/providers/AccountVariables.js +139 -32
  272. package/dist/providers/AddAccountForm.js +125 -38
  273. package/dist/providers/CliDetail.js +343 -36
  274. package/dist/providers/InstallPage.js +644 -59
  275. package/dist/providers/ProviderList.d.ts +2 -1
  276. package/dist/providers/ProviderList.js +215 -23
  277. package/dist/providers/ProvidersPane.d.ts +4 -2
  278. package/dist/providers/ProvidersPane.js +244 -64
  279. package/dist/providers/account-actions.js +54 -30
  280. package/dist/providers/index.js +1 -1
  281. package/dist/providers/install-steps.js +12 -9
  282. package/dist/providers/pane-target.d.ts +3 -0
  283. package/dist/providers/pane-target.js +34 -13
  284. package/dist/providers/parts.js +62 -12
  285. package/dist/providers/provider-abilities.js +5 -5
  286. package/dist/providers/provider-groups.js +75 -40
  287. package/dist/providers/variables.js +73 -39
  288. package/dist/scope.js +6 -6
  289. package/dist/settings/sections.js +18 -18
  290. package/dist/state/chats.js +404 -192
  291. package/dist/state/index.js +1 -1
  292. package/dist/state/provider-accounts.js +70 -47
  293. package/dist/state/providers.js +45 -16
  294. package/dist/state/usage.js +154 -77
  295. package/dist/storage.js +69 -68
  296. package/dist/testing/index.js +1 -1
  297. package/dist/testing/prompts.js +105 -67
  298. package/dist/transport.js +10 -10
  299. package/dist/ui/PlainTextarea.js +27 -3
  300. package/dist/usage/LimitsList.js +646 -40
  301. package/dist/usage/UsageBreakdown.js +879 -38
  302. package/dist/usage/UsageChart.js +311 -32
  303. package/dist/usage/UsageDialog.js +46 -4
  304. package/dist/usage/UsageLimits.js +467 -34
  305. package/dist/usage/UsageLimitsCard.js +95 -11
  306. package/dist/usage/UsagePage.js +817 -96
  307. package/dist/usage/UsagePane.js +164 -10
  308. package/dist/usage/UsageSummary.js +151 -6
  309. package/dist/usage/UsageTiles.js +164 -14
  310. package/dist/usage/format.js +32 -32
  311. package/dist/usage/index.d.ts +1 -1
  312. package/dist/usage/index.js +2 -1
  313. package/dist/usage/limit-groups.d.ts +2 -0
  314. package/dist/usage/limit-groups.js +77 -59
  315. package/dist/usage/limits.js +78 -43
  316. package/dist/usage/money.js +20 -4
  317. package/dist/usage/summary.js +85 -64
  318. package/package.json +8 -8
  319. package/src/agents/ModelOptionControl.tsx +3 -1
  320. package/src/agents/option-words.ts +27 -0
  321. package/src/chat/account-choice.ts +41 -1
  322. package/src/chat/composer-effort.ts +32 -0
  323. package/src/chat/forks.ts +4 -5
  324. package/src/chat/index.ts +3 -1
  325. package/src/chat/logic/effort.ts +32 -0
  326. package/src/chat/logic/picker-entries.ts +45 -10
  327. package/src/chat/logic/resume-compaction.ts +95 -17
  328. package/src/chat/logic/timeline.ts +11 -3
  329. package/src/chat/preferences.ts +35 -0
  330. package/src/chat/subagent-view.ts +2 -3
  331. package/src/chat/ui/AnsiOutput.tsx +1 -2
  332. package/src/chat/ui/BookmarkSubmenu.tsx +3 -3
  333. package/src/chat/ui/ChatActivity.tsx +14 -22
  334. package/src/chat/ui/ChatReferenceChip.tsx +2 -3
  335. package/src/chat/ui/Composer.tsx +15 -7
  336. package/src/chat/ui/EditDiff.tsx +2 -3
  337. package/src/chat/ui/LimitState.tsx +2 -2
  338. package/src/chat/ui/Markdown.tsx +10 -8
  339. package/src/chat/ui/MermaidBlock.tsx +2 -3
  340. package/src/chat/ui/Pickers.tsx +49 -29
  341. package/src/chat/ui/PromptComposer.tsx +7 -9
  342. package/src/chat/ui/ResumeCompactionDock.tsx +16 -4
  343. package/src/chat/ui/RunSettings.tsx +67 -28
  344. package/src/chat/ui/Scrubber.tsx +3 -3
  345. package/src/chat/ui/ShellCommand.tsx +2 -0
  346. package/src/chat/ui/SubagentInfo.tsx +2 -3
  347. package/src/chat/ui/SubagentTimeline.tsx +12 -16
  348. package/src/chat/ui/Timeline.tsx +6 -6
  349. package/src/chat/ui/UnifiedDiff.tsx +3 -4
  350. package/src/chat/ui/VisualFrame.tsx +5 -8
  351. package/src/chat/ui/code-theme.ts +4 -4
  352. package/src/chat/ui/composer/placeholder.ts +2 -2
  353. package/src/chat/ui/composer/use-compaction-offer.ts +36 -16
  354. package/src/chat/ui/composer/use-composer-menus.ts +4 -9
  355. package/src/chat/ui/composer/use-composer-submit.ts +2 -1
  356. package/src/chat/ui/composer/use-effort-stepper.ts +56 -0
  357. package/src/chat/ui/composer/use-notice.ts +2 -2
  358. package/src/chat/ui/diff/EditorEditDiff.tsx +9 -13
  359. package/src/chat/ui/diff/LegacyEditDiff.tsx +12 -17
  360. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +13 -21
  361. package/src/chat/ui/diff/use-review-stack.ts +4 -4
  362. package/src/chat/ui/diff-theme.ts +3 -3
  363. package/src/chat/ui/file-links.ts +2 -2
  364. package/src/chat/ui/intelligent-ui/UiReply.tsx +2 -0
  365. package/src/chat/ui/intelligent-ui/renderers/chart.tsx +3 -3
  366. package/src/chat/ui/intelligent-ui/renderers/content.tsx +5 -6
  367. package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +2 -1
  368. package/src/chat/ui/intelligent-ui/renderers/map.tsx +2 -1
  369. package/src/chat/ui/intelligent-ui/use-truncated.ts +16 -19
  370. package/src/chat/ui/intelligent-ui/use-ui-links.ts +3 -3
  371. package/src/chat/ui/rows/ForksRow.tsx +3 -5
  372. package/src/chat/ui/rows/GeneratedImageRow.tsx +2 -1
  373. package/src/chat/ui/rows/MessageRows.tsx +12 -21
  374. package/src/chat/ui/rows/SubagentRow.tsx +3 -3
  375. package/src/chat/ui/rows/TaskRow.tsx +1 -1
  376. package/src/chat/ui/rows/WorkRows.tsx +10 -5
  377. package/src/chat/ui/useToggleSet.ts +15 -18
  378. package/src/chat/ui/visual-theme.ts +2 -3
  379. package/src/host-hooks.ts +113 -0
  380. package/src/lazy.tsx +2 -0
  381. package/src/locales/en/agent-chat.ts +134 -108
  382. package/src/locales/en/agent-prompts.ts +7 -7
  383. package/src/locales/en/agent-providers.ts +35 -34
  384. package/src/locales/en/agent-usage.ts +26 -20
  385. package/src/locales/nl/agent-chat.ts +126 -100
  386. package/src/locales/nl/agent-prompts.ts +5 -5
  387. package/src/locales/nl/agent-providers.ts +33 -32
  388. package/src/locales/nl/agent-usage.ts +25 -20
  389. package/src/providers/CliDetail.tsx +2 -1
  390. package/src/providers/InstallPage.tsx +2 -4
  391. package/src/providers/ProviderList.tsx +12 -2
  392. package/src/providers/ProvidersPane.tsx +45 -15
  393. package/src/providers/pane-target.ts +20 -4
  394. package/src/state/chats.ts +2 -2
  395. package/src/usage/LimitsList.tsx +12 -13
  396. package/src/usage/UsageBreakdown.tsx +17 -6
  397. package/src/usage/UsageLimits.tsx +2 -1
  398. package/src/usage/UsagePage.tsx +3 -3
  399. package/src/usage/index.ts +1 -1
  400. package/src/usage/limit-groups.ts +12 -0
  401. package/src/usage/limits.ts +2 -2
  402. package/src/usage/money.ts +1 -2
@@ -1,14 +1,14 @@
1
1
  import { Bot, Eye, FolderSearch, Globe, ListTodo, Search, SquarePen, Terminal, Workflow, Zap } from 'lucide-react';
2
2
  function entry(icon, summary, rest = {}) {
3
- return {
4
- icon,
5
- summary,
6
- grouped: true,
7
- changesFiles: false,
8
- readsImage: false,
9
- shell: false,
10
- ...rest
11
- };
3
+ return {
4
+ icon,
5
+ summary,
6
+ grouped: true,
7
+ changesFiles: false,
8
+ readsImage: false,
9
+ shell: false,
10
+ ...rest
11
+ };
12
12
  }
13
13
  /*
14
14
  * Every tool the thread has a word for, in one table so a new name is never missing from a lookup. A
@@ -16,30 +16,50 @@ function entry(icon, summary, rest = {}) {
16
16
  * string of its input.
17
17
  */
18
18
  export const TOOL_CATALOG = {
19
- Read: entry(Eye, ['file_path'], { readsImage: true }),
20
- // Only `readImagePath` ever had this one, which is why it has no sentence of its own yet.
21
- NotebookRead: entry(Eye, ['file_path', 'notebook_path'], { grouped: false, readsImage: true }),
22
- // These three read as "Edited 3 files" through `changesFiles`, so they carry no copy of that sentence.
23
- Edit: entry(SquarePen, ['file_path'], { grouped: false, changesFiles: true }),
24
- Write: entry(SquarePen, ['file_path'], { changesFiles: true }),
25
- MultiEdit: entry(SquarePen, ['file_path'], { grouped: false, changesFiles: true }),
26
- NotebookEdit: entry(SquarePen, ['file_path', 'notebook_path']),
27
- // Codex reports a patch as the paths it touches; its own input carries no path of its own.
28
- ApplyPatch: entry(SquarePen, ['summary'], { grouped: false, changesFiles: true }),
29
- // Codex's command executions arrive under this name too.
30
- Bash: entry(Terminal, ['description', 'command'], { shell: true }),
31
- Grep: entry(Search, ['pattern']),
32
- Glob: entry(FolderSearch, ['pattern']),
33
- WebFetch: entry(Globe, ['url', 'query']),
34
- WebSearch: entry(Globe, ['url', 'query']),
35
- Task: entry(Bot, ['description']),
36
- Agent: entry(Bot, ['description']),
37
- Skill: entry(Zap, ['skill']),
38
- // A plan is a list of objects, so there is no line to lift out of it.
39
- TodoWrite: entry(ListTodo, []),
40
- // Its input is the whole script; the line takes what the CLI says the workflow is about instead.
41
- Workflow: entry(Workflow, [], { grouped: false })
19
+ Read: entry(Eye, ['file_path'], {
20
+ readsImage: true
21
+ }),
22
+ // Only `readImagePath` ever had this one, which is why it has no sentence of its own yet.
23
+ NotebookRead: entry(Eye, ['file_path', 'notebook_path'], {
24
+ grouped: false,
25
+ readsImage: true
26
+ }),
27
+ // These three read as "Edited 3 files" through `changesFiles`, so they carry no copy of that sentence.
28
+ Edit: entry(SquarePen, ['file_path'], {
29
+ grouped: false,
30
+ changesFiles: true
31
+ }),
32
+ Write: entry(SquarePen, ['file_path'], {
33
+ changesFiles: true
34
+ }),
35
+ MultiEdit: entry(SquarePen, ['file_path'], {
36
+ grouped: false,
37
+ changesFiles: true
38
+ }),
39
+ NotebookEdit: entry(SquarePen, ['file_path', 'notebook_path']),
40
+ // Codex reports a patch as the paths it touches; its own input carries no path of its own.
41
+ ApplyPatch: entry(SquarePen, ['summary'], {
42
+ grouped: false,
43
+ changesFiles: true
44
+ }),
45
+ // Codex's command executions arrive under this name too.
46
+ Bash: entry(Terminal, ['description', 'command'], {
47
+ shell: true
48
+ }),
49
+ Grep: entry(Search, ['pattern']),
50
+ Glob: entry(FolderSearch, ['pattern']),
51
+ WebFetch: entry(Globe, ['url', 'query']),
52
+ WebSearch: entry(Globe, ['url', 'query']),
53
+ Task: entry(Bot, ['description']),
54
+ Agent: entry(Bot, ['description']),
55
+ Skill: entry(Zap, ['skill']),
56
+ // A plan is a list of objects, so there is no line to lift out of it.
57
+ TodoWrite: entry(ListTodo, []),
58
+ // Its input is the whole script; the line takes what the CLI says the workflow is about instead.
59
+ Workflow: entry(Workflow, [], {
60
+ grouped: false
61
+ })
42
62
  };
43
63
  export function toolEntry(name) {
44
- return TOOL_CATALOG[name];
45
- }
64
+ return TOOL_CATALOG[name];
65
+ }
@@ -1,139 +1,163 @@
1
1
  import { isRecord } from './json.js';
2
2
  import { toolEntry } from './tool-catalog.js';
3
3
  function str(value) {
4
- return typeof value === 'string' ? value : null;
4
+ return typeof value === 'string' ? value : null;
5
5
  }
6
6
  /* The one line that says what a tool call is about: the command, the file, the pattern. */
7
7
  export function toolSummary(name, input) {
8
- if (!isRecord(input)) {
9
- return '';
10
- }
11
- const known = toolEntry(name);
12
- if (known === undefined) {
13
- // A tool nobody wrote down, an MCP one above all, gets its best guess from the first string it was given.
14
- const first = Object.values(input).find((value) => typeof value === 'string');
15
- return typeof first === 'string' ? first : '';
16
- }
17
- for (const key of known.summary) {
18
- const value = str(input[key]);
19
- if (value !== null) {
20
- return value;
21
- }
22
- }
8
+ if (!isRecord(input)) {
23
9
  return '';
10
+ }
11
+ const known = toolEntry(name);
12
+ if (known === undefined) {
13
+ // A tool nobody wrote down, an MCP one above all, gets its best guess from the first string it was given.
14
+ const first = Object.values(input).find(value => typeof value === 'string');
15
+ return typeof first === 'string' ? first : '';
16
+ }
17
+ for (const key of known.summary) {
18
+ const value = str(input[key]);
19
+ if (value !== null) {
20
+ return value;
21
+ }
22
+ }
23
+ return '';
24
24
  }
25
25
  // The input keys whose value is a file a call is about.
26
26
  const PATH_KEYS = new Set(['file_path', 'notebook_path']);
27
27
  /* Whether the one line of a call is the path of a file, which a row cuts in the middle so the name stays. */
28
28
  export function toolSummaryIsPath(name, input) {
29
- const known = toolEntry(name);
30
- if (known === undefined || !isRecord(input)) {
31
- return false;
32
- }
33
- const key = known.summary.find((candidate) => str(input[candidate]) !== null);
34
- return key !== undefined && PATH_KEYS.has(key);
29
+ const known = toolEntry(name);
30
+ if (known === undefined || !isRecord(input)) {
31
+ return false;
32
+ }
33
+ const key = known.summary.find(candidate => str(input[candidate]) !== null);
34
+ return key !== undefined && PATH_KEYS.has(key);
35
35
  }
36
36
  /* The command of a shell call, as it was run; null for any other call or one without a command. */
37
37
  export function shellCommand(name, input) {
38
- if (toolEntry(name)?.shell !== true || !isRecord(input)) {
39
- return null;
40
- }
41
- const command = str(input.command);
42
- return command === null || command.trim() === '' ? null : command;
38
+ if (toolEntry(name)?.shell !== true || !isRecord(input)) {
39
+ return null;
40
+ }
41
+ const command = str(input.command);
42
+ return command === null || command.trim() === '' ? null : command;
43
43
  }
44
44
  // A shell call's description is already the detail of its row.
45
45
  const SHELL_SHOWN = new Set(['command', 'description']);
46
46
  function valueText(value) {
47
- // An empty string can be the point of a call (clearing a field), so it shows as one.
48
- return typeof value === 'string' && value !== '' ? value : (JSON.stringify(value) ?? String(value));
47
+ // An empty string can be the point of a call (clearing a field), so it shows as one.
48
+ return typeof value === 'string' && value !== '' ? value : JSON.stringify(value) ?? String(value);
49
49
  }
50
50
  /* The input of a call as lines: a shell command as itself, every other key as `key value`, null included. */
51
51
  export function toolCallLines(name, input) {
52
- if (!isRecord(input)) {
53
- const text = input === null || input === undefined || input === '' ? null : valueText(input);
54
- return { command: null, args: [], text };
55
- }
56
- const command = shellCommand(name, input);
57
- const args = Object.entries(input)
58
- .filter(([key, value]) => value !== undefined && !(command !== null && SHELL_SHOWN.has(key)))
59
- .map(([key, value]) => [key, valueText(value)]);
60
- return { command, args, text: null };
52
+ if (!isRecord(input)) {
53
+ const text = input === null || input === undefined || input === '' ? null : valueText(input);
54
+ return {
55
+ command: null,
56
+ args: [],
57
+ text
58
+ };
59
+ }
60
+ const command = shellCommand(name, input);
61
+ const args = Object.entries(input).filter(([key, value]) => value !== undefined && !(command !== null && SHELL_SHOWN.has(key))).map(([key, value]) => [key, valueText(value)]);
62
+ return {
63
+ command,
64
+ args,
65
+ text: null
66
+ };
61
67
  }
62
68
  /* A failed call's output with the exit code its tool put on the first line ("Exit code 1"), as Claude Code's shell does. */
63
69
  export function exitCodeOf(output) {
64
- const match = /^Exit code (-?\d+)[ \t]*(?:\r?\n|$)/.exec(output);
65
- if (match === null || Number(match[1]) === 0) {
66
- return { code: null, rest: output };
67
- }
68
- return { code: Number(match[1]), rest: output.slice(match[0].length) };
70
+ const match = /^Exit code (-?\d+)[ \t]*(?:\r?\n|$)/.exec(output);
71
+ if (match === null || Number(match[1]) === 0) {
72
+ return {
73
+ code: null,
74
+ rest: output
75
+ };
76
+ }
77
+ return {
78
+ code: Number(match[1]),
79
+ rest: output.slice(match[0].length)
80
+ };
69
81
  }
70
82
  /* Whether an output says anything; whitespace alone does not. */
71
83
  export function hasOutput(output) {
72
- return output !== null && output.trim() !== '';
84
+ return output !== null && output.trim() !== '';
73
85
  }
74
86
  /* Whether opening a call shows anything: a diff, the input it was given or what it answered. */
75
87
  export function hasToolBody(tool) {
76
- if (hasFileChanges(tool) || hasOutput(tool.output)) {
77
- return true;
78
- }
79
- const lines = toolCallLines(tool.name, tool.input);
80
- return lines.command !== null || lines.args.length > 0 || lines.text !== null;
88
+ if (hasFileChanges(tool) || hasOutput(tool.output)) {
89
+ return true;
90
+ }
91
+ const lines = toolCallLines(tool.name, tool.input);
92
+ return lines.command !== null || lines.args.length > 0 || lines.text !== null;
81
93
  }
82
94
  // What `GET /fs/file` will serve; a path with another suffix is not worth asking the host about.
83
95
  const IMAGE_SUFFIXES = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'];
84
96
  /* The image file a tool call looked at, so the row can draw it; null for every other call. */
85
97
  export function readImagePath(name, input) {
86
- if (toolEntry(name)?.readsImage !== true) {
87
- return null;
88
- }
89
- const path = isRecord(input) ? str(input.file_path) : null;
90
- if (path === null) {
91
- return null;
92
- }
93
- const lowered = path.toLowerCase();
94
- return IMAGE_SUFFIXES.some((suffix) => lowered.endsWith(suffix)) ? path : null;
98
+ if (toolEntry(name)?.readsImage !== true) {
99
+ return null;
100
+ }
101
+ const path = isRecord(input) ? str(input.file_path) : null;
102
+ if (path === null) {
103
+ return null;
104
+ }
105
+ const lowered = path.toLowerCase();
106
+ return IMAGE_SUFFIXES.some(suffix => lowered.endsWith(suffix)) ? path : null;
95
107
  }
96
108
  /* The before and after text of a file-changing tool call, so the thread can show it as a diff. */
97
109
  export function fileChanges(name, input) {
98
- if (!isRecord(input)) {
99
- return [];
100
- }
101
- const path = str(input.file_path) ?? '';
102
- if (name === 'Edit') {
103
- return [{ path, before: str(input.old_string) ?? '', after: str(input.new_string) ?? '' }];
104
- }
105
- if (name === 'Write') {
106
- return [{ path, before: '', after: str(input.content) ?? '' }];
107
- }
108
- if (name === 'MultiEdit' && Array.isArray(input.edits)) {
109
- return input.edits.filter(isRecord).map((edit) => ({ path, before: str(edit.old_string) ?? '', after: str(edit.new_string) ?? '' }));
110
- }
110
+ if (!isRecord(input)) {
111
111
  return [];
112
+ }
113
+ const path = str(input.file_path) ?? '';
114
+ if (name === 'Edit') {
115
+ return [{
116
+ path,
117
+ before: str(input.old_string) ?? '',
118
+ after: str(input.new_string) ?? ''
119
+ }];
120
+ }
121
+ if (name === 'Write') {
122
+ return [{
123
+ path,
124
+ before: '',
125
+ after: str(input.content) ?? ''
126
+ }];
127
+ }
128
+ if (name === 'MultiEdit' && Array.isArray(input.edits)) {
129
+ return input.edits.filter(isRecord).map(edit => ({
130
+ path,
131
+ before: str(edit.old_string) ?? '',
132
+ after: str(edit.new_string) ?? ''
133
+ }));
134
+ }
135
+ return [];
112
136
  }
113
137
  export function isFileChange(name) {
114
- return toolEntry(name)?.changesFiles === true;
138
+ return toolEntry(name)?.changesFiles === true;
115
139
  }
116
140
  /* The unified diffs a provider put next to a tool call; empty for one that reports before and after. */
117
141
  export function unifiedChanges(tool) {
118
- return (tool.changes ?? []).filter((change) => change.diff !== '');
142
+ return (tool.changes ?? []).filter(change => change.diff !== '');
119
143
  }
120
144
  /* The same, for the copy an approval carries so the person can read what they are approving. */
121
145
  export function approvalChanges(input) {
122
- const changes = isRecord(input) ? input.changes : null;
123
- if (!Array.isArray(changes)) {
124
- return [];
125
- }
126
- return changes.filter((change) => isRecord(change) && typeof change.path === 'string' && typeof change.diff === 'string' && change.diff !== '');
146
+ const changes = isRecord(input) ? input.changes : null;
147
+ if (!Array.isArray(changes)) {
148
+ return [];
149
+ }
150
+ return changes.filter(change => isRecord(change) && typeof change.path === 'string' && typeof change.diff === 'string' && change.diff !== '');
127
151
  }
128
152
  /* Whether a settled call is worth a row in the turn's changed files card. */
129
153
  export function hasFileChanges(tool) {
130
- return unifiedChanges(tool).length > 0 || fileChanges(tool.name, tool.input).length > 0;
154
+ return unifiedChanges(tool).length > 0 || fileChanges(tool.name, tool.input).length > 0;
131
155
  }
132
156
  /* When a running call started: what the CLI reported, or the moment the call appeared. */
133
157
  export function toolStartedAt(tool) {
134
- return tool.progress?.startedAt ?? tool.createdAt;
158
+ return tool.progress?.startedAt ?? tool.createdAt;
135
159
  }
136
160
  // Keep the full buffer so the renderer can carry ANSI state into the visible tail.
137
161
  export function liveOutput(tool) {
138
- return tool.progress?.output || null;
139
- }
162
+ return tool.progress?.output || null;
163
+ }
@@ -11,36 +11,36 @@ const MAX_CONTENT_HEIGHT_PX = 10_000_000;
11
11
  */
12
12
  const remembered = new Map();
13
13
  function keyOf(visualId, width) {
14
- return `${visualId}@${Math.round(width)}`;
14
+ return `${visualId}@${Math.round(width)}`;
15
15
  }
16
16
  /* A height a page reported, held to the visual's own maximum and the limits, in whole pixels. */
17
17
  export function clampVisualHeight(visual, height) {
18
- return Math.min(Math.max(Math.ceil(Math.min(height, visual.maxHeight)), VISUAL_LIMITS.minHeight), VISUAL_LIMITS.maxHeight);
18
+ return Math.min(Math.max(Math.ceil(Math.min(height, visual.maxHeight)), VISUAL_LIMITS.minHeight), VISUAL_LIMITS.maxHeight);
19
19
  }
20
20
  export function visualContentHeight(height) {
21
- return Math.min(MAX_CONTENT_HEIGHT_PX, Math.max(VISUAL_LIMITS.minHeight, Math.ceil(height)));
21
+ return Math.min(MAX_CONTENT_HEIGHT_PX, Math.max(VISUAL_LIMITS.minHeight, Math.ceil(height)));
22
22
  }
23
23
  export function initialVisualContentHeight(visual, width) {
24
- const cached = remembered.get(keyOf(visual.id, width));
25
- if (cached !== undefined) {
26
- return cached;
27
- }
28
- const below = visual.heights?.filter(([measured]) => measured <= width).sort((left, right) => right[0] - left[0])[0];
29
- const above = visual.heights?.filter(([measured]) => measured >= width).sort((left, right) => left[0] - right[0])[0];
30
- return below || above ? visualContentHeight(Math.max(below?.[1] ?? 0, above?.[1] ?? 0)) : DEFAULT_HEIGHT_PX;
24
+ const cached = remembered.get(keyOf(visual.id, width));
25
+ if (cached !== undefined) {
26
+ return cached;
27
+ }
28
+ const below = visual.heights?.filter(([measured]) => measured <= width).sort((left, right) => right[0] - left[0])[0];
29
+ const above = visual.heights?.filter(([measured]) => measured >= width).sort((left, right) => left[0] - right[0])[0];
30
+ return below || above ? visualContentHeight(Math.max(below?.[1] ?? 0, above?.[1] ?? 0)) : DEFAULT_HEIGHT_PX;
31
31
  }
32
32
  /*
33
33
  * The height a frame `width` CSS pixels wide starts at: what the page reported in a frame that wide
34
34
  * before, else what the host measured, else a modest default.
35
35
  */
36
36
  export function initialVisualHeight(visual, width) {
37
- return remembered.get(keyOf(visual.id, width)) ?? visualFrameHeight(visual, width) ?? clampVisualHeight(visual, DEFAULT_HEIGHT_PX);
37
+ return remembered.get(keyOf(visual.id, width)) ?? visualFrameHeight(visual, width) ?? clampVisualHeight(visual, DEFAULT_HEIGHT_PX);
38
38
  }
39
39
  export function rememberVisualHeight(visualId, width, height) {
40
- const key = keyOf(visualId, width);
41
- remembered.delete(key);
42
- remembered.set(key, height);
43
- if (remembered.size > REMEMBERED_HEIGHTS) {
44
- remembered.delete(remembered.keys().next().value);
45
- }
46
- }
40
+ const key = keyOf(visualId, width);
41
+ remembered.delete(key);
42
+ remembered.set(key, height);
43
+ if (remembered.size > REMEMBERED_HEIGHTS) {
44
+ remembered.delete(remembered.keys().next().value);
45
+ }
46
+ }
@@ -1,4 +1,7 @@
1
1
  export function visualViewportGeometry(contentHeight, availableHeight, top) {
2
- const height = Math.max(1, Math.min(contentHeight, availableHeight));
3
- return { height, top: Math.max(0, Math.min(-top, contentHeight - height)) };
4
- }
2
+ const height = Math.max(1, Math.min(contentHeight, availableHeight));
3
+ return {
4
+ height,
5
+ top: Math.max(0, Math.min(-top, contentHeight - height))
6
+ };
7
+ }
@@ -1,10 +1,10 @@
1
1
  export function dayPartOf(now) {
2
- const hour = now.getHours();
3
- if (hour < 5) {
4
- return 'night';
5
- }
6
- if (hour < 12) {
7
- return 'morning';
8
- }
9
- return hour < 18 ? 'afternoon' : 'evening';
10
- }
2
+ const hour = now.getHours();
3
+ if (hour < 5) {
4
+ return 'night';
5
+ }
6
+ if (hour < 12) {
7
+ return 'morning';
8
+ }
9
+ return hour < 18 ? 'afternoon' : 'evening';
10
+ }
@@ -1,47 +1,58 @@
1
1
  import i18next from 'i18next';
2
2
  import { formatElapsedShort } from '@adecore/ui/format';
3
3
  export function workflowAgentState(agent, workflowRunning) {
4
- if (agent.status !== 'running') {
5
- return agent.status;
6
- }
7
- if (!workflowRunning) {
8
- return 'stopped';
9
- }
10
- return agent.startedAt === null ? 'waiting' : 'running';
4
+ if (agent.status !== 'running') {
5
+ return agent.status;
6
+ }
7
+ if (!workflowRunning) {
8
+ return 'stopped';
9
+ }
10
+ return agent.startedAt === null ? 'waiting' : 'running';
11
11
  }
12
12
  /*
13
13
  * The phases in the order the script announced them, each with the agents it started in it. A phase
14
14
  * announced ahead of its agents is there without any, and agents of no known phase come first, untitled.
15
15
  */
16
16
  export function workflowPhases(workflow, workflowRunning) {
17
- const known = new Map(workflow.phases.map((phase) => [phase.index, phase]));
18
- const loose = [];
19
- const byPhase = new Map();
20
- for (const agent of workflow.agents) {
21
- const view = { agent, state: workflowAgentState(agent, workflowRunning) };
22
- if (agent.phaseIndex === null || !known.has(agent.phaseIndex)) {
23
- loose.push(view);
24
- continue;
25
- }
26
- byPhase.set(agent.phaseIndex, [...(byPhase.get(agent.phaseIndex) ?? []), view]);
17
+ const known = new Map(workflow.phases.map(phase => [phase.index, phase]));
18
+ const loose = [];
19
+ const byPhase = new Map();
20
+ for (const agent of workflow.agents) {
21
+ const view = {
22
+ agent,
23
+ state: workflowAgentState(agent, workflowRunning)
24
+ };
25
+ if (agent.phaseIndex === null || !known.has(agent.phaseIndex)) {
26
+ loose.push(view);
27
+ continue;
27
28
  }
28
- const phases = workflow.phases.map((phase) => ({ key: `phase-${phase.index}`, title: phase.title, agents: byPhase.get(phase.index) ?? [] }));
29
- return loose.length > 0 ? [{ key: 'loose', title: null, agents: loose }, ...phases] : phases;
29
+ byPhase.set(agent.phaseIndex, [...(byPhase.get(agent.phaseIndex) ?? []), view]);
30
+ }
31
+ const phases = workflow.phases.map(phase => ({
32
+ key: `phase-${phase.index}`,
33
+ title: phase.title,
34
+ agents: byPhase.get(phase.index) ?? []
35
+ }));
36
+ return loose.length > 0 ? [{
37
+ key: 'loose',
38
+ title: null,
39
+ agents: loose
40
+ }, ...phases] : phases;
30
41
  }
31
42
  /* What the line of an agent that is not at work says about its time; one at work counts on by itself. */
32
43
  export function workflowAgentTime(view) {
33
- const duration = view.agent.durationMs === null ? null : formatElapsedShort(view.agent.durationMs);
34
- switch (view.state) {
35
- case 'running':
36
- return null;
37
- case 'waiting':
38
- return i18next.t('agent-chat:rows.workflow.waiting');
39
- case 'stopped':
40
- return i18next.t('agent-chat:rows.workflow.stopped');
41
- case 'done':
42
- case 'failed':
43
- return duration === null
44
- ? i18next.t(`agent-chat:common.status.${view.state}`)
45
- : i18next.t(`agent-chat:rows.subagent.${view.state}In`, { duration });
46
- }
47
- }
44
+ const duration = view.agent.durationMs === null ? null : formatElapsedShort(view.agent.durationMs);
45
+ switch (view.state) {
46
+ case 'running':
47
+ return null;
48
+ case 'waiting':
49
+ return i18next.t('agent-chat:rows.workflow.waiting');
50
+ case 'stopped':
51
+ return i18next.t('agent-chat:rows.workflow.stopped');
52
+ case 'done':
53
+ case 'failed':
54
+ return duration === null ? i18next.t(`agent-chat:common.status.${view.state}`) : i18next.t(`agent-chat:rows.subagent.${view.state}In`, {
55
+ duration
56
+ });
57
+ }
58
+ }