@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
@@ -11,80 +11,91 @@ const storageKey = () => chatStorageKey('stash');
11
11
  // Past this the list is an archive nobody reads; the oldest entry makes room for a new one.
12
12
  export const STASH_LIMIT = 20;
13
13
  function strings(value) {
14
- return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
14
+ return Array.isArray(value) ? value.filter(entry => typeof entry === 'string') : [];
15
15
  }
16
16
  function attachments(value) {
17
- if (!Array.isArray(value)) {
18
- return [];
19
- }
20
- return value.filter(isRecord).map((entry) => ({
21
- name: typeof entry.name === 'string' ? entry.name : '',
22
- mime: typeof entry.mime === 'string' ? entry.mime : '',
23
- size: typeof entry.size === 'number' ? entry.size : 0
24
- }));
17
+ if (!Array.isArray(value)) {
18
+ return [];
19
+ }
20
+ return value.filter(isRecord).map(entry => ({
21
+ name: typeof entry.name === 'string' ? entry.name : '',
22
+ mime: typeof entry.mime === 'string' ? entry.mime : '',
23
+ size: typeof entry.size === 'number' ? entry.size : 0
24
+ }));
25
25
  }
26
26
  function stashedQuote(value) {
27
- if (!isRecord(value) || typeof value.text !== 'string' || typeof value.chatId !== 'string' || typeof value.itemId !== 'string') {
28
- return undefined;
29
- }
30
- return { text: value.text, chatId: value.chatId, itemId: value.itemId };
27
+ if (!isRecord(value) || typeof value.text !== 'string' || typeof value.chatId !== 'string' || typeof value.itemId !== 'string') {
28
+ return undefined;
29
+ }
30
+ return {
31
+ text: value.text,
32
+ chatId: value.chatId,
33
+ itemId: value.itemId
34
+ };
31
35
  }
32
36
  function stashedQuoteField(value) {
33
- const quote = stashedQuote(value);
34
- return quote === undefined ? {} : { quote };
37
+ const quote = stashedQuote(value);
38
+ return quote === undefined ? {} : {
39
+ quote
40
+ };
35
41
  }
36
42
  /* Only the fields we know today, so anything an older or a broken write left behind falls away here. */
