@adecore/agents-react 0.23.0 → 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
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { ErrorBoundary } from '@adecore/ui';
4
- import { AgentTurnRow, ApprovalHistoryRow, AssistantRow, CompactionRow, NoteRow, QuestionHistoryRow, ReportRow, ThinkingRow, UserRow } from './MessageRows.js';
4
+ import { AgentTurnRow, ApprovalHistoryRow, AssistantRow, CompactionRow, LiveThoughtRow, NoteRow, QuestionHistoryRow, ReportRow, ThinkingRow, UserRow } from './MessageRows.js';
5
5
  import { isImageGeneration } from '../../logic/generated-image.js';
6
6
  import { ForksRow } from './ForksRow.js';
7
7
  import { GeneratedImageRow } from './GeneratedImageRow.js';
@@ -32,6 +32,8 @@ export function Row({ row, chatId, toggleGroup, toggleTurn, toggleSubagent, open
32
32
  return _jsx(ReportRow, { id: row.id, text: row.text });
33
33
  case 'thinking':
34
34
  return _jsx(ThinkingRow, { chatId: chatId, item: row.item });
35
+ case 'live-thought':
36
+ return _jsx(LiveThoughtRow, { chatId: chatId, item: row.item });
35
37
  case 'work':
36
38
  return isImageGeneration(row.tool) ? _jsx(GeneratedImageRow, { chatId: chatId, tool: row.tool }) : _jsx(WorkRow, { tool: row.tool });
37
39
  case 'work-live':
@@ -14,7 +14,7 @@ import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows.js';
14
14
  import { entryTimeOf, statusWordOf, taskIdOf } from '../../subagent-list.js';
15
15
  import { useSubagentSupport } from '../../subagent-support.js';
16
16
  import { canOpenSubagent, crumbOf } from '../../subagent-view.js';
17
- import { chatHost } from '../../../host.js';
17
+ import { useChatHost } from '../../../host.js';
18
18
  import { useChatScope } from '../../../scope.js';
19
19
  import { useCurrentItem } from '../../../state/chats.js';
20
20
  // The work of a long-running agent scrolls inside its row instead of pushing the thread away.
@@ -85,10 +85,11 @@ function SubagentResult({ itemId, result }) {
85
85
  * the work the thread kept and, once it settled, the report it wrote.
86
86
  */
87
87
  export function SubagentRow({ chatId, item, work, expanded, onToggle, onOpenConversation }) {
88
+ const host = useChatHost();
88
89
  const { t } = useTranslation('agent-chat');
89
90
  const { id } = useChatScope();
90
91
  const taskId = taskIdOf(item);
91
- const task = chatHost().tasks.useTask(id, taskId);
92
+ const task = host.tasks.useTask(id, taskId);
92
93
  // A task paused on its child's limit is still a running row on the wire, but nothing is at work.
93
94
  const running = item.status === 'running' && statusWordOf(item, task) !== 'paused';
94
95
  const detail = item.description || item.summary || item.subagentType || '';
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { Ellipsis, Maximize2, Trash2 } from 'lucide-react';
4
4
  import { ButtonGroup, ErrorBoundary, Icon, IconButton, Menu, Surface } from '@adecore/ui';
5
- import { chatHost } from '../../../host.js';
5
+ import { useChatHost } from '../../../host.js';
6
6
  import { useChatScope } from '../../../scope.js';
7
7
  import { useVisualDialog } from '../../visuals.js';
8
8
  import { VisualFrame } from '../VisualFrame.js';
@@ -13,9 +13,10 @@ import { VisualFrame } from '../VisualFrame.js';
13
13
  * sit here.
14
14
  */
15
15
  export function VisualRow({ chatId, visual }) {
16
+ const host = useChatHost();
16
17
  const { t } = useTranslation('agent-chat');
17
18
  const { keyOf } = useChatScope();
18
- if (chatHost().visuals === null) {
19
+ if (host.visuals === null) {
19
20
  return null;
20
21
  }
21
22
  const open = (kind) => useVisualDialog.getState().open(keyOf(chatId), visual.id, kind);
@@ -1,15 +1,18 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { ChatCheckpointDiff, ChatToolItem, ChatTurnItem } from '@adecore/agent-contracts';
3
3
  import type { BaseMoved } from '../../logic/timeline.js';
4
- export declare function ToggleLine({ icon, label, detail, open, onToggle, failed, live, trailing, className }: {
4
+ export declare function ToggleLine({ icon, label, detail, command, path, open, onToggle, failed, live, trailing, time, className }: {
5
5
  icon: ReactNode;
6
6
  label: string;
7
7
  detail?: string;
8
- open: boolean;
9
- onToggle(): void;
8
+ command?: boolean;
9
+ path?: boolean;
10
+ open?: boolean;
11
+ onToggle?(): void;
10
12
  failed?: boolean;
11
13
  live?: boolean;
12
14
  trailing?: ReactNode;
15
+ time?: number;
13
16
  className?: string;
14
17
  }): import("react").JSX.Element;
15
18
  export declare function WorkRow({ tool, nested, detail, icon, label, failed }: {
@@ -1,36 +1,49 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Suspense, useEffect, useState } from 'react';
2
+ import { Fragment, Suspense, useEffect, useState } from 'react';
3
3
  import clsx from 'clsx';
4
4
  import i18next from 'i18next';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { ChevronRight, FileDiff, X } from 'lucide-react';
7
- import { fileChanges, liveOutput, readImagePath, toolStartedAt, toolSummary, unifiedChanges } from '../../logic/tools.js';
7
+ import { exitCodeOf, fileChanges, hasOutput, hasToolBody, liveOutput, readImagePath, shellCommand, toolCallLines, toolStartedAt, toolSummary, toolSummaryIsPath, unifiedChanges } from '../../logic/tools.js';
8
8
  import { useOpenForFind } from '../find-reveal.js';
9
- import { chatHost } from '../../../host.js';
9
+ import { useChatHost } from '../../../host.js';
10
10
  import { lazyNamed } from '../../../lazy.js';
11
11
  import { useChatActions } from '../../actions.js';
12
12
  import { useChatScope } from '../../../scope.js';
13
13
  import { useCurrentItem } from '../../../state/chats.js';
14
14
  import { useTimelineFlash } from '../../timeline-flash.js';
15
15
  import { formatClockDuration, formatElapsedShort } from '@adecore/ui/format';
16
- import { Icon, Spinner, useTickingText } from '@adecore/ui';
16
+ import { Icon, MiddleTruncate, Spinner, useTickingText } from '@adecore/ui';
17
17
  import { ROW_GUTTER, toolIcon } from '../icons.js';
18
18
  import { AnsiOutput } from '../AnsiOutput.js';
19
+ import { RowTime } from '../RowTime.js';
20
+ import { ShellCommand } from '../ShellCommand.js';
19
21
  import { DiffStack, ReviewStackView } from '../diff/DiffStack.js';
20
22
  import { reviewEntries } from '../diff/review-plan.js';
21
23
  import { useReviewStack } from '../diff/use-review-stack.js';
22
24
  // A checkpoint opens its renderer only when a file is expanded.
23
25
  const UnifiedDiff = lazyNamed(() => import('../UnifiedDiff.js'), 'default');
24
26
  const OUTPUT_LIMIT = 4000;
27
+ /* The line that says how much of a text past the limit is left out; empty for a text within it. */
28
+ function clipNotice(text) {
29
+ return text.length > OUTPUT_LIMIT ? `\n${i18next.t('agent-chat:work.moreCharacters', { count: text.length - OUTPUT_LIMIT })}` : '';
30
+ }
25
31
  function clip(text) {
26
- return text.length > OUTPUT_LIMIT
27
- ? `${text.slice(0, OUTPUT_LIMIT)}\n${i18next.t('agent-chat:work.moreCharacters', { count: text.length - OUTPUT_LIMIT })}`
28
- : text;
32
+ return text.slice(0, OUTPUT_LIMIT) + clipNotice(text);
29
33
  }
30
- export function ToggleLine({ icon, label, detail, open, onToggle, failed, live, trailing, className }) {
31
- return (_jsxs("button", { className: clsx(
32
- // Fix the width so long commands reach the truncation inside the negative margins.
33
- '-mx-1 mb-0.5 flex h-7 w-[calc(100%+8px)] items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover', failed && 'text-status-error', className), onClick: onToggle, children: [_jsx("span", { className: clsx(ROW_GUTTER, live && 'text-accent'), children: icon }), _jsx("span", { className: clsx('shrink-0', live && 'chat-live-text'), children: label }), detail && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-text-faint", children: detail })), _jsx("span", { className: "grow" }), trailing, failed && _jsx(Icon, { icon: X, size: 12, className: "shrink-0" }), _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') })] }));
34
+ /*
35
+ * The line of a call, a subagent or a group. Without `onToggle` it has nothing to open: no chevron, and
36
+ * not a button. `time` shows at the right edge while the line is hovered or focused.
37
+ */
38
+ export function ToggleLine({ icon, label, detail, command, path, open = false, onToggle, failed, live, trailing, time, className }) {
39
+ const classes = clsx(
40
+ // Fix the width so long commands reach the truncation inside the negative margins.
41
+ 'group/line -mx-1 mb-0.5 flex h-7 w-[calc(100%+8px)] items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted', onToggle !== undefined && 'hover:bg-surface-hover', failed && 'text-status-error', className);
42
+ const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: clsx(ROW_GUTTER, live && 'text-accent'), children: icon }), _jsx("span", { className: clsx('shrink-0', live && 'chat-live-text'), children: label }), detail && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-text-faint", children: command ? _jsx(ShellCommand, { command: detail }) : path ? _jsx(MiddleTruncate, { text: detail }) : detail })), _jsx("span", { className: "grow" }), trailing, time !== undefined && _jsx(RowTime, { at: time }), failed && _jsx(Icon, { icon: X, size: 12, className: "shrink-0" }), onToggle !== undefined && (_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') }))] }));
43
+ if (onToggle === undefined) {
44
+ return _jsx("div", { className: classes, children: content });
45
+ }
46
+ return (_jsx("button", { className: classes, onClick: onToggle, children: content }));
34
47
  }
35
48
  /* The diff renderers load lazily, so a diff waits on them under a line that says so. */
36
49
  function DiffSuspense({ children }) {
@@ -39,23 +52,45 @@ function DiffSuspense({ children }) {
39
52
  }
40
53
  /* A file in a changed files card, which opens its diff under it. */
41
54
  function ChangedFileLine({ path, open, onToggle, trailing, children }) {
42
- return (_jsxs("div", { className: "border-t border-border", children: [_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-text-muted hover:bg-surface-hover", "data-file-path": path, onClick: onToggle, children: [_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') }), _jsx("span", { className: "min-w-0 truncate font-mono text-text", children: path }), _jsx("span", { className: "grow" }), trailing] }), open && _jsx("div", { className: "border-t border-border", children: children })] }));
55
+ return (_jsxs("div", { className: "border-t border-border", children: [_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-text-muted hover:bg-surface-hover", "data-file-path": path, onClick: onToggle, children: [_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') }), _jsx(MiddleTruncate, { text: path, className: "font-mono text-text" }), _jsx("span", { className: "grow" }), trailing] }), open && _jsx("div", { className: "border-t border-border", children: children })] }));
56
+ }
57
+ /* A diff keeps its card, with what the call answered under it. */
58
+ function DiffBody({ tool, entries, patched }) {
59
+ return (_jsxs("div", { className: "mt-1.5 mb-2 ml-6 overflow-hidden rounded-md border border-border bg-surface-raised", children: [_jsx(DiffStack, { entries: entries }), hasOutput(tool.output) && !patched && (_jsx("pre", { "data-find-field": "output", className: clsx('max-h-64 overflow-auto whitespace-pre-wrap border-t border-border px-3 py-2 font-mono text-code select-text', tool.state === 'error' ? 'text-chat-removed' : 'text-chat-output'), children: _jsx(AnsiOutput, { text: tool.output, limit: OUTPUT_LIMIT }) }))] }));
43
60
  }
61
+ /* What a call answered, muted under the call; a failure in the error color, or its exit code when the tool names one. */
62
+ function ToolOutput({ tool }) {
63
+ const { t } = useTranslation('agent-chat');
64
+ if (!hasOutput(tool.output)) {
65
+ return null;
66
+ }
67
+ const failed = tool.state === 'error';
68
+ const { code, rest } = failed ? exitCodeOf(tool.output) : { code: null, rest: tool.output };
69
+ return (_jsxs(_Fragment, { children: [hasOutput(rest) && (_jsx("pre", { "data-find-field": "output", className: clsx('max-h-64 overflow-auto whitespace-pre-wrap', failed && code === null ? 'text-status-error' : 'text-text-muted'), children: _jsx(AnsiOutput, { text: rest, limit: OUTPUT_LIMIT }) })), code !== null && _jsx("div", { className: "text-status-error", children: t('work.exitCode', { code: String(code) }) })] }));
70
+ }
71
+ /* An opened call without a card: what it was asked in the foreground, what it answered muted below. */
44
72
  function ToolBody({ tool }) {
45
73
  const patches = unifiedChanges(tool);
46
74
  const changes = patches.length > 0 ? [] : fileChanges(tool.name, tool.input);
47
- return (_jsxs("div", { className: "mt-1.5 mb-2 ml-6 overflow-hidden rounded-md border border-border bg-surface-raised", children: [patches.length + changes.length > 0 ? (_jsx(DiffStack, { entries: reviewEntries(patches, changes) })) : (_jsx("pre", { className: "max-h-64 overflow-auto px-3 py-2 font-mono text-code text-text-muted select-text", children: clip(JSON.stringify(tool.input, null, 2) ?? '') })), tool.output !== null && tool.output !== '' && patches.length === 0 && (_jsx("pre", { "data-find-field": "output", className: clsx('max-h-64 overflow-auto whitespace-pre-wrap border-t border-border px-3 py-2 font-mono text-code select-text', tool.state === 'error' ? 'text-chat-removed' : 'text-chat-output'), children: _jsx(AnsiOutput, { text: tool.output, limit: OUTPUT_LIMIT }) }))] }));
75
+ if (patches.length + changes.length > 0) {
76
+ return _jsx(DiffBody, { tool: tool, entries: reviewEntries(patches, changes), patched: patches.length > 0 });
77
+ }
78
+ const lines = toolCallLines(tool.name, tool.input);
79
+ return (_jsxs("div", { className: "mt-0.5 mb-2 ml-6 flex flex-col gap-1.5 font-mono text-code select-text", children: [lines.command !== null && (_jsxs("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap wrap-anywhere text-text", children: [_jsx(ShellCommand, { command: lines.command.slice(0, OUTPUT_LIMIT) }), clipNotice(lines.command)] })), lines.args.length > 0 && (_jsx("dl", { className: "grid max-h-64 grid-cols-[auto_minmax(0,1fr)] gap-x-3 overflow-auto", children: lines.args.map(([key, value]) => (_jsxs(Fragment, { children: [_jsx("dt", { className: "text-text-faint", children: key }), _jsx("dd", { className: "whitespace-pre-wrap wrap-anywhere text-text", children: clip(value) })] }, key))) })), lines.text !== null && _jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap wrap-anywhere text-text", children: clip(lines.text) }), _jsx(ToolOutput, { tool: tool })] }));
48
80
  }
49
81
  /*
50
- * One settled tool call: a line, and its input and output behind it. An image the call looked at is
51
- * drawn under the line. `icon`, `label` and `failed` let a row that knows the call better name it.
82
+ * One settled tool call: a line, and what it was asked and answered behind it. An image the call
83
+ * looked at is drawn under the line. `icon`, `label` and `failed` let a row that knows the call better name it.
52
84
  */
53
85
  export function WorkRow({ tool, nested, detail, icon, label, failed }) {
86
+ const host = useChatHost();
54
87
  const [open, setOpen] = useState(false);
55
88
  const image = tool.state === 'done' ? readImagePath(tool.name, tool.input) : null;
56
- const { ReadImage } = chatHost();
89
+ const { ReadImage } = host;
57
90
  useOpenForFind(tool.id, 'output', setOpen);
58
- return (_jsxs("div", { "data-find-item": tool.id, className: nested ? 'ml-6' : undefined, children: [_jsx(ToggleLine, { icon: icon ?? toolIcon(tool.name), label: label ?? tool.name, detail: detail ?? toolSummary(tool.name, tool.input), open: open, onToggle: () => setOpen((o) => !o), failed: failed ?? tool.state === 'error' }), image !== null && ReadImage !== null && _jsx(ReadImage, { path: image }), open && _jsx(ToolBody, { tool: tool })] }));
91
+ const summary = detail ?? toolSummary(tool.name, tool.input);
92
+ const opens = hasToolBody(tool);
93
+ return (_jsxs("div", { "data-find-item": tool.id, className: nested ? 'ml-6' : undefined, children: [_jsx(ToggleLine, { icon: icon ?? toolIcon(tool.name), label: label ?? tool.name, detail: summary, command: detail === undefined && summary === shellCommand(tool.name, tool.input), path: detail === undefined && toolSummaryIsPath(tool.name, tool.input), open: open && opens, onToggle: opens ? () => setOpen((o) => !o) : undefined, failed: failed ?? tool.state === 'error', time: tool.createdAt }), image !== null && ReadImage !== null && _jsx(ReadImage, { path: image }), open && opens && _jsx(ToolBody, { tool: tool })] }));
59
94
  }
60
95
  /* "running for 12s" next to a live call. */
61
96
  export function RunningFor({ startedAt }) {
@@ -68,19 +103,21 @@ export function WorkLiveRow({ chatId, tool: derived }) {
68
103
  const [open, setOpen] = useState(false);
69
104
  const tool = useCurrentItem(chatId, derived);
70
105
  const tail = liveOutput(tool);
71
- return (_jsxs("div", { children: [_jsx(ToggleLine, { icon: toolIcon(tool.name), label: tool.name, detail: toolSummary(tool.name, tool.input) || tool.progress?.description || '', open: open, onToggle: () => setOpen((o) => !o), trailing: _jsx(RunningFor, { startedAt: toolStartedAt(tool) }), live: true }), open && _jsx(ToolBody, { tool: tool }), tail !== null && !open && (_jsx("pre", { className: "mt-1.5 mb-2 ml-6 max-h-48 overflow-auto rounded-md border border-border bg-surface-raised px-3 py-2 font-mono text-code whitespace-pre-wrap text-chat-output select-text", children: _jsx(AnsiOutput, { text: tail, tailLines: 12 }) }))] }));
106
+ const summary = toolSummary(tool.name, tool.input);
107
+ const opens = hasToolBody(tool);
108
+ return (_jsxs("div", { children: [_jsx(ToggleLine, { icon: toolIcon(tool.name), label: tool.name, detail: summary || tool.progress?.description || '', command: summary !== '' && summary === shellCommand(tool.name, tool.input), path: summary !== '' && toolSummaryIsPath(tool.name, tool.input), open: open && opens, onToggle: opens ? () => setOpen((o) => !o) : undefined, trailing: _jsx(RunningFor, { startedAt: toolStartedAt(tool) }), live: true }), open && opens && _jsx(ToolBody, { tool: tool }), tail !== null && !open && (_jsx("pre", { className: "mt-1.5 mb-2 ml-6 max-h-48 overflow-auto rounded-md border border-border bg-surface-raised px-3 py-2 font-mono text-code whitespace-pre-wrap text-chat-output select-text", children: _jsx(AnsiOutput, { text: tail, tailLines: 12 }) }))] }));
72
109
  }
73
110
  /* A run of tool calls as one line ("Read 4 files"); opening it lists every call. */
74
111
  export function WorkGroupRow({ tools, summary, expanded, onToggle }) {
75
112
  const failed = tools.some((tool) => tool.state === 'error');
76
- return (_jsx("div", { children: _jsx(ToggleLine, { icon: toolIcon(tools[0].name), label: summary, open: expanded, onToggle: onToggle, failed: failed }) }));
113
+ return (_jsx("div", { children: _jsx(ToggleLine, { icon: toolIcon(tools[0].name), label: summary, open: expanded, onToggle: onToggle, failed: failed, time: tools[0].createdAt }) }));
77
114
  }
78
115
  /*
79
116
  * A settled turn folded behind how long it took and what it did. A line and not a button, like the
80
117
  * tool lines it hides; the work reads fainter than the time so the eye lands on the time first.
81
118
  */
82
119
  export function TurnFoldRow({ turn, label, work, expanded, onToggle }) {
83
- return (_jsxs("button", { className: clsx('group -mx-1 mb-2 flex h-7 w-[calc(100%+8px)] min-w-0 items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover', turn.state === 'error' && 'text-status-error'), "aria-expanded": expanded, onClick: onToggle, children: [_jsx("span", { className: ROW_GUTTER, children: _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('transition-transform', expanded && 'rotate-90') }) }), _jsx("span", { className: "shrink-0 group-hover:text-text", children: label }), work.length > 0 && _jsx("span", { className: "min-w-0 truncate text-text-faint", children: work.map((part) => ` · ${part}`).join('') })] }));
120
+ return (_jsxs("button", { className: clsx('group group/line -mx-1 mb-2 flex h-7 w-[calc(100%+8px)] min-w-0 items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover', turn.state === 'error' && 'text-status-error'), "aria-expanded": expanded, onClick: onToggle, children: [_jsx("span", { className: ROW_GUTTER, children: _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('transition-transform', expanded && 'rotate-90') }) }), _jsx("span", { className: "shrink-0 group-hover:text-text", children: label }), work.length > 0 && _jsx("span", { className: "min-w-0 truncate text-text-faint", children: work.map((part) => ` · ${part}`).join('') }), _jsx("span", { className: "grow" }), _jsx(RowTime, { at: turn.createdAt })] }));
84
121
  }
85
122
  function omittedLabel(reason) {
86
123
  return reason === 'binary' ? i18next.t('agent-chat:work.omitted.binary') : i18next.t('agent-chat:work.omitted.tooLarge');
@@ -9,7 +9,7 @@ import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows.js';
9
9
  import { useChatScope } from '../../../scope.js';
10
10
  import { Icon, IconButton } from '@adecore/ui';
11
11
  import { useChatActions } from '../../actions.js';
12
- import { chatHost } from '../../../host.js';
12
+ import { useChatHost } from '../../../host.js';
13
13
  function AgentLine({ view, onOpen }) {
14
14
  const { agent, state } = view;
15
15
  const time = workflowAgentTime(view);
@@ -25,6 +25,7 @@ function PhaseBlock({ phase, onOpen }) {
25
25
  }
26
26
  // Keep background progress visible after the launcher turn ends.
27
27
  export function WorkflowRow({ tool, workflow, chatId, onOpenAgent }) {
28
+ const host = useChatHost();
28
29
  const { t } = useTranslation('agent-chat');
29
30
  const { id } = useChatScope();
30
31
  // A host that does not answer `chat.subagent` has no conversation to open for anyone.
@@ -36,7 +37,7 @@ export function WorkflowRow({ tool, workflow, chatId, onOpenAgent }) {
36
37
  const stop = () => {
37
38
  if (chatId && workflow.taskId) {
38
39
  void actions.stopTask(chatId, workflow.taskId).catch((error) => {
39
- chatHost().notify({
40
+ host.notify({
40
41
  kind: 'error',
41
42
  title: t('activity.stopFailed'),
42
43
  description: error instanceof Error ? error.message : t('subagents.noAnswer')
@@ -0,0 +1 @@
1
+ export declare const TIMESTAMP_FORMAT: Intl.DateTimeFormatOptions;
@@ -0,0 +1,2 @@
1
+ /* The full date and time a row's time names on its tooltip. */
2
+ export const TIMESTAMP_FORMAT = { dateStyle: 'full', timeStyle: 'medium' };
@@ -1,13 +1,14 @@
1
1
  import { useLayoutEffect, useMemo } from 'react';
2
2
  import { diffSyntaxDocument } from '@adecore/editor-react';
3
- import { diffSourceTokens } from './diff-syntax.js';
3
+ import { useChatHost } from '../../host.js';
4
+ import { diffSourceTokens, diffSyntaxRuntime } from './diff-syntax.js';
4
5
  function createSourceBinding(document, language, theme, runtime) {
5
6
  const mapping = diffSyntaxDocument(document, language, theme);
6
7
  const listeners = new Set();
7
8
  let source;
8
9
  const current = () => {
9
10
  if (source === undefined) {
10
- source = diffSourceTokens(document, mapping, runtime);
11
+ source = diffSourceTokens(document, mapping, runtime());
11
12
  source.subscribe(() => {
12
13
  for (const listener of [...listeners]) {
13
14
  listener();
@@ -33,8 +34,10 @@ function createSourceBinding(document, language, theme, runtime) {
33
34
  }
34
35
  };
35
36
  }
37
+ /* Without a `runtime`, the shared one of the host's `code`. */
36
38
  export function useDiffSourceTokens(document, language, theme, runtime) {
37
- const binding = useMemo(() => createSourceBinding(document, language, theme, runtime), [document, language, theme, runtime]);
39
+ const { code } = useChatHost();
40
+ const binding = useMemo(() => createSourceBinding(document, language, theme, () => runtime ?? diffSyntaxRuntime(code)), [document, language, theme, runtime, code]);
38
41
  useLayoutEffect(() => () => binding.release(), [binding]);
39
42
  return binding.tokens;
40
43
  }
@@ -1,6 +1,6 @@
1
1
  import { useLayoutEffect, useState } from 'react';
2
2
  import { cleanVisualVariables } from '@adecore/agent-contracts/visual';
3
- import { chatHost } from '../../host.js';
3
+ import { useChatHost } from '../../host.js';
4
4
  /*
5
5
  * A page's theme from the app's tokens. The names follow common component themes, where `--accent`
6
6
  * is a quiet hover ground and `--primary` the color that stands out, so the app's accent is the
@@ -142,7 +142,8 @@ const THEME_ATTRIBUTES = ['class', 'style', 'data-theme'];
142
142
  * accent or a font a person picks reaches every frame as well.
143
143
  */
144
144
  export function useVisualTheme(ref) {
145
- const mode = chatHost().code.useMode();
145
+ const host = useChatHost();
146
+ const mode = host.code.useMode();
146
147
  const [theme, setTheme] = useState(null);
147
148
  useLayoutEffect(() => {
148
149
  const element = ref.current;
package/dist/host.d.ts CHANGED
@@ -1,14 +1,13 @@
1
- import type { ComponentProps, ComponentType, ReactNode, RefObject } from 'react';
1
+ import { type ComponentProps, type ComponentType, type ReactNode, type RefObject } from 'react';
2
2
  import type { Extension } from '@codemirror/state';
3
3
  import type { EditorView } from '@codemirror/view';
4
4
  import type { Highlighter, ThemeRegistration } from 'shiki';
5
5
  import type { EditorEngine } from '@adecore/editor';
6
- import type { AgentKind, ChatCheckpointDiff, ChatConfigurePayload, ChatItem, ChatSubagentItem, ChatUiChoicePayload, ChatUiQueryPayload, ChatUiQueryReading, ChatUiLinkPayload, ChatUiLinkReading } from '@adecore/agent-contracts';
6
+ import type { AgentKind, ChatCheckpointDiff, ChatConfigurePayload, ChatGoalAction, ChatItem, ChatSubagentItem, ChatUiChoicePayload, ChatUiQueryPayload, ChatUiQueryReading, ChatUiLinkPayload, ChatUiLinkReading } from '@adecore/agent-contracts';
7
7
  import type { TimelineRow } from './chat/logic/timeline.js';
8
8
  import type { FindReveal } from './chat/ui/find-reveal.js';
9
9
  import type { PromptAction } from './prompts/logic/prompts.js';
10
10
  import type { HostPrompt, PromptViewProps } from './prompts/logic/subjects.js';
11
- import { type ChatStorageOptions } from './storage.js';
12
11
  export interface AccentChoice {
13
12
  id: string;
14
13
  color: string;
@@ -34,6 +33,7 @@ export interface ChatActions {
34
33
  turnDiff(chatId: string, turnId: string): Promise<ChatCheckpointDiff | null>;
35
34
  stopSubagent(chatId: string, toolUseId: string): Promise<void>;
36
35
  stopTask(chatId: string, taskId: string): Promise<void>;
36
+ goal?(chatId: string, action: ChatGoalAction): Promise<void>;
37
37
  approve(chatId: string, requestId: string, decision: 'allow' | 'allow-always' | 'deny', message?: string): Promise<void>;
38
38
  answer(chatId: string, requestId: string, answers: Record<string, string>): Promise<void>;
39
39
  dismiss(chatId: string, itemId: string): Promise<void>;
@@ -126,7 +126,6 @@ export interface ReplyAuthor {
126
126
  mark?: ReactNode;
127
127
  }
128
128
  export interface ChatHost {
129
- storage?: ChatStorageOptions;
130
129
  intelligentUi?: {
131
130
  subscribe?(scopeId: string, chatId: string, changed: () => void): () => void;
132
131
  link?(scopeId: string, payload: ChatUiLinkPayload): Promise<ChatUiLinkReading>;
@@ -215,6 +214,7 @@ export interface ChatHost {
215
214
  stopTask(scopeId: string, childId: string, title: string, run: () => void): void;
216
215
  };
217
216
  fork: ((chatId: string, turnId: string) => void) | null;
217
+ openNewChat: ((scopeId: string, chatId: string) => void) | null;
218
218
  openSettings(section: 'providers' | 'agents'): void;
219
219
  useResumeAtReset(scopeId: string): boolean;
220
220
  useComposerPlaceholder(scopeId: string, chatId: string): string | null;
@@ -224,5 +224,8 @@ export interface ChatHost {
224
224
  useReplyAuthor(scopeId: string, chatId: string): ReplyAuthor | null;
225
225
  visuals: VisualHost | null;
226
226
  }
227
- export declare function setChatHost(patch: Partial<ChatHost>): void;
228
- export declare function chatHost(): ChatHost;
227
+ export declare function ChatHostProvider({ host, children }: {
228
+ host: Partial<ChatHost>;
229
+ children?: ReactNode;
230
+ }): import("react").FunctionComponentElement<import("react").ProviderProps<ChatHost>>;
231
+ export declare function useChatHost(): ChatHost;
package/dist/host.js CHANGED
@@ -1,6 +1,6 @@
1
+ import { createContext, createElement, useContext, useState } from 'react';
1
2
  import { isApplePlatform } from '@adecore/ui';
2
3
  import { PlainTextarea } from './ui/PlainTextarea.js';
3
- import { configureChatStorage } from './storage.js';
4
4
  const NO_PROMPTS = [];
5
5
  const NO_CHATS = [];
6
6
  const NO_ROWS = [];
@@ -37,6 +37,7 @@ const DEFAULT_HOST = {
37
37
  tasks: { useTasks: () => undefined, useTask: () => null },
38
38
  confirm: { stopSubagents: (_scopeId, _chatId, run) => run(), stopTask: (_scopeId, _childId, _title, run) => run() },
39
39
  fork: null,
40
+ openNewChat: null,
40
41
  openSettings: () => undefined,
41
42
  useResumeAtReset: () => true,
42
43
  useComposerPlaceholder: () => null,
@@ -46,13 +47,23 @@ const DEFAULT_HOST = {
46
47
  useReplyAuthor: () => null,
47
48
  visuals: null
48
49
  };
49
- let host = DEFAULT_HOST;
50
- export function setChatHost(patch) {
51
- if (patch.storage !== undefined) {
52
- configureChatStorage(patch.storage);
50
+ const ChatHostContext = createContext(DEFAULT_HOST);
51
+ /*
52
+ * Hands the views under it a host: `host` over the one of a provider above it, member by member, and
53
+ * over the defaults at the top. A part of an app that loads later and adds hooks renders a provider of
54
+ * its own around what it draws, so every view under it calls the same hooks from its first render on.
55
+ * The host is read once, as the provider mounts, since a hook that changed under a mounted view would
56
+ * break the order of its hooks: a provider that gets another `host` throws, and a new `key` remounts it.
57
+ */
58
+ export function ChatHostProvider({ host, children }) {
59
+ const parent = useContext(ChatHostContext);
60
+ const [pinned] = useState(() => ({ host, value: { ...parent, ...host } }));
61
+ if (pinned.host !== host) {
62
+ throw new Error('A ChatHostProvider reads its host once: hand it the same object on every render, or a new key to mount it with another');
53
63
  }
54
- host = { ...host, ...patch };
64
+ return createElement(ChatHostContext.Provider, { value: pinned.value }, children);
55
65
  }
56
- export function chatHost() {
57
- return host;
66
+ /* The host of the nearest `ChatHostProvider`, or the defaults outside one. */
67
+ export function useChatHost() {
68
+ return useContext(ChatHostContext);
58
69
  }
@@ -0,0 +1,8 @@
1
+ export { type ChatActions, type FileRef, type ShellCodeBlockContext, type ChatPlace, type SubagentTask, type TimelineFindOptions, type TimelineFind, type ComposerDictationProps, type ComposerSlotProps, type SubagentSlotProps, type ThreadCard, type VisualHost, type ReplyAuthor, type ChatHost, ChatHostProvider, useChatHost, type AccentChoice, type ChatToast, type TextareaProps, type ResourceUrl } from './host.js';
2
+ export { type ChatScope, ChatScopeContext, useChatScope } from './scope.js';
3
+ export { type ChatRequestMap, type ChatEventMap, type ChatTransportStatus, type ChatTransport, ChatTransportError, errorCode, isConnectionError } from './transport.js';
4
+ export { portTransport, type PortTransport } from './port-transport.js';
5
+ export { onChatStorageConfiguration, configureChatStorage, chatStorageKey, chatStorageLegacyKeys, chatStorageAdapter, hydrateChatStorage, createChatStore, type ChatStorageRecord, type ChatStorageAdapter, type ChatStorageOptions } from './storage.js';
6
+ export { setLazyPrefetch, onLazyOpenError } from './lazy.js';
7
+ export { type MountedEntry, MountedRegistry } from './mounted-registry.js';
8
+ export { type AgentsSettingsSection, PROVIDERS_SECTION, USAGE_SECTION, settingsSection } from './settings/sections.js';
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // Public API: exports.test.ts snapshots this list, so a name added or dropped here is an API change.
2
+ export { ChatHostProvider, useChatHost } from './host.js';
3
+ export { ChatScopeContext, useChatScope } from './scope.js';
4
+ export { ChatTransportError, errorCode, isConnectionError } from './transport.js';
5
+ export { portTransport } from './port-transport.js';
6
+ export { onChatStorageConfiguration, configureChatStorage, chatStorageKey, chatStorageLegacyKeys, chatStorageAdapter, hydrateChatStorage, createChatStore } from './storage.js';
7
+ export { setLazyPrefetch, onLazyOpenError } from './lazy.js';
8
+ export { MountedRegistry } from './mounted-registry.js';
9
+ export { PROVIDERS_SECTION, USAGE_SECTION, settingsSection } from './settings/sections.js';