@adecore/agents-react 0.31.12 → 0.33.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 (409) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/AccountDot.js +57 -6
  3. package/dist/agents/AgentIcon.js +88 -12
  4. package/dist/agents/ModelOptionControl.js +153 -18
  5. package/dist/agents/ProviderLogo.js +49 -4
  6. package/dist/agents/account-limits.js +17 -14
  7. package/dist/agents/accounts.js +99 -67
  8. package/dist/agents/agent-marks.js +5 -3
  9. package/dist/agents/model-name.js +42 -31
  10. package/dist/agents/model-options.js +8 -8
  11. package/dist/agents/model-requirement.js +17 -14
  12. package/dist/agents/option-words.d.ts +7 -0
  13. package/dist/agents/option-words.js +35 -0
  14. package/dist/agents/provider-paths.js +6 -6
  15. package/dist/agents/status-look.js +32 -12
  16. package/dist/chat/account-choice.d.ts +13 -0
  17. package/dist/chat/account-choice.js +90 -20
  18. package/dist/chat/actions.js +126 -59
  19. package/dist/chat/activity.js +5 -5
  20. package/dist/chat/attachments.js +74 -53
  21. package/dist/chat/bookmarks.js +58 -48
  22. package/dist/chat/chat-client.js +344 -263
  23. package/dist/chat/chat-references.js +3 -3
  24. package/dist/chat/composer-effort.d.ts +5 -0
  25. package/dist/chat/composer-effort.js +26 -0
  26. package/dist/chat/composer-send.js +13 -13
  27. package/dist/chat/drafts.js +115 -79
  28. package/dist/chat/forks.js +81 -24
  29. package/dist/chat/guards.js +15 -43
  30. package/dist/chat/index.d.ts +3 -1
  31. package/dist/chat/index.js +3 -2
  32. package/dist/chat/logic/ansi.js +170 -167
  33. package/dist/chat/logic/answers.js +2 -2
  34. package/dist/chat/logic/bookmarks.js +19 -19
  35. package/dist/chat/logic/command-looks.js +138 -96
  36. package/dist/chat/logic/context-usage.js +13 -9
  37. package/dist/chat/logic/continue-after-stop.js +15 -19
  38. package/dist/chat/logic/effort.d.ts +14 -0
  39. package/dist/chat/logic/effort.js +34 -0
  40. package/dist/chat/logic/embedded-code.js +387 -326
  41. package/dist/chat/logic/fork.js +134 -110
  42. package/dist/chat/logic/generated-image.js +54 -23
  43. package/dist/chat/logic/goal.js +28 -20
  44. package/dist/chat/logic/handback.js +6 -6
  45. package/dist/chat/logic/json.js +2 -2
  46. package/dist/chat/logic/limit.js +46 -30
  47. package/dist/chat/logic/picker-entries.d.ts +5 -3
  48. package/dist/chat/logic/picker-entries.js +83 -43
  49. package/dist/chat/logic/resume-compaction.d.ts +14 -1
  50. package/dist/chat/logic/resume-compaction.js +93 -24
  51. package/dist/chat/logic/scrubber.js +188 -136
  52. package/dist/chat/logic/thought.js +13 -16
  53. package/dist/chat/logic/thread-cards.js +60 -48
  54. package/dist/chat/logic/timeline-copy.js +30 -38
  55. package/dist/chat/logic/timeline-target.js +92 -63
  56. package/dist/chat/logic/timeline.js +499 -355
  57. package/dist/chat/logic/tool-catalog.js +54 -34
  58. package/dist/chat/logic/tools.js +106 -82
  59. package/dist/chat/logic/visual-height.js +18 -18
  60. package/dist/chat/logic/visual-viewport.js +6 -3
  61. package/dist/chat/logic/welcome.js +9 -9
  62. package/dist/chat/logic/workflow.d.ts +10 -0
  63. package/dist/chat/logic/workflow.js +130 -32
  64. package/dist/chat/mentions.js +149 -109
  65. package/dist/chat/persisted-json.js +51 -54
  66. package/dist/chat/preferences.d.ts +4 -0
  67. package/dist/chat/preferences.js +162 -84
  68. package/dist/chat/prompt-hold.js +9 -9
  69. package/dist/chat/quote.js +21 -30
  70. package/dist/chat/reading-width.js +12 -10
  71. package/dist/chat/recent-messages.js +34 -21
  72. package/dist/chat/resume-compaction-dismissals.js +25 -5
  73. package/dist/chat/runtime-modes.js +3 -3
  74. package/dist/chat/send-key.js +11 -7
  75. package/dist/chat/stash.js +89 -69
  76. package/dist/chat/subagent-conversation.js +181 -139
  77. package/dist/chat/subagent-list.js +65 -67
  78. package/dist/chat/subagent-support.js +12 -7
  79. package/dist/chat/subagent-view.js +132 -44
  80. package/dist/chat/thumbnails.js +88 -60
  81. package/dist/chat/timeline-flash.js +24 -12
  82. package/dist/chat/timeline-scroll.js +116 -86
  83. package/dist/chat/ui/AccountPill.js +126 -15
  84. package/dist/chat/ui/AnsiOutput.js +62 -6
  85. package/dist/chat/ui/BookmarkMarker.js +231 -41
  86. package/dist/chat/ui/BookmarkSubmenu.js +165 -18
  87. package/dist/chat/ui/ChatActivity.js +649 -70
  88. package/dist/chat/ui/ChatReferenceChip.js +104 -9
  89. package/dist/chat/ui/CodeBlock.js +132 -58
  90. package/dist/chat/ui/Composer.js +866 -132
  91. package/dist/chat/ui/ComposerInput.js +309 -120
  92. package/dist/chat/ui/DiffPool.js +75 -14
  93. package/dist/chat/ui/EditDiff.js +160 -21
  94. package/dist/chat/ui/FadingWords.js +32 -3
  95. package/dist/chat/ui/GoalDock.js +235 -42
  96. package/dist/chat/ui/ImageView.js +617 -61
  97. package/dist/chat/ui/LimitState.js +446 -72
  98. package/dist/chat/ui/Markdown.js +991 -173
  99. package/dist/chat/ui/MermaidBlock.js +285 -79
  100. package/dist/chat/ui/MessageActions.js +251 -39
  101. package/dist/chat/ui/ModelMarks.js +55 -5
  102. package/dist/chat/ui/Pickers.js +664 -113
  103. package/dist/chat/ui/PromptComposer.js +281 -51
  104. package/dist/chat/ui/QuoteButton.js +151 -57
  105. package/dist/chat/ui/ResumeCompactionDock.d.ts +6 -2
  106. package/dist/chat/ui/ResumeCompactionDock.js +141 -6
  107. package/dist/chat/ui/RowTime.js +59 -5
  108. package/dist/chat/ui/RunSettings.js +1744 -154
  109. package/dist/chat/ui/Scrubber.js +517 -88
  110. package/dist/chat/ui/ShellCommand.js +183 -107
  111. package/dist/chat/ui/SubagentControls.js +212 -24
  112. package/dist/chat/ui/SubagentInfo.js +170 -13
  113. package/dist/chat/ui/SubagentStopButton.js +115 -24
  114. package/dist/chat/ui/SubagentTimeline.js +357 -91
  115. package/dist/chat/ui/Timeline.js +988 -476
  116. package/dist/chat/ui/TimelineMenu.js +552 -37
  117. package/dist/chat/ui/UnifiedDiff.js +234 -27
  118. package/dist/chat/ui/UploadThumb.js +37 -7
  119. package/dist/chat/ui/VisualDialogs.js +251 -20
  120. package/dist/chat/ui/VisualFrame.js +321 -95
  121. package/dist/chat/ui/Welcome.js +72 -7
  122. package/dist/chat/ui/chips.js +1 -1
  123. package/dist/chat/ui/code-lines.js +36 -36
  124. package/dist/chat/ui/code-streaming.js +1 -1
  125. package/dist/chat/ui/code-theme.js +7 -7
  126. package/dist/chat/ui/composer/ComposerControls.js +329 -21
  127. package/dist/chat/ui/composer/ComposerMenu.js +358 -30
  128. package/dist/chat/ui/composer/DraftParts.js +185 -11
  129. package/dist/chat/ui/composer/QueuedMessages.js +138 -13
  130. package/dist/chat/ui/composer/chips.js +29 -19
  131. package/dist/chat/ui/composer/editor.js +79 -63
  132. package/dist/chat/ui/composer/insert.js +26 -12
  133. package/dist/chat/ui/composer/key-handler.js +180 -127
  134. package/dist/chat/ui/composer/keys.js +90 -73
  135. package/dist/chat/ui/composer/menu-aria.js +18 -9
  136. package/dist/chat/ui/composer/placeholder.js +78 -31
  137. package/dist/chat/ui/composer/surface.js +13 -37
  138. package/dist/chat/ui/composer/use-chat-controls.js +230 -90
  139. package/dist/chat/ui/composer/use-compaction-offer.js +50 -18
  140. package/dist/chat/ui/composer/use-composer-draft.js +65 -34
  141. package/dist/chat/ui/composer/use-composer-menus.js +478 -193
  142. package/dist/chat/ui/composer/use-composer-submit.js +251 -109
  143. package/dist/chat/ui/composer/use-continuable-turn.js +33 -6
  144. package/dist/chat/ui/composer/use-draft-files.js +245 -93
  145. package/dist/chat/ui/composer/use-effort-stepper.d.ts +13 -0
  146. package/dist/chat/ui/composer/use-effort-stepper.js +88 -0
  147. package/dist/chat/ui/composer/use-notice.js +61 -16
  148. package/dist/chat/ui/composer/use-pending-requests.js +38 -17
  149. package/dist/chat/ui/composer/use-prompt-history.js +117 -45
  150. package/dist/chat/ui/composer/use-prompt-hold.js +119 -35
  151. package/dist/chat/ui/composer/use-take-back.js +94 -72
  152. package/dist/chat/ui/diff/ApprovalReview.js +101 -23
  153. package/dist/chat/ui/diff/DiffFallbackBoundary.js +21 -13
  154. package/dist/chat/ui/diff/DiffOmitted.js +56 -6
  155. package/dist/chat/ui/diff/DiffStack.js +92 -8
  156. package/dist/chat/ui/diff/DiffUnavailable.js +56 -6
  157. package/dist/chat/ui/diff/EditorEditDiff.js +263 -51
  158. package/dist/chat/ui/diff/EditorPatchDiff.js +39 -14
  159. package/dist/chat/ui/diff/LegacyDiffPool.js +27 -10
  160. package/dist/chat/ui/diff/LegacyEditDiff.js +97 -20
  161. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +172 -42
  162. package/dist/chat/ui/diff/RawDiff.js +65 -5
  163. package/dist/chat/ui/diff/ReviewDiff.js +77 -5
  164. package/dist/chat/ui/diff/diff-props.js +1 -1
  165. package/dist/chat/ui/diff/diff-source-budget.js +46 -35
  166. package/dist/chat/ui/diff/editor-edit-model.js +18 -14
  167. package/dist/chat/ui/diff/review-plan.js +63 -40
  168. package/dist/chat/ui/diff/review-settle.js +24 -9
  169. package/dist/chat/ui/diff/syntax-runtime.js +236 -201
  170. package/dist/chat/ui/diff/use-review-stack.js +146 -25
  171. package/dist/chat/ui/diff-syntax.js +70 -58
  172. package/dist/chat/ui/diff-theme.js +31 -12
  173. package/dist/chat/ui/file-links.js +39 -10
  174. package/dist/chat/ui/find-reveal.js +29 -8
  175. package/dist/chat/ui/full-diff.js +17 -12
  176. package/dist/chat/ui/highlighter.js +143 -113
  177. package/dist/chat/ui/icons.js +16 -7
  178. package/dist/chat/ui/index.js +1 -1
  179. package/dist/chat/ui/intelligent-ui/UiBlockFrame.js +556 -82
  180. package/dist/chat/ui/intelligent-ui/UiFallbackPart.js +73 -5
  181. package/dist/chat/ui/intelligent-ui/UiReply.js +666 -262
  182. package/dist/chat/ui/intelligent-ui/block-local.js +59 -31
  183. package/dist/chat/ui/intelligent-ui/chart-data.js +77 -67
  184. package/dist/chat/ui/intelligent-ui/node-text.js +77 -91
  185. package/dist/chat/ui/intelligent-ui/registry.js +46 -46
  186. package/dist/chat/ui/intelligent-ui/render-context.js +1 -1
  187. package/dist/chat/ui/intelligent-ui/renderers/base-land.js +1 -1
  188. package/dist/chat/ui/intelligent-ui/renderers/binding.js +3 -3
  189. package/dist/chat/ui/intelligent-ui/renderers/chart.js +1223 -123
  190. package/dist/chat/ui/intelligent-ui/renderers/choices.js +312 -34
  191. package/dist/chat/ui/intelligent-ui/renderers/content.js +1241 -86
  192. package/dist/chat/ui/intelligent-ui/renderers/data.js +619 -54
  193. package/dist/chat/ui/intelligent-ui/renderers/inputs.js +868 -67
  194. package/dist/chat/ui/intelligent-ui/renderers/links.js +366 -62
  195. package/dist/chat/ui/intelligent-ui/renderers/map-slots.js +118 -60
  196. package/dist/chat/ui/intelligent-ui/renderers/map-style.js +85 -78
  197. package/dist/chat/ui/intelligent-ui/renderers/map-view.js +282 -217
  198. package/dist/chat/ui/intelligent-ui/renderers/map.js +621 -69
  199. package/dist/chat/ui/intelligent-ui/renderers/place-point.js +15 -8
  200. package/dist/chat/ui/intelligent-ui/renderers/structure.js +262 -20
  201. package/dist/chat/ui/intelligent-ui/renderers/text.js +674 -49
  202. package/dist/chat/ui/intelligent-ui/reply-parts.js +24 -15
  203. package/dist/chat/ui/intelligent-ui/table-data.js +97 -57
  204. package/dist/chat/ui/intelligent-ui/tones.js +31 -31
  205. package/dist/chat/ui/intelligent-ui/use-in-view.js +30 -12
  206. package/dist/chat/ui/intelligent-ui/use-later.js +28 -13
  207. package/dist/chat/ui/intelligent-ui/use-truncated.js +45 -21
  208. package/dist/chat/ui/intelligent-ui/use-ui-links.js +296 -109
  209. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +256 -246
  210. package/dist/chat/ui/markdown-blocks.js +296 -262
  211. package/dist/chat/ui/mermaid.d.ts +8 -20
  212. package/dist/chat/ui/mermaid.js +47 -84
  213. package/dist/chat/ui/quote-selection.js +32 -29
  214. package/dist/chat/ui/rehype-chips.js +35 -23
  215. package/dist/chat/ui/rehype-fade.js +28 -17
  216. package/dist/chat/ui/remark-html-as-text.js +22 -15
  217. package/dist/chat/ui/reply-context.js +1 -1
  218. package/dist/chat/ui/reveal.js +161 -72
  219. package/dist/chat/ui/rows/ForksRow.js +226 -24
  220. package/dist/chat/ui/rows/GeneratedImageRow.js +541 -87
  221. package/dist/chat/ui/rows/MessageRows.js +1706 -159
  222. package/dist/chat/ui/rows/RowContainer.js +57 -7
  223. package/dist/chat/ui/rows/Rows.js +463 -54
  224. package/dist/chat/ui/rows/SubagentRow.js +577 -60
  225. package/dist/chat/ui/rows/TaskRow.js +359 -40
  226. package/dist/chat/ui/rows/VisualRow.js +233 -11
  227. package/dist/chat/ui/rows/WorkRows.d.ts +3 -0
  228. package/dist/chat/ui/rows/WorkRows.js +1945 -164
  229. package/dist/chat/ui/rows/WorkflowRow.js +756 -37
  230. package/dist/chat/ui/rows/row-rhythm.js +27 -17
  231. package/dist/chat/ui/theme-watch.js +26 -23
  232. package/dist/chat/ui/timestamp-format.js +4 -1
  233. package/dist/chat/ui/use-diff-source-tokens.js +70 -34
  234. package/dist/chat/ui/useToggleSet.js +51 -19
  235. package/dist/chat/ui/visual-theme.js +153 -128
  236. package/dist/chat/visual-bridge.js +123 -123
  237. package/dist/chat/visual-viewport.js +94 -83
  238. package/dist/chat/visuals.js +13 -5
  239. package/dist/host-hooks.d.ts +29 -0
  240. package/dist/host-hooks.js +78 -0
  241. package/dist/host.js +120 -48
  242. package/dist/index.js +1 -1
  243. package/dist/lazy.js +38 -32
  244. package/dist/locales/en/agent-chat.d.ts +42 -0
  245. package/dist/locales/en/agent-chat.js +755 -713
  246. package/dist/locales/en/agent-prompts.js +42 -42
  247. package/dist/locales/en/agent-providers.d.ts +1 -0
  248. package/dist/locales/en/agent-providers.js +166 -165
  249. package/dist/locales/en/agent-usage.d.ts +6 -0
  250. package/dist/locales/en/agent-usage.js +129 -123
  251. package/dist/locales/nl/agent-chat.d.ts +42 -0
  252. package/dist/locales/nl/agent-chat.js +755 -713
  253. package/dist/locales/nl/agent-prompts.js +42 -42
  254. package/dist/locales/nl/agent-providers.d.ts +1 -0
  255. package/dist/locales/nl/agent-providers.js +166 -165
  256. package/dist/locales/nl/agent-usage.d.ts +6 -0
  257. package/dist/locales/nl/agent-usage.js +129 -123
  258. package/dist/locales.js +14 -14
  259. package/dist/mounted-registry.js +31 -30
  260. package/dist/port-transport.js +122 -111
  261. package/dist/prompts/index.js +1 -1
  262. package/dist/prompts/logic/focus.js +15 -14
  263. package/dist/prompts/logic/keys.js +93 -59
  264. package/dist/prompts/logic/prompts.js +27 -14
  265. package/dist/prompts/logic/subjects.js +60 -46
  266. package/dist/prompts/logic/useFocusAfterAnswer.js +60 -20
  267. package/dist/prompts/logic/usePromptSession.js +88 -77
  268. package/dist/prompts/ui/ApprovalBody.js +246 -27
  269. package/dist/prompts/ui/PromptActions.js +215 -9
  270. package/dist/prompts/ui/PromptCard.js +215 -36
  271. package/dist/prompts/ui/PromptView.js +372 -34
  272. package/dist/prompts/ui/QuestionBody.js +269 -73
  273. package/dist/providers/AccountColors.js +36 -5
  274. package/dist/providers/AccountDetail.js +683 -50
  275. package/dist/providers/AccountVariables.js +139 -32
  276. package/dist/providers/AddAccountForm.js +125 -38
  277. package/dist/providers/CliDetail.js +343 -36
  278. package/dist/providers/InstallPage.js +644 -59
  279. package/dist/providers/ProviderList.d.ts +2 -1
  280. package/dist/providers/ProviderList.js +215 -23
  281. package/dist/providers/ProvidersPane.d.ts +4 -2
  282. package/dist/providers/ProvidersPane.js +244 -64
  283. package/dist/providers/account-actions.js +54 -30
  284. package/dist/providers/index.js +1 -1
  285. package/dist/providers/install-steps.js +12 -9
  286. package/dist/providers/pane-target.d.ts +3 -0
  287. package/dist/providers/pane-target.js +34 -13
  288. package/dist/providers/parts.js +62 -12
  289. package/dist/providers/provider-abilities.js +5 -5
  290. package/dist/providers/provider-groups.js +75 -40
  291. package/dist/providers/variables.js +73 -39
  292. package/dist/scope.js +6 -6
  293. package/dist/settings/sections.js +18 -18
  294. package/dist/state/chats.js +404 -192
  295. package/dist/state/index.js +1 -1
  296. package/dist/state/provider-accounts.js +70 -47
  297. package/dist/state/providers.js +45 -16
  298. package/dist/state/usage.js +154 -77
  299. package/dist/storage.js +69 -68
  300. package/dist/testing/index.js +1 -1
  301. package/dist/testing/prompts.js +105 -67
  302. package/dist/transport.js +10 -10
  303. package/dist/ui/PlainTextarea.js +27 -3
  304. package/dist/usage/LimitsList.js +646 -40
  305. package/dist/usage/UsageBreakdown.js +879 -38
  306. package/dist/usage/UsageChart.js +311 -32
  307. package/dist/usage/UsageDialog.js +46 -4
  308. package/dist/usage/UsageLimits.js +467 -34
  309. package/dist/usage/UsageLimitsCard.js +95 -11
  310. package/dist/usage/UsagePage.js +817 -96
  311. package/dist/usage/UsagePane.js +164 -10
  312. package/dist/usage/UsageSummary.js +151 -6
  313. package/dist/usage/UsageTiles.js +164 -14
  314. package/dist/usage/format.js +32 -32
  315. package/dist/usage/index.d.ts +1 -1
  316. package/dist/usage/index.js +2 -1
  317. package/dist/usage/limit-groups.d.ts +2 -0
  318. package/dist/usage/limit-groups.js +77 -59
  319. package/dist/usage/limits.js +78 -43
  320. package/dist/usage/money.js +20 -4
  321. package/dist/usage/summary.js +85 -64
  322. package/package.json +9 -9
  323. package/src/agents/ModelOptionControl.tsx +3 -1
  324. package/src/agents/option-words.ts +27 -0
  325. package/src/chat/account-choice.ts +41 -1
  326. package/src/chat/composer-effort.ts +32 -0
  327. package/src/chat/forks.ts +4 -5
  328. package/src/chat/index.ts +3 -1
  329. package/src/chat/logic/effort.ts +32 -0
  330. package/src/chat/logic/picker-entries.ts +45 -10
  331. package/src/chat/logic/resume-compaction.ts +95 -17
  332. package/src/chat/logic/timeline.ts +11 -3
  333. package/src/chat/logic/workflow.ts +86 -4
  334. package/src/chat/preferences.ts +35 -0
  335. package/src/chat/subagent-view.ts +2 -3
  336. package/src/chat/ui/AnsiOutput.tsx +1 -2
  337. package/src/chat/ui/BookmarkSubmenu.tsx +3 -3
  338. package/src/chat/ui/ChatActivity.tsx +14 -22
  339. package/src/chat/ui/ChatReferenceChip.tsx +2 -3
  340. package/src/chat/ui/Composer.tsx +15 -7
  341. package/src/chat/ui/EditDiff.tsx +2 -3
  342. package/src/chat/ui/LimitState.tsx +2 -2
  343. package/src/chat/ui/Markdown.tsx +10 -8
  344. package/src/chat/ui/MermaidBlock.tsx +57 -49
  345. package/src/chat/ui/Pickers.tsx +49 -29
  346. package/src/chat/ui/PromptComposer.tsx +7 -9
  347. package/src/chat/ui/ResumeCompactionDock.tsx +16 -4
  348. package/src/chat/ui/RunSettings.tsx +67 -28
  349. package/src/chat/ui/Scrubber.tsx +3 -3
  350. package/src/chat/ui/ShellCommand.tsx +2 -0
  351. package/src/chat/ui/SubagentInfo.tsx +2 -3
  352. package/src/chat/ui/SubagentTimeline.tsx +12 -16
  353. package/src/chat/ui/Timeline.tsx +6 -6
  354. package/src/chat/ui/UnifiedDiff.tsx +3 -4
  355. package/src/chat/ui/VisualFrame.tsx +5 -8
  356. package/src/chat/ui/code-theme.ts +4 -4
  357. package/src/chat/ui/composer/placeholder.ts +2 -2
  358. package/src/chat/ui/composer/use-compaction-offer.ts +36 -16
  359. package/src/chat/ui/composer/use-composer-menus.ts +4 -9
  360. package/src/chat/ui/composer/use-composer-submit.ts +2 -1
  361. package/src/chat/ui/composer/use-effort-stepper.ts +56 -0
  362. package/src/chat/ui/composer/use-notice.ts +2 -2
  363. package/src/chat/ui/diff/EditorEditDiff.tsx +9 -13
  364. package/src/chat/ui/diff/LegacyEditDiff.tsx +12 -17
  365. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +13 -21
  366. package/src/chat/ui/diff/use-review-stack.ts +4 -4
  367. package/src/chat/ui/diff-theme.ts +3 -3
  368. package/src/chat/ui/file-links.ts +2 -2
  369. package/src/chat/ui/intelligent-ui/UiReply.tsx +2 -0
  370. package/src/chat/ui/intelligent-ui/renderers/chart.tsx +3 -3
  371. package/src/chat/ui/intelligent-ui/renderers/content.tsx +5 -6
  372. package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +2 -1
  373. package/src/chat/ui/intelligent-ui/renderers/map.tsx +2 -1
  374. package/src/chat/ui/intelligent-ui/use-truncated.ts +16 -19
  375. package/src/chat/ui/intelligent-ui/use-ui-links.ts +3 -3
  376. package/src/chat/ui/mermaid.ts +52 -96
  377. package/src/chat/ui/rows/ForksRow.tsx +3 -5
  378. package/src/chat/ui/rows/GeneratedImageRow.tsx +2 -1
  379. package/src/chat/ui/rows/MessageRows.tsx +12 -21
  380. package/src/chat/ui/rows/SubagentRow.tsx +3 -3
  381. package/src/chat/ui/rows/TaskRow.tsx +1 -1
  382. package/src/chat/ui/rows/WorkRows.tsx +11 -6
  383. package/src/chat/ui/rows/WorkflowRow.tsx +144 -54
  384. package/src/chat/ui/useToggleSet.ts +15 -18
  385. package/src/chat/ui/visual-theme.ts +2 -3
  386. package/src/host-hooks.ts +113 -0
  387. package/src/lazy.tsx +2 -0
  388. package/src/locales/en/agent-chat.ts +142 -108
  389. package/src/locales/en/agent-prompts.ts +7 -7
  390. package/src/locales/en/agent-providers.ts +35 -34
  391. package/src/locales/en/agent-usage.ts +26 -20
  392. package/src/locales/nl/agent-chat.ts +134 -100
  393. package/src/locales/nl/agent-prompts.ts +5 -5
  394. package/src/locales/nl/agent-providers.ts +33 -32
  395. package/src/locales/nl/agent-usage.ts +25 -20
  396. package/src/providers/CliDetail.tsx +2 -1
  397. package/src/providers/InstallPage.tsx +2 -4
  398. package/src/providers/ProviderList.tsx +12 -2
  399. package/src/providers/ProvidersPane.tsx +45 -15
  400. package/src/providers/pane-target.ts +20 -4
  401. package/src/state/chats.ts +2 -2
  402. package/src/usage/LimitsList.tsx +12 -13
  403. package/src/usage/UsageBreakdown.tsx +17 -6
  404. package/src/usage/UsageLimits.tsx +2 -1
  405. package/src/usage/UsagePage.tsx +3 -3
  406. package/src/usage/index.ts +1 -1
  407. package/src/usage/limit-groups.ts +12 -0
  408. package/src/usage/limits.ts +2 -2
  409. package/src/usage/money.ts +1 -2