37
43
  export function parseStash(raw) {
38
- if (raw === null) {
39
- return [];
40
- }
41
- try {
42
- const stored = JSON.parse(raw);
43
- if (!Array.isArray(stored)) {
44
- return [];
45
- }
46
- return stored
47
- .filter(isRecord)
48
- .filter((entry) => typeof entry.id === 'string' && typeof entry.text === 'string')
49
- .map((entry) => ({
50
- id: entry.id,
51
- text: entry.text,
52
- mentions: strings(entry.mentions),
53
- skills: strings(entry.skills),
54
- chats: strings(entry.chats),
55
- attachments: attachments(entry.attachments),
56
- ...stashedQuoteField(entry.quote),
57
- createdAt: typeof entry.createdAt === 'number' ? entry.createdAt : 0
58
- }))
59
- .slice(0, STASH_LIMIT);
60
- }
61
- catch {
62
- return [];
44
+ if (raw === null) {
45
+ return [];
46
+ }
47
+ try {
48
+ const stored = JSON.parse(raw);
49
+ if (!Array.isArray(stored)) {
50
+ return [];
63
51
  }
52
+ return stored.filter(isRecord).filter(entry => typeof entry.id === 'string' && typeof entry.text === 'string').map(entry => ({
53
+ id: entry.id,
54
+ text: entry.text,
55
+ mentions: strings(entry.mentions),
56
+ skills: strings(entry.skills),
57
+ chats: strings(entry.chats),
58
+ attachments: attachments(entry.attachments),
59
+ ...stashedQuoteField(entry.quote),
60
+ createdAt: typeof entry.createdAt === 'number' ? entry.createdAt : 0
61
+ })).slice(0, STASH_LIMIT);
62
+ } catch {
63
+ return [];
64
+ }
64
65
  }
65
66
  /* Newest first, capped: the entry that has been waiting longest is the one nobody comes back for. */
66
67
  export function withStashed(prompts, entry) {
67
- return [entry, ...prompts].slice(0, STASH_LIMIT);
68
+ return [entry, ...prompts].slice(0, STASH_LIMIT);
68
69
  }
69
70
  /*
70
71
  * What a draft looks like on the shelf; null when there is nothing worth putting there. A quote that
71
72
  * knows its reply stays apart, since it leads back to that reply in `chatId`; any other is folded into the text.
72
73
  */
73
74
  export function stashedFrom(draft, id, now, chatId) {
74
- if (isEmptyDraft(draft)) {
75
- return null;
76
- }
77
- const kept = draft.quote !== '' && draft.quoteSource !== null;
78
- return {
79
- id,
80
- text: kept ? draft.text : withQuote(draft.quote, draft.text),
81
- ...(kept ? { quote: { text: draft.quote, chatId, itemId: draft.quoteSource } } : {}),
82
- mentions: [...draft.mentions],
83
- skills: [...draft.skills],
84
- chats: [...draft.chats],
85
- attachments: draft.attachments.map((attachment) => ({ name: attachment.name, mime: attachment.mime, size: uploadBytes(attachment) })),
86
- createdAt: now
87
- };
75
+ if (isEmptyDraft(draft)) {
76
+ return null;
77
+ }
78
+ const kept = draft.quote !== '' && draft.quoteSource !== null;
79
+ return {
80
+ id,
81
+ text: kept ? draft.text : withQuote(draft.quote, draft.text),
82
+ ...(kept ? {
83
+ quote: {
84
+ text: draft.quote,
85
+ chatId,
86
+ itemId: draft.quoteSource
87
+ }
88
+ } : {}),
89
+ mentions: [...draft.mentions],
90
+ skills: [...draft.skills],
91
+ chats: [...draft.chats],
92
+ attachments: draft.attachments.map(attachment => ({
93
+ name: attachment.name,
94
+ mime: attachment.mime,
95
+ size: uploadBytes(attachment)
96
+ })),
97
+ createdAt: now
98
+ };
88
99
  }
89
100
  /* The limit of `chats` in a send. */
90
101
  export const STASH_CHATS_LIMIT = 16;
@@ -93,26 +104,35 @@ export const STASH_CHATS_LIMIT = 16;
93
104
  * order they were picked. `dropped` counts the chats left out because the project no longer has them.
94
105
  */
95
106
  export function restorableChats(stashed, referable, chatId) {
96
- const others = stashed.filter((id) => id !== chatId);
97
- const chats = others.filter((id) => referable.has(id));
98
- return { chats: chats.slice(0, STASH_CHATS_LIMIT), dropped: others.length - chats.length };
107
+ const others = stashed.filter(id => id !== chatId);
108
+ const chats = others.filter(id => referable.has(id));
109
+ return {
110
+ chats: chats.slice(0, STASH_CHATS_LIMIT),
111
+ dropped: others.length - chats.length
112
+ };
99
113
  }
100
114
  const storage = persistedJson(storageKey, parseStash, [], () => chatStorageLegacyKeys('stash'));
101
115
  /* Prompts put aside for later can move to another chat, so the shelf is shared across chats. */
102
- export const useStash = createChatStore(() => ({ prompts: [] }), (store) => store.setState({ prompts: storage.read() }));
116
+ export const useStash = createChatStore(() => ({
117
+ prompts: []
118
+ }), store => store.setState({
119
+ prompts: storage.read()
120
+ }));
103
121
  function write(prompts) {
104
- useStash.setState({ prompts });
105
- storage.write(prompts);
122
+ useStash.setState({
123
+ prompts
124
+ });
125
+ storage.write(prompts);
106
126
  }
107
127
  /* Puts a draft on the shelf; false when the composer held nothing to put there. */
108
128
  export function stashDraft(draft, chatId) {
109
- const entry = stashedFrom(draft, `stash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, Date.now(), chatId);
110
- if (!entry) {
111
- return false;
112
- }
113
- write(withStashed(useStash.getState().prompts, entry));
114
- return true;
129
+ const entry = stashedFrom(draft, `stash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, Date.now(), chatId);
130
+ if (!entry) {
131
+ return false;
132
+ }
133
+ write(withStashed(useStash.getState().prompts, entry));
134
+ return true;
115
135
  }
116
136
  export function forgetStashed(id) {
117
- write(useStash.getState().prompts.filter((entry) => entry.id !== id));
118
- }
137
+ write(useStash.getState().prompts.filter(entry => entry.id !== id));
138
+ }
@@ -3,16 +3,16 @@ import { errorCode, isConnectionError } from '../transport.js';
3
3
  // What the panel opens on: the newest end of the conversation, which is where an agent that works is.
