@adecore/agents-react 0.23.1 → 0.24.1

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 (344) 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 +130 -907
  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/surface.d.ts +1 -0
  88. package/dist/chat/ui/composer/surface.js +44 -0
  89. package/dist/chat/ui/composer/use-chat-controls.d.ts +28 -0
  90. package/dist/chat/ui/composer/use-chat-controls.js +112 -0
  91. package/dist/chat/ui/composer/use-compaction-offer.d.ts +2 -0
  92. package/dist/chat/ui/composer/use-compaction-offer.js +23 -0
  93. package/dist/chat/ui/composer/use-composer-draft.d.ts +14 -0
  94. package/dist/chat/ui/composer/use-composer-draft.js +39 -0
  95. package/dist/chat/ui/composer/use-composer-menus.d.ts +52 -0
  96. package/dist/chat/ui/composer/use-composer-menus.js +232 -0
  97. package/dist/chat/ui/composer/use-composer-submit.d.ts +32 -0
  98. package/dist/chat/ui/composer/use-composer-submit.js +113 -0
  99. package/dist/chat/ui/composer/use-draft-files.d.ts +27 -0
  100. package/dist/chat/ui/composer/use-draft-files.js +111 -0
  101. package/dist/chat/ui/composer/use-notice.d.ts +6 -0
  102. package/dist/chat/ui/composer/use-notice.js +18 -0
  103. package/dist/chat/ui/composer/use-pending-requests.d.ts +2 -0
  104. package/dist/chat/ui/composer/use-pending-requests.js +22 -0
  105. package/dist/chat/ui/composer/use-prompt-history.d.ts +8 -0
  106. package/dist/chat/ui/composer/use-prompt-history.js +57 -0
  107. package/dist/chat/ui/composer/use-prompt-hold.d.ts +6 -0
  108. package/dist/chat/ui/composer/use-prompt-hold.js +48 -0
  109. package/dist/chat/ui/composer/use-take-back.d.ts +13 -0
  110. package/dist/chat/ui/composer/use-take-back.js +82 -0
  111. package/dist/chat/ui/diff/EditorEditDiff.js +4 -3
  112. package/dist/chat/ui/diff/LegacyDiffPool.js +3 -2
  113. package/dist/chat/ui/diff/LegacyEditDiff.js +3 -2
  114. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +3 -2
  115. package/dist/chat/ui/diff/syntax-runtime.d.ts +2 -1
  116. package/dist/chat/ui/diff/syntax-runtime.js +9 -5
  117. package/dist/chat/ui/diff-syntax.d.ts +2 -2
  118. package/dist/chat/ui/diff-syntax.js +1 -2
  119. package/dist/chat/ui/diff-theme.js +10 -9
  120. package/dist/chat/ui/file-links.d.ts +1 -1
  121. package/dist/chat/ui/file-links.js +7 -5
  122. package/dist/chat/ui/highlighter.d.ts +27 -0
  123. package/dist/chat/ui/highlighter.js +151 -0
  124. package/dist/chat/ui/index.d.ts +67 -0
  125. package/dist/chat/ui/index.js +64 -0
  126. package/dist/chat/ui/intelligent-ui/UiReply.js +3 -2
  127. package/dist/chat/ui/intelligent-ui/renderers/content.js +3 -2
  128. package/dist/chat/ui/intelligent-ui/use-ui-links.js +2 -2
  129. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +4 -3
  130. package/dist/chat/ui/markdown-blocks.d.ts +8 -0
  131. package/dist/chat/ui/markdown-blocks.js +260 -12
  132. package/dist/chat/ui/mermaid.d.ts +23 -0
  133. package/dist/chat/ui/mermaid.js +93 -0
  134. package/dist/chat/ui/rows/ForksRow.js +5 -3
  135. package/dist/chat/ui/rows/GeneratedImageRow.js +6 -4
  136. package/dist/chat/ui/rows/MessageRows.d.ts +4 -0
  137. package/dist/chat/ui/rows/MessageRows.js +36 -13
  138. package/dist/chat/ui/rows/Rows.js +3 -1
  139. package/dist/chat/ui/rows/SubagentRow.js +3 -2
  140. package/dist/chat/ui/rows/VisualRow.js +3 -2
  141. package/dist/chat/ui/rows/WorkRows.d.ts +6 -3
  142. package/dist/chat/ui/rows/WorkRows.js +57 -20
  143. package/dist/chat/ui/rows/WorkflowRow.js +3 -2
  144. package/dist/chat/ui/timestamp-format.d.ts +1 -0
  145. package/dist/chat/ui/timestamp-format.js +2 -0
  146. package/dist/chat/ui/use-diff-source-tokens.js +6 -3
  147. package/dist/chat/ui/visual-theme.js +3 -2
  148. package/dist/host.d.ts +9 -6
  149. package/dist/host.js +19 -8
  150. package/dist/index.d.ts +8 -0
  151. package/dist/index.js +9 -0
  152. package/dist/locales/en/agent-chat.d.ts +658 -0
  153. package/dist/locales/en/agent-chat.js +657 -0
  154. package/dist/locales/en/agent-prompts.d.ts +44 -0
  155. package/dist/locales/en/agent-prompts.js +43 -0
  156. package/dist/locales/en/agent-providers.d.ts +132 -0
  157. package/dist/locales/en/agent-providers.js +131 -0
  158. package/dist/locales/en/agent-usage.d.ts +132 -0
  159. package/dist/locales/en/agent-usage.js +131 -0
  160. package/dist/locales/nl/agent-chat.d.ts +658 -0
  161. package/dist/locales/nl/agent-chat.js +657 -0
  162. package/dist/locales/nl/agent-prompts.d.ts +44 -0
  163. package/dist/locales/nl/agent-prompts.js +43 -0
  164. package/dist/locales/nl/agent-providers.d.ts +132 -0
  165. package/dist/locales/nl/agent-providers.js +131 -0
  166. package/dist/locales/nl/agent-usage.d.ts +132 -0
  167. package/dist/locales/nl/agent-usage.js +131 -0
  168. package/dist/locales.js +9 -8
  169. package/dist/prompts/index.d.ts +11 -0
  170. package/dist/prompts/index.js +12 -0
  171. package/dist/prompts/logic/subjects.d.ts +2 -1
  172. package/dist/prompts/logic/subjects.js +6 -4
  173. package/dist/prompts/ui/ApprovalBody.js +6 -4
  174. package/dist/prompts/ui/PromptCard.js +5 -4
  175. package/dist/prompts/ui/PromptView.js +3 -2
  176. package/dist/prompts/ui/QuestionBody.js +3 -2
  177. package/dist/providers/AccountColors.js +2 -2
  178. package/dist/providers/AccountDetail.js +7 -6
  179. package/dist/providers/AccountVariables.js +3 -1
  180. package/dist/providers/AddAccountForm.js +3 -2
  181. package/dist/providers/ProvidersPane.js +4 -3
  182. package/dist/providers/account-actions.d.ts +4 -3
  183. package/dist/providers/account-actions.js +6 -7
  184. package/dist/providers/index.d.ts +16 -0
  185. package/dist/providers/index.js +17 -0
  186. package/dist/providers/provider-abilities.d.ts +2 -1
  187. package/dist/providers/provider-abilities.js +4 -0
  188. package/dist/state/chats.js +4 -2
  189. package/dist/state/index.d.ts +4 -0
  190. package/dist/state/index.js +5 -0
  191. package/dist/testing/index.d.ts +1 -0
  192. package/dist/testing/index.js +2 -0
  193. package/dist/{prompts/logic/prompts.fixtures.d.ts → testing/prompts.d.ts} +1 -1
  194. package/dist/theme.css +13 -3
  195. package/dist/usage/UsageBreakdown.js +3 -2
  196. package/dist/usage/UsageLimits.js +4 -3
  197. package/dist/usage/UsagePage.js +3 -2
  198. package/dist/usage/index.d.ts +15 -0
  199. package/dist/usage/index.js +15 -0
  200. package/package.json +53 -1031
  201. package/src/agents/AccountDot.tsx +3 -1
  202. package/src/agents/accounts.ts +6 -6
  203. package/src/chat/actions.ts +8 -5
  204. package/src/chat/bookmarks.ts +23 -14
  205. package/src/chat/chat-client.ts +8 -0
  206. package/src/chat/composer-send.ts +27 -0
  207. package/src/chat/forks.ts +27 -6
  208. package/src/chat/index.ts +98 -0
  209. package/src/chat/logic/embedded-code.ts +409 -0
  210. package/src/chat/logic/fork.ts +1 -0
  211. package/src/chat/logic/goal.ts +33 -0
  212. package/src/chat/logic/scrubber.ts +6 -5
  213. package/src/chat/logic/thought.ts +40 -0
  214. package/src/chat/logic/thread-cards.ts +2 -0
  215. package/src/chat/logic/timeline.ts +25 -1
  216. package/src/chat/logic/tool-catalog.ts +5 -1
  217. package/src/chat/logic/tools.ts +76 -0
  218. package/src/chat/preferences.ts +26 -3
  219. package/src/chat/reading-width.ts +39 -0
  220. package/src/chat/send-key.ts +38 -0
  221. package/src/chat/ui/BookmarkMarker.tsx +4 -2
  222. package/src/chat/ui/BookmarkSubmenu.tsx +4 -3
  223. package/src/chat/ui/ChatActivity.tsx +14 -10
  224. package/src/chat/ui/ChatReferenceChip.tsx +3 -4
  225. package/src/chat/ui/CodeBlock.tsx +33 -124
  226. package/src/chat/ui/Composer.tsx +212 -1358
  227. package/src/chat/ui/ComposerInput.tsx +5 -4
  228. package/src/chat/ui/EditDiff.tsx +3 -2
  229. package/src/chat/ui/GoalDock.tsx +104 -0
  230. package/src/chat/ui/LimitState.tsx +5 -3
  231. package/src/chat/ui/Markdown.tsx +113 -39
  232. package/src/chat/ui/MermaidBlock.tsx +119 -0
  233. package/src/chat/ui/MessageActions.tsx +13 -8
  234. package/src/chat/ui/Pickers.tsx +8 -7
  235. package/src/chat/ui/PromptComposer.tsx +4 -3
  236. package/src/chat/ui/RowTime.tsx +21 -0
  237. package/src/chat/ui/RunSettings.tsx +9 -4
  238. package/src/chat/ui/ShellCommand.tsx +134 -0
  239. package/src/chat/ui/SubagentInfo.tsx +4 -3
  240. package/src/chat/ui/SubagentStopButton.tsx +4 -3
  241. package/src/chat/ui/SubagentTimeline.tsx +5 -1
  242. package/src/chat/ui/Timeline.tsx +167 -105
  243. package/src/chat/ui/TimelineMenu.tsx +42 -7
  244. package/src/chat/ui/UnifiedDiff.tsx +3 -2
  245. package/src/chat/ui/VisualFrame.tsx +6 -7
  246. package/src/chat/ui/code-theme.ts +4 -4
  247. package/src/chat/ui/composer/ComposerControls.tsx +147 -0
  248. package/src/chat/ui/composer/ComposerMenu.tsx +138 -0
  249. package/src/chat/ui/composer/DraftParts.tsx +86 -0
  250. package/src/chat/ui/composer/QueuedMessages.tsx +64 -0
  251. package/src/chat/ui/composer/key-handler.ts +174 -0
  252. package/src/chat/ui/composer/keys.ts +32 -10
  253. package/src/chat/ui/composer/placeholder.ts +48 -0
  254. package/src/chat/ui/composer/surface.ts +45 -0
  255. package/src/chat/ui/composer/use-chat-controls.ts +134 -0
  256. package/src/chat/ui/composer/use-compaction-offer.ts +25 -0
  257. package/src/chat/ui/composer/use-composer-draft.ts +71 -0
  258. package/src/chat/ui/composer/use-composer-menus.ts +289 -0
  259. package/src/chat/ui/composer/use-composer-submit.ts +163 -0
  260. package/src/chat/ui/composer/use-draft-files.ts +135 -0
  261. package/src/chat/ui/composer/use-notice.ts +28 -0
  262. package/src/chat/ui/composer/use-pending-requests.ts +23 -0
  263. package/src/chat/ui/composer/use-prompt-history.ts +76 -0
  264. package/src/chat/ui/composer/use-prompt-hold.ts +58 -0
  265. package/src/chat/ui/composer/use-take-back.ts +91 -0
  266. package/src/chat/ui/diff/DiffFallbackBoundary.tsx +2 -2
  267. package/src/chat/ui/diff/EditorEditDiff.tsx +4 -3
  268. package/src/chat/ui/diff/LegacyDiffPool.tsx +3 -2
  269. package/src/chat/ui/diff/LegacyEditDiff.tsx +3 -2
  270. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +3 -2
  271. package/src/chat/ui/diff/syntax-runtime.ts +10 -5
  272. package/src/chat/ui/diff-syntax.ts +2 -2
  273. package/src/chat/ui/diff-theme.ts +10 -9
  274. package/src/chat/ui/file-links.ts +7 -5
  275. package/src/chat/ui/highlighter.ts +185 -0
  276. package/src/chat/ui/index.ts +109 -0
  277. package/src/chat/ui/intelligent-ui/UiReply.tsx +5 -4
  278. package/src/chat/ui/intelligent-ui/renderers/content.tsx +3 -2
  279. package/src/chat/ui/intelligent-ui/use-ui-links.ts +2 -2
  280. package/src/chat/ui/intelligent-ui/use-ui-queries.ts +4 -3
  281. package/src/chat/ui/markdown-blocks.ts +300 -12
  282. package/src/chat/ui/mermaid.ts +118 -0
  283. package/src/chat/ui/rows/ForksRow.tsx +5 -3
  284. package/src/chat/ui/rows/GeneratedImageRow.tsx +6 -4
  285. package/src/chat/ui/rows/MessageRows.tsx +73 -18
  286. package/src/chat/ui/rows/Rows.tsx +14 -1
  287. package/src/chat/ui/rows/SubagentRow.tsx +3 -2
  288. package/src/chat/ui/rows/VisualRow.tsx +3 -2
  289. package/src/chat/ui/rows/WorkRows.tsx +148 -47
  290. package/src/chat/ui/rows/WorkflowRow.tsx +3 -2
  291. package/src/chat/ui/timestamp-format.ts +2 -0
  292. package/src/chat/ui/use-diff-source-tokens.ts +10 -4
  293. package/src/chat/ui/visual-theme.ts +3 -2
  294. package/src/host.ts +31 -15
  295. package/src/index.ts +49 -0
  296. package/src/locales/en/agent-chat.ts +657 -0
  297. package/src/locales/en/agent-prompts.ts +43 -0
  298. package/src/locales/en/agent-providers.ts +131 -0
  299. package/src/locales/en/agent-usage.ts +131 -0
  300. package/src/locales/nl/agent-chat.ts +657 -0
  301. package/src/locales/nl/agent-prompts.ts +43 -0
  302. package/src/locales/nl/agent-providers.ts +131 -0
  303. package/src/locales/nl/agent-usage.ts +132 -0
  304. package/src/locales.ts +9 -8
  305. package/src/prompts/index.ts +35 -0
  306. package/src/prompts/logic/subjects.ts +12 -4
  307. package/src/prompts/ui/ApprovalBody.tsx +6 -4
  308. package/src/prompts/ui/PromptCard.tsx +11 -4
  309. package/src/prompts/ui/PromptView.tsx +3 -2
  310. package/src/prompts/ui/QuestionBody.tsx +3 -2
  311. package/src/providers/AccountColors.tsx +2 -2
  312. package/src/providers/AccountDetail.tsx +13 -7
  313. package/src/providers/AccountVariables.tsx +3 -1
  314. package/src/providers/AddAccountForm.tsx +3 -2
  315. package/src/providers/ProvidersPane.tsx +4 -3
  316. package/src/providers/account-actions.ts +7 -7
  317. package/src/providers/index.ts +17 -0
  318. package/src/providers/provider-abilities.ts +6 -1
  319. package/src/state/chats.ts +4 -2
  320. package/src/state/index.ts +39 -0
  321. package/src/testing/index.ts +2 -0
  322. package/src/{prompts/logic/prompts.fixtures.ts → testing/prompts.ts} +1 -1
  323. package/src/theme.css +13 -3
  324. package/src/usage/UsageBreakdown.tsx +3 -2
  325. package/src/usage/UsageLimits.tsx +4 -3
  326. package/src/usage/UsagePage.tsx +3 -2
  327. package/src/usage/index.ts +16 -0
  328. package/dist/locales/en/agent-chat.json +0 -597
  329. package/dist/locales/en/agent-prompts.json +0 -43
  330. package/dist/locales/en/agent-providers.json +0 -131
  331. package/dist/locales/en/agent-usage.json +0 -131
  332. package/dist/locales/nl/agent-chat.json +0 -597
  333. package/dist/locales/nl/agent-prompts.json +0 -43
  334. package/dist/locales/nl/agent-providers.json +0 -131
  335. package/dist/locales/nl/agent-usage.json +0 -131
  336. package/src/locales/en/agent-chat.json +0 -597
  337. package/src/locales/en/agent-prompts.json +0 -43
  338. package/src/locales/en/agent-providers.json +0 -131
  339. package/src/locales/en/agent-usage.json +0 -131
  340. package/src/locales/nl/agent-chat.json +0 -597
  341. package/src/locales/nl/agent-prompts.json +0 -43
  342. package/src/locales/nl/agent-providers.json +0 -131
  343. package/src/locales/nl/agent-usage.json +0 -131
  344. /package/dist/{prompts/logic/prompts.fixtures.js → testing/prompts.js} +0 -0