@@ -17,163 +17,215 @@ const WIDTH_PERSON_PX = 8;
17
17
  const WIDTH_WAKE_PX = 5;
18
18
  /* `marks` is what `bookmarkRows` answers: the bookmark drawn at a row, by row id. */
19
19
  export function ticksOf(rows, marks = new Map()) {
20
- return rows.flatMap((row, rowIndex) => {
21
- const bookmark = marks.get(row.id) ?? null;
22
- if (row.kind === 'user') {
23
- // A message of only attachments still has a place in the thread; its names stand in for the text.
24
- const text = row.item.text !== '' ? row.item.text : (row.item.attachments ?? []).map((attachment) => attachment.name).join(', ');
25
- return [{ id: row.id, rowIndex, kind: 'person', text, createdAt: row.item.createdAt, turnId: row.item.turnId, bookmark }];
26
- }
27
- // The other turns nobody asked for (a sub-agent that finished, the CLI going on) are no place to return to.
28
- if (row.kind === 'turn-start' && ((row.turn.taskIds?.length ?? 0) > 0 || (row.turn.messageFrom?.length ?? 0) > 0)) {
29
- return [{ id: row.id, rowIndex, kind: 'wake', text: row.label, createdAt: row.turn.createdAt, turnId: row.turn.id, bookmark: null }];
30
- }
31
- if (bookmark === null) {
32
- return [];
33
- }
34
- if (row.kind === 'assistant') {
35
- return [{ id: row.id, rowIndex, kind: 'bookmark', text: row.item.text, createdAt: row.item.createdAt, turnId: row.item.turnId, bookmark }];
36
- }
37
- // The fold of a turn a marked reply is hidden in; the card reads the start the bookmark kept.
38
- const turnId = row.kind === 'turn-fold' ? row.turn.id : null;
39
- return [{ id: row.id, rowIndex, kind: 'bookmark', text: bookmark.excerpt, createdAt: bookmark.createdAt, turnId, bookmark }];
40
- });
20
+ return rows.flatMap((row, rowIndex) => {
21
+ const bookmark = marks.get(row.id) ?? null;
22
+ if (row.kind === 'user') {
23
+ // A message of only attachments still has a place in the thread; its names stand in for the text.
24
+ const text = row.item.text !== '' ? row.item.text : (row.item.attachments ?? []).map(attachment => attachment.name).join(', ');
25
+ return [{
26
+ id: row.id,
27
+ rowIndex,
28
+ kind: 'person',
29
+ text,
30
+ createdAt: row.item.createdAt,
31
+ turnId: row.item.turnId,
32
+ bookmark
33
+ }];
34
+ }
35
+ // The other turns nobody asked for (a sub-agent that finished, the CLI going on) are no place to return to.
36
+ if (row.kind === 'turn-start' && ((row.turn.taskIds?.length ?? 0) > 0 || (row.turn.messageFrom?.length ?? 0) > 0)) {
37
+ return [{
38
+ id: row.id,
39
+ rowIndex,
40
+ kind: 'wake',
41
+ text: row.label,
42
+ createdAt: row.turn.createdAt,
43
+ turnId: row.turn.id,
44
+ bookmark: null
45
+ }];
46
+ }
47
+ if (bookmark === null) {
48
+ return [];
49
+ }
50
+ if (row.kind === 'assistant') {
51
+ return [{
52
+ id: row.id,
53
+ rowIndex,
54
+ kind: 'bookmark',
55
+ text: row.item.text,
56
+ createdAt: row.item.createdAt,
57
+ turnId: row.item.turnId,
58
+ bookmark
59
+ }];
60
+ }
61
+ // The fold of a turn a marked reply is hidden in; the card reads the start the bookmark kept.
62
+ const turnId = row.kind === 'turn-fold' ? row.turn.id : null;
63
+ return [{
64
+ id: row.id,
65
+ rowIndex,
66
+ kind: 'bookmark',
67
+ text: bookmark.excerpt,
68
+ createdAt: bookmark.createdAt,
69
+ turnId,
70
+ bookmark
71
+ }];
72
+ });
41
73
  }
