@adecore/agents-react 0.0.1 → 0.17.0-beta.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 (513) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +53 -0
  3. package/dist/agents/AccountDot.d.ts +4 -0
  4. package/dist/agents/AccountDot.js +8 -0
  5. package/dist/agents/AgentIcon.d.ts +6 -0
  6. package/dist/agents/AgentIcon.js +20 -0
  7. package/dist/agents/ModelOptionControl.d.ts +15 -0
  8. package/dist/agents/ModelOptionControl.js +33 -0
  9. package/dist/agents/ProviderLogo.d.ts +8 -0
  10. package/dist/agents/ProviderLogo.js +8 -0
  11. package/dist/agents/account-limits.d.ts +7 -0
  12. package/dist/agents/account-limits.js +40 -0
  13. package/dist/agents/accounts.d.ts +22 -0
  14. package/dist/agents/accounts.js +113 -0
  15. package/dist/agents/model-name.d.ts +12 -0
  16. package/dist/agents/model-name.js +56 -0
  17. package/dist/agents/model-options.d.ts +5 -0
  18. package/dist/agents/model-options.js +15 -0
  19. package/dist/agents/provider-paths.d.ts +2 -0
  20. package/dist/agents/provider-paths.js +8 -0
  21. package/dist/agents/status-look.d.ts +13 -0
  22. package/dist/agents/status-look.js +24 -0
  23. package/dist/chat/account-choice.d.ts +11 -0
  24. package/dist/chat/account-choice.js +30 -0
  25. package/dist/chat/actions.d.ts +6 -0
  26. package/dist/chat/actions.js +68 -0
  27. package/dist/chat/activity.d.ts +5 -0
  28. package/dist/chat/activity.js +6 -0
  29. package/dist/chat/attachments.d.ts +23 -0
  30. package/dist/chat/attachments.js +86 -0
  31. package/dist/chat/bookmarks.d.ts +14 -0
  32. package/dist/chat/bookmarks.js +73 -0
  33. package/dist/chat/chat-client.d.ts +55 -0
  34. package/dist/chat/chat-client.js +279 -0
  35. package/dist/chat/chat-references.d.ts +5 -0
  36. package/dist/chat/chat-references.js +5 -0
  37. package/dist/chat/drafts.d.ts +29 -0
  38. package/dist/chat/drafts.js +116 -0
  39. package/dist/chat/forks.d.ts +2 -0
  40. package/dist/chat/forks.js +28 -0
  41. package/dist/chat/guards.d.ts +12 -0
  42. package/dist/chat/guards.js +69 -0
  43. package/dist/chat/logic/ansi.d.ts +13 -0
  44. package/dist/chat/logic/ansi.js +185 -0
  45. package/dist/chat/logic/answers.d.ts +1 -0
  46. package/dist/chat/logic/answers.js +8 -0
  47. package/dist/chat/logic/bookmarks.d.ts +5 -0
  48. package/dist/chat/logic/bookmarks.js +33 -0
  49. package/dist/chat/logic/context-usage.d.ts +12 -0
  50. package/dist/chat/logic/context-usage.js +21 -0
  51. package/dist/chat/logic/fork.d.ts +45 -0
  52. package/dist/chat/logic/fork.js +148 -0
  53. package/dist/chat/logic/handback.d.ts +2 -0
  54. package/dist/chat/logic/handback.js +8 -0
  55. package/dist/chat/logic/json.d.ts +1 -0
  56. package/dist/chat/logic/json.js +4 -0
  57. package/dist/chat/logic/limit.d.ts +7 -0
  58. package/dist/chat/logic/limit.js +34 -0
  59. package/dist/chat/logic/resume-compaction.d.ts +14 -0
  60. package/dist/chat/logic/resume-compaction.js +47 -0
  61. package/dist/chat/logic/scrubber.d.ts +50 -0
  62. package/dist/chat/logic/scrubber.js +220 -0
  63. package/dist/chat/logic/thread-cards.d.ts +3 -0
  64. package/dist/chat/logic/thread-cards.js +59 -0
  65. package/dist/chat/logic/timeline-copy.d.ts +4 -0
  66. package/dist/chat/logic/timeline-copy.js +59 -0
  67. package/dist/chat/logic/timeline-target.d.ts +12 -0
  68. package/dist/chat/logic/timeline-target.js +34 -0
  69. package/dist/chat/logic/timeline.d.ts +115 -0
  70. package/dist/chat/logic/timeline.js +343 -0
  71. package/dist/chat/logic/tool-catalog.d.ts +10 -0
  72. package/dist/chat/logic/tool-catalog.js +44 -0
  73. package/dist/chat/logic/tools.d.ts +15 -0
  74. package/dist/chat/logic/tools.js +82 -0
  75. package/dist/chat/logic/welcome.d.ts +2 -0
  76. package/dist/chat/logic/welcome.js +10 -0
  77. package/dist/chat/logic/workflow.d.ts +14 -0
  78. package/dist/chat/logic/workflow.js +47 -0
  79. package/dist/chat/mentions.d.ts +65 -0
  80. package/dist/chat/mentions.js +184 -0
  81. package/dist/chat/persisted-json.d.ts +5 -0
  82. package/dist/chat/persisted-json.js +58 -0
  83. package/dist/chat/preferences.d.ts +27 -0
  84. package/dist/chat/preferences.js +139 -0
  85. package/dist/chat/quote.d.ts +2 -0
  86. package/dist/chat/quote.js +25 -0
  87. package/dist/chat/recent-messages.d.ts +17 -0
  88. package/dist/chat/recent-messages.js +36 -0
  89. package/dist/chat/resume-compaction-dismissals.d.ts +3 -0
  90. package/dist/chat/resume-compaction-dismissals.js +14 -0
  91. package/dist/chat/runtime-modes.d.ts +4 -0
  92. package/dist/chat/runtime-modes.js +15 -0
  93. package/dist/chat/stash.d.ts +24 -0
  94. package/dist/chat/stash.js +91 -0
  95. package/dist/chat/subagent-conversation.d.ts +41 -0
  96. package/dist/chat/subagent-conversation.js +167 -0
  97. package/dist/chat/subagent-list.d.ts +19 -0
  98. package/dist/chat/subagent-list.js +106 -0
  99. package/dist/chat/subagent-support.d.ts +6 -0
  100. package/dist/chat/subagent-support.js +14 -0
  101. package/dist/chat/subagent-view.d.ts +35 -0
  102. package/dist/chat/subagent-view.js +96 -0
  103. package/dist/chat/thumbnails.d.ts +10 -0
  104. package/dist/chat/thumbnails.js +89 -0
  105. package/dist/chat/timeline-flash.d.ts +12 -0
  106. package/dist/chat/timeline-flash.js +16 -0
  107. package/dist/chat/timeline-scroll.d.ts +27 -0
  108. package/dist/chat/timeline-scroll.js +152 -0
  109. package/dist/chat/ui/AccountPill.d.ts +3 -0
  110. package/dist/chat/ui/AccountPill.js +23 -0
  111. package/dist/chat/ui/AnsiOutput.d.ts +5 -0
  112. package/dist/chat/ui/AnsiOutput.js +9 -0
  113. package/dist/chat/ui/BookmarkMarker.d.ts +8 -0
  114. package/dist/chat/ui/BookmarkMarker.js +57 -0
  115. package/dist/chat/ui/BookmarkSubmenu.d.ts +3 -0
  116. package/dist/chat/ui/BookmarkSubmenu.js +33 -0
  117. package/dist/chat/ui/ChatActivity.d.ts +7 -0
  118. package/dist/chat/ui/ChatActivity.js +84 -0
  119. package/dist/chat/ui/ChatReferenceChip.d.ts +4 -0
  120. package/dist/chat/ui/ChatReferenceChip.js +16 -0
  121. package/dist/chat/ui/CodeBlock.d.ts +4 -0
  122. package/dist/chat/ui/CodeBlock.js +132 -0
  123. package/dist/chat/ui/Composer.d.ts +15 -0
  124. package/dist/chat/ui/Composer.js +856 -0
  125. package/dist/chat/ui/ComposerInput.d.ts +29 -0
  126. package/dist/chat/ui/ComposerInput.js +127 -0
  127. package/dist/chat/ui/DiffPool.d.ts +5 -0
  128. package/dist/chat/ui/DiffPool.js +26 -0
  129. package/dist/chat/ui/EditDiff.d.ts +4 -0
  130. package/dist/chat/ui/EditDiff.js +21 -0
  131. package/dist/chat/ui/FadingWords.d.ts +3 -0
  132. package/dist/chat/ui/FadingWords.js +5 -0
  133. package/dist/chat/ui/ImageView.d.ts +6 -0
  134. package/dist/chat/ui/ImageView.js +81 -0
  135. package/dist/chat/ui/LimitState.d.ts +8 -0
  136. package/dist/chat/ui/LimitState.js +112 -0
  137. package/dist/chat/ui/Markdown.d.ts +18 -0
  138. package/dist/chat/ui/Markdown.js +159 -0
  139. package/dist/chat/ui/MessageActions.d.ts +9 -0
  140. package/dist/chat/ui/MessageActions.js +53 -0
  141. package/dist/chat/ui/Pickers.d.ts +21 -0
  142. package/dist/chat/ui/Pickers.js +111 -0
  143. package/dist/chat/ui/PromptComposer.d.ts +13 -0
  144. package/dist/chat/ui/PromptComposer.js +56 -0
  145. package/dist/chat/ui/QuoteButton.d.ts +7 -0
  146. package/dist/chat/ui/QuoteButton.js +74 -0
  147. package/dist/chat/ui/ResumeCompactionDock.d.ts +5 -0
  148. package/dist/chat/ui/ResumeCompactionDock.js +14 -0
  149. package/dist/chat/ui/RunSettings.d.ts +28 -0
  150. package/dist/chat/ui/RunSettings.js +153 -0
  151. package/dist/chat/ui/Scrubber.d.ts +17 -0
  152. package/dist/chat/ui/Scrubber.js +118 -0
  153. package/dist/chat/ui/SubagentControls.d.ts +11 -0
  154. package/dist/chat/ui/SubagentControls.js +36 -0
  155. package/dist/chat/ui/SubagentInfo.d.ts +4 -0
  156. package/dist/chat/ui/SubagentInfo.js +34 -0
  157. package/dist/chat/ui/SubagentStopButton.d.ts +7 -0
  158. package/dist/chat/ui/SubagentStopButton.js +34 -0
  159. package/dist/chat/ui/SubagentTimeline.d.ts +4 -0
  160. package/dist/chat/ui/SubagentTimeline.js +107 -0
  161. package/dist/chat/ui/Timeline.d.ts +6 -0
  162. package/dist/chat/ui/Timeline.js +424 -0
  163. package/dist/chat/ui/TimelineMenu.d.ts +12 -0
  164. package/dist/chat/ui/TimelineMenu.js +54 -0
  165. package/dist/chat/ui/UnifiedDiff.d.ts +11 -0
  166. package/dist/chat/ui/UnifiedDiff.js +66 -0
  167. package/dist/chat/ui/UploadThumb.d.ts +4 -0
  168. package/dist/chat/ui/UploadThumb.js +11 -0
  169. package/dist/chat/ui/Welcome.d.ts +4 -0
  170. package/dist/chat/ui/Welcome.js +16 -0
  171. package/dist/chat/ui/chips.d.ts +4 -0
  172. package/dist/chat/ui/chips.js +11 -0
  173. package/dist/chat/ui/code-lines.d.ts +18 -0
  174. package/dist/chat/ui/code-lines.js +46 -0
  175. package/dist/chat/ui/code-streaming.d.ts +1 -0
  176. package/dist/chat/ui/code-streaming.js +3 -0
  177. package/dist/chat/ui/code-theme.d.ts +3 -0
  178. package/dist/chat/ui/code-theme.js +12 -0
  179. package/dist/chat/ui/composer/chips.d.ts +6 -0
  180. package/dist/chat/ui/composer/chips.js +31 -0
  181. package/dist/chat/ui/composer/editor.d.ts +11 -0
  182. package/dist/chat/ui/composer/editor.js +98 -0
  183. package/dist/chat/ui/composer/insert.d.ts +2 -0
  184. package/dist/chat/ui/composer/insert.js +19 -0
  185. package/dist/chat/ui/composer/keys.d.ts +30 -0
  186. package/dist/chat/ui/composer/keys.js +100 -0
  187. package/dist/chat/ui/diff-theme.d.ts +2 -0
  188. package/dist/chat/ui/diff-theme.js +20 -0
  189. package/dist/chat/ui/file-links.d.ts +5 -0
  190. package/dist/chat/ui/file-links.js +20 -0
  191. package/dist/chat/ui/find-reveal.d.ts +7 -0
  192. package/dist/chat/ui/find-reveal.js +13 -0
  193. package/dist/chat/ui/full-diff.d.ts +6 -0
  194. package/dist/chat/ui/full-diff.js +19 -0
  195. package/dist/chat/ui/icons.d.ts +4 -0
  196. package/dist/chat/ui/icons.js +20 -0
  197. package/dist/chat/ui/markdown-blocks.d.ts +6 -0
  198. package/dist/chat/ui/markdown-blocks.js +103 -0
  199. package/dist/chat/ui/quote-selection.d.ts +3 -0
  200. package/dist/chat/ui/quote-selection.js +46 -0
  201. package/dist/chat/ui/rehype-chips.d.ts +23 -0
  202. package/dist/chat/ui/rehype-chips.js +32 -0
  203. package/dist/chat/ui/rehype-fade.d.ts +23 -0
  204. package/dist/chat/ui/rehype-fade.js +36 -0
  205. package/dist/chat/ui/remark-html-as-text.d.ts +8 -0
  206. package/dist/chat/ui/remark-html-as-text.js +26 -0
  207. package/dist/chat/ui/reply-context.d.ts +5 -0
  208. package/dist/chat/ui/reply-context.js +2 -0
  209. package/dist/chat/ui/reveal.d.ts +13 -0
  210. package/dist/chat/ui/reveal.js +114 -0
  211. package/dist/chat/ui/rows/ForksRow.d.ts +4 -0
  212. package/dist/chat/ui/rows/ForksRow.js +38 -0
  213. package/dist/chat/ui/rows/MessageRows.d.ts +40 -0
  214. package/dist/chat/ui/rows/MessageRows.js +204 -0
  215. package/dist/chat/ui/rows/Rows.d.ts +12 -0
  216. package/dist/chat/ui/rows/Rows.js +61 -0
  217. package/dist/chat/ui/rows/SubagentRow.d.ts +17 -0
  218. package/dist/chat/ui/rows/SubagentRow.js +101 -0
  219. package/dist/chat/ui/rows/TaskRow.d.ts +8 -0
  220. package/dist/chat/ui/rows/TaskRow.js +63 -0
  221. package/dist/chat/ui/rows/WorkRows.d.ts +47 -0
  222. package/dist/chat/ui/rows/WorkRows.js +168 -0
  223. package/dist/chat/ui/rows/WorkflowRow.d.ts +8 -0
  224. package/dist/chat/ui/rows/WorkflowRow.js +48 -0
  225. package/dist/chat/ui/rows/row-rhythm.d.ts +6 -0
  226. package/dist/chat/ui/rows/row-rhythm.js +34 -0
  227. package/dist/chat/ui/useToggleSet.d.ts +6 -0
  228. package/dist/chat/ui/useToggleSet.js +25 -0
  229. package/dist/host.d.ts +195 -0
  230. package/dist/host.js +55 -0
  231. package/dist/lazy.d.ts +6 -0
  232. package/dist/lazy.js +57 -0
  233. package/dist/locales/en/agent-chat.json +446 -0
  234. package/dist/locales/en/agent-prompts.json +42 -0
  235. package/dist/locales/en/agent-providers.json +131 -0
  236. package/dist/locales/en/agent-usage.json +131 -0
  237. package/dist/locales/nl/agent-chat.json +446 -0
  238. package/dist/locales/nl/agent-prompts.json +42 -0
  239. package/dist/locales/nl/agent-providers.json +131 -0
  240. package/dist/locales/nl/agent-usage.json +131 -0
  241. package/dist/locales.d.ts +5 -0
  242. package/dist/locales.js +20 -0
  243. package/dist/mounted-registry.d.ts +7 -0
  244. package/dist/mounted-registry.js +39 -0
  245. package/dist/port-transport.d.ts +6 -0
  246. package/dist/port-transport.js +129 -0
  247. package/dist/prompts/logic/focus.d.ts +2 -0
  248. package/dist/prompts/logic/focus.js +23 -0
  249. package/dist/prompts/logic/keys.d.ts +42 -0
  250. package/dist/prompts/logic/keys.js +94 -0
  251. package/dist/prompts/logic/prompts.d.ts +34 -0
  252. package/dist/prompts/logic/prompts.fixtures.d.ts +5 -0
  253. package/dist/prompts/logic/prompts.fixtures.js +79 -0
  254. package/dist/prompts/logic/prompts.js +32 -0
  255. package/dist/prompts/logic/subjects.d.ts +50 -0
  256. package/dist/prompts/logic/subjects.js +63 -0
  257. package/dist/prompts/logic/useFocusAfterAnswer.d.ts +6 -0
  258. package/dist/prompts/logic/useFocusAfterAnswer.js +28 -0
  259. package/dist/prompts/logic/usePromptSession.d.ts +24 -0
  260. package/dist/prompts/logic/usePromptSession.js +87 -0
  261. package/dist/prompts/ui/ApprovalBody.d.ts +13 -0
  262. package/dist/prompts/ui/ApprovalBody.js +34 -0
  263. package/dist/prompts/ui/PromptActions.d.ts +27 -0
  264. package/dist/prompts/ui/PromptActions.js +18 -0
  265. package/dist/prompts/ui/PromptCard.d.ts +16 -0
  266. package/dist/prompts/ui/PromptCard.js +50 -0
  267. package/dist/prompts/ui/PromptView.d.ts +2 -0
  268. package/dist/prompts/ui/PromptView.js +47 -0
  269. package/dist/prompts/ui/QuestionBody.d.ts +9 -0
  270. package/dist/prompts/ui/QuestionBody.js +87 -0
  271. package/dist/providers/AccountColors.d.ts +5 -0
  272. package/dist/providers/AccountColors.js +8 -0
  273. package/dist/providers/AccountDetail.d.ts +12 -0
  274. package/dist/providers/AccountDetail.js +69 -0
  275. package/dist/providers/AccountVariables.d.ts +8 -0
  276. package/dist/providers/AccountVariables.js +43 -0
  277. package/dist/providers/AddAccountForm.d.ts +10 -0
  278. package/dist/providers/AddAccountForm.js +54 -0
  279. package/dist/providers/CliDetail.d.ts +12 -0
  280. package/dist/providers/CliDetail.js +54 -0
  281. package/dist/providers/ProvidersPane.d.ts +9 -0
  282. package/dist/providers/ProvidersPane.js +86 -0
  283. package/dist/providers/account-actions.d.ts +7 -0
  284. package/dist/providers/account-actions.js +57 -0
  285. package/dist/providers/parts.d.ts +9 -0
  286. package/dist/providers/parts.js +18 -0
  287. package/dist/providers/provider-abilities.d.ts +2 -0
  288. package/dist/providers/provider-abilities.js +7 -0
  289. package/dist/providers/variables.d.ts +13 -0
  290. package/dist/providers/variables.js +63 -0
  291. package/dist/scope.d.ts +11 -0
  292. package/dist/scope.js +10 -0
  293. package/dist/settings/sections.d.ts +13 -0
  294. package/dist/settings/sections.js +32 -0
  295. package/dist/state/chats.d.ts +44 -0
  296. package/dist/state/chats.js +199 -0
  297. package/dist/state/provider-accounts.d.ts +17 -0
  298. package/dist/state/provider-accounts.js +67 -0
  299. package/dist/state/providers.d.ts +17 -0
  300. package/dist/state/providers.js +33 -0
  301. package/dist/state/usage.d.ts +44 -0
  302. package/dist/state/usage.js +121 -0
  303. package/dist/storage.d.ts +20 -0
  304. package/dist/storage.js +89 -0
  305. package/dist/theme.css +196 -0
  306. package/dist/transport.d.ts +24 -0
  307. package/dist/transport.js +18 -0
  308. package/dist/ui/PlainTextarea.d.ts +2 -0
  309. package/dist/ui/PlainTextarea.js +5 -0
  310. package/dist/usage/LimitsList.d.ts +18 -0
  311. package/dist/usage/LimitsList.js +73 -0
  312. package/dist/usage/UsageBreakdown.d.ts +9 -0
  313. package/dist/usage/UsageBreakdown.js +67 -0
  314. package/dist/usage/UsageChart.d.ts +10 -0
  315. package/dist/usage/UsageChart.js +47 -0
  316. package/dist/usage/UsageDialog.d.ts +6 -0
  317. package/dist/usage/UsageDialog.js +12 -0
  318. package/dist/usage/UsageLimits.d.ts +1 -0
  319. package/dist/usage/UsageLimits.js +57 -0
  320. package/dist/usage/UsageLimitsCard.d.ts +4 -0
  321. package/dist/usage/UsageLimitsCard.js +26 -0
  322. package/dist/usage/UsagePage.d.ts +7 -0
  323. package/dist/usage/UsagePage.js +154 -0
  324. package/dist/usage/UsagePane.d.ts +3 -0
  325. package/dist/usage/UsagePane.js +21 -0
  326. package/dist/usage/UsageSummary.d.ts +12 -0
  327. package/dist/usage/UsageSummary.js +15 -0
  328. package/dist/usage/UsageTiles.d.ts +7 -0
  329. package/dist/usage/UsageTiles.js +19 -0
  330. package/dist/usage/format.d.ts +13 -0
  331. package/dist/usage/format.js +55 -0
  332. package/dist/usage/limit-groups.d.ts +22 -0
  333. package/dist/usage/limit-groups.js +86 -0
  334. package/dist/usage/limits.d.ts +4 -0
  335. package/dist/usage/limits.js +58 -0
  336. package/dist/usage/money.d.ts +1 -0
  337. package/dist/usage/money.js +13 -0
  338. package/dist/usage/summary.d.ts +34 -0
  339. package/dist/usage/summary.js +94 -0
  340. package/package.json +895 -3
  341. package/src/agents/AccountDot.tsx +14 -0
  342. package/src/agents/AgentIcon.tsx +26 -0
  343. package/src/agents/ModelOptionControl.tsx +68 -0
  344. package/src/agents/ProviderLogo.tsx +20 -0
  345. package/src/agents/account-limits.ts +61 -0
  346. package/src/agents/accounts.ts +137 -0
  347. package/src/agents/model-name.ts +70 -0
  348. package/src/agents/model-options.ts +21 -0
  349. package/src/agents/provider-paths.ts +10 -0
  350. package/src/agents/status-look.ts +43 -0
  351. package/src/chat/account-choice.ts +44 -0
  352. package/src/chat/actions.ts +72 -0
  353. package/src/chat/activity.ts +8 -0
  354. package/src/chat/attachments.ts +118 -0
  355. package/src/chat/bookmarks.ts +87 -0
  356. package/src/chat/chat-client.ts +345 -0
  357. package/src/chat/chat-references.ts +11 -0
  358. package/src/chat/drafts.ts +165 -0
  359. package/src/chat/forks.ts +33 -0
  360. package/src/chat/guards.ts +84 -0
  361. package/src/chat/logic/ansi.ts +206 -0
  362. package/src/chat/logic/answers.ts +8 -0
  363. package/src/chat/logic/bookmarks.ts +42 -0
  364. package/src/chat/logic/context-usage.ts +36 -0
  365. package/src/chat/logic/fork.ts +200 -0
  366. package/src/chat/logic/handback.ts +10 -0
  367. package/src/chat/logic/json.ts +4 -0
  368. package/src/chat/logic/limit.ts +46 -0
  369. package/src/chat/logic/resume-compaction.ts +71 -0
  370. package/src/chat/logic/scrubber.ts +289 -0
  371. package/src/chat/logic/thread-cards.ts +64 -0
  372. package/src/chat/logic/timeline-copy.ts +65 -0
  373. package/src/chat/logic/timeline-target.ts +52 -0
  374. package/src/chat/logic/timeline.ts +419 -0
  375. package/src/chat/logic/tool-catalog.ts +62 -0
  376. package/src/chat/logic/tools.ts +102 -0
  377. package/src/chat/logic/welcome.ts +13 -0
  378. package/src/chat/logic/workflow.ts +66 -0
  379. package/src/chat/mentions.ts +232 -0
  380. package/src/chat/persisted-json.ts +67 -0
  381. package/src/chat/preferences.ts +179 -0
  382. package/src/chat/quote.ts +26 -0
  383. package/src/chat/recent-messages.ts +59 -0
  384. package/src/chat/resume-compaction-dismissals.ts +17 -0
  385. package/src/chat/runtime-modes.ts +18 -0
  386. package/src/chat/stash.ts +122 -0
  387. package/src/chat/subagent-conversation.ts +203 -0
  388. package/src/chat/subagent-list.ts +141 -0
  389. package/src/chat/subagent-support.ts +21 -0
  390. package/src/chat/subagent-view.ts +137 -0
  391. package/src/chat/thumbnails.ts +108 -0
  392. package/src/chat/timeline-flash.ts +33 -0
  393. package/src/chat/timeline-scroll.ts +199 -0
  394. package/src/chat/ui/AccountPill.tsx +31 -0
  395. package/src/chat/ui/AnsiOutput.tsx +18 -0
  396. package/src/chat/ui/BookmarkMarker.tsx +108 -0
  397. package/src/chat/ui/BookmarkSubmenu.tsx +53 -0
  398. package/src/chat/ui/ChatActivity.tsx +198 -0
  399. package/src/chat/ui/ChatReferenceChip.tsx +28 -0
  400. package/src/chat/ui/CodeBlock.tsx +175 -0
  401. package/src/chat/ui/Composer.tsx +1326 -0
  402. package/src/chat/ui/ComposerInput.tsx +187 -0
  403. package/src/chat/ui/DiffPool.tsx +36 -0
  404. package/src/chat/ui/EditDiff.tsx +30 -0
  405. package/src/chat/ui/FadingWords.tsx +18 -0
  406. package/src/chat/ui/ImageView.tsx +159 -0
  407. package/src/chat/ui/LimitState.tsx +165 -0
  408. package/src/chat/ui/Markdown.tsx +258 -0
  409. package/src/chat/ui/MessageActions.tsx +88 -0
  410. package/src/chat/ui/Pickers.tsx +272 -0
  411. package/src/chat/ui/PromptComposer.tsx +119 -0
  412. package/src/chat/ui/QuoteButton.tsx +103 -0
  413. package/src/chat/ui/ResumeCompactionDock.tsx +28 -0
  414. package/src/chat/ui/RunSettings.tsx +546 -0
  415. package/src/chat/ui/Scrubber.tsx +265 -0
  416. package/src/chat/ui/SubagentControls.tsx +66 -0
  417. package/src/chat/ui/SubagentInfo.tsx +67 -0
  418. package/src/chat/ui/SubagentStopButton.tsx +45 -0
  419. package/src/chat/ui/SubagentTimeline.tsx +170 -0
  420. package/src/chat/ui/Timeline.tsx +628 -0
  421. package/src/chat/ui/TimelineMenu.tsx +124 -0
  422. package/src/chat/ui/UnifiedDiff.tsx +99 -0
  423. package/src/chat/ui/UploadThumb.tsx +13 -0
  424. package/src/chat/ui/Welcome.tsx +22 -0
  425. package/src/chat/ui/chips.ts +15 -0
  426. package/src/chat/ui/code-lines.ts +60 -0
  427. package/src/chat/ui/code-streaming.ts +4 -0
  428. package/src/chat/ui/code-theme.ts +15 -0
  429. package/src/chat/ui/composer/chips.ts +43 -0
  430. package/src/chat/ui/composer/editor.ts +118 -0
  431. package/src/chat/ui/composer/insert.ts +22 -0
  432. package/src/chat/ui/composer/keys.ts +144 -0
  433. package/src/chat/ui/diff-theme.ts +23 -0
  434. package/src/chat/ui/file-links.ts +24 -0
  435. package/src/chat/ui/find-reveal.ts +23 -0
  436. package/src/chat/ui/full-diff.ts +25 -0
  437. package/src/chat/ui/icons.tsx +24 -0
  438. package/src/chat/ui/markdown-blocks.ts +123 -0
  439. package/src/chat/ui/quote-selection.ts +53 -0
  440. package/src/chat/ui/rehype-chips.ts +62 -0
  441. package/src/chat/ui/rehype-fade.ts +64 -0
  442. package/src/chat/ui/remark-html-as-text.ts +36 -0
  443. package/src/chat/ui/reply-context.ts +4 -0
  444. package/src/chat/ui/reveal.ts +135 -0
  445. package/src/chat/ui/rows/ForksRow.tsx +79 -0
  446. package/src/chat/ui/rows/MessageRows.tsx +415 -0
  447. package/src/chat/ui/rows/Rows.tsx +81 -0
  448. package/src/chat/ui/rows/SubagentRow.tsx +209 -0
  449. package/src/chat/ui/rows/TaskRow.tsx +91 -0
  450. package/src/chat/ui/rows/WorkRows.tsx +445 -0
  451. package/src/chat/ui/rows/WorkflowRow.tsx +120 -0
  452. package/src/chat/ui/rows/row-rhythm.ts +37 -0
  453. package/src/chat/ui/useToggleSet.ts +39 -0
  454. package/src/host.ts +324 -0
  455. package/src/lazy.tsx +64 -0
  456. package/src/locales/en/agent-chat.json +446 -0
  457. package/src/locales/en/agent-prompts.json +42 -0
  458. package/src/locales/en/agent-providers.json +131 -0
  459. package/src/locales/en/agent-usage.json +131 -0
  460. package/src/locales/nl/agent-chat.json +446 -0
  461. package/src/locales/nl/agent-prompts.json +42 -0
  462. package/src/locales/nl/agent-providers.json +131 -0
  463. package/src/locales/nl/agent-usage.json +131 -0
  464. package/src/locales.ts +33 -0
  465. package/src/mounted-registry.ts +45 -0
  466. package/src/port-transport.ts +146 -0
  467. package/src/prompts/logic/focus.ts +25 -0
  468. package/src/prompts/logic/keys.ts +116 -0
  469. package/src/prompts/logic/prompts.fixtures.ts +84 -0
  470. package/src/prompts/logic/prompts.ts +58 -0
  471. package/src/prompts/logic/subjects.ts +122 -0
  472. package/src/prompts/logic/useFocusAfterAnswer.ts +38 -0
  473. package/src/prompts/logic/usePromptSession.ts +114 -0
  474. package/src/prompts/ui/ApprovalBody.tsx +109 -0
  475. package/src/prompts/ui/PromptActions.tsx +109 -0
  476. package/src/prompts/ui/PromptCard.tsx +101 -0
  477. package/src/prompts/ui/PromptView.tsx +111 -0
  478. package/src/prompts/ui/QuestionBody.tsx +174 -0
  479. package/src/providers/AccountColors.tsx +8 -0
  480. package/src/providers/AccountDetail.tsx +209 -0
  481. package/src/providers/AccountVariables.tsx +126 -0
  482. package/src/providers/AddAccountForm.tsx +121 -0
  483. package/src/providers/CliDetail.tsx +157 -0
  484. package/src/providers/ProvidersPane.tsx +236 -0
  485. package/src/providers/account-actions.ts +67 -0
  486. package/src/providers/parts.tsx +25 -0
  487. package/src/providers/provider-abilities.ts +9 -0
  488. package/src/providers/variables.ts +87 -0
  489. package/src/scope.ts +30 -0
  490. package/src/settings/sections.ts +47 -0
  491. package/src/state/chats.ts +279 -0
  492. package/src/state/provider-accounts.ts +87 -0
  493. package/src/state/providers.ts +50 -0
  494. package/src/state/usage.ts +196 -0
  495. package/src/storage.ts +113 -0
  496. package/src/theme.css +196 -0
  497. package/src/transport.ts +50 -0
  498. package/src/ui/PlainTextarea.tsx +6 -0
  499. package/src/usage/LimitsList.tsx +232 -0
  500. package/src/usage/UsageBreakdown.tsx +210 -0
  501. package/src/usage/UsageChart.tsx +113 -0
  502. package/src/usage/UsageDialog.tsx +20 -0
  503. package/src/usage/UsageLimits.tsx +145 -0
  504. package/src/usage/UsageLimitsCard.tsx +36 -0
  505. package/src/usage/UsagePage.tsx +276 -0
  506. package/src/usage/UsagePane.tsx +52 -0
  507. package/src/usage/UsageSummary.tsx +50 -0
  508. package/src/usage/UsageTiles.tsx +34 -0
  509. package/src/usage/format.ts +71 -0
  510. package/src/usage/limit-groups.ts +119 -0
  511. package/src/usage/limits.ts +71 -0
  512. package/src/usage/money.ts +14 -0
  513. package/src/usage/summary.ts +137 -0
