@adecore/agents-react 0.23.1 → 0.24.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 (341) hide show
  1. package/README.md +14 -11
  2. package/dist/agents/AccountDot.js +3 -1
  3. package/dist/agents/accounts.d.ts +3 -2
  4. package/dist/agents/accounts.js +5 -6
  5. package/dist/chat/actions.d.ts +2 -2
  6. package/dist/chat/actions.js +8 -5
  7. package/dist/chat/bookmarks.d.ts +5 -3
  8. package/dist/chat/bookmarks.js +13 -14
  9. package/dist/chat/chat-client.d.ts +1 -0
  10. package/dist/chat/chat-client.js +7 -0
  11. package/dist/chat/composer-send.d.ts +3 -0
  12. package/dist/chat/composer-send.js +22 -0
  13. package/dist/chat/forks.js +22 -5
  14. package/dist/chat/index.d.ts +31 -0
  15. package/dist/chat/index.js +28 -0
  16. package/dist/chat/logic/embedded-code.d.ts +8 -0
  17. package/dist/chat/logic/embedded-code.js +371 -0
  18. package/dist/chat/logic/fork.js +1 -0
  19. package/dist/chat/logic/goal.d.ts +6 -0
  20. package/dist/chat/logic/goal.js +26 -0
  21. package/dist/chat/logic/scrubber.d.ts +1 -1
  22. package/dist/chat/logic/scrubber.js +6 -5
  23. package/dist/chat/logic/thought.d.ts +3 -0
  24. package/dist/chat/logic/thought.js +35 -0
  25. package/dist/chat/logic/thread-cards.js +2 -0
  26. package/dist/chat/logic/timeline.d.ts +5 -0
  27. package/dist/chat/logic/timeline.js +22 -1
  28. package/dist/chat/logic/tool-catalog.d.ts +1 -0
  29. package/dist/chat/logic/tool-catalog.js +3 -1
  30. package/dist/chat/logic/tools.d.ts +14 -0
  31. package/dist/chat/logic/tools.js +57 -0
  32. package/dist/chat/preferences.d.ts +6 -0
  33. package/dist/chat/preferences.js +19 -3
  34. package/dist/chat/reading-width.d.ts +9 -0
  35. package/dist/chat/reading-width.js +27 -0
  36. package/dist/chat/send-key.d.ts +10 -0
  37. package/dist/chat/send-key.js +24 -0
  38. package/dist/chat/ui/BookmarkMarker.js +4 -2
  39. package/dist/chat/ui/BookmarkSubmenu.js +4 -3
  40. package/dist/chat/ui/ChatActivity.js +14 -10
  41. package/dist/chat/ui/ChatReferenceChip.js +3 -4
  42. package/dist/chat/ui/CodeBlock.d.ts +2 -1
  43. package/dist/chat/ui/CodeBlock.js +14 -96
  44. package/dist/chat/ui/Composer.d.ts +1 -1
  45. package/dist/chat/ui/Composer.js +117 -906
  46. package/dist/chat/ui/ComposerInput.js +5 -4
  47. package/dist/chat/ui/EditDiff.js +3 -2
  48. package/dist/chat/ui/GoalDock.d.ts +9 -0
  49. package/dist/chat/ui/GoalDock.js +63 -0
  50. package/dist/chat/ui/LimitState.js +5 -3
  51. package/dist/chat/ui/Markdown.d.ts +2 -1
  52. package/dist/chat/ui/Markdown.js +70 -31
  53. package/dist/chat/ui/MermaidBlock.d.ts +3 -0
  54. package/dist/chat/ui/MermaidBlock.js +73 -0
  55. package/dist/chat/ui/MessageActions.js +12 -7
  56. package/dist/chat/ui/Pickers.js +6 -5
  57. package/dist/chat/ui/PromptComposer.js +4 -3
  58. package/dist/chat/ui/RowTime.d.ts +3 -0
  59. package/dist/chat/ui/RowTime.js +12 -0
  60. package/dist/chat/ui/RunSettings.js +5 -4
  61. package/dist/chat/ui/ShellCommand.d.ts +3 -0
  62. package/dist/chat/ui/ShellCommand.js +110 -0
  63. package/dist/chat/ui/SubagentInfo.js +4 -3
  64. package/dist/chat/ui/SubagentStopButton.js +4 -3
  65. package/dist/chat/ui/SubagentTimeline.js +4 -1
  66. package/dist/chat/ui/Timeline.js +70 -40
  67. package/dist/chat/ui/TimelineMenu.d.ts +2 -1
  68. package/dist/chat/ui/TimelineMenu.js +18 -8
  69. package/dist/chat/ui/UnifiedDiff.js +3 -2
  70. package/dist/chat/ui/VisualFrame.js +6 -7
  71. package/dist/chat/ui/code-theme.d.ts +2 -1
  72. package/dist/chat/ui/code-theme.js +4 -4
  73. package/dist/chat/ui/composer/ComposerControls.d.ts +27 -0
  74. package/dist/chat/ui/composer/ComposerControls.js +34 -0
  75. package/dist/chat/ui/composer/ComposerMenu.d.ts +4 -0
  76. package/dist/chat/ui/composer/ComposerMenu.js +46 -0
  77. package/dist/chat/ui/composer/DraftParts.d.ts +18 -0
  78. package/dist/chat/ui/composer/DraftParts.js +25 -0
  79. package/dist/chat/ui/composer/QueuedMessages.d.ts +10 -0
  80. package/dist/chat/ui/composer/QueuedMessages.js +20 -0
  81. package/dist/chat/ui/composer/key-handler.d.ts +20 -0
  82. package/dist/chat/ui/composer/key-handler.js +150 -0
  83. package/dist/chat/ui/composer/keys.d.ts +7 -2
  84. package/dist/chat/ui/composer/keys.js +19 -9
  85. package/dist/chat/ui/composer/placeholder.d.ts +9 -0
  86. package/dist/chat/ui/composer/placeholder.js +38 -0
  87. package/dist/chat/ui/composer/use-chat-controls.d.ts +28 -0
  88. package/dist/chat/ui/composer/use-chat-controls.js +112 -0
  89. package/dist/chat/ui/composer/use-compaction-offer.d.ts +2 -0
  90. package/dist/chat/ui/composer/use-compaction-offer.js +23 -0
  91. package/dist/chat/ui/composer/use-composer-draft.d.ts +14 -0
  92. package/dist/chat/ui/composer/use-composer-draft.js +39 -0
  93. package/dist/chat/ui/composer/use-composer-menus.d.ts +52 -0
  94. package/dist/chat/ui/composer/use-composer-menus.js +232 -0
  95. package/dist/chat/ui/composer/use-composer-submit.d.ts +32 -0
  96. package/dist/chat/ui/composer/use-composer-submit.js +113 -0
  97. package/dist/chat/ui/composer/use-draft-files.d.ts +27 -0
  98. package/dist/chat/ui/composer/use-draft-files.js +111 -0
  99. package/dist/chat/ui/composer/use-notice.d.ts +6 -0
  100. package/dist/chat/ui/composer/use-notice.js +18 -0
  101. package/dist/chat/ui/composer/use-pending-requests.d.ts +2 -0
  102. package/dist/chat/ui/composer/use-pending-requests.js +22 -0
  103. package/dist/chat/ui/composer/use-prompt-history.d.ts +8 -0
  104. package/dist/chat/ui/composer/use-prompt-history.js +57 -0
  105. package/dist/chat/ui/composer/use-prompt-hold.d.ts +6 -0
  106. package/dist/chat/ui/composer/use-prompt-hold.js +48 -0
  107. package/dist/chat/ui/composer/use-take-back.d.ts +13 -0
  108. package/dist/chat/ui/composer/use-take-back.js +82 -0
  109. package/dist/chat/ui/diff/EditorEditDiff.js +4 -3
  110. package/dist/chat/ui/diff/LegacyDiffPool.js +3 -2
  111. package/dist/chat/ui/diff/LegacyEditDiff.js +3 -2
  112. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +3 -2
  113. package/dist/chat/ui/diff/syntax-runtime.d.ts +2 -1
  114. package/dist/chat/ui/diff/syntax-runtime.js +9 -5
  115. package/dist/chat/ui/diff-syntax.d.ts +2 -2
  116. package/dist/chat/ui/diff-syntax.js +1 -2
  117. package/dist/chat/ui/diff-theme.js +10 -9
  118. package/dist/chat/ui/file-links.d.ts +1 -1
  119. package/dist/chat/ui/file-links.js +7 -5
  120. package/dist/chat/ui/highlighter.d.ts +27 -0
  121. package/dist/chat/ui/highlighter.js +151 -0
  122. package/dist/chat/ui/index.d.ts +67 -0
  123. package/dist/chat/ui/index.js +64 -0
  124. package/dist/chat/ui/intelligent-ui/UiReply.js +3 -2
  125. package/dist/chat/ui/intelligent-ui/renderers/content.js +3 -2
  126. package/dist/chat/ui/intelligent-ui/use-ui-links.js +2 -2
  127. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +4 -3
  128. package/dist/chat/ui/markdown-blocks.d.ts +8 -0
  129. package/dist/chat/ui/markdown-blocks.js +260 -12
  130. package/dist/chat/ui/mermaid.d.ts +23 -0
  131. package/dist/chat/ui/mermaid.js +93 -0
  132. package/dist/chat/ui/rows/ForksRow.js +5 -3
  133. package/dist/chat/ui/rows/GeneratedImageRow.js +6 -4
  134. package/dist/chat/ui/rows/MessageRows.d.ts +4 -0
  135. package/dist/chat/ui/rows/MessageRows.js +36 -13
  136. package/dist/chat/ui/rows/Rows.js +3 -1
  137. package/dist/chat/ui/rows/SubagentRow.js +3 -2
  138. package/dist/chat/ui/rows/VisualRow.js +3 -2
  139. package/dist/chat/ui/rows/WorkRows.d.ts +6 -3
  140. package/dist/chat/ui/rows/WorkRows.js +57 -20
  141. package/dist/chat/ui/rows/WorkflowRow.js +3 -2
  142. package/dist/chat/ui/timestamp-format.d.ts +1 -0
  143. package/dist/chat/ui/timestamp-format.js +2 -0
  144. package/dist/chat/ui/use-diff-source-tokens.js +6 -3
  145. package/dist/chat/ui/visual-theme.js +3 -2
  146. package/dist/host.d.ts +9 -6
  147. package/dist/host.js +19 -8
  148. package/dist/index.d.ts +8 -0
  149. package/dist/index.js +9 -0
  150. package/dist/locales/en/agent-chat.d.ts +658 -0
  151. package/dist/locales/en/agent-chat.js +657 -0
  152. package/dist/locales/en/agent-prompts.d.ts +44 -0
  153. package/dist/locales/en/agent-prompts.js +43 -0
  154. package/dist/locales/en/agent-providers.d.ts +132 -0
  155. package/dist/locales/en/agent-providers.js +131 -0
  156. package/dist/locales/en/agent-usage.d.ts +132 -0
  157. package/dist/locales/en/agent-usage.js +131 -0
  158. package/dist/locales/nl/agent-chat.d.ts +658 -0
  159. package/dist/locales/nl/agent-chat.js +657 -0
  160. package/dist/locales/nl/agent-prompts.d.ts +44 -0
  161. package/dist/locales/nl/agent-prompts.js +43 -0
  162. package/dist/locales/nl/agent-providers.d.ts +132 -0
  163. package/dist/locales/nl/agent-providers.js +131 -0
  164. package/dist/locales/nl/agent-usage.d.ts +132 -0
  165. package/dist/locales/nl/agent-usage.js +131 -0
  166. package/dist/locales.js +9 -8
  167. package/dist/prompts/index.d.ts +11 -0
  168. package/dist/prompts/index.js +12 -0
  169. package/dist/prompts/logic/subjects.d.ts +2 -1
  170. package/dist/prompts/logic/subjects.js +6 -4
  171. package/dist/prompts/ui/ApprovalBody.js +6 -4
  172. package/dist/prompts/ui/PromptCard.js +5 -4
  173. package/dist/prompts/ui/PromptView.js +3 -2
  174. package/dist/prompts/ui/QuestionBody.js +3 -2
  175. package/dist/providers/AccountColors.js +2 -2
  176. package/dist/providers/AccountDetail.js +7 -6
  177. package/dist/providers/AccountVariables.js +3 -1
  178. package/dist/providers/AddAccountForm.js +3 -2
  179. package/dist/providers/ProvidersPane.js +4 -3
  180. package/dist/providers/account-actions.d.ts +4 -3
  181. package/dist/providers/account-actions.js +6 -7
  182. package/dist/providers/index.d.ts +16 -0
  183. package/dist/providers/index.js +17 -0
  184. package/dist/providers/provider-abilities.d.ts +2 -1
  185. package/dist/providers/provider-abilities.js +4 -0
  186. package/dist/state/chats.js +4 -2
  187. package/dist/state/index.d.ts +4 -0
  188. package/dist/state/index.js +5 -0
  189. package/dist/testing/index.d.ts +1 -0
  190. package/dist/testing/index.js +2 -0
  191. package/dist/{prompts/logic/prompts.fixtures.d.ts → testing/prompts.d.ts} +1 -1
  192. package/dist/theme.css +13 -3
  193. package/dist/usage/UsageBreakdown.js +3 -2
  194. package/dist/usage/UsageLimits.js +4 -3
  195. package/dist/usage/UsagePage.js +3 -2
  196. package/dist/usage/index.d.ts +15 -0
  197. package/dist/usage/index.js +15 -0
  198. package/package.json +53 -1031
  199. package/src/agents/AccountDot.tsx +3 -1
  200. package/src/agents/accounts.ts +6 -6
  201. package/src/chat/actions.ts +8 -5
  202. package/src/chat/bookmarks.ts +23 -14
  203. package/src/chat/chat-client.ts +8 -0
  204. package/src/chat/composer-send.ts +27 -0
  205. package/src/chat/forks.ts +27 -6
  206. package/src/chat/index.ts +98 -0
  207. package/src/chat/logic/embedded-code.ts +409 -0
  208. package/src/chat/logic/fork.ts +1 -0
  209. package/src/chat/logic/goal.ts +33 -0
  210. package/src/chat/logic/scrubber.ts +6 -5
  211. package/src/chat/logic/thought.ts +40 -0
  212. package/src/chat/logic/thread-cards.ts +2 -0
  213. package/src/chat/logic/timeline.ts +25 -1
  214. package/src/chat/logic/tool-catalog.ts +5 -1
  215. package/src/chat/logic/tools.ts +76 -0
  216. package/src/chat/preferences.ts +26 -3
  217. package/src/chat/reading-width.ts +39 -0
  218. package/src/chat/send-key.ts +38 -0
  219. package/src/chat/ui/BookmarkMarker.tsx +4 -2
  220. package/src/chat/ui/BookmarkSubmenu.tsx +4 -3
  221. package/src/chat/ui/ChatActivity.tsx +14 -10
  222. package/src/chat/ui/ChatReferenceChip.tsx +3 -4
  223. package/src/chat/ui/CodeBlock.tsx +33 -124
  224. package/src/chat/ui/Composer.tsx +162 -1324
  225. package/src/chat/ui/ComposerInput.tsx +5 -4
  226. package/src/chat/ui/EditDiff.tsx +3 -2
  227. package/src/chat/ui/GoalDock.tsx +104 -0
  228. package/src/chat/ui/LimitState.tsx +5 -3
  229. package/src/chat/ui/Markdown.tsx +113 -39
  230. package/src/chat/ui/MermaidBlock.tsx +119 -0
  231. package/src/chat/ui/MessageActions.tsx +13 -8
  232. package/src/chat/ui/Pickers.tsx +8 -7
  233. package/src/chat/ui/PromptComposer.tsx +4 -3
  234. package/src/chat/ui/RowTime.tsx +21 -0
  235. package/src/chat/ui/RunSettings.tsx +9 -4
  236. package/src/chat/ui/ShellCommand.tsx +134 -0
  237. package/src/chat/ui/SubagentInfo.tsx +4 -3
  238. package/src/chat/ui/SubagentStopButton.tsx +4 -3
  239. package/src/chat/ui/SubagentTimeline.tsx +5 -1
  240. package/src/chat/ui/Timeline.tsx +167 -105
  241. package/src/chat/ui/TimelineMenu.tsx +42 -7
  242. package/src/chat/ui/UnifiedDiff.tsx +3 -2
  243. package/src/chat/ui/VisualFrame.tsx +6 -7
  244. package/src/chat/ui/code-theme.ts +4 -4
  245. package/src/chat/ui/composer/ComposerControls.tsx +147 -0
  246. package/src/chat/ui/composer/ComposerMenu.tsx +138 -0
  247. package/src/chat/ui/composer/DraftParts.tsx +86 -0
  248. package/src/chat/ui/composer/QueuedMessages.tsx +64 -0
  249. package/src/chat/ui/composer/key-handler.ts +174 -0
  250. package/src/chat/ui/composer/keys.ts +32 -10
  251. package/src/chat/ui/composer/placeholder.ts +48 -0
  252. package/src/chat/ui/composer/use-chat-controls.ts +134 -0
  253. package/src/chat/ui/composer/use-compaction-offer.ts +25 -0
  254. package/src/chat/ui/composer/use-composer-draft.ts +71 -0
  255. package/src/chat/ui/composer/use-composer-menus.ts +289 -0
  256. package/src/chat/ui/composer/use-composer-submit.ts +163 -0
  257. package/src/chat/ui/composer/use-draft-files.ts +135 -0
  258. package/src/chat/ui/composer/use-notice.ts +28 -0
  259. package/src/chat/ui/composer/use-pending-requests.ts +23 -0
  260. package/src/chat/ui/composer/use-prompt-history.ts +76 -0
  261. package/src/chat/ui/composer/use-prompt-hold.ts +58 -0
  262. package/src/chat/ui/composer/use-take-back.ts +91 -0
  263. package/src/chat/ui/diff/DiffFallbackBoundary.tsx +2 -2
  264. package/src/chat/ui/diff/EditorEditDiff.tsx +4 -3
  265. package/src/chat/ui/diff/LegacyDiffPool.tsx +3 -2
  266. package/src/chat/ui/diff/LegacyEditDiff.tsx +3 -2
  267. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +3 -2
  268. package/src/chat/ui/diff/syntax-runtime.ts +10 -5
  269. package/src/chat/ui/diff-syntax.ts +2 -2
  270. package/src/chat/ui/diff-theme.ts +10 -9
  271. package/src/chat/ui/file-links.ts +7 -5
  272. package/src/chat/ui/highlighter.ts +185 -0
  273. package/src/chat/ui/index.ts +109 -0
  274. package/src/chat/ui/intelligent-ui/UiReply.tsx +5 -4
  275. package/src/chat/ui/intelligent-ui/renderers/content.tsx +3 -2
  276. package/src/chat/ui/intelligent-ui/use-ui-links.ts +2 -2
  277. package/src/chat/ui/intelligent-ui/use-ui-queries.ts +4 -3
  278. package/src/chat/ui/markdown-blocks.ts +300 -12
  279. package/src/chat/ui/mermaid.ts +118 -0
  280. package/src/chat/ui/rows/ForksRow.tsx +5 -3
  281. package/src/chat/ui/rows/GeneratedImageRow.tsx +6 -4
  282. package/src/chat/ui/rows/MessageRows.tsx +73 -18
  283. package/src/chat/ui/rows/Rows.tsx +14 -1
  284. package/src/chat/ui/rows/SubagentRow.tsx +3 -2
  285. package/src/chat/ui/rows/VisualRow.tsx +3 -2
  286. package/src/chat/ui/rows/WorkRows.tsx +148 -47
  287. package/src/chat/ui/rows/WorkflowRow.tsx +3 -2
  288. package/src/chat/ui/timestamp-format.ts +2 -0
  289. package/src/chat/ui/use-diff-source-tokens.ts +10 -4
  290. package/src/chat/ui/visual-theme.ts +3 -2
  291. package/src/host.ts +31 -15
  292. package/src/index.ts +49 -0
  293. package/src/locales/en/agent-chat.ts +657 -0
  294. package/src/locales/en/agent-prompts.ts +43 -0
  295. package/src/locales/en/agent-providers.ts +131 -0
  296. package/src/locales/en/agent-usage.ts +131 -0
  297. package/src/locales/nl/agent-chat.ts +657 -0
  298. package/src/locales/nl/agent-prompts.ts +43 -0
  299. package/src/locales/nl/agent-providers.ts +131 -0
  300. package/src/locales/nl/agent-usage.ts +132 -0
  301. package/src/locales.ts +9 -8
  302. package/src/prompts/index.ts +35 -0
  303. package/src/prompts/logic/subjects.ts +12 -4
  304. package/src/prompts/ui/ApprovalBody.tsx +6 -4
  305. package/src/prompts/ui/PromptCard.tsx +11 -4
  306. package/src/prompts/ui/PromptView.tsx +3 -2
  307. package/src/prompts/ui/QuestionBody.tsx +3 -2
  308. package/src/providers/AccountColors.tsx +2 -2
  309. package/src/providers/AccountDetail.tsx +13 -7
  310. package/src/providers/AccountVariables.tsx +3 -1
  311. package/src/providers/AddAccountForm.tsx +3 -2
  312. package/src/providers/ProvidersPane.tsx +4 -3
  313. package/src/providers/account-actions.ts +7 -7
  314. package/src/providers/index.ts +17 -0
  315. package/src/providers/provider-abilities.ts +6 -1
  316. package/src/state/chats.ts +4 -2
  317. package/src/state/index.ts +39 -0
  318. package/src/testing/index.ts +2 -0
  319. package/src/{prompts/logic/prompts.fixtures.ts → testing/prompts.ts} +1 -1
  320. package/src/theme.css +13 -3
  321. package/src/usage/UsageBreakdown.tsx +3 -2
  322. package/src/usage/UsageLimits.tsx +4 -3
  323. package/src/usage/UsagePage.tsx +3 -2
  324. package/src/usage/index.ts +16 -0
  325. package/dist/locales/en/agent-chat.json +0 -597
  326. package/dist/locales/en/agent-prompts.json +0 -43
  327. package/dist/locales/en/agent-providers.json +0 -131
  328. package/dist/locales/en/agent-usage.json +0 -131
  329. package/dist/locales/nl/agent-chat.json +0 -597
  330. package/dist/locales/nl/agent-prompts.json +0 -43
  331. package/dist/locales/nl/agent-providers.json +0 -131
  332. package/dist/locales/nl/agent-usage.json +0 -131
  333. package/src/locales/en/agent-chat.json +0 -597
  334. package/src/locales/en/agent-prompts.json +0 -43
  335. package/src/locales/en/agent-providers.json +0 -131
  336. package/src/locales/en/agent-usage.json +0 -131
  337. package/src/locales/nl/agent-chat.json +0 -597
  338. package/src/locales/nl/agent-prompts.json +0 -43
  339. package/src/locales/nl/agent-providers.json +0 -131
  340. package/src/locales/nl/agent-usage.json +0 -131
  341. /package/dist/{prompts/logic/prompts.fixtures.js → testing/prompts.js} +0 -0