42
74
  /* `marked` and `found` say per message whether it has a bookmark and whether a find hit falls under it; absent, none has. */
43
75
  export function layoutTicks(kinds, height, marked = [], found = []) {
44
- const count = kinds.length;
45
- const room = Math.max(0, Math.floor(height));
46
- const slotCount = Math.min(count, Math.floor(room / MIN_PITCH_PX));
47
- if (slotCount === 0) {
48
- return { top: 0, pitch: MIN_PITCH_PX, count, slots: [] };
49
- }
50
- const pitch = Math.min(PITCH_PX, Math.floor(room / slotCount));
51
- const top = Math.floor((room - slotCount * pitch) / 2);
52
- const inset = Math.floor((pitch - TICK_HEIGHT_PX) / 2);
53
- const slots = [];
54
- for (let i = 0; i < slotCount; i++) {
55
- const first = Math.floor((i * count) / slotCount);
56
- const last = Math.floor(((i + 1) * count) / slotCount) - 1;
57
- // A merged tick is the person's as soon as one message in it is, since those are what the strip is for.
58
- const run = kinds.slice(first, last + 1);
59
- const kind = run.includes('person') ? 'person' : run.includes('bookmark') ? 'bookmark' : 'wake';
60
- slots.push({
61
- first,
62
- last,
63
- kind,
64
- marked: marked.slice(first, last + 1).includes(true),
65
- found: found.slice(first, last + 1).includes(true),
66
- y: top + i * pitch + inset
67
- });
68
- }
69
- return { top, pitch, count, slots };
76
+ const count = kinds.length;
77
+ const room = Math.max(0, Math.floor(height));
78
+ const slotCount = Math.min(count, Math.floor(room / MIN_PITCH_PX));
79
+ if (slotCount === 0) {
80
+ return {
81
+ top: 0,
82
+ pitch: MIN_PITCH_PX,
83
+ count,
84
+ slots: []
85
+ };
86
+ }
87
+ const pitch = Math.min(PITCH_PX, Math.floor(room / slotCount));
88
+ const top = Math.floor((room - slotCount * pitch) / 2);
89
+ const inset = Math.floor((pitch - TICK_HEIGHT_PX) / 2);
90
+ const slots = [];
91
+ for (let i = 0; i < slotCount; i++) {
92
+ const first = Math.floor(i * count / slotCount);
93
+ const last = Math.floor((i + 1) * count / slotCount) - 1;
94
+ // A merged tick is the person's as soon as one message in it is, since those are what the strip is for.
95
+ const run = kinds.slice(first, last + 1);
96
+ const kind = run.includes('person') ? 'person' : run.includes('bookmark') ? 'bookmark' : 'wake';
97
+ slots.push({
98
+ first,
99
+ last,
100
+ kind,
101
+ marked: marked.slice(first, last + 1).includes(true),
102
+ found: found.slice(first, last + 1).includes(true),
103
+ y: top + i * pitch + inset
104
+ });
105
+ }
106
+ return {
107
+ top,
108
+ pitch,
109
+ count,
110
+ slots
111
+ };
70
112
  }