@@ -0,0 +1,96 @@
1
+ import i18next from 'i18next';
2
+ import { useMemo } from 'react';
3
+ import { create } from 'zustand';
4
+ import { useChatScope } from '../scope.js';
5
+ import { useChatRow } from '../state/chats.js';
6
+ import { useSubagentSupport } from './subagent-support.js';
7
+ export const MAIN_AGENT = [];
8
+ const NO_ITEMS = [];
9
+ export function crumbOf(item) {
10
+ return { toolUseId: item.toolUseId, description: item.description };
11
+ }
12
+ function stepLabel(step) {
13
+ return step.description || i18next.t('agent-chat:rows.subagent.label');
14
+ }
15
+ /* A row in the main agent's thread or an entry of the flyout opens its conversation straight away. */
16
+ export function openFromMain(step) {
17
+ return [step];
18
+ }
19
+ export function openBelow(trail, step) {
20
+ return [...trail, step];
21
+ }
22
+ export function trailTo(trail, depth) {
23
+ return depth <= 0 ? MAIN_AGENT : trail.slice(0, depth);
24
+ }
25
+ export function stepBack(trail) {
26
+ return trailTo(trail, trail.length - 1);
27
+ }
28
+ /*
29
+ * A sub-agent's conversation is read back, so there is nobody to write to. The composer stays, since
30
+ * the chat's own approvals and questions are answered there.
31
+ */
32
+ export function composerWrites(trail) {
33
+ return trail.length === 0;
34
+ }
35
+ /* The crumbs after the chat's own title, which the bar draws as the first crumb and the way back. */
36
+ export function breadcrumbOf(trail) {
37
+ return trail.map((step, index) => ({ label: stepLabel(step), depth: index + 1, current: index === trail.length - 1 }));
38
+ }
39
+ /* A row without a pointer of its own can only be opened by a machine that answers `chat.subagent` for it. */
40
+ export function canOpenSubagent(item, machineRefused) {
41
+ return item.native !== undefined || !machineRefused;
42
+ }
43
+ /* The row of the call that opened a conversation, a nested one included, since its row is in the thread too. */
44
+ export function subagentOf(structure, toolUseId) {
45
+ return Object.values(structure).find((item) => item.kind === 'subagent' && item.toolUseId === toolUseId) ?? null;
46
+ }
47
+ /* The subagents a chat can open, in the order the thread has them. */
48
+ export function openableSubagents(order, structure, machineRefused) {
49
+ return order.flatMap((id) => {
50
+ const item = structure[id];
51
+ return item?.kind === 'subagent' && canOpenSubagent(item, machineRefused) ? [item] : [];
52
+ });
53
+ }
54
+ /*
55
+ * What a chat shows in its place, for this page's life only: a look into a subagent is a moment
56
+ * rather than a place, so it is never written to the project or to the host.
57
+ */
58
+ export const useSubagentView = create((set, get) => ({
59
+ trails: {},
60
+ show(key, trail) {
61
+ const trails = { ...get().trails };
62
+ if (trail.length === 0) {
63
+ delete trails[key];
64
+ }
65
+ else {
66
+ trails[key] = trail;
67
+ }
68
+ set({ trails });
69
+ },
70
+ back(key) {
71
+ const trail = get().trails[key];
72
+ if (trail === undefined || trail.length === 0) {
73
+ return false;
74
+ }
75
+ get().show(key, stepBack(trail));
76
+ return true;
77
+ }
78
+ }));
79
+ /* The trail of a chat in the scope this is rendered in, and a way to set it. */
80
+ export function useSubagentTrail(chatId) {
81
+ const key = useChatScope().keyOf(chatId);
82
+ const trail = useSubagentView((s) => s.trails[key] ?? MAIN_AGENT);
83
+ return { trail, show: (next) => useSubagentView.getState().show(key, next) };
84
+ }
85
+ export function useOpenableSubagents(chatId) {
86
+ const { id } = useChatScope();
87
+ const refused = useSubagentSupport((s) => s.unsupported[id] === true);
88
+ // The structure and not the items, so a delta growing a reply does not walk the thread again.
89
+ const order = useChatRow(chatId, (row) => row?.order);
90
+ const structure = useChatRow(chatId, (row) => row?.structure);
91
+ return useMemo(() => (structure === undefined ? [] : openableSubagents(order ?? NO_ITEMS, structure, refused)), [order, structure, refused]);
92
+ }
93
+ export function useSubagentItem(chatId, toolUseId) {
94
+ const structure = useChatRow(chatId, (row) => row?.structure);
95
+ return useMemo(() => (structure === undefined ? null : subagentOf(structure, toolUseId)), [structure, toolUseId]);
96
+ }
@@ -0,0 +1,10 @@
1
+ import type { ChatAttachmentUpload } from '@adecore/agent-contracts';
2
+ export declare const THUMBNAIL_PX = 256;
3
+ export interface ThumbnailCrop {
4
+ sx: number;
5
+ sy: number;
6
+ size: number;
7
+ out: number;
8
+ }
9
+ export declare function thumbnailCrop(width: number, height: number, max?: number): ThumbnailCrop;
10
+ export declare function useUploadThumbnail(upload: ChatAttachmentUpload): string | null;
@@ -0,0 +1,89 @@
1
+ import i18next from 'i18next';
2
+ import { useEffect, useState } from 'react';
3
+ import { uploadPreviewUrl } from './attachments.js';
4
+ /* The edge of a composer thumbnail: a few times the 56 px it is drawn at, so a sharp screen still gets a sharp one. */
5
+ export const THUMBNAIL_PX = 256;
6
+ /* The square in the middle of an image that a thumbnail shows, the same part `object-cover` would. */
7
+ export function thumbnailCrop(width, height, max = THUMBNAIL_PX) {
8
+ const size = Math.max(1, Math.min(width, height));
9
+ return {
10
+ sx: Math.max(0, Math.floor((width - size) / 2)),
11
+ sy: Math.max(0, Math.floor((height - size) / 2)),
12
+ size,
13
+ out: Math.min(max, size)
14
+ };
15
+ }
16
+ function bytesOf(base64) {
17
+ const binary = atob(base64);
18
+ const bytes = new Uint8Array(new ArrayBuffer(binary.length));
19
+ for (let i = 0; i < binary.length; i++) {
20
+ bytes[i] = binary.charCodeAt(i);
21
+ }
22
+ return bytes;
23
+ }
24
+ function dataUrlOf(blob) {
25
+ return new Promise((resolve, reject) => {
26
+ const reader = new FileReader();
27
+ reader.onerror = () => reject(reader.error ?? new Error(i18next.t('agent-chat:attachments.unreadableThumbnail')));
28
+ reader.onload = () => resolve(String(reader.result));
29
+ reader.readAsDataURL(blob);
30
+ });
31
+ }
32
+ /*
33
+ * A still of the middle of an image, decoded once. The composer used to draw the full data URL in a
34
+ * 56 px box, which a browser decodes again for every paint, so a tall screenshot made typing stutter.
35
+ * An animated image gives its first frame. Whatever cannot be decoded this way (an SVG, a browser
36
+ * without `OffscreenCanvas`) falls back to the image itself, which is what it was before.
37
+ */
38
+ async function makeThumbnail(upload) {
39
+ try {
40
+ const bitmap = await createImageBitmap(new Blob([bytesOf(upload.data)], { type: upload.mime }));
41
+ const crop = thumbnailCrop(bitmap.width, bitmap.height);
42
+ const canvas = new OffscreenCanvas(crop.out, crop.out);
43
+ const context = canvas.getContext('2d');
44
+ if (!context) {
45
+ bitmap.close();
46
+ return uploadPreviewUrl(upload);
47
+ }
48
+ context.drawImage(bitmap, crop.sx, crop.sy, crop.size, crop.size, 0, 0, crop.out, crop.out);
49
+ bitmap.close();
50
+ return await dataUrlOf(await canvas.convertToBlob({ type: 'image/png' }));
51
+ }
52
+ catch {
53
+ return uploadPreviewUrl(upload);
54
+ }
55
+ }
56
+ // Keyed by the upload itself, so a composer that mounts again finds it and a removed file lets it go.
57
+ const made = new WeakMap();
58
+ const making = new WeakMap();
59
+ function thumbnailOf(upload) {
60
+ let promise = making.get(upload);
61
+ if (!promise) {
62
+ promise = makeThumbnail(upload).then((url) => {
63
+ made.set(upload, url);
64
+ return url;
65
+ });
66
+ making.set(upload, promise);
67
+ }
68
+ return promise;
69
+ }
70
+ /* The thumbnail of an image the composer holds, or null while it is being made. */
71
+ export function useUploadThumbnail(upload) {
72
+ const [ready, setReady] = useState(null);
73
+ const cached = made.get(upload);
74
+ useEffect(() => {
75
+ if (made.has(upload)) {
76
+ return;
77
+ }
78
+ let cancelled = false;
79
+ void thumbnailOf(upload).then((url) => {
80
+ if (!cancelled) {
81
+ setReady({ upload, url });
82
+ }
83
+ });
84
+ return () => {
85
+ cancelled = true;
86
+ };
87
+ }, [upload]);
88
+ return cached ?? (ready?.upload === upload ? ready.url : null);
89
+ }
@@ -0,0 +1,12 @@
1
+ export interface TimelineFlash {
2
+ key: string;
3
+ rowId: string;
4
+ opens: boolean;
5
+ nonce: number;
6
+ }
7
+ interface TimelineFlashStore {
8
+ target: TimelineFlash | null;
9
+ flash(key: string, rowId: string, opens: boolean): void;
10
+ }
11
+ export declare const useTimelineFlash: import("zustand").UseBoundStore<import("zustand").StoreApi<TimelineFlashStore>>;
12
+ export {};
@@ -0,0 +1,16 @@
1
+ import { create } from 'zustand';
2
+ /* A little longer than the animation of `.chat-flash`, so a row that scrolls into view again later is neither lit nor opened a second time. */
3
+ const FLASH_MS = 2000;
4
+ export const useTimelineFlash = create((set, get) => ({
5
+ target: null,
6
+ flash(key, rowId, opens) {
7
+ const nonce = (get().target?.nonce ?? 0) + 1;
8
+ set({ target: { key, rowId, opens, nonce } });
9
+ const timer = setTimeout(() => {
10
+ if (get().target?.nonce === nonce) {
11
+ set({ target: null });
12
+ }
13
+ }, FLASH_MS);
14
+ timer.unref?.();
15
+ }
16
+ }));
@@ -0,0 +1,27 @@
1
+ type Scroller = {
2
+ element: HTMLElement;
3
+ follow: (enabled: boolean) => void;
4
+ coveredHeight: () => number;
5
+ };
6
+ export declare function registerTimeline(chatId: string, element: HTMLElement | null, follow: Scroller['follow'], coveredHeight: Scroller['coveredHeight']): () => void;
7
+ export declare function setTimelineAtEnd(chatId: string, atEnd: boolean): void;
8
+ export declare function subscribeTimelineEnd(listener: () => void): () => void;
9
+ export declare function timelineAtEnd(chatId: string): boolean;
10
+ export declare function scrollTimelineToEnd(chatId: string, behavior?: ScrollBehavior): void;
11
+ export declare function pageTimeline(chatId: string, direction: -1 | 1): boolean;
12
+ export declare function registerMessageStepper(key: string, step: (direction: -1 | 1) => boolean): () => void;
13
+ export declare function stepTimelineMessage(key: string, direction: -1 | 1): boolean;
14
+ export declare function registerItemJumper(key: string, jump: (itemId: string) => void): () => void;
15
+ export declare function jumpToTimelineItem(key: string, itemId: string): boolean;
16
+ export type TurnTarget = 'prompt' | 'changes';
17
+ type TurnJump = (turnId: string, target: TurnTarget) => void;
18
+ export declare function registerTurnJumper(key: string, jump: TurnJump): () => void;
19
+ export declare function jumpToTimelineTurn(key: string, turnId: string, target: TurnTarget): boolean;
20
+ export declare function wantsEarlier(scroller: HTMLElement): boolean;
21
+ export interface ReadingAnchor {
22
+ id: string;
23
+ offset: number;
24
+ }
25
+ export declare function firstRowInView(scroller: HTMLElement): ReadingAnchor | null;
26
+ export declare function restoreAnchor(scroller: HTMLElement, anchor: ReadingAnchor): void;
27
+ export {};
@@ -0,0 +1,152 @@
1
+ // A page is a screen minus a little, so the line you were reading is still on it after the jump.
2
+ const PAGE_OVERLAP = 0.9;
3
+ const scrollers = new Map();
4
+ /* The timeline hands its scroller over so the composer, which never sees it, can page through it. */
5
+ export function registerTimeline(chatId, element, follow, coveredHeight) {
6
+ if (element === null) {
7
+ return () => undefined;
8
+ }
9
+ scrollers.set(chatId, { element, follow, coveredHeight });
10
+ return () => {
11
+ if (scrollers.get(chatId)?.element === element) {
12
+ scrollers.delete(chatId);
13
+ ends.delete(chatId);
14
+ }
15
+ };
16
+ }
17
+ /* The timeline owns following; the composer subscribes here to show its jump-to-end button. */
18
+ const ends = new Map();
19
+ const listeners = new Set();
20
+ export function setTimelineAtEnd(chatId, atEnd) {
21
+ if (ends.get(chatId) === atEnd) {
22
+ return;
23
+ }
24
+ ends.set(chatId, atEnd);
25
+ for (const listener of listeners) {
26
+ listener();
27
+ }
28
+ }
29
+ export function subscribeTimelineEnd(listener) {
30
+ listeners.add(listener);
31
+ return () => {
32
+ listeners.delete(listener);
33
+ };
34
+ }
35
+ /* A thread nobody has scrolled is at its end, so the button stays away until there is a way back. */
36
+ export function timelineAtEnd(chatId) {
37
+ return ends.get(chatId) ?? true;
38
+ }
39
+ export function scrollTimelineToEnd(chatId, behavior = 'smooth') {
40
+ const scroller = scrollers.get(chatId);
41
+ if (scroller) {
42
+ scroller.follow(true);
43
+ scroller.element.scrollTo({ top: scroller.element.scrollHeight, behavior });
44
+ }
45
+ }
46
+ /* Pages the thread of this chat up or down; false when it has no timeline on screen. */
47
+ export function pageTimeline(chatId, direction) {
48
+ const scroller = scrollers.get(chatId);
49
+ if (!scroller) {
50
+ return false;
51
+ }
52
+ scroller.follow(false);
53
+ const { element } = scroller;
54
+ element.scrollBy({ top: direction * Math.max(0, element.clientHeight - scroller.coveredHeight()) * PAGE_OVERLAP, behavior: 'smooth' });
55
+ return true;
56
+ }
57
+ /*
58
+ * The keyboard steps from one message of the person to the next through the timeline on screen,
59
+ * which is the only side that knows where its rows start. Keyed with the scope's `keyOf`, the way
60
+ * the app's shortcuts name the chat that has the focus.
61
+ */
62
+ const steppers = new Map();
63
+ export function registerMessageStepper(key, step) {
64
+ steppers.set(key, step);
65
+ return () => {
66
+ if (steppers.get(key) === step) {
67
+ steppers.delete(key);
68
+ }
69
+ };
70
+ }
71
+ /* False when that chat has no timeline on screen or no message in that direction. */
72
+ export function stepTimelineMessage(key, direction) {
73
+ return steppers.get(key)?.(direction) ?? false;
74
+ }
75
+ /*
76
+ * A jump to one message of a chat, asked from outside its thread (the chat's menu). A thread that is
77
+ * not on screen yet gets it when it registers, since the menu may have to show the chat first.
78
+ * Keyed with the scope's `keyOf`, like the steppers.
79
+ */
80
+ const jumpers = new Map();
81
+ const waitingJumps = new Map();
82
+ export function registerItemJumper(key, jump) {
83
+ jumpers.set(key, jump);
84
+ const waiting = waitingJumps.get(key);
85
+ if (waiting !== undefined) {
86
+ waitingJumps.delete(key);
87
+ jump(waiting);
88
+ }
89
+ return () => {
90
+ if (jumpers.get(key) === jump) {
91
+ jumpers.delete(key);
92
+ }
93
+ };
94
+ }
95
+ /* False when that chat has no thread on screen; the jump then waits for the next one that registers. */
96
+ export function jumpToTimelineItem(key, itemId) {
97
+ const jump = jumpers.get(key);
98
+ if (jump === undefined) {
99
+ waitingJumps.set(key, itemId);
100
+ return false;
101
+ }
102
+ jump(itemId);
103
+ return true;
104
+ }
105
+ const turnJumpers = new Map();
106
+ const waitingTurnJumps = new Map();
107
+ export function registerTurnJumper(key, jump) {
108
+ turnJumpers.set(key, jump);
109
+ const waiting = waitingTurnJumps.get(key);
110
+ if (waiting !== undefined) {
111
+ waitingTurnJumps.delete(key);
112
+ jump(waiting.turnId, waiting.target);
113
+ }
114
+ return () => {
115
+ if (turnJumpers.get(key) === jump) {
116
+ turnJumpers.delete(key);
117
+ }
118
+ };
119
+ }
120
+ /* False when that chat has no thread on screen; the jump then waits for the next one that registers. */
121
+ export function jumpToTimelineTurn(key, turnId, target) {
122
+ const jump = turnJumpers.get(key);
123
+ if (jump === undefined) {
124
+ waitingTurnJumps.set(key, { turnId, target });
125
+ return false;
126
+ }
127
+ jump(turnId, target);
128
+ return true;
129
+ }
130
+ /* How near the top, in screens, the page before is asked for, so it is there before a reader reaches the edge. */
131
+ const EARLIER_SCREENS = 1.5;
132
+ export function wantsEarlier(scroller) {
133
+ return scroller.clientHeight > 0 && scroller.scrollTop < scroller.clientHeight * EARLIER_SCREENS;
134
+ }
135
+ /* The first row in view, found by the rows' `data-item-id`, for a thread that keeps every row in the document. */
136
+ export function firstRowInView(scroller) {
137
+ const top = scroller.getBoundingClientRect().top;
138
+ for (const row of scroller.querySelectorAll('[data-item-id]')) {
139
+ const rect = row.getBoundingClientRect();
140
+ if (rect.bottom > top) {
141
+ return { id: row.dataset.itemId, offset: rect.top - top };
142
+ }
143
+ }
144
+ return null;
145
+ }
146
+ /* Puts the anchored row back where it was; nothing moves when that row is gone. */
147
+ export function restoreAnchor(scroller, anchor) {
148
+ const row = scroller.querySelector(`[data-item-id="${CSS.escape(anchor.id)}"]`);
149
+ if (row !== null) {
150
+ scroller.scrollTop += row.getBoundingClientRect().top - scroller.getBoundingClientRect().top - anchor.offset;
151
+ }
152
+ }
@@ -0,0 +1,3 @@
1
+ export declare function AccountPill({ chatId }: {
2
+ chatId: string;
3
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useTranslation } from 'react-i18next';
3
+ import { AccountDot } from '../../agents/AccountDot.js';
4
+ import { useAccountChoice } from '../account-choice.js';
5
+ import { useChats } from '../../state/chats.js';
6
+ import { useChatScope } from '../../scope.js';
7
+ import { Pill, Tooltip } from '@adecore/ui';
8
+ function AccountPillOf({ provider, account }) {
9
+ const { t } = useTranslation('agent-chat');
10
+ const choice = useAccountChoice(provider, account);
11
+ if (choice === null) {
12
+ return null;
13
+ }
14
+ const name = choice.current === null ? choice.currentId : choice.nameOf(choice.current);
15
+ return (_jsx(Tooltip, { label: t('account.pill', { provider: choice.providerName, account: name }), children: _jsx(Pill, { icon: _jsx(AccountDot, { color: choice.current?.account.color, className: "size-1.75" }), children: _jsx("span", { className: "max-w-32 truncate", children: name }) }) }));
16
+ }
17
+ /* Which account a chat node runs under, from the status every client gets; only while its CLI has a choice of accounts. */
18
+ export function AccountPill({ chatId }) {
19
+ const { keyOf } = useChatScope();
20
+ const provider = useChats((s) => s.statusByKey[keyOf(chatId)]?.info.provider);
21
+ const account = useChats((s) => s.statusByKey[keyOf(chatId)]?.info.account);
22
+ return provider === undefined ? null : _jsx(AccountPillOf, { provider: provider, account: account });
23
+ }
@@ -0,0 +1,5 @@
1
+ export declare function AnsiOutput({ text, limit, tailLines }: {
2
+ text: string;
3
+ limit?: number;
4
+ tailLines?: number;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { parseAnsi } from '../logic/ansi.js';
5
+ export function AnsiOutput({ text, limit, tailLines }) {
6
+ const { t } = useTranslation('agent-chat');
7
+ const { tokens, omitted } = useMemo(() => parseAnsi(text, { limit, tailLines }), [text, limit, tailLines]);
8
+ return (_jsxs(_Fragment, { children: [tokens.map((token, index) => (_jsx("span", { style: token.style, children: token.content }, index))), omitted > 0 && `\n${t('work.moreCharacters', { count: omitted })}`] }));
9
+ }
@@ -0,0 +1,8 @@
1
+ import { type ChatBookmark } from '@adecore/agent-contracts';
2
+ interface BookmarkMarkerProps {
3
+ chatId: string;
4
+ itemId: string;
5
+ bookmark: ChatBookmark | null;
6
+ }
7
+ export declare function BookmarkMarker({ chatId, itemId, bookmark }: BookmarkMarkerProps): import("react").JSX.Element | null;
8
+ export {};
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ import clsx from 'clsx';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { Bookmark, Pencil, X } from 'lucide-react';
6
+ import { CHAT_BOOKMARK_LIMITS } from '@adecore/agent-contracts';
7
+ import { nameBookmark, removeBookmark, useBookmarkNaming } from '../bookmarks.js';
8
+ import { bookmarkLabel } from '../logic/bookmarks.js';
9
+ import { useChatScope } from '../../scope.js';
10
+ import { ButtonGroup, Icon, IconButton, Input } from '@adecore/ui';
11
+ /*
12
+ * A bookmark as a chapter line across the thread, drawn before the message it marks. Without a
13
+ * bookmark it only stands while the name field of a mark still on its way to the host is open.
14
+ */
15
+ export function BookmarkMarker({ chatId, itemId, bookmark }) {
16
+ const { t } = useTranslation('agent-chat');
17
+ const scope = useChatScope();
18
+ const chatKey = scope.keyOf(chatId);
19
+ const naming = useBookmarkNaming((s) => s.chatKey === chatKey && s.itemId === itemId);
20
+ if (bookmark === null && !naming) {
21
+ return null;
22
+ }
23
+ return (_jsxs("div", { className: "group/bookmark mb-2 flex h-7 min-w-0 items-center gap-2 text-xs select-none", children: [_jsx(Icon, { icon: Bookmark, size: 14, className: "shrink-0 text-accent" }), naming ? (_jsx(NameField, { initial: bookmark?.name ?? '', onDone: (name) => {
24
+ useBookmarkNaming.getState().close();
25
+ if (name !== null) {
26
+ void nameBookmark(scope, chatId, itemId, name, bookmark?.name);
27
+ }
28
+ } })) : (bookmark !== null && (_jsx("span", { className: clsx('min-w-0 truncate', bookmark.name === undefined ? 'text-text-muted' : 'text-text'), children: bookmarkLabel(bookmark) }))), _jsx("span", { className: "min-w-6 grow border-t border-border" }), bookmark !== null && !naming && (_jsxs(ButtonGroup, { render: _jsx("span", {}), className: "-ml-2 max-w-0 shrink-0 overflow-hidden opacity-0 group-hover/bookmark:ml-0 group-hover/bookmark:max-w-none group-hover/bookmark:opacity-100 group-has-focus-visible/bookmark:ml-0 group-has-focus-visible/bookmark:max-w-none group-has-focus-visible/bookmark:opacity-100", children: [_jsx(IconButton, { icon: Pencil, size: "xs", label: t('bookmarks.rename'), onClick: () => useBookmarkNaming.getState().open(chatKey, itemId) }), _jsx(IconButton, { icon: X, size: "xs", label: t('bookmarks.remove'), onClick: () => void removeBookmark(scope, chatId, bookmark) })] }))] }));
29
+ }
30
+ /* Settles with the name on Enter or when the focus leaves, and with null on Escape, which keeps the name as it was. */
31
+ function NameField({ initial, onDone }) {
32
+ const { t } = useTranslation('agent-chat');
33
+ const ref = useRef(null);
34
+ const settled = useRef(false);
35
+ // Again a frame later: the menu the field was opened from hands the focus back as it closes.
36
+ useEffect(() => {
37
+ ref.current?.focus();
38
+ const frame = requestAnimationFrame(() => ref.current?.focus());
39
+ return () => cancelAnimationFrame(frame);
40
+ }, []);
41
+ const settle = (name) => {
42
+ if (settled.current) {
43
+ return;
44
+ }
45
+ settled.current = true;
46
+ onDone(name);
47
+ };
48
+ return (_jsx(Input, { ref: ref, size: "sm", defaultValue: initial, maxLength: CHAT_BOOKMARK_LIMITS.name, placeholder: t('bookmarks.namePlaceholder'), "aria-label": t('bookmarks.nameLabel'), className: "w-64 max-w-full min-w-0 select-text", onPointerDown: (e) => e.stopPropagation(), onFocus: (e) => e.currentTarget.select(), onBlur: (e) => settle(e.currentTarget.value), onKeyDown: (e) => {
49
+ e.stopPropagation();
50
+ if (e.key === 'Enter') {
51
+ settle(e.currentTarget.value);
52
+ }
53
+ if (e.key === 'Escape') {
54
+ settle(null);
55
+ }
56
+ } }));
57
+ }
@@ -0,0 +1,3 @@
1
+ export declare function BookmarkSubmenu({ chatId }: {
2
+ chatId: string;
3
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import clsx from 'clsx';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { Bookmark, Pencil, X } from 'lucide-react';
6
+ import { goToBookmark, removeBookmark } from '../bookmarks.js';
7
+ import { bookmarkLabel, bookmarksInThreadOrder } from '../logic/bookmarks.js';
8
+ import { chatHost } from '../../host.js';
9
+ import { useChatScope } from '../../scope.js';
10
+ import { useChatRow } from '../../state/chats.js';
11
+ import { Icon, Menu } from '@adecore/ui';
12
+ /*
13
+ * "Bookmarks" in the menu of a chat node or a chat view: the chat's bookmarks in the order of the
14
+ * thread, each a jump to its message, with rename and remove on the row. A chat without bookmarks
15
+ * draws nothing.
16
+ */
17
+ export function BookmarkSubmenu({ chatId }) {
18
+ const { t } = useTranslation('agent-chat');
19
+ const scope = useChatScope();
20
+ const bookmarks = useChatRow(chatId, (row) => row?.bookmarks);
21
+ const order = useChatRow(chatId, (row) => row?.order);
22
+ const place = chatHost().useChatPlace(chatId);
23
+ const sorted = useMemo(() => bookmarksInThreadOrder(bookmarks ?? [], order ?? []), [bookmarks, order]);
24
+ if (sorted.length === 0) {
25
+ return null;
26
+ }
27
+ const go = (itemId, rename) => {
28
+ if (!goToBookmark(scope, chatId, itemId, rename)) {
29
+ place.go();
30
+ }
31
+ };
32
+ return (_jsxs(Menu.SubmenuRoot, { children: [_jsxs(Menu.SubmenuTrigger, { children: [_jsx(Icon, { icon: Bookmark, size: 14 }), " ", t('bookmarks.menu')] }), _jsx(Menu.Popup, { className: "max-w-80 min-w-56", children: sorted.map((bookmark) => (_jsxs(Menu.Row, { "aria-label": bookmarkLabel(bookmark), children: [_jsxs(Menu.Item, { onClick: () => go(bookmark.itemId, false), children: [_jsx(Icon, { icon: Bookmark, size: 14, className: "shrink-0 text-accent" }), _jsx("span", { className: clsx('min-w-0 grow truncate', bookmark.name === undefined && 'text-text-muted'), children: bookmarkLabel(bookmark) })] }), _jsx(Menu.RowAction, { icon: Pencil, label: t('bookmarks.rename'), onClick: () => go(bookmark.itemId, true) }), _jsx(Menu.RowAction, { icon: X, label: t('bookmarks.remove'), onClick: () => void removeBookmark(scope, chatId, bookmark) })] }, bookmark.itemId))) })] }));
33
+ }
@@ -0,0 +1,7 @@
1
+ import { type StatusWord } from '../../agents/status-look.js';
2
+ export declare function ChatActivity({ chatId }: {
3
+ chatId: string;
4
+ }): import("react").JSX.Element | null;
5
+ export declare function StatusIcon({ word }: {
6
+ word: StatusWord;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,84 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import clsx from 'clsx';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { Activity, Square, SquareTerminal } from 'lucide-react';
6
+ import { backgroundCounts } from '../activity.js';
7
+ import { badgeCountOf, entryTimeOf, flyoutSubagents, statusWordOf, subagentTitle, summaryWordOf, taskIdOf } from '../subagent-list.js';
8
+ import { useSubagentSupport } from '../subagent-support.js';
9
+ import { canOpenSubagent, crumbOf, openFromMain, useSubagentTrail } from '../subagent-view.js';
10
+ import { SubagentStopButton } from './SubagentStopButton.js';
11
+ import { formatElapsedShort } from '@adecore/ui/format';
12
+ import { Icon, IconButton, Popover, Surface, useNow } from '@adecore/ui';
13
+ import { useChatRow } from '../../state/chats.js';
14
+ import { chatHost } from '../../host.js';
15
+ import { useChatScope } from '../../scope.js';
16
+ import { useChatActions } from '../actions.js';
17
+ import { statusLookOf } from '../../agents/status-look.js';
18
+ const NO_TASKS = [];
19
+ const NO_ITEMS = [];
20
+ const ROW_BODY = 'flex min-h-9 min-w-0 grow items-center gap-2.5 rounded-md px-2.5 py-1.5 text-left';
21
+ /* What the chat keeps working on beside the thread, in one small line over the composer: its sub-agents and what runs in the background. */
22
+ export function ChatActivity({ chatId }) {
23
+ const { t } = useTranslation('agent-chat');
24
+ const order = useChatRow(chatId, (row) => row?.order) ?? NO_ITEMS;
25
+ const structure = useChatRow(chatId, (row) => row?.structure);
26
+ const subagents = useMemo(() => (structure === undefined ? [] : flyoutSubagents(order, structure)), [order, structure]);
27
+ const { id } = useChatScope();
28
+ const tasks = chatHost().tasks.useTasks(id);
29
+ const words = useMemo(() => subagents.map((item) => {
30
+ const taskId = taskIdOf(item);
31
+ return statusWordOf(item, taskId === null ? null : (tasks?.[taskId] ?? null));
32
+ }), [subagents, tasks]);
33
+ const background = useChatRow(chatId, (row) => row?.info.background) ?? NO_TASKS;
34
+ if (subagents.length === 0 && background.length === 0) {
35
+ return null;
36
+ }
37
+ const { shells, monitors } = backgroundCounts(background);
38
+ const Slot = chatHost().SubagentSlot;
39
+ return (_jsxs("div", { className: "mb-3 flex flex-wrap items-center gap-2", children: [subagents.length > 0 &&
40
+ (Slot === null ? (_jsx(Flyout, { icon: _jsx(StatusIcon, { word: summaryWordOf(words) }), label: t('activity.subagents', { count: badgeCountOf(words) }), heading: t('activity.subagents', { count: subagents.length }), children: _jsx(SubagentRows, { chatId: chatId, items: subagents }) })) : (_jsx(Slot, { chatId: chatId, items: subagents }))), background.length > 0 && (_jsx(Flyout, { icon: _jsx(Icon, { icon: shells > 0 ? SquareTerminal : Activity, size: 14 }), label: [shells > 0 && t('activity.shells', { count: shells }), monitors > 0 && t('activity.monitors', { count: monitors })]
41
+ .filter(Boolean)
42
+ .join(' · '), children: _jsx(BackgroundTaskRows, { chatId: chatId, tasks: background }) }))] }));
43
+ }
44
+ export function StatusIcon({ word }) {
45
+ const look = statusLookOf(word);
46
+ return _jsx(Icon, { icon: look.icon, size: 14, className: clsx('shrink-0', look.tone, look.spins && 'animate-spin') });
47
+ }
48
+ /* A chip that opens a list over it, headed by what the chip says unless the list counts more than the chip does. */
49
+ function Flyout({ icon, label, heading = label, children }) {
50
+ return (_jsxs(Popover.Root, { children: [_jsxs(Surface, { render: _jsx(Popover.Trigger, {}), className: "pointer-events-auto inline-flex h-7.5 items-center gap-1.5 rounded-full px-3 text-xs text-text-muted hover:text-text", children: [icon, label] }), _jsxs(Popover.Popup, { side: "top", className: "w-80", children: [_jsx("div", { className: "px-2.5 pt-1.5 pb-1 text-xs text-text-faint", children: heading }), children] })] }));
51
+ }
52
+ /* One line of a flyout; with `onOpen` the line leads somewhere and closes the flyout on the way. */
53
+ function ActivityRow({ icon, title, detail, time, onOpen, children }) {
54
+ const body = (_jsxs(_Fragment, { children: [icon, _jsxs("span", { className: "flex min-w-0 grow flex-col", children: [_jsx("span", { className: "truncate text-sm text-text", children: title }), detail && _jsx("span", { className: "truncate font-mono text-xs text-text-faint", children: detail })] }), time !== '' && _jsx("span", { className: "shrink-0 text-xs text-text-faint tabular-nums", children: time })] }));
55
+ // The stop is a button of its own beside the line, since a button cannot hold another.
56
+ return (_jsxs("div", { className: clsx('flex items-center gap-1 rounded-md', onOpen && 'hover:bg-surface-hover'), children: [onOpen ? (_jsx(Popover.Close, { className: ROW_BODY, onClick: onOpen, children: body })) : (_jsx("div", { className: ROW_BODY, children: body })), children] }));
57
+ }
58
+ /* Only drawn while the flyout is open, so the clock ticks for nobody otherwise. */
59
+ function SubagentRows({ chatId, items }) {
60
+ const now = useNow(1000, items.some((item) => item.status === 'running'));
61
+ return items.map((item) => _jsx(SubagentEntry, { chatId: chatId, item: item, now: now }, item.id));
62
+ }
63
+ function SubagentEntry({ chatId, item, now }) {
64
+ const { t } = useTranslation('agent-chat');
65
+ const { id } = useChatScope();
66
+ const refused = useSubagentSupport((s) => s.unsupported[id] === true);
67
+ const task = chatHost().tasks.useTask(id, taskIdOf(item));
68
+ const { show } = useSubagentTrail(chatId);
69
+ const word = statusWordOf(item, task);
70
+ return (_jsx(ActivityRow, { icon: _jsx(StatusIcon, { word: word }), title: _jsxs(_Fragment, { children: [subagentTitle(item), _jsxs("span", { className: "sr-only", children: [", ", t(`common.status.${word}`)] })] }), time: entryTimeOf(item, task, now), onOpen: canOpenSubagent(item, refused) ? () => show(openFromMain(crumbOf(item))) : undefined, children: _jsx(SubagentStopButton, { chatId: chatId, item: item, className: "mr-1.5" }) }));
71
+ }
72
+ /* Only drawn while the flyout is open, so the clock ticks for nobody otherwise. */
73
+ function BackgroundTaskRows({ chatId, tasks }) {
74
+ const { t } = useTranslation('agent-chat');
75
+ const now = useNow(1000);
76
+ const actions = useChatActions();
77
+ function stop(taskId) {
78
+ void actions.stopTask(chatId, taskId).catch((e) => {
79
+ const description = e instanceof Error ? e.message : t('subagents.noAnswer');
80
+ chatHost().notify({ kind: 'error', title: t('activity.stopFailed'), description });
81
+ });
82
+ }
83
+ return tasks.map((task) => (_jsx(ActivityRow, { icon: _jsx(Icon, { icon: task.kind === 'shell' ? SquareTerminal : Activity, size: 14, className: "shrink-0 text-text-faint" }), title: task.description || task.command || t(`activity.${task.kind}`), detail: task.description ? task.command : null, time: formatElapsedShort(now - task.startedAt), children: _jsx(IconButton, { icon: Square, size: "xs", label: t('activity.stop'), className: "mr-1.5", onClick: () => stop(task.id) }) }, task.id)));
84
+ }