@@ -0,0 +1,118 @@
1
+ import type { MermaidConfig } from 'mermaid';
2
+
3
+ /* The colors of a diagram, each a token of the theme resolved to an opaque color over the frame it is drawn in. */
4
+ export interface MermaidColors {
5
+ ground: string;
6
+ node: string;
7
+ nodeBorder: string;
8
+ text: string;
9
+ line: string;
10
+ cluster: string;
11
+ clusterBorder: string;
12
+ note: string;
13
+ }
14
+
15
+ /* The token each color reads. Borders carry an alpha, so they are resolved over the ground. */
16
+ export const MERMAID_TOKENS: Readonly<Record<keyof MermaidColors, string>> = {
17
+ ground: '--chat-code-bg',
18
+ node: '--surface-raised',
19
+ nodeBorder: '--border-strong',
20
+ text: '--text',
21
+ line: '--text-muted',
22
+ cluster: '--surface',
23
+ clusterBorder: '--border',
24
+ note: '--accent-soft'
25
+ };
26
+
27
+ // Mermaid's own list plus what keeps a diagram in the theme and out of HTML: a directive in the text cannot change these.
28
+ const SECURE_KEYS = [
29
+ 'secure',
30
+ 'securityLevel',
31
+ 'startOnLoad',
32
+ 'maxTextSize',
33
+ 'maxEdges',
34
+ 'suppressErrorRendering',
35
+ 'htmlLabels',
36
+ 'theme',
37
+ 'themeVariables',
38
+ 'themeCSS',
39
+ 'darkMode',
40
+ 'fontFamily'
41
+ ];
42
+
43
+ /*
44
+ * Strict: no HTML in labels, no click handlers, no links that run script. What comes out is drawn as an
45
+ * image as well, which never runs script and loads nothing, whatever the text of the diagram says.
46
+ */
47
+ export function mermaidConfig(colors: MermaidColors, dark: boolean, font: { family: string; size: string }): MermaidConfig {
48
+ return {
49
+ startOnLoad: false,
50
+ securityLevel: 'strict',
51
+ htmlLabels: false,
52
+ suppressErrorRendering: true,
53
+ secure: SECURE_KEYS,
54
+ theme: 'base',
55
+ darkMode: dark,
56
+ fontFamily: font.family,
57
+ themeVariables: {
58
+ darkMode: dark,
59
+ fontFamily: font.family,
60
+ fontSize: font.size,
61
+ background: colors.ground,
62
+ primaryColor: colors.node,
63
+ primaryTextColor: colors.text,
64
+ primaryBorderColor: colors.nodeBorder,
65
+ secondaryColor: colors.note,
66
+ tertiaryColor: colors.cluster,
67
+ mainBkg: colors.node,
68
+ nodeBorder: colors.nodeBorder,
69
+ textColor: colors.text,
70
+ titleColor: colors.text,
71
+ lineColor: colors.line,
72
+ clusterBkg: colors.cluster,
73
+ clusterBorder: colors.clusterBorder,
74
+ edgeLabelBackground: colors.ground,
75
+ noteBkgColor: colors.note,
76
+ noteTextColor: colors.text,
77
+ noteBorderColor: colors.nodeBorder
78
+ }
79
+ };
80
+ }
81
+
82
+ export interface SizedSvg {
83
+ svg: string;
84
+ width: number;
85
+ height: number;
86
+ }
87
+
88
+ const ROOT = /<svg\b[^>]*>/;
89
+ const VIEW_BOX = /\sviewBox="([^"]*)"/;
90
+ const SIZE_ATTRIBUTES = /\s(?:width|height|style)="[^"]*"/g;
91
+
92
+ /*
93
+ * The diagram at the size it was laid out at. Mermaid fits it to the width of its container instead,
94
+ * which an image does not have, so the root takes the size its view box names. Null for anything
95
+ * without one.
96
+ */
97
+ export function sizedSvg(svg: string): SizedSvg | null {
98
+ const root = ROOT.exec(svg);
99
+ const viewBox = root === null ? null : VIEW_BOX.exec(root[0]);
100
+ if (root === null || viewBox === null) {
101
+ return null;
102
+ }
103
+ const [, , boxWidth, boxHeight] = viewBox[1]!
104
+ .trim()
105
+ .split(/[\s,]+/)
106
+ .map(Number);
107
+ if (!Number.isFinite(boxWidth) || !Number.isFinite(boxHeight) || boxWidth! <= 0 || boxHeight! <= 0) {
108
+ return null;
109
+ }
110
+ const width = Math.ceil(boxWidth!);
111
+ const height = Math.ceil(boxHeight!);
112
+ const tag = root[0].replace(SIZE_ATTRIBUTES, '').replace(/^<svg\b/, `<svg width="${width}" height="${height}"`);
113
+ return { svg: svg.slice(0, root.index) + tag + svg.slice(root.index + root[0].length), width, height };
114
+ }
115
+
116
+ export function svgDataUrl(svg: string): string {
117
+ return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
118
+ }
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
2
2
  import { ChevronRight, GitFork } from 'lucide-react';