@@ -6,12 +6,12 @@ import { AgentIcon } from '../../agents/AgentIcon';
6
6
  import { ProviderLogo } from '../../agents/ProviderLogo';
7
7
  import { agentChipOf, modelName } from '../../agents/model-name';
8
8
  import { modelRequirementOf } from '../../agents/model-requirement';
9
- import { chatHost } from '../../host';
9
+ import { useChatHost } from '../../host';
10
10
  import { ChatScopeContext } from '../../scope';
11
11
  import { useReportedModels } from '../../state/chats';
12
12
  import { pickerEntriesOf, type PickerEntry } from '../logic/picker-entries';
13
13
  import { forgetStashed, STASH_SHORTCUT, useStash, type StashedPrompt } from '../stash';
14
- import { Icon, IconButton, Menu, Popover, Tooltip } from '@adecore/ui';
14
+ import { Icon, IconButton, Menu, Pill, Popover, Tooltip } from '@adecore/ui';
15
15
 
16
16
  const triggerClass =
17
17
  'flex h-7 shrink-0 items-center gap-1 whitespace-nowrap rounded-md px-2 text-xs text-text-muted hover:bg-surface-hover hover:text-text data-[popup-open]:bg-surface-active data-[popup-open]:text-text';
@@ -58,6 +58,7 @@ export function ModelPicker({
58
58
  finalFocus,
59
59
  footer
60
60
  }: ModelPickerProps) {
61
+ const host = useChatHost();
61
62
  const { t } = useTranslation('agent-chat');
62
63
  const [query, setQuery] = useState('');
63
64
  const [legacyOpen, setLegacyOpen] = useState(false);
@@ -73,7 +74,7 @@ export function ModelPicker({
73
74
 
74
75
  const entries = useMemo(() => pickerEntriesOf(providers, trimmed, legacyOpen), [providers, trimmed, legacyOpen]);
75
76
  const scope = useContext(ChatScopeContext);
76
- const machine = chatHost().useMachineLabel(scope?.id ?? '');
77
+ const machine = host.useMachineLabel(scope?.id ?? '');
77
78
  const reported = useReportedModels(provider);
78
79
  const requirementOf = (entry: PickerEntry & { kind: 'model' }) => modelRequirementOf(entry.model, entry.provider, reported);
79
80
  // A CLI that is too old blocks all its models; one way to its settings under the group says it once.
@@ -205,9 +206,9 @@ export function ModelPicker({
205
206
  <Menu.Check kind="radio" checked={chosen} />
206
207
  <span className="min-w-0 truncate">{entry.model.name}</span>
207
208
  {entry.model.badge && (
208
- <span className="rounded bg-accent-soft px-1 text-[11px] leading-5 font-medium uppercase text-accent">
209
- {entry.model.badge}
210
- </span>
209
+ <Pill tone="accent" shape="tag" size="sm">
210
+ {entry.model.badge.charAt(0).toLocaleUpperCase() + entry.model.badge.slice(1)}
211
+ </Pill>
211
212
  )}
212
213
  <span className="grow" />
213
214
  {entry.model.legacy && <span className="text-xs text-text-faint">{t('pickers.model.legacy')}</span>}
@@ -226,7 +227,7 @@ export function ModelPicker({
226
227
  className="cursor-row flex w-full items-center rounded-md px-2.5 py-1.5 text-left text-xs text-text-muted"
227
228
  onClick={() => {
228
229
  setOpen(false);
229
- chatHost().openSettings('providers');
230
+ host.openSettings('providers');
230
231
  }}
231
232
  >
232
233
  {t('pickers.model.providerSettings')}
@@ -8,7 +8,7 @@ import { answerPrompt, isBlockingSubject, promptCreatedAt, promptIdOf, type Prom
8
8
  import { useFocusAfterAnswer } from '../../prompts/logic/useFocusAfterAnswer';
9
9
  import { usePromptSession } from '../../prompts/logic/usePromptSession';
10
10
  import { PromptView } from '../../prompts/ui/PromptView';
11
- import { chatHost } from '../../host';
11
+ import { useChatHost } from '../../host';
12
12
  import { useChatScope } from '../../scope';
13
13
  import { useChatActions } from '../actions';
14
14
  import { Button, Icon } from '@adecore/ui';
@@ -53,10 +53,11 @@ export function PromptComposer({
53
53
  }) {
54
54
  const { t } = useTranslation('agent-chat');
55
55
  const { id } = useChatScope();
56
+ const host = useChatHost();
56
57
  const actions = useChatActions();
57
58
  const elsewhere = onShowElsewhere !== undefined;
58
59
  // A card the app raises itself waits in the chat beside the CLI's own requests.
59
- const extra = chatHost().prompts.useExtra(id, chatId);
60
+ const extra = host.prompts.useExtra(id, chatId);
60
61
  const subjects = useMemo(
61
62
  (): PromptSubject[] => [
62
63
  ...pending.map((item): PromptSubject => ({ kind: 'chat', nodeId: chatId, item })),
@@ -117,7 +118,7 @@ export function PromptComposer({
117
118
  onAction={(action) => {
118
119
  refocus.hold();
119
120
  void session
120
- .act(active, () => answerPrompt(active, action, actions))
121
+ .act(active, () => answerPrompt(active, action, actions, host))
121
122
  .then((result) => {
122
123
  if (result === 'failed') {
123
124
  refocus.release();
@@ -0,0 +1,21 @@
1
+ import { Tooltip } from '@adecore/ui';
2
+ import { formatClock, formatDateTime, useFormatLocale } from '@adecore/ui/format';
3
+ import { TIMESTAMP_FORMAT } from './timestamp-format';
4
+
5
+ /*
6
+ * The wall-clock time of a row at its right edge, shown only while an element marked `group/line`
7
+ * around it is hovered or has the keyboard focus. Hidden, it takes no room and is no tab stop.
8
+ */
9
+ export function RowTime({ at }: { at: number }) {
10
+ useFormatLocale();
11
+ return (
12
+ <Tooltip label={formatDateTime(at, TIMESTAMP_FORMAT)}>
13
+ <time
14
+ dateTime={new Date(at).toISOString()}
15
+ className="hidden shrink-0 text-xs text-text-faint tabular-nums select-none group-hover/line:inline group-focus-visible/line:inline group-has-focus-visible/line:inline"
16
+ >
17
+ {formatClock(at)}
18
+ </time>
19
+ </Tooltip>
20
+ );
21
+ }
@@ -25,8 +25,8 @@ import { modelName, shortModelName } from '../../agents/model-name';
25
25
  import { CONTEXT_OPTION, contextFraction, contextSegments, orderOptions, type ContextPart } from '../logic/context-usage';
26
26
  import { RUNTIME_MODES } from '../runtime-modes';
27
27
  import { formatClock, formatWeekdayClock, isSameDay, formatPercent, formatTokens } from '@adecore/ui/format';
28
- import { Icon, Menu, Tooltip, useNow } from '@adecore/ui';
29
- import { chatHost } from '../../host';
28
+ import { Icon, Menu, Pill, Tooltip, useNow } from '@adecore/ui';
29
+ import { useChatHost } from '../../host';
30
30
  import { useUsageLimits } from '../../usage/limits';
31
31
 
32
32
  const MINUTE_MS = 60_000;
@@ -177,7 +177,11 @@ export function RunSettings({
177
177
  <Menu.RadioItem key={row.slug} value={modelValue(entry.kind, row.slug)} closeOnClick>
178
178
  <AgentIcon kind={entry.kind} size={14} className="shrink-0" />
179
179
  <span className="min-w-0 truncate">{row.name}</span>
180
- {row.badge && <span className="rounded bg-accent-soft px-1 text-[11px] leading-5 font-medium uppercase text-accent">{row.badge}</span>}
180
+ {row.badge && (
181
+ <Pill tone="accent" shape="tag" size="sm">
182
+ {row.badge.charAt(0).toLocaleUpperCase() + row.badge.slice(1)}
183
+ </Pill>
184
+ )}
181
185
  </Menu.RadioItem>
182
186
  ))}
183
187
  </Menu.Group>
@@ -308,6 +312,7 @@ function sessionTone(used: number): { bar: string; text: string } {
308
312
  * the conversation goes along to those. A switch applies from the next turn.
309
313
  */
310
314
  function AccountSubmenu({ provider, account }: { provider: AgentKind; account: AccountPick }) {
315
+ const host = useChatHost();
311
316
  const { t } = useTranslation('agent-chat');
312
317
  const { choice, started, onPick } = account;
313
318
  return (
@@ -330,7 +335,7 @@ function AccountSubmenu({ provider, account }: { provider: AgentKind; account: A
330
335
  </Menu.RadioGroup>
331
336
  </Menu.Group>
332
337
  <Menu.Separator />
333
- <Menu.Item className="text-text-muted" onClick={() => chatHost().openSettings('providers')}>
338
+ <Menu.Item className="text-text-muted" onClick={() => host.openSettings('providers')}>
334
339
  <Icon icon={Settings} size={14} className="shrink-0 text-text-faint" />
335
340
  {t('pickers.account.manage')}
336
341
  </Menu.Item>
@@ -0,0 +1,134 @@
1
+ import { useEffect, useState, type ReactNode } from 'react';
2
+ import type { BundledLanguage } from 'shiki';
3
+ import { EMBEDDED_CODE_LIMIT, SHELL_LANGUAGE, embeddedCode } from '../logic/embedded-code';
4
+ import type { CodeToken } from './code-lines';
5
+ import { useChatHost } from '../../host';
6
+ import { useCodeTheme } from './code-theme';
7
+ import { tokenStyle, useCodeHighlighter, type CodeHighlighter, type Highlighter } from './highlighter';
8
+
9
+ /* One colored run of a command, as offsets into it. */
10
+ interface Run extends CodeToken {
11
+ start: number;
12
+ end: number;
13
+ }
14
+
15
+ // Rows redraw often and a thread holds many commands, so each is tokenized once per theme.
16
+ const CACHE_LIMIT = 300;
17
+ const cache = new Map<string, Run[]>();
18
+
19
+ /* The runs of `code` in one language, placed at `offset`; a run in the theme's own foreground takes the color around it. */
20
+ function runsOf(highlighter: Highlighter, code: string, language: string, theme: string, offset: number): Run[] {
21
+ const fg = highlighter.getTheme(theme).fg.toLowerCase();
22
+ const { tokens } = highlighter.codeToTokens(code, { lang: language as BundledLanguage, theme });
23
+ return tokens.flat().map((token) => ({
24
+ start: offset + token.offset,
25
+ end: offset + token.offset + token.content.length,
26
+ content: token.content,
27
+ color: token.color?.toLowerCase() === fg ? undefined : token.color,
28
+ fontStyle: token.fontStyle
29
+ }));
30
+ }
31
+
32
+ /* `base` with `[start, end)` cut out of it and `inner` in its place. */
33
+ function overlay(base: readonly Run[], start: number, end: number, inner: readonly Run[]): Run[] {
34
+ const kept: Run[] = [];
35
+ for (const run of base) {
36
+ if (run.end <= start || run.start >= end) {
37
+ kept.push(run);
38
+ continue;
39
+ }
40
+ if (run.start < start) {
41
+ kept.push({ ...run, end: start, content: run.content.slice(0, start - run.start) });
42
+ }
43
+ if (run.end > end) {
44
+ kept.push({ ...run, start: end, content: run.content.slice(end - run.start) });
45
+ }
46
+ }
47
+ return [...kept, ...inner].sort((left, right) => left.start - right.start);
48
+ }
49
+
50
+ function languagesOf(command: string): Set<string> {
51
+ return new Set([SHELL_LANGUAGE, ...embeddedCode(command).map(({ language }) => language)]);
52
+ }
53
+
54
+ /* The colored runs of a command, or null while a grammar or the theme is still on its way. */
55
+ function highlight(command: string, theme: string, code: CodeHighlighter): Run[] | null {
56
+ const key = `${theme}\n${command}`;
57
+ const known = cache.get(key);
58
+ if (known !== undefined) {
59
+ // Touched entries move to the end, so the oldest falls out first.
60
+ cache.delete(key);
61
+ cache.set(key, known);
62
+ return known;
63
+ }
64
+ const embedded = embeddedCode(command);
65
+ const highlighter = code.ready([SHELL_LANGUAGE, ...embedded.map(({ language }) => language)], theme);
66
+ if (highlighter === null) {
67
+ return null;
68
+ }
69
+ let runs = runsOf(highlighter, command, code.language(SHELL_LANGUAGE), theme, 0);
70
+ for (const part of embedded) {
71
+ runs = overlay(runs, part.start, part.end, runsOf(highlighter, command.slice(part.start, part.end), code.language(part.language), theme, part.start));
72
+ }
73
+ cache.set(key, runs);
74
+ if (cache.size > CACHE_LIMIT) {
75
+ cache.delete(cache.keys().next().value!);
76
+ }
77
+ return runs;
78
+ }
79
+
80
+ function draw(command: string, runs: readonly Run[]): ReactNode[] {
81
+ const parts: ReactNode[] = [];
82
+ let at = 0;
83
+ for (const run of runs) {
84
+ // Shiki leaves the line breaks out of its tokens; they come from the command itself.
85
+ if (run.start > at) {
86
+ parts.push(command.slice(at, run.start));
87
+ }
88
+ const style = tokenStyle(run);
89
+ parts.push(
90
+ style === undefined ? (
91
+ run.content
92
+ ) : (
93
+ <span key={run.start} style={style}>
94
+ {run.content}
95
+ </span>
96
+ )
97
+ );
98
+ at = run.end;
99
+ }
100
+ if (at < command.length) {
101
+ parts.push(command.slice(at));
102
+ }
103
+ return parts;
104
+ }
105
+
106
+ /*
107
+ * A shell command in the colors of the code theme, with the code inside it (a `bash -lc` script, a
108
+ * `python3 -c` argument, a heredoc) in its own language. Plain text until the grammars are in, which
109
+ * changes no size; a command past the limit stays plain.
110
+ */
111
+ export function ShellCommand({ command }: { command: string }) {
112
+ const theme = useCodeTheme();
113
+ const { custom } = useChatHost().code;
114
+ const highlighter = useCodeHighlighter();
115
+ // Bumped when a load settles, so the cache is asked again.
116
+ const [, setLoads] = useState(0);
117
+ const tooLong = command.length > EMBEDDED_CODE_LIMIT;
118
+ const runs = tooLong ? null : highlight(command, theme, highlighter);
119
+
120
+ useEffect(() => {
121
+ if (runs !== null || tooLong) {
122
+ return;
123
+ }
124
+ let cancelled = false;
125
+ Promise.all([highlighter.loadTheme(theme, custom), ...[...languagesOf(command)].map((lang) => highlighter.loadLanguage(lang))])
126
+ .then(() => !cancelled && setLoads((count) => count + 1))
127
+ .catch(() => undefined);
128
+ return () => {
129
+ cancelled = true;
130
+ };
131
+ }, [highlighter, command, theme, custom, runs, tooLong]);
132
+
133
+ return <>{runs === null ? command : draw(command, runs)}</>;
134
+ }
@@ -7,7 +7,7 @@ import { SubagentActions, SubagentBreadcrumb } from './SubagentControls';
7
7
  import { useNow } from '@adecore/ui';
8
8
  import { useModelName } from '../../agents/model-name';
9
9
  import { useChatRow } from '../../state/chats';
10
- import { chatHost } from '../../host';
10
+ import { useChatHost } from '../../host';
11
11
  import { useChatScope } from '../../scope';
12
12
 
13
13
  /*
@@ -15,17 +15,18 @@ import { useChatScope } from '../../scope';
15
15
  * and what it spent, and the way out. Only the way down and out for a conversation whose row the thread lost.
16
16
  */
17
17
  export function SubagentInfo({ chatId, toolUseId }: { chatId: string; toolUseId: string }) {
18
+ const host = useChatHost();
18
19
  const { t } = useTranslation('agent-chat');
19
20
  const { id } = useChatScope();
20
21
  const item = useSubagentItem(chatId, toolUseId);
21
22
  const provider = useChatRow(chatId, (row) => row?.info.provider);
22
- const task = chatHost().tasks.useTask(id, item === null ? null : taskIdOf(item));
23
+ const task = host.tasks.useTask(id, item === null ? null : taskIdOf(item));
23
24
  const modelName = useModelName(provider, item?.model ?? '');
24
25
  const now = useNow(1000, item?.status === 'running');
25
26
  const word = item === null ? null : statusWordOf(item, task);
26
27
  const facts = item === null ? [] : subagentFacts(item, item.model === undefined ? null : modelName);
27
28
  return (
28
- <section aria-label={t('subagents.info.label')} className="shrink-0 border-b border-border px-4 py-1.5">
29
+ <section aria-label={t('subagents.info.label')} className="shrink-0 border-b border-border py-1.5 pr-1.5 pl-4">
29
30
  <div className="flex min-w-0 items-center gap-2 text-xs text-text-faint">
30
31
  <SubagentBreadcrumb chatId={chatId} className="max-w-1/3 shrink-0 font-medium" />
31
32
  {item !== null && word !== null && (
@@ -1,7 +1,7 @@
1
1
  import { useTranslation } from 'react-i18next';
2
2
  import { Square } from 'lucide-react';
3
3
  import type { ChatSubagentItem } from '@adecore/agent-contracts';
4
- import { chatHost } from '../../host';
4
+ import { useChatHost } from '../../host';
5
5
  import { useChatScope } from '../../scope';
6
6
  import { useChatRow } from '../../state/chats';
7
7
  import { useChatActions } from '../actions';
@@ -20,6 +20,7 @@ export function SubagentStopButton({
20
20
  size?: 'sm' | 'xs';
21
21
  className?: string;
22
22
  }) {
23
+ const host = useChatHost();
23
24
  const { t } = useTranslation('agent-chat');
24
25
  const { id } = useChatScope();
25
26
  const actions = useChatActions();
@@ -32,12 +33,12 @@ export function SubagentStopButton({
32
33
  void actions.stopSubagent(chatId, item.toolUseId).catch((e: unknown) => {
33
34
  const stale = e instanceof Error && 'code' in e && e.code === 'subagent-stale';
34
35
  const description = stale ? t('subagents.stale') : e instanceof Error ? e.message : t('subagents.noAnswer');
35
- chatHost().notify({ kind: 'error', title: t('subagents.stopFailed'), description });
36
+ host.notify({ kind: 'error', title: t('subagents.stopFailed'), description });
36
37
  });
37
38
  };
38
39
  const run = (): void => {
39
40
  if (stop === 'task' && item.childId !== undefined) {
40
- chatHost().confirm.stopTask(id, item.childId, subagentTitle(item), send);
41
+ host.confirm.stopTask(id, item.childId, subagentTitle(item), send);
41
42
  return;
42
43
  }
43
44
  send();
@@ -17,6 +17,8 @@ import { FOLLOW_THRESHOLD_PX, rowRhythm } from './rows/row-rhythm';
17
17
  import { useToggleSet } from './useToggleSet';
18
18
  import { FileLinkContext } from './file-links';
19
19
  import { useChatRow } from '../../state/chats';
20
+ import { useChatPreferences } from '../preferences';
21
+ import { readingWidthStyle } from '../reading-width';
20
22
  import { useChatScope } from '../../scope';
21
23
  import { EmptyState, ContextMenu, Icon } from '@adecore/ui';
22
24
 
@@ -109,12 +111,14 @@ export function SubagentTimeline({ chatId, toolUseId }: { chatId: string; toolUs
109
111
  }
110
112
  }, [rows, state.status, loadEarlier]);
111
113
 
114
+ const readingWidth = useChatPreferences((preferences) => preferences.readingWidth);
115
+
112
116
  const openChild = (step: SubagentStep): void => {
113
117
  show(openBelow(trail, step));
114
118
  };
115
119
 
116
120
  return (
117
- <div className="flex h-full min-h-0 flex-col">
121
+ <div className="flex h-full min-h-0 flex-col" style={readingWidthStyle(readingWidth)}>
118
122
  <SubagentInfo chatId={chatId} toolUseId={toolUseId} />
119
123
  {state.status === 'loading' && <div className="chat-column-content px-4 pt-4 text-xs text-text-faint">{t('subagents.loading')}</div>}
120
124
  {state.status === 'failed' && (