4
4
  export const SUBAGENT_PAGE = 60;
5
5
  export const INITIAL_CONVERSATION = {
6
- status: 'loading',
7
- items: [],
8
- pending: [],
9
- source: null,
10
- context: null,
11
- cursor: null,
12
- live: false,
13
- loadingEarlier: false,
14
- error: null,
15
- unsupported: false
6
+ status: 'loading',
7
+ items: [],
8
+ pending: [],
9
+ source: null,
10
+ context: null,
11
+ cursor: null,
12
+ live: false,
13
+ loadingEarlier: false,
14
+ error: null,
15
+ unsupported: false
16
16
  };
17
17
  /*
18
18
  * The newest page laid over what is on screen. An item that is already there is replaced where it
@@ -20,27 +20,32 @@ export const INITIAL_CONVERSATION = {
20
20
  * happened than one page holds, so what is held is dropped for it rather than shown with a hole.
21
21
  */
22
22
  export function mergeNewest(current, currentCursor, page, pageCursor) {
23
- const known = new Map(current.map((item, index) => [item.id, index]));
24
- if (current.length > 0 && page.length > 0 && !page.some((item) => known.has(item.id))) {
25
- return { items: page, cursor: pageCursor };
23
+ const known = new Map(current.map((item, index) => [item.id, index]));
24
+ if (current.length > 0 && page.length > 0 && !page.some(item => known.has(item.id))) {
25
+ return {
26
+ items: page,
27
+ cursor: pageCursor
28
+ };
29
+ }
30
+ const items = [...current];
31
+ for (const item of page) {
32
+ const index = known.get(item.id);
33
+ if (index === undefined) {
34
+ items.push(item);
35
+ } else {
36
+ items[index] = item;
26
37
  }
27
- const items = [...current];
28
- for (const item of page) {
29
- const index = known.get(item.id);
30
- if (index === undefined) {
31
- items.push(item);
32
- }
33
- else {
34
- items[index] = item;
35
- }
36
- }
37
- return { items, cursor: current.length === 0 ? pageCursor : currentCursor };
38
+ }
39
+ return {
40
+ items,
41
+ cursor: current.length === 0 ? pageCursor : currentCursor
42
+ };
38
43
  }
39
44
  function pendingOf(items) {
40
- return items.filter((item) => (item.kind === 'approval' && item.decision === 'pending') || (item.kind === 'question' && item.state === 'pending'));
45
+ return items.filter(item => item.kind === 'approval' && item.decision === 'pending' || item.kind === 'question' && item.state === 'pending');
41
46
  }
42
47
  function messageOf(error) {
43
- return error instanceof Error ? error.message : i18next.t('agent-chat:subagents.noAnswer');
48
+ return error instanceof Error ? error.message : i18next.t('agent-chat:subagents.noAnswer');
44
49
  }
45
50
  /*
46
51
  * One subagent's conversation as a panel follows it. Opening asks for the newest page and holds the
@@ -49,125 +54,162 @@ function messageOf(error) {
49
54
  * last thing it says.
50
55
  */
51
56
  export class SubagentConversation {
52
- transport;
53
- chatId;
54
- toolUseId;
55
- onChange;
56
- unsubscribe = [];
57
- state = INITIAL_CONVERSATION;
58
- disposed = false;
59
- // One request at a time, so a refresh never lands under an older page that arrived after it.
60
- queue = Promise.resolve();
61
- refreshWaiting = false;
62
- earlier = null;
63
- constructor(transport, chatId, toolUseId, onChange) {
64
- this.transport = transport;
65
- this.chatId = chatId;
66
- this.toolUseId = toolUseId;
67
- this.onChange = onChange;
68
- }
69
- get current() {
70
- return this.state;
57
+ transport;
58
+ chatId;
59
+ toolUseId;
60
+ onChange;
61
+ unsubscribe = [];
62
+ state = INITIAL_CONVERSATION;
63
+ disposed = false;
64
+ // One request at a time, so a refresh never lands under an older page that arrived after it.
65
+ queue = Promise.resolve();
66
+ refreshWaiting = false;
67
+ earlier = null;
68
+ constructor(transport, chatId, toolUseId, onChange) {
69
+ this.transport = transport;
70
+ this.chatId = chatId;
71
+ this.toolUseId = toolUseId;
72
+ this.onChange = onChange;
73
+ }
74
+ get current() {
75
+ return this.state;
76
+ }
77
+ start() {
78
+ this.unsubscribe.push(this.transport.on('chat.subagentChanged', event => {
79
+ if (event.chatId === this.chatId && event.toolUseId === this.toolUseId) {
80
+ void this.refresh();
81
+ }
82
+ }), this.transport.subscribeStatus(status => {
83
+ if (status === 'open') {
84
+ void this.enqueue(() => this.readNewest(true));
85
+ }
86
+ }));
87
+ return this.enqueue(() => this.readNewest(true));
88
+ }
89
+ /* The newest page again; calls that arrive while one waits become that one. */
90
+ refresh() {
91
+ if (this.refreshWaiting) {
92
+ return this.queue;
71
93
  }
72
- start() {
73
- this.unsubscribe.push(this.transport.on('chat.subagentChanged', (event) => {
74
- if (event.chatId === this.chatId && event.toolUseId === this.toolUseId) {
75
- void this.refresh();
76
- }
77
- }), this.transport.subscribeStatus((status) => {
78
- if (status === 'open') {
79
- void this.enqueue(() => this.readNewest(true));
80
- }
81
- }));
82
- return this.enqueue(() => this.readNewest(true));
83
- }
84
- /* The newest page again; calls that arrive while one waits become that one. */
85
- refresh() {
86
- if (this.refreshWaiting) {
87
- return this.queue;
88
- }
89
- this.refreshWaiting = true;
90
- return this.enqueue(() => {
91
- this.refreshWaiting = false;
92
- return this.readNewest(false);
94
+ this.refreshWaiting = true;
95
+ return this.enqueue(() => {
96
+ this.refreshWaiting = false;
97
+ return this.readNewest(false);
98
+ });
99
+ }
100
+ loadEarlier() {
101
+ // A page on its way answers every call made meanwhile; a scroll asks for one on every frame.
102
+ this.earlier ??= this.enqueue(async () => {
103
+ const cursor = this.state.cursor;
104
+ if (cursor === null) {
105
+ return;
106
+ }
107
+ this.set({
108
+ loadingEarlier: true
109
+ });
110
+ try {
111
+ const page = await this.ask({
112
+ cursor,
113
+ limit: SUBAGENT_PAGE
93
114
  });
94
- }
95
- loadEarlier() {
96
- // A page on its way answers every call made meanwhile; a scroll asks for one on every frame.
97
- this.earlier ??= this.enqueue(async () => {
98
- const cursor = this.state.cursor;
99
- if (cursor === null) {
100
- return;
101
- }
102
- this.set({ loadingEarlier: true });
103
- try {
104
- const page = await this.ask({ cursor, limit: SUBAGENT_PAGE });
105
- const items = [...page.items, ...this.state.items];
106
- this.set({ items, pending: page.pending ?? pendingOf(items), cursor: page.history.cursor, live: page.live, loadingEarlier: false });
107
- }
108
- catch (error) {
109
- if (errorCode(error) === 'history-expired') {
110
- // The record was written again under this panel; what it holds now is the only truth.
111
- this.set({ items: [], cursor: null, loadingEarlier: false });
112
- await this.readNewest(false);
113
- return;
114
- }
115
- this.set({ loadingEarlier: false, error: messageOf(error) });
116
- }
117
- }).finally(() => {
118
- this.earlier = null;
115
+ const items = [...page.items, ...this.state.items];
116
+ this.set({
117
+ items,
118
+ pending: page.pending ?? pendingOf(items),
119
+ cursor: page.history.cursor,
120
+ live: page.live,
121
+ loadingEarlier: false
119
122
  });
120
- return this.earlier;
121
- }
122
- dispose() {
123
- if (this.disposed) {
124
- return;
125
- }
126
- this.disposed = true;
127
- for (const off of this.unsubscribe.splice(0)) {
128
- off();
129
- }
130
- if (this.transport.status === 'open') {
131
- void this.transport.request('chat.subagent', { chatId: this.chatId, toolUseId: this.toolUseId, limit: 1, watch: false }).catch(() => undefined);
123
+ } catch (error) {
124
+ if (errorCode(error) === 'history-expired') {
125
+ // The record was written again under this panel; what it holds now is the only truth.
126
+ this.set({
127
+ items: [],
128
+ cursor: null,
129
+ loadingEarlier: false
130
+ });
131
+ await this.readNewest(false);
132
+ return;
132
133
  }
134
+ this.set({
135
+ loadingEarlier: false,
136
+ error: messageOf(error)
137
+ });
138
+ }
139
+ }).finally(() => {
140
+ this.earlier = null;
141
+ });
142
+ return this.earlier;
143
+ }
144
+ dispose() {
145
+ if (this.disposed) {
146
+ return;
133
147
  }
134
- async readNewest(watch) {
135
- try {
136
- const page = await this.ask({ limit: SUBAGENT_PAGE, ...(watch ? { watch: true } : {}) });
137
- const merged = mergeNewest(this.state.items, this.state.cursor, page.items, page.history.cursor);
138
- this.set({
139
- status: 'ready',
140
- items: merged.items,
141
- pending: page.pending ?? pendingOf(merged.items),
142
- cursor: merged.cursor,
143
- live: page.live,
144
- source: page.source,
145
- context: page.context ?? null,
146
- error: null
147
- });
148
- }
149
- catch (error) {
150
- if (this.state.status === 'ready' && isConnectionError(error)) {
151
- // What is on screen stays; the socket that comes back asks again.
152
- return;
153
- }
154
- const unsupported = errorCode(error) === 'unknown-request';
155
- this.set({ status: 'failed', error: messageOf(error), unsupported });
156
- }
148
+ this.disposed = true;
149
+ for (const off of this.unsubscribe.splice(0)) {
150
+ off();
157
151
  }
158
- ask(extra) {
159
- return this.transport.request('chat.subagent', { chatId: this.chatId, toolUseId: this.toolUseId, ...extra });
152
+ if (this.transport.status === 'open') {
153
+ void this.transport.request('chat.subagent', {
154
+ chatId: this.chatId,
155
+ toolUseId: this.toolUseId,
156
+ limit: 1,
157
+ watch: false
158
+ }).catch(() => undefined);
160
159
  }
161
- enqueue(work) {
162
- const next = this.queue.then(() => (this.disposed ? undefined : work()));
163
- this.queue = next.catch(() => undefined);
164
- return next;
160
+ }
161
+ async readNewest(watch) {
162
+ try {
163
+ const page = await this.ask({
164
+ limit: SUBAGENT_PAGE,
165
+ ...(watch ? {
166
+ watch: true
167
+ } : {})
168
+ });
169
+ const merged = mergeNewest(this.state.items, this.state.cursor, page.items, page.history.cursor);
170
+ this.set({
171
+ status: 'ready',
172
+ items: merged.items,
173
+ pending: page.pending ?? pendingOf(merged.items),
174
+ cursor: merged.cursor,
175
+ live: page.live,
176
+ source: page.source,
177
+ context: page.context ?? null,
178
+ error: null
179
+ });
180
+ } catch (error) {
181
+ if (this.state.status === 'ready' && isConnectionError(error)) {
182
+ // What is on screen stays; the socket that comes back asks again.
183
+ return;
184
+ }
185
+ const unsupported = errorCode(error) === 'unknown-request';
186
+ this.set({
187
+ status: 'failed',
188
+ error: messageOf(error),
189
+ unsupported
190
+ });
165
191
  }
166
- set(patch) {
167
- if (this.disposed) {
168
- return;
169
- }
170
- this.state = { ...this.state, ...patch };
171
- this.onChange(this.state);
192
+ }
193
+ ask(extra) {
194
+ return this.transport.request('chat.subagent', {
195
+ chatId: this.chatId,
196
+ toolUseId: this.toolUseId,
197
+ ...extra
198
+ });
199
+ }
200
+ enqueue(work) {
201
+ const next = this.queue.then(() => this.disposed ? undefined : work());
202
+ this.queue = next.catch(() => undefined);
203
+ return next;
204
+ }
205
+ set(patch) {
206
+ if (this.disposed) {
207
+ return;
172
208
  }
173
- }
209
+ this.state = {
210
+ ...this.state,
211
+ ...patch
212
+ };
213
+ this.onChange(this.state);
214
+ }
215
+ }