3
3
  import { useForkIdsAfter } from '../../forks';
4
4
  import { ROW_GUTTER } from '../icons';
5
- import { chatHost } from '../../../host';
5
+ import { useChatHost } from '../../../host';
6
6
  import { Icon, Menu } from '@adecore/ui';
7
7
 
8
8
  const LINE = '-mx-1 mb-0.5 flex h-7 items-center gap-2 rounded-md px-1 text-xs text-text-muted';
@@ -52,7 +52,8 @@ function ForksLabel({ label, link = true }: { label: string; link?: boolean }) {
52
52
 
53
53
  // A fork no longer in this project has nowhere to lead, so it only says it is there.
54
54
  function OneFork({ forkId, label }: { forkId: string; label: string }) {
55
- const place = chatHost().useChatPlace(forkId);
55
+ const host = useChatHost();
56
+ const place = host.useChatPlace(forkId);
56
57
  return (
57
58
  <div className="flex">
58
59
  {place.title === null ? (
@@ -69,8 +70,9 @@ function OneFork({ forkId, label }: { forkId: string; label: string }) {
69
70
  }
70
71
 
71
72
  function ForkItem({ forkId }: { forkId: string }) {
73
+ const host = useChatHost();
72
74
  const { t } = useTranslation('agent-chat');
73
- const place = chatHost().useChatPlace(forkId);
75
+ const place = host.useChatPlace(forkId);
74
76
  return (
75
77
  <Menu.Item disabled={place.title === null} onClick={place.go}>
76
78
  <Icon icon={GitFork} size={14} /> <span className="truncate">{place.title ?? t('fork.pill.label')}</span>
@@ -5,14 +5,14 @@ import { Trans, useTranslation } from 'react-i18next';
5
5
  import { Check, Copy, Ellipsis, ExternalLink, FolderDown, ImageIcon, Maximize2 } from 'lucide-react';
6
6
  import type { ChatAttachment, ChatToolItem } from '@adecore/agent-contracts';
7
7
  import { Button, ButtonGroup, copyText, ErrorBoundary, FileIcon, Icon, IconButton, Menu, Surface } from '@adecore/ui';
8
- import { chatHost } from '../../../host';
8
+ import { useChatHost } from '../../../host';
9
9
  import { useChatScope } from '../../../scope';
10
10
  import { useCurrentItem } from '../../../state/chats';
11
11
  import { formatBytes } from '../../attachments';
12
12
  import { attachmentAspect, generatedImageView, type GeneratedImageFailure } from '../../logic/generated-image';
13
13
  import { toolStartedAt } from '../../logic/tools';
14
14
  import { CHIP_IN_MESSAGE, MENTION_TONE } from '../chips';
15
- import { openFileLink, useFileLinkCwd } from '../file-links';
15
+ import { useFileLinkCwd, useOpenFileLink } from '../file-links';
16
16
  import { ImageThumb } from '../ImageView';
17
17
  import { ROW_GUTTER } from '../icons';
18
18
  import { RunningFor, WorkRow } from './WorkRows';
@@ -67,13 +67,15 @@ function HeadLine({ label, detail, live, startedAt }: { label: string; detail?:
67
67
  function SavedFile({ path }: { path: string }) {
68
68
  const cwd = useFileLinkCwd();
69
69
  const { id } = useChatScope();
70
+ const { fileLinks } = useChatHost();
71
+ const openFileLink = useOpenFileLink();
70
72
  const chip = (
71
73
  <>
72
74
  <FileIcon path={path} size={14} />
73
75
  <span className="truncate">{path}</span>
74
76
  </>
75
77
  );
76
- if (chatHost().fileLinks === null) {
78
+ if (fileLinks === null) {
77
79
  return <span className={clsx(CHIP_IN_MESSAGE, MENTION_TONE)}>{chip}</span>;
78
80
  }
79
81
  return (
@@ -91,7 +93,7 @@ function SavedFile({ path }: { path: string }) {
91
93
  function ReadyImage({ chatId, attachment, prompt, transparent }: { chatId: string; attachment: ChatAttachment; prompt: string | null; transparent: boolean }) {
92
94
  const { t } = useTranslation('agent-chat');
93
95
  const { id: scopeId } = useChatScope();
94
- const { attachments } = chatHost();
96
+ const { attachments } = useChatHost();
95
97
  const source = attachments.useUrl(scopeId, chatId, attachment.id);
96
98
  const savedKey = `${scopeId}\n${chatId}\n${attachment.id}`;
97
99
  const [lightbox, setLightbox] = useState(false);
@@ -14,21 +14,22 @@ import type {
14
14
  import { WAITING_NOTE_PREFIX } from '@adecore/agent-contracts';
15
15
  import { fileBadge, formatBytes, isImageAttachment } from '../../attachments';
16
16
  import { useChatRow, useCurrentItem } from '../../../state/chats';
17
- import { chatHost } from '../../../host';
17
+ import { useChatHost } from '../../../host';
18
18
  import { useChatScope } from '../../../scope';
19
19
  import { splitQuote } from '../../quote';
20
20
  import { jumpToTimelineItem } from '../../timeline-scroll';
21
21
  import { useProviders } from '../../../state/providers';
22
22
  import { ChatReferenceChip } from '../ChatReferenceChip';
23
23
  import { ImageThumb } from '../ImageView';
24
- import { MessageMarkdown, ReplyMarkdown } from '../Markdown';
24
+ import { Markdown, MessageMarkdown, ReplyMarkdown } from '../Markdown';
25
25
  import { FadingWords } from '../FadingWords';
26
26
  import { settledBlocksText } from '../markdown-blocks';
27
27
  import { WHOLE_FADE_CLASS } from '../rehype-fade';
28
28
  import { useRevealedText } from '../reveal';
29
29
  import { formatAgo, formatElapsedShort, formatMoment, formatTokens } from '@adecore/ui/format';
30
- import { Icon, Tooltip, useTickingText } from '@adecore/ui';
31
- import { toolSummary } from '../../logic/tools';
30
+ import { Icon, MiddleTruncate, Tooltip, useTickingText } from '@adecore/ui';
31
+ import { thoughtLine, thoughtPreview } from '../../logic/thought';
32
+ import { toolSummary, toolSummaryIsPath } from '../../logic/tools';
32
33
  import { ROW_GUTTER } from '../icons';
33
34
  import { useOpenForFind } from '../find-reveal';
34
35
  import { ReplyContext, UiReplyNavigationContext } from '../reply-context';
@@ -42,9 +43,10 @@ const USER_FOLD_CHARS = 600;
42
43
  const FOLD = 'max-h-[10em] overflow-hidden [mask-image:linear-gradient(to_bottom,black_70%,transparent)]';
43
44
 
44
45
  function useReplyAuthor(chatId: string) {
46
+ const host = useChatHost();
45
47
  const { id } = useChatScope();
46
48
  const context = useContext(ReplyContext);
47
- const author = chatHost().useReplyAuthor(id, context?.chatId ?? chatId);
49
+ const author = host.useReplyAuthor(id, context?.chatId ?? chatId);
48
50
  return context !== null && context.chatId === undefined ? null : author;
49
51
  }
50
52
 
@@ -53,8 +55,9 @@ function useReplyAuthor(chatId: string) {
53
55
  * hands a link that opens a window to the system browser, which cannot reach a blob of this page.
54
56
  */
55
57
  function AttachmentLink({ chatId, attachment }: { chatId: string; attachment: ChatAttachment }) {
58
+ const host = useChatHost();
56
59
  const { id } = useChatScope();
57
- const { url } = chatHost().attachments.useUrl(id, chatId, attachment.id);
60
+ const { url } = host.attachments.useUrl(id, chatId, attachment.id);
58
61
  const badge = fileBadge(attachment.name);
59
62
  return (
60
63
  <Tooltip label={attachment.name}>
@@ -78,8 +81,9 @@ function AttachmentLink({ chatId, attachment }: { chatId: string; attachment: Ch
78
81
 
79
82
  /* A picture attached to a message, which opens large. */
80
83
  function AttachmentThumb({ chatId, attachment }: { chatId: string; attachment: ChatAttachment }) {
84
+ const host = useChatHost();
81
85
  const { id } = useChatScope();
82
- const source = chatHost().attachments.useUrl(id, chatId, attachment.id);
86
+ const source = host.attachments.useUrl(id, chatId, attachment.id);
83
87
  return <ImageThumb source={source} alt={attachment.name} className="max-h-32 max-w-48 object-cover" />;
84
88
  }
85
89
 
@@ -264,6 +268,7 @@ function Writing() {
264
268
  * written fades anything: an old reply scrolled back into view just stands there.
265
269
  */
266
270
  export function AssistantRow({ chatId, item: derived }: { chatId: string; item: ChatAssistantItem }) {
271
+ const host = useChatHost();
267
272
  const item = useCurrentItem(chatId, derived);
268
273
  const scope = useChatScope();
269
274
  const context = useContext(ReplyContext);
@@ -271,7 +276,7 @@ export function AssistantRow({ chatId, item: derived }: { chatId: string; item:
271
276
  () => (context === null && !item.parentToolUseId ? { scopeId: scope.id, chatId, itemId: item.id, streaming: item.streaming } : undefined),
272
277
  [context, item.parentToolUseId, scope.id, chatId, item.id, item.streaming]
273
278
  );
274
- const mode = chatHost().useStreaming();
279
+ const mode = host.useStreaming();
275
280
  const [sawWriting] = useState(item.streaming);
276
281
  const live = mode === 'words' && item.streaming;
277
282
  const reveal = useRevealedText(item.text, live);
@@ -329,12 +334,14 @@ export function AssistantRow({ chatId, item: derived }: { chatId: string; item:
329
334
 
330
335
  /*
331
336
  * What the model thought before it answered. It shimmers while it streams and folds itself away
332
- * once the answer starts, because the thought is worth a glance and rarely worth reading twice.
337
+ * once the answer starts, because the thought is worth a glance and rarely worth reading twice:
338
+ * folded, it shows the heading it opens with or itself on one line, and opened, it reads as Markdown.
333
339
  */
334
340
  export function ThinkingRow({ chatId, item: derived }: { chatId: string; item: ChatThinkingItem }) {
341
+ const host = useChatHost();
335
342
  const { t } = useTranslation('agent-chat');
336
343
  const item = useCurrentItem(chatId, derived);
337
- const mode = chatHost().useStreaming();
344
+ const mode = host.useStreaming();
338
345
  const [open, setOpen] = useState(false);
339
346
  const reveal = useRevealedText(item.text, mode === 'words' && item.streaming);
340
347
  // A block at a time, the paragraphs of the thought that closed are shown as they land.
@@ -342,31 +349,72 @@ export function ThinkingRow({ chatId, item: derived }: { chatId: string; item: C
342
349
  // Whole, the thought stays behind "Thinking…" until it is done and then folds like any other.
343
350
  const shown = open || reveal.active || (settled !== null && settled !== '');
344
351
  const text = settled ?? reveal.text;
352
+ const live = useMemo(() => (item.streaming && mode !== 'whole' ? thoughtLine(text) : ''), [item.streaming, mode, text]);
353
+ const preview = useMemo(() => (item.streaming ? '' : thoughtPreview(item.text)), [item.streaming, item.text]);
354
+ const duration = formatElapsedShort((item.endedAt ?? item.createdAt) - item.createdAt);
345
355
  useOpenForFind(item.id, 'text', setOpen);
346
356
  return (
347
357
  <div data-find-item={item.id} className="-mx-1 px-1 pb-2">
348
- <button className="flex items-center gap-2 text-xs text-text-muted hover:text-text" disabled={item.streaming} onClick={() => setOpen((o) => !o)}>
358
+ <button
359
+ className="flex w-full min-w-0 items-center gap-2 text-left text-xs text-text-muted hover:text-text"
360
+ disabled={item.streaming}
361
+ aria-expanded={item.streaming ? undefined : open}
362
+ onClick={() => setOpen((o) => !o)}
363
+ >
349
364
  <span className={ROW_GUTTER}>
350
365
  <Icon icon={Brain} size={12} />
351
366
  </span>
352
367
  {item.streaming ? (
353
- <span className="chat-live-text">{t('rows.thinking.live')}</span>
368
+ <span className="chat-live-text min-w-0 truncate">{live || t('rows.thinking.live')}</span>
369
+ ) : preview === '' ? (
370
+ <>
371
+ <span>{t('rows.thinking.thoughtFor', { duration })}</span>
372
+ <Icon icon={ChevronDown} size={12} className={clsx('shrink-0 transition-transform', open && 'rotate-180')} />
373
+ </>
354
374
  ) : (
355
375
  <>
356
- <span>{t('rows.thinking.thoughtFor', { duration: formatElapsedShort((item.endedAt ?? item.createdAt) - item.createdAt) })}</span>
357
- <Icon icon={ChevronDown} size={12} className={clsx('transition-transform', open && 'rotate-180')} />
376
+ <span className="min-w-0 truncate">{open ? t('rows.thinking.thought') : preview}</span>
377
+ <span className="grow" />
378
+ <span className="shrink-0 text-text-faint tabular-nums">{duration}</span>
379
+ <Icon icon={ChevronDown} size={12} className={clsx('shrink-0 transition-transform', open && 'rotate-180')} />
358
380
  </>
359
381
  )}
360
382
  </button>
361
383
  {shown && text !== '' && (
362
- <div data-find-field="text" className="mt-1 border-l border-border pl-2.5 text-sm whitespace-pre-wrap text-text-faint select-text">
363
- {reveal.active ? <FadingWords text={reveal.text} /> : text}
384
+ <div data-find-field="text" className="mt-1 border-l border-border pl-2.5 select-text">
385
+ {reveal.active ? (
386
+ <div className="text-sm whitespace-pre-wrap text-text-faint">
387
+ <FadingWords text={reveal.text} />
388
+ </div>
389
+ ) : (
390
+ <Markdown text={text} muted />
391
+ )}
364
392
  </div>
365
393
  )}
366
394
  </div>
367
395
  );
368
396
  }
369
397
 
398
+ /*
399
+ * The latest thought of a running turn over the call it led to, as its heading or first sentence,
400
+ * so what the model found stays in view while it checks it. Nothing while the thought has no line yet.
401
+ */
402
+ export function LiveThoughtRow({ chatId, item: derived }: { chatId: string; item: ChatThinkingItem }) {
403
+ const item = useCurrentItem(chatId, derived);
404
+ const line = useMemo(() => thoughtLine(item.text), [item.text]);
405
+ if (line === '') {
406
+ return null;
407
+ }
408
+ return (
409
+ <div className="-mx-1 mb-0.5 flex min-h-7 items-start gap-2 px-1 py-1 text-xs text-text-muted">
410
+ <span className={ROW_GUTTER}>
411
+ <Icon icon={Brain} size={12} />
412
+ </span>
413
+ <span className="line-clamp-4 min-w-0 wrap-anywhere select-text">{line}</span>
414
+ </div>
415
+ );
416
+ }
417
+
370
418
  const NOTE_ICON = {
371
419
  info: <Icon icon={Info} size={12} />,
372
420
  warning: <Icon icon={TriangleAlert} size={12} />,
@@ -417,8 +465,9 @@ export function NoteRow({ id, level, text, from }: { id: string; level: 'info' |
417
465
 
418
466
  /* "Open fork" on a note a fork sent, or "Open to answer" on one about a waiting child, while that chat is still in the project. */
419
467
  function OpenChatButton({ chatId, label }: { chatId: string; label: 'openFork' | 'openWaiting' }) {
468
+ const host = useChatHost();
420
469
  const { t } = useTranslation('agent-chat');
421
- const place = chatHost().useChatPlace(chatId);
470
+ const place = host.useChatPlace(chatId);
422
471
  if (place.title === null) {
423
472
  return null;
424
473
  }
@@ -486,7 +535,13 @@ export function ApprovalHistoryRow({ item }: { item: ChatApprovalItem }) {
486
535
  <span className={clsx(ROW_GUTTER, item.decision === 'deny' && 'text-status-error')}>{DECISION_ICON[item.decision]}</span>
487
536
  <span className={clsx(item.decision === 'deny' && 'text-status-error')}>{t(`rows.approval.${item.decision}`)}</span>
488
537
  <span className="text-text-muted">{item.toolName}</span>
489
- <span className="min-w-0 truncate font-mono">{toolSummary(item.toolName, item.input)}</span>
538
+ <span className="min-w-0 truncate font-mono">
539
+ {toolSummaryIsPath(item.toolName, item.input) ? (
540
+ <MiddleTruncate text={toolSummary(item.toolName, item.input)} />
541
+ ) : (
542
+ toolSummary(item.toolName, item.input)
543
+ )}
544
+ </span>
490
545
  </div>
491
546
  );
492
547
  }
@@ -3,7 +3,18 @@ import { ErrorBoundary } from '@adecore/ui';
3
3
  import type { ThreadCard } from '../../../host';
4
4
  import type { TimelineRow } from '../../logic/timeline';
5
5
  import type { SubagentStep } from '../../subagent-view';
6
- import { AgentTurnRow, ApprovalHistoryRow, AssistantRow, CompactionRow, NoteRow, QuestionHistoryRow, ReportRow, ThinkingRow, UserRow } from './MessageRows';
6
+ import {
7
+ AgentTurnRow,
8
+ ApprovalHistoryRow,
9
+ AssistantRow,
10
+ CompactionRow,
11
+ LiveThoughtRow,
12
+ NoteRow,
13
+ QuestionHistoryRow,
14
+ ReportRow,
15
+ ThinkingRow,
16
+ UserRow
17
+ } from './MessageRows';
7
18
  import { isImageGeneration } from '../../logic/generated-image';
8
19
  import { ForksRow } from './ForksRow';
9
20
  import { GeneratedImageRow } from './GeneratedImageRow';
@@ -52,6 +63,8 @@ export function Row({ row, chatId, toggleGroup, toggleTurn, toggleSubagent, open
52
63
  return <ReportRow id={row.id} text={row.text} />;
53
64
  case 'thinking':
54
65
  return <ThinkingRow chatId={chatId} item={row.item} />;
66
+ case 'live-thought':
67
+ return <LiveThoughtRow chatId={chatId} item={row.item} />;
55
68
  case 'work':
56
69
  return isImageGeneration(row.tool) ? <GeneratedImageRow chatId={chatId} tool={row.tool} /> : <WorkRow tool={row.tool} />;
57
70
  case 'work-live':
@@ -15,7 +15,7 @@ import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows';
15
15
  import { entryTimeOf, statusWordOf, taskIdOf } from '../../subagent-list';
16
16
  import { useSubagentSupport } from '../../subagent-support';
17
17
  import { canOpenSubagent, crumbOf, type SubagentStep } from '../../subagent-view';
18
- import { chatHost, type SubagentTask } from '../../../host';
18
+ import { useChatHost, type SubagentTask } from '../../../host';
19
19
  import { useChatScope } from '../../../scope';
20
20
  import { useCurrentItem } from '../../../state/chats';
21
21
 
@@ -135,10 +135,11 @@ export function SubagentRow({
135
135
  /* Opens everything it did in the thread's place, for a surface that has somewhere to open it. */
136
136
  onOpenConversation?(): void;
137
137
  }) {
138
+ const host = useChatHost();
138
139
  const { t } = useTranslation('agent-chat');
139
140
  const { id } = useChatScope();
140
141
  const taskId = taskIdOf(item);
141
- const task = chatHost().tasks.useTask(id, taskId);
142
+ const task = host.tasks.useTask(id, taskId);
142
143
  // A task paused on its child's limit is still a running row on the wire, but nothing is at work.
143
144
  const running = item.status === 'running' && statusWordOf(item, task) !== 'paused';
144
145
  const detail = item.description || item.summary || item.subagentType || '';
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
2
2
  import { Ellipsis, Maximize2, Trash2 } from 'lucide-react';
3
3
  import type { ChatVisual } from '@adecore/agent-contracts';
4
4
  import { ButtonGroup, ErrorBoundary, Icon, IconButton, Menu, Surface } from '@adecore/ui';
5
- import { chatHost } from '../../../host';
5
+ import { useChatHost } from '../../../host';
6
6
  import { useChatScope } from '../../../scope';
7
7
  import { useVisualDialog } from '../../visuals';
8
8
  import { VisualFrame } from '../VisualFrame';
@@ -14,9 +14,10 @@ import { VisualFrame } from '../VisualFrame';
14
14
  * sit here.
15
15
  */
16
16
  export function VisualRow({ chatId, visual }: { chatId: string; visual: ChatVisual }) {
17
+ const host = useChatHost();
17
18
  const { t } = useTranslation('agent-chat');
18
19
  const { keyOf } = useChatScope();
19
- if (chatHost().visuals === null) {
20
+ if (host.visuals === null) {
20
21
  return null;
21
22
  }
22
23
  const open = (kind: 'expand' | 'remove'): void => useVisualDialog.getState().open(keyOf(chatId), visual.id, kind);