71
113
  /*
72
114
  * The tick whose stretch of the thread a row falls in: a tick stands for its row and every row up to
73
115
  * the next tick's, and a row above the first tick counts under the first. Null without ticks.
74
116
  */
75
117
  export function tickOfRow(ticks, rowIndex) {
76
- if (ticks.length === 0) {
77
- return null;
78
- }
79
- return Math.max(0, lastIndexAtOrBelow(ticks.length, (index) => ticks[index].rowIndex, rowIndex));
118
+ if (ticks.length === 0) {
119
+ return null;
120
+ }
121
+ return Math.max(0, lastIndexAtOrBelow(ticks.length, index => ticks[index].rowIndex, rowIndex));
80
122
  }
81
123
  /* Per tick, whether any of the rows has a find hit in its stretch. */
82
124
  export function ticksWithHits(ticks, hitRows) {
83
- const found = ticks.map(() => false);
84
- for (const row of hitRows) {
85
- const tick = tickOfRow(ticks, row);
86
- if (tick !== null) {
87
- found[tick] = true;
88
- }
125
+ const found = ticks.map(() => false);
126
+ for (const row of hitRows) {
127
+ const tick = tickOfRow(ticks, row);
128
+ if (tick !== null) {
129
+ found[tick] = true;
89
130
  }
90
- return found;
131
+ }
132
+ return found;
91
133
  }
92
134
  /* The message under a height in the strip; inside a merged tick the height picks among its messages. */
93
135
  export function messageAt(layout, y) {
94
- const { slots, top, pitch } = layout;
95
- if (slots.length === 0) {
96
- return null;
97
- }
98
- const offset = y - top;
99
- const index = Math.min(slots.length - 1, Math.max(0, Math.floor(offset / pitch)));
100
- const slot = slots[index];
101
- const fraction = Math.min(1, Math.max(0, (offset - index * pitch) / pitch));
102
- return slot.first + Math.min(slot.last - slot.first, Math.floor(fraction * (slot.last - slot.first + 1)));
136
+ const {
137
+ slots,
138
+ top,
139
+ pitch
140
+ } = layout;
141
+ if (slots.length === 0) {
142
+ return null;
143
+ }
144
+ const offset = y - top;
145
+ const index = Math.min(slots.length - 1, Math.max(0, Math.floor(offset / pitch)));
146
+ const slot = slots[index];
147
+ const fraction = Math.min(1, Math.max(0, (offset - index * pitch) / pitch));
148
+ return slot.first + Math.min(slot.last - slot.first, Math.floor(fraction * (slot.last - slot.first + 1)));
103
149
  }
104
150
  export function slotOf(layout, message) {
105
- const { slots } = layout;
106
- let low = 0;
107
- let high = slots.length - 1;
108
- while (low <= high) {
109
- const middle = (low + high) >> 1;
110
- const slot = slots[middle];
111
- if (message < slot.first) {
112
- high = middle - 1;
113
- }
114
- else if (message > slot.last) {
115
- low = middle + 1;
116
- }
117
- else {
118
- return middle;
119
- }
151
+ const {
152
+ slots
153
+ } = layout;
154
+ let low = 0;
155
+ let high = slots.length - 1;
156
+ while (low <= high) {
157
+ const middle = low + high >> 1;
158
+ const slot = slots[middle];
159
+ if (message < slot.first) {
160
+ high = middle - 1;
161
+ } else if (message > slot.last) {
162
+ low = middle + 1;
163
+ } else {
164
+ return middle;
120
165
  }
121
- return null;
166
+ }
167
+ return null;
122
168
  }
123
169
  /*
124
170
  * At rest every tick of a kind is as long as the next, so length never competes with the brightness
125
171
  * that says what is on screen. Only a pointer on the strip magnifies, the way a dock does, one step out.
126
172
  */
127
173
  export function tickWidth(kind, distanceFromPointer) {
128
- if (distanceFromPointer === 0) {
129
- return WIDTH_HOVERED_PX;
130
- }
131
- if (distanceFromPointer === 1) {
132
- return kind === 'wake' ? WIDTH_NEAR_WAKE_PX : WIDTH_NEAR_PERSON_PX;
133
- }
134
- return kind === 'wake' ? WIDTH_WAKE_PX : WIDTH_PERSON_PX;
174
+ if (distanceFromPointer === 0) {
175
+ return WIDTH_HOVERED_PX;
176
+ }
177
+ if (distanceFromPointer === 1) {
178
+ return kind === 'wake' ? WIDTH_NEAR_WAKE_PX : WIDTH_NEAR_PERSON_PX;
179
+ }
180
+ return kind === 'wake' ? WIDTH_WAKE_PX : WIDTH_PERSON_PX;
135
181
  }
136
182
  /* The last index whose value is at most `limit`, or -1. The values only grow. */
137
183
  function lastIndexAtOrBelow(length, valueAt, limit) {
138
- let low = 0;
139
- let high = length - 1;
140
- let found = -1;
141
- while (low <= high) {
142
- const middle = (low + high) >> 1;
143
- if (valueAt(middle) <= limit) {
144
- found = middle;
145
- low = middle + 1;
146
- }
147
- else {
148
- high = middle - 1;
149
- }
184
+ let low = 0;
185
+ let high = length - 1;
186
+ let found = -1;
187
+ while (low <= high) {
188
+ const middle = low + high >> 1;
189
+ if (valueAt(middle) <= limit) {
190
+ found = middle;
191
+ low = middle + 1;
192
+ } else {
193
+ high = middle - 1;
150
194
  }
151
- return found;
195
+ }
196
+ return found;
152
197
  }
153
198
  /* The last index whose start lies at or above a line, or -1. */
154
199
  function lastAtOrAbove(starts, line) {
155
- return lastIndexAtOrBelow(starts.length, (index) => starts[index], line);
200
+ return lastIndexAtOrBelow(starts.length, index => starts[index], line);
156
201
  }
157
202
  /*
158
203
  * The messages on screen. A message counts from its own start to the start of the next one, so the
159
204
  * question whose answer fills the screen is in view even after it scrolled out at the top.
160
205
  */
161
- export function messagesInView({ starts, scrollTop, visibleHeight }) {
162
- const bottom = scrollTop + visibleHeight;
163
- if (starts.length === 0 || visibleHeight <= 0 || starts[0] >= bottom) {
164
- return null;
165
- }
166
- const first = Math.max(0, lastAtOrAbove(starts, scrollTop));
167
- let last = lastAtOrAbove(starts, bottom);
168
- // A row that starts on the very last line has not a pixel on screen yet.
169
- if (starts[last] >= bottom) {
170
- last--;
171
- }
172
- return { first, last: Math.max(first, last) };
206
+ export function messagesInView({
207
+ starts,
208
+ scrollTop,
209
+ visibleHeight
210
+ }) {
211
+ const bottom = scrollTop + visibleHeight;
212
+ if (starts.length === 0 || visibleHeight <= 0 || starts[0] >= bottom) {
213
+ return null;
214
+ }
215
+ const first = Math.max(0, lastAtOrAbove(starts, scrollTop));
216
+ let last = lastAtOrAbove(starts, bottom);
217
+ // A row that starts on the very last line has not a pixel on screen yet.
218
+ if (starts[last] >= bottom) {
219
+ last--;
220
+ }
221
+ return {
222
+ first,
223
+ last: Math.max(first, last)
224
+ };
173
225
  }
174
226
  /* Whether a drawn tick covers any of the messages on screen. */
175
227
  export function slotInView(slot, range) {
176
- return range !== null && slot.last >= range.first && slot.first <= range.last;
228
+ return range !== null && slot.last >= range.first && slot.first <= range.last;
177
229
  }
178
230
  /*
179
231
  * The message a step back or forward lands on, among the ones `eligible` allows. A jump puts a
@@ -181,20 +233,20 @@ export function slotInView(slot, range) {
181
233
  * a long answer is the question it belongs to. A pixel of slack absorbs rounding in the scroller.
182
234
  */
183
235
  export function stepMessage(starts, eligible, scrollTop, direction) {
184
- if (direction === -1) {
185
- for (let i = lastAtOrAbove(starts, scrollTop - 1.5); i >= 0; i--) {
186
- if (eligible(i)) {
187
- return i;
188
- }
189
- }
190
- return null;
191
- }
192
- for (let i = lastAtOrAbove(starts, scrollTop + 1) + 1; i < starts.length; i++) {
193
- if (eligible(i)) {
194
- return i;
195
- }
236
+ if (direction === -1) {
237
+ for (let i = lastAtOrAbove(starts, scrollTop - 1.5); i >= 0; i--) {
238
+ if (eligible(i)) {
239
+ return i;
240
+ }
196
241
  }
197
242
  return null;
243
+ }
244
+ for (let i = lastAtOrAbove(starts, scrollTop + 1) + 1; i < starts.length; i++) {
245
+ if (eligible(i)) {
246
+ return i;
247
+ }
248
+ }
249
+ return null;
198
250
  }
199
251
  /*
200
252
  * The left padding of the thread in a view that draws the strip at its left edge. A wide view keeps
@@ -203,10 +255,10 @@ export function stepMessage(starts, eligible, scrollTop, direction) {
203
255
  * widest the content column runs (`readingMeasure`).
204
256
  */
205
257
  export function threadPaddingLeft(width, strip, measure = readingMeasure(DEFAULT_READING_WIDTH)) {
206
- if (!strip) {
207
- return THREAD_PADDING_PX;
208
- }
209
- // The column's margin is half of what the padding leaves, so the padding counts the clearance twice.
210
- const padding = 2 * STRIP_CLEARANCE_PX + measure + THREAD_PADDING_PX - Math.floor(width);
211
- return Math.min(STRIP_CLEARANCE_PX, Math.max(THREAD_PADDING_PX, padding));
212
- }
258
+ if (!strip) {
259
+ return THREAD_PADDING_PX;
260
+ }
261
+ // The column's margin is half of what the padding leaves, so the padding counts the clearance twice.
262
+ const padding = 2 * STRIP_CLEARANCE_PX + measure + THREAD_PADDING_PX - Math.floor(width);
263
+ return Math.min(STRIP_CLEARANCE_PX, Math.max(THREAD_PADDING_PX, padding));
264
+ }
@@ -6,30 +6,27 @@ const LIST_MARKER = /^[ \t]*(?:[-*+]|\d+[.)])[ \t]+/gm;
6
6
  const SENTENCE_END = /[.!?]["'”’)\]]*(?=\s)/;
7
7
  /* The thought as one line of plain text: the marks gone and every run of white space one space. */
8
8
  export function flattenThought(text) {
9
- return stripMarkdown(text.replace(LIST_MARKER, '')).replace(/\s+/g, ' ').trim();
9
+ return stripMarkdown(text.replace(LIST_MARKER, '')).replace(/\s+/g, ' ').trim();
10
10
  }
11
11
  function headingOf(line) {
12
- return HEADING_LINE.exec(line)?.[1] ?? null;
12
+ return HEADING_LINE.exec(line)?.[1] ?? null;
13
13
  }
14
14
  /* What a folded thought shows on its one line: the heading it opens with, or the whole thought flattened for the row to cut off. */
15
15
  export function thoughtPreview(text) {
16
- const heading = headingOf(text.trimStart().split('\n', 1)[0] ?? '');
17
- return flattenThought(heading ?? text);
16
+ const heading = headingOf(text.trimStart().split('\n', 1)[0] ?? '');
17
+ return flattenThought(heading ?? text);
18
18
  }
19
19
  /*
20
20
  * What the model is thinking about now, in a line: the heading of the last stretch it titled, which
21
21
  * is the one it is on, or the first sentence of a thought that titles nothing.
22
22
  */
23
23
  export function thoughtLine(text) {
24
- const headings = text
25
- .split('\n')
26
- .map(headingOf)
27
- .filter((heading) => heading !== null);
28
- const last = headings.at(-1);
29
- if (last !== undefined) {
30
- return flattenThought(last);
31
- }
32
- const flat = flattenThought(text);
33
- const end = SENTENCE_END.exec(flat);
34
- return end === null ? flat : flat.slice(0, end.index + end[0].length);
35
- }
24
+ const headings = text.split('\n').map(headingOf).filter(heading => heading !== null);
25
+ const last = headings.at(-1);
26
+ if (last !== undefined) {
27
+ return flattenThought(last);
28
+ }
29
+ const flat = flattenThought(text);
30
+ const end = SENTENCE_END.exec(flat);
31
+ return end === null ? flat : flat.slice(0, end.index + end[0].length);
32
+ }
@@ -4,34 +4,41 @@
4
4
  * goes above it.
5
5
  */
6
6
  function rowTime(row) {
7
- switch (row.kind) {
8
- case 'user':
9
- case 'assistant':
10
- case 'thinking':
11
- case 'approval':
12
- case 'question':
13
- case 'subagent':
14
- return row.item.createdAt;
15
- case 'turn-start':
16
- case 'turn-fold':
17
- return row.turn.createdAt;
18
- case 'work':
19
- case 'work-live':
20
- case 'workflow':
21
- return row.tool.createdAt;
22
- case 'work-group':
23
- return row.tools[0]?.createdAt ?? null;
24
- case 'live-thought':
25
- return row.at;
26
- case 'working':
27
- return Number.POSITIVE_INFINITY;
28
- default:
29
- return null;
30
- }
7
+ switch (row.kind) {
8
+ case 'user':
9
+ case 'assistant':
10
+ case 'thinking':
11
+ case 'approval':
12
+ case 'question':
13
+ case 'subagent':
14
+ return row.item.createdAt;
15
+ case 'turn-start':
16
+ case 'turn-fold':
17
+ return row.turn.createdAt;
18
+ case 'work':
19
+ case 'work-live':
20
+ case 'workflow':
21
+ return row.tool.createdAt;
22
+ case 'work-group':
23
+ return row.tools[0]?.createdAt ?? null;
24
+ case 'live-thought':
25
+ return row.at;
26
+ case 'working':
27
+ return Number.POSITIVE_INFINITY;
28
+ default:
29
+ return null;
30
+ }
31
31
  }
32
32
  /* Prefixed, so a card never shares a key with a row of the chat's own. */
33
33
  export function cardRows(cards) {
34
- return cards.map((card) => ({ at: card.at, row: { kind: 'app-card', id: `app-card-${card.id}`, card } }));
34
+ return cards.map(card => ({
35
+ at: card.at,
36
+ row: {
37
+ kind: 'app-card',
38
+ id: `app-card-${card.id}`,
39
+ card
40
+ }
41
+ }));
35
42
  }
36
43
  /*
37
44
  * The visuals as rows, keyed apart from the chat's own rows. `heldFrom` is when the first item this
@@ -39,9 +46,14 @@ export function cardRows(cards) {
39
46
  * page and waits for it, rather than stacking up at the top of the thread.
40
47
  */
41
48
  export function visualRows(visuals, heldFrom = null) {
42
- return visuals
43
- .filter((visual) => heldFrom === null || visual.at >= heldFrom)
44
- .map((visual) => ({ at: visual.at, row: { kind: 'visual', id: `visual-${visual.id}`, visual } }));
49
+ return visuals.filter(visual => heldFrom === null || visual.at >= heldFrom).map(visual => ({
50
+ at: visual.at,
51
+ row: {
52
+ kind: 'visual',
53
+ id: `visual-${visual.id}`,
54
+ visual
55
+ }
56
+ }));
45
57
  }
46
58
  /*
47
59
  * The thread's rows with timed rows among them: each goes right before the first row that began after
@@ -50,30 +62,30 @@ export function visualRows(visuals, heldFrom = null) {
50
62
  * timed rows the rows come back as they are, the same array.
51
63
  */
52
64
  export function withTimedRows(rows, timed) {
53
- if (timed.length === 0) {
54
- return rows;
65
+ if (timed.length === 0) {
66
+ return rows;
67
+ }
68
+ // Sorting is stable, which is what keeps rows of the same moment in the order they came.
69
+ const pending = [...timed].sort((first, second) => first.at - second.at);
70
+ const merged = [];
71
+ let next = 0;
72
+ for (const row of rows) {
73
+ const time = rowTime(row);
74
+ while (time !== null && next < pending.length && pending[next].at < time) {
75
+ merged.push(pending[next].row);
76
+ next += 1;
55
77
  }
56
- // Sorting is stable, which is what keeps rows of the same moment in the order they came.
57
- const pending = [...timed].sort((first, second) => first.at - second.at);
58
- const merged = [];
59
- let next = 0;
60
- for (const row of rows) {
61
- const time = rowTime(row);
62
- while (time !== null && next < pending.length && pending[next].at < time) {
63
- merged.push(pending[next].row);
64
- next += 1;
65
- }
66
- merged.push(row);
67
- }
68
- for (; next < pending.length; next++) {
69
- merged.push(pending[next].row);
70
- }
71
- return merged;
78
+ merged.push(row);
79
+ }
80
+ for (; next < pending.length; next++) {
81
+ merged.push(pending[next].row);
82
+ }
83
+ return merged;
72
84
  }
73
85
  /*
74
86
  * What goes among a thread's rows by its moment: the visuals, then the app's cards, so a visual comes
75
87
  * first among rows of the same moment. `visuals` is null where the host draws none.
76
88
  */
77
89
  export function timedRowsOf(cards, visuals, heldFrom = null) {
78
- return [...(visuals === null ? [] : visualRows(visuals, heldFrom)), ...cardRows(cards)];
79
- }
90
+ return [...(visuals === null ? [] : visualRows(visuals, heldFrom)), ...cardRows(cards)];
91
+ }
@@ -10,50 +10,42 @@ import { stripAnsi } from './ansi.js';
10
10
  * `file_path`.
11
11
  */
12
12
  export function stripMarkdown(text) {
13
- return text
14
- .replace(/^ *```[^\n]*\n?/gm, '')
15
- .replace(/^ *(#{1,6}) +/gm, '')
16
- .replace(/^ *> ?/gm, '')
17
- .replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1')
18
- .replace(/\[([^\]]*)\]\([^)]*\)/g, '$1')
19
- .replace(/(\*\*|__)(?=\S)([\s\S]*?\S)\1/g, '$2')
20
- .replace(/\*(?=\S)([^*\n]*\S)\*/g, '$1')
21
- .replace(/`+([^`]+)`+/g, '$1')
22
- .trim();
13
+ return text.replace(/^ *```[^\n]*\n?/gm, '').replace(/^ *(#{1,6}) +/gm, '').replace(/^ *> ?/gm, '').replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1').replace(/\[([^\]]*)\]\([^)]*\)/g, '$1').replace(/(\*\*|__)(?=\S)([\s\S]*?\S)\1/g, '$2').replace(/\*(?=\S)([^*\n]*\S)\*/g, '$1').replace(/`+([^`]+)`+/g, '$1').trim();
23
14
  }
24
15
  /* What a tool call has to show for itself: what it answered, or what it has answered so far. */
25
16
  function outputOf(tool) {
26
- const output = tool.output ?? tool.progress?.output ?? null;
27
- return output === null ? null : stripAnsi(output);
17
+ const output = tool.output ?? tool.progress?.output ?? null;
18
+ return output === null ? null : stripAnsi(output);
28
19
  }
29
20
  /* The whole item under the pointer as plain text, or null for a row that carries no message. */
30
21
  export function messageTextOf(row) {
31
- switch (row.kind) {
32
- case 'user':
33
- return row.item.text || null;
34
- case 'assistant':
35
- return stripMarkdown(row.item.text) || null;
36
- case 'report':
37
- return stripMarkdown(row.text) || null;
38
- case 'thinking':
39
- return row.item.text || null;
40
- case 'work':
41
- case 'work-live':
42
- case 'workflow':
43
- return outputOf(row.tool);
44
- case 'work-group': {
45
- const outputs = row.tools.map(outputOf).filter((output) => output !== null);
46
- return outputs.length > 0 ? outputs.join('\n\n') : null;
47
- }
48
- case 'subagent':
49
- return row.item.result ?? row.item.summary ?? null;
50
- case 'note':
51
- return row.text;
52
- default:
53
- return null;
54
- }
22
+ switch (row.kind) {
23
+ case 'user':
24
+ return row.item.text || null;
25
+ case 'assistant':
26
+ return stripMarkdown(row.item.text) || null;
27
+ case 'report':
28
+ return stripMarkdown(row.text) || null;
29
+ case 'thinking':
30
+ return row.item.text || null;
31
+ case 'work':
32
+ case 'work-live':
33
+ case 'workflow':
34
+ return outputOf(row.tool);
35
+ case 'work-group':
36
+ {
37
+ const outputs = row.tools.map(outputOf).filter(output => output !== null);
38
+ return outputs.length > 0 ? outputs.join('\n\n') : null;
39
+ }
40
+ case 'subagent':
41
+ return row.item.result ?? row.item.summary ?? null;
42
+ case 'note':
43
+ return row.text;
44
+ default:
45
+ return null;
46
+ }
55
47
  }
56
48
  /* The markdown an answer was written in; every other row has none to copy. */
57
49
  export function markdownOf(row) {
58
- return row.kind === 'assistant' ? row.item.text || null : row.kind === 'report' ? row.text || null : null;
59
- }
50
+ return row.kind === 'assistant' ? row.item.text || null : row.kind === 'report' ? row.text || null : null;
51
+ }