@adecore/agents-react 0.23.1 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. package/README.md +14 -11
  2. package/dist/agents/AccountDot.js +3 -1
  3. package/dist/agents/accounts.d.ts +3 -2
  4. package/dist/agents/accounts.js +5 -6
  5. package/dist/chat/actions.d.ts +2 -2
  6. package/dist/chat/actions.js +8 -5
  7. package/dist/chat/bookmarks.d.ts +5 -3
  8. package/dist/chat/bookmarks.js +13 -14
  9. package/dist/chat/chat-client.d.ts +1 -0
  10. package/dist/chat/chat-client.js +7 -0
  11. package/dist/chat/composer-send.d.ts +3 -0
  12. package/dist/chat/composer-send.js +22 -0
  13. package/dist/chat/forks.js +22 -5
  14. package/dist/chat/index.d.ts +31 -0
  15. package/dist/chat/index.js +28 -0
  16. package/dist/chat/logic/embedded-code.d.ts +8 -0
  17. package/dist/chat/logic/embedded-code.js +371 -0
  18. package/dist/chat/logic/fork.js +1 -0
  19. package/dist/chat/logic/goal.d.ts +6 -0
  20. package/dist/chat/logic/goal.js +26 -0
  21. package/dist/chat/logic/scrubber.d.ts +1 -1
  22. package/dist/chat/logic/scrubber.js +6 -5
  23. package/dist/chat/logic/thought.d.ts +3 -0
  24. package/dist/chat/logic/thought.js +35 -0
  25. package/dist/chat/logic/thread-cards.js +2 -0
  26. package/dist/chat/logic/timeline.d.ts +5 -0
  27. package/dist/chat/logic/timeline.js +22 -1
  28. package/dist/chat/logic/tool-catalog.d.ts +1 -0
  29. package/dist/chat/logic/tool-catalog.js +3 -1
  30. package/dist/chat/logic/tools.d.ts +14 -0
  31. package/dist/chat/logic/tools.js +57 -0
  32. package/dist/chat/preferences.d.ts +6 -0
  33. package/dist/chat/preferences.js +19 -3
  34. package/dist/chat/reading-width.d.ts +9 -0
  35. package/dist/chat/reading-width.js +27 -0
  36. package/dist/chat/send-key.d.ts +10 -0
  37. package/dist/chat/send-key.js +24 -0
  38. package/dist/chat/ui/BookmarkMarker.js +4 -2
  39. package/dist/chat/ui/BookmarkSubmenu.js +4 -3
  40. package/dist/chat/ui/ChatActivity.js +14 -10
  41. package/dist/chat/ui/ChatReferenceChip.js +3 -4
  42. package/dist/chat/ui/CodeBlock.d.ts +2 -1
  43. package/dist/chat/ui/CodeBlock.js +14 -96
  44. package/dist/chat/ui/Composer.d.ts +1 -1
  45. package/dist/chat/ui/Composer.js +130 -907
  46. package/dist/chat/ui/ComposerInput.js +5 -4
  47. package/dist/chat/ui/EditDiff.js +3 -2
  48. package/dist/chat/ui/GoalDock.d.ts +9 -0
  49. package/dist/chat/ui/GoalDock.js +63 -0
  50. package/dist/chat/ui/LimitState.js +5 -3
  51. package/dist/chat/ui/Markdown.d.ts +2 -1
  52. package/dist/chat/ui/Markdown.js +70 -31
  53. package/dist/chat/ui/MermaidBlock.d.ts +3 -0
  54. package/dist/chat/ui/MermaidBlock.js +73 -0
  55. package/dist/chat/ui/MessageActions.js +12 -7
  56. package/dist/chat/ui/Pickers.js +6 -5
  57. package/dist/chat/ui/PromptComposer.js +4 -3
  58. package/dist/chat/ui/RowTime.d.ts +3 -0
  59. package/dist/chat/ui/RowTime.js +12 -0
  60. package/dist/chat/ui/RunSettings.js +5 -4
  61. package/dist/chat/ui/ShellCommand.d.ts +3 -0
  62. package/dist/chat/ui/ShellCommand.js +110 -0
  63. package/dist/chat/ui/SubagentInfo.js +4 -3
  64. package/dist/chat/ui/SubagentStopButton.js +4 -3
  65. package/dist/chat/ui/SubagentTimeline.js +4 -1
  66. package/dist/chat/ui/Timeline.js +70 -40
  67. package/dist/chat/ui/TimelineMenu.d.ts +2 -1
  68. package/dist/chat/ui/TimelineMenu.js +18 -8
  69. package/dist/chat/ui/UnifiedDiff.js +3 -2
  70. package/dist/chat/ui/VisualFrame.js +6 -7
  71. package/dist/chat/ui/code-theme.d.ts +2 -1
  72. package/dist/chat/ui/code-theme.js +4 -4
  73. package/dist/chat/ui/composer/ComposerControls.d.ts +27 -0
  74. package/dist/chat/ui/composer/ComposerControls.js +34 -0
  75. package/dist/chat/ui/composer/ComposerMenu.d.ts +4 -0
  76. package/dist/chat/ui/composer/ComposerMenu.js +46 -0
  77. package/dist/chat/ui/composer/DraftParts.d.ts +18 -0
  78. package/dist/chat/ui/composer/DraftParts.js +25 -0
  79. package/dist/chat/ui/composer/QueuedMessages.d.ts +10 -0
  80. package/dist/chat/ui/composer/QueuedMessages.js +20 -0
  81. package/dist/chat/ui/composer/key-handler.d.ts +20 -0
  82. package/dist/chat/ui/composer/key-handler.js +150 -0
  83. package/dist/chat/ui/composer/keys.d.ts +7 -2
  84. package/dist/chat/ui/composer/keys.js +19 -9
  85. package/dist/chat/ui/composer/placeholder.d.ts +9 -0
  86. package/dist/chat/ui/composer/placeholder.js +38 -0
  87. package/dist/chat/ui/composer/surface.d.ts +1 -0
  88. package/dist/chat/ui/composer/surface.js +44 -0
  89. package/dist/chat/ui/composer/use-chat-controls.d.ts +28 -0
  90. package/dist/chat/ui/composer/use-chat-controls.js +112 -0
  91. package/dist/chat/ui/composer/use-compaction-offer.d.ts +2 -0
  92. package/dist/chat/ui/composer/use-compaction-offer.js +23 -0
  93. package/dist/chat/ui/composer/use-composer-draft.d.ts +14 -0
  94. package/dist/chat/ui/composer/use-composer-draft.js +39 -0
  95. package/dist/chat/ui/composer/use-composer-menus.d.ts +52 -0
  96. package/dist/chat/ui/composer/use-composer-menus.js +232 -0
  97. package/dist/chat/ui/composer/use-composer-submit.d.ts +32 -0
  98. package/dist/chat/ui/composer/use-composer-submit.js +113 -0
  99. package/dist/chat/ui/composer/use-draft-files.d.ts +27 -0
  100. package/dist/chat/ui/composer/use-draft-files.js +111 -0
  101. package/dist/chat/ui/composer/use-notice.d.ts +6 -0
  102. package/dist/chat/ui/composer/use-notice.js +18 -0
  103. package/dist/chat/ui/composer/use-pending-requests.d.ts +2 -0
  104. package/dist/chat/ui/composer/use-pending-requests.js +22 -0
  105. package/dist/chat/ui/composer/use-prompt-history.d.ts +8 -0
  106. package/dist/chat/ui/composer/use-prompt-history.js +57 -0
  107. package/dist/chat/ui/composer/use-prompt-hold.d.ts +6 -0
  108. package/dist/chat/ui/composer/use-prompt-hold.js +48 -0
  109. package/dist/chat/ui/composer/use-take-back.d.ts +13 -0
  110. package/dist/chat/ui/composer/use-take-back.js +82 -0
  111. package/dist/chat/ui/diff/EditorEditDiff.js +4 -3
  112. package/dist/chat/ui/diff/LegacyDiffPool.js +3 -2
  113. package/dist/chat/ui/diff/LegacyEditDiff.js +3 -2
  114. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +3 -2
  115. package/dist/chat/ui/diff/syntax-runtime.d.ts +2 -1
  116. package/dist/chat/ui/diff/syntax-runtime.js +9 -5
  117. package/dist/chat/ui/diff-syntax.d.ts +2 -2
  118. package/dist/chat/ui/diff-syntax.js +1 -2
  119. package/dist/chat/ui/diff-theme.js +10 -9
  120. package/dist/chat/ui/file-links.d.ts +1 -1
  121. package/dist/chat/ui/file-links.js +7 -5
  122. package/dist/chat/ui/highlighter.d.ts +27 -0
  123. package/dist/chat/ui/highlighter.js +151 -0
  124. package/dist/chat/ui/index.d.ts +67 -0
  125. package/dist/chat/ui/index.js +64 -0
  126. package/dist/chat/ui/intelligent-ui/UiReply.js +3 -2
  127. package/dist/chat/ui/intelligent-ui/renderers/content.js +3 -2
  128. package/dist/chat/ui/intelligent-ui/use-ui-links.js +2 -2
  129. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +4 -3
  130. package/dist/chat/ui/markdown-blocks.d.ts +8 -0
  131. package/dist/chat/ui/markdown-blocks.js +260 -12
  132. package/dist/chat/ui/mermaid.d.ts +23 -0
  133. package/dist/chat/ui/mermaid.js +93 -0
  134. package/dist/chat/ui/rows/ForksRow.js +5 -3
  135. package/dist/chat/ui/rows/GeneratedImageRow.js +6 -4
  136. package/dist/chat/ui/rows/MessageRows.d.ts +4 -0
  137. package/dist/chat/ui/rows/MessageRows.js +36 -13
  138. package/dist/chat/ui/rows/Rows.js +3 -1
  139. package/dist/chat/ui/rows/SubagentRow.js +3 -2
  140. package/dist/chat/ui/rows/VisualRow.js +3 -2
  141. package/dist/chat/ui/rows/WorkRows.d.ts +6 -3
  142. package/dist/chat/ui/rows/WorkRows.js +57 -20
  143. package/dist/chat/ui/rows/WorkflowRow.js +3 -2
  144. package/dist/chat/ui/timestamp-format.d.ts +1 -0
  145. package/dist/chat/ui/timestamp-format.js +2 -0
  146. package/dist/chat/ui/use-diff-source-tokens.js +6 -3
  147. package/dist/chat/ui/visual-theme.js +3 -2
  148. package/dist/host.d.ts +9 -6
  149. package/dist/host.js +19 -8
  150. package/dist/index.d.ts +8 -0
  151. package/dist/index.js +9 -0
  152. package/dist/locales/en/agent-chat.d.ts +658 -0
  153. package/dist/locales/en/agent-chat.js +657 -0
  154. package/dist/locales/en/agent-prompts.d.ts +44 -0
  155. package/dist/locales/en/agent-prompts.js +43 -0
  156. package/dist/locales/en/agent-providers.d.ts +132 -0
  157. package/dist/locales/en/agent-providers.js +131 -0
  158. package/dist/locales/en/agent-usage.d.ts +132 -0
  159. package/dist/locales/en/agent-usage.js +131 -0
  160. package/dist/locales/nl/agent-chat.d.ts +658 -0
  161. package/dist/locales/nl/agent-chat.js +657 -0
  162. package/dist/locales/nl/agent-prompts.d.ts +44 -0
  163. package/dist/locales/nl/agent-prompts.js +43 -0
  164. package/dist/locales/nl/agent-providers.d.ts +132 -0
  165. package/dist/locales/nl/agent-providers.js +131 -0
  166. package/dist/locales/nl/agent-usage.d.ts +132 -0
  167. package/dist/locales/nl/agent-usage.js +131 -0
  168. package/dist/locales.js +9 -8
  169. package/dist/prompts/index.d.ts +11 -0
  170. package/dist/prompts/index.js +12 -0
  171. package/dist/prompts/logic/subjects.d.ts +2 -1
  172. package/dist/prompts/logic/subjects.js +6 -4
  173. package/dist/prompts/ui/ApprovalBody.js +6 -4
  174. package/dist/prompts/ui/PromptCard.js +5 -4
  175. package/dist/prompts/ui/PromptView.js +3 -2
  176. package/dist/prompts/ui/QuestionBody.js +3 -2
  177. package/dist/providers/AccountColors.js +2 -2
  178. package/dist/providers/AccountDetail.js +7 -6
  179. package/dist/providers/AccountVariables.js +3 -1
  180. package/dist/providers/AddAccountForm.js +3 -2
  181. package/dist/providers/ProvidersPane.js +4 -3
  182. package/dist/providers/account-actions.d.ts +4 -3
  183. package/dist/providers/account-actions.js +6 -7
  184. package/dist/providers/index.d.ts +16 -0
  185. package/dist/providers/index.js +17 -0
  186. package/dist/providers/provider-abilities.d.ts +2 -1
  187. package/dist/providers/provider-abilities.js +4 -0
  188. package/dist/state/chats.js +4 -2
  189. package/dist/state/index.d.ts +4 -0
  190. package/dist/state/index.js +5 -0
  191. package/dist/testing/index.d.ts +1 -0
  192. package/dist/testing/index.js +2 -0
  193. package/dist/{prompts/logic/prompts.fixtures.d.ts → testing/prompts.d.ts} +1 -1
  194. package/dist/theme.css +13 -3
  195. package/dist/usage/UsageBreakdown.js +3 -2
  196. package/dist/usage/UsageLimits.js +4 -3
  197. package/dist/usage/UsagePage.js +3 -2
  198. package/dist/usage/index.d.ts +15 -0
  199. package/dist/usage/index.js +15 -0
  200. package/package.json +53 -1031
  201. package/src/agents/AccountDot.tsx +3 -1
  202. package/src/agents/accounts.ts +6 -6
  203. package/src/chat/actions.ts +8 -5
  204. package/src/chat/bookmarks.ts +23 -14
  205. package/src/chat/chat-client.ts +8 -0
  206. package/src/chat/composer-send.ts +27 -0
  207. package/src/chat/forks.ts +27 -6
  208. package/src/chat/index.ts +98 -0
  209. package/src/chat/logic/embedded-code.ts +409 -0
  210. package/src/chat/logic/fork.ts +1 -0
  211. package/src/chat/logic/goal.ts +33 -0
  212. package/src/chat/logic/scrubber.ts +6 -5
  213. package/src/chat/logic/thought.ts +40 -0
  214. package/src/chat/logic/thread-cards.ts +2 -0
  215. package/src/chat/logic/timeline.ts +25 -1
  216. package/src/chat/logic/tool-catalog.ts +5 -1
  217. package/src/chat/logic/tools.ts +76 -0
  218. package/src/chat/preferences.ts +26 -3
  219. package/src/chat/reading-width.ts +39 -0
  220. package/src/chat/send-key.ts +38 -0
  221. package/src/chat/ui/BookmarkMarker.tsx +4 -2
  222. package/src/chat/ui/BookmarkSubmenu.tsx +4 -3
  223. package/src/chat/ui/ChatActivity.tsx +14 -10
  224. package/src/chat/ui/ChatReferenceChip.tsx +3 -4
  225. package/src/chat/ui/CodeBlock.tsx +33 -124
  226. package/src/chat/ui/Composer.tsx +212 -1358
  227. package/src/chat/ui/ComposerInput.tsx +5 -4
  228. package/src/chat/ui/EditDiff.tsx +3 -2
  229. package/src/chat/ui/GoalDock.tsx +104 -0
  230. package/src/chat/ui/LimitState.tsx +5 -3
  231. package/src/chat/ui/Markdown.tsx +113 -39
  232. package/src/chat/ui/MermaidBlock.tsx +119 -0
  233. package/src/chat/ui/MessageActions.tsx +13 -8
  234. package/src/chat/ui/Pickers.tsx +8 -7
  235. package/src/chat/ui/PromptComposer.tsx +4 -3
  236. package/src/chat/ui/RowTime.tsx +21 -0
  237. package/src/chat/ui/RunSettings.tsx +9 -4
  238. package/src/chat/ui/ShellCommand.tsx +134 -0
  239. package/src/chat/ui/SubagentInfo.tsx +4 -3
  240. package/src/chat/ui/SubagentStopButton.tsx +4 -3
  241. package/src/chat/ui/SubagentTimeline.tsx +5 -1
  242. package/src/chat/ui/Timeline.tsx +167 -105
  243. package/src/chat/ui/TimelineMenu.tsx +42 -7
  244. package/src/chat/ui/UnifiedDiff.tsx +3 -2
  245. package/src/chat/ui/VisualFrame.tsx +6 -7
  246. package/src/chat/ui/code-theme.ts +4 -4
  247. package/src/chat/ui/composer/ComposerControls.tsx +147 -0
  248. package/src/chat/ui/composer/ComposerMenu.tsx +138 -0
  249. package/src/chat/ui/composer/DraftParts.tsx +86 -0
  250. package/src/chat/ui/composer/QueuedMessages.tsx +64 -0
  251. package/src/chat/ui/composer/key-handler.ts +174 -0
  252. package/src/chat/ui/composer/keys.ts +32 -10
  253. package/src/chat/ui/composer/placeholder.ts +48 -0
  254. package/src/chat/ui/composer/surface.ts +45 -0
  255. package/src/chat/ui/composer/use-chat-controls.ts +134 -0
  256. package/src/chat/ui/composer/use-compaction-offer.ts +25 -0
  257. package/src/chat/ui/composer/use-composer-draft.ts +71 -0
  258. package/src/chat/ui/composer/use-composer-menus.ts +289 -0
  259. package/src/chat/ui/composer/use-composer-submit.ts +163 -0
  260. package/src/chat/ui/composer/use-draft-files.ts +135 -0
  261. package/src/chat/ui/composer/use-notice.ts +28 -0
  262. package/src/chat/ui/composer/use-pending-requests.ts +23 -0
  263. package/src/chat/ui/composer/use-prompt-history.ts +76 -0
  264. package/src/chat/ui/composer/use-prompt-hold.ts +58 -0
  265. package/src/chat/ui/composer/use-take-back.ts +91 -0
  266. package/src/chat/ui/diff/DiffFallbackBoundary.tsx +2 -2
  267. package/src/chat/ui/diff/EditorEditDiff.tsx +4 -3
  268. package/src/chat/ui/diff/LegacyDiffPool.tsx +3 -2
  269. package/src/chat/ui/diff/LegacyEditDiff.tsx +3 -2
  270. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +3 -2
  271. package/src/chat/ui/diff/syntax-runtime.ts +10 -5
  272. package/src/chat/ui/diff-syntax.ts +2 -2
  273. package/src/chat/ui/diff-theme.ts +10 -9
  274. package/src/chat/ui/file-links.ts +7 -5
  275. package/src/chat/ui/highlighter.ts +185 -0
  276. package/src/chat/ui/index.ts +109 -0
  277. package/src/chat/ui/intelligent-ui/UiReply.tsx +5 -4
  278. package/src/chat/ui/intelligent-ui/renderers/content.tsx +3 -2
  279. package/src/chat/ui/intelligent-ui/use-ui-links.ts +2 -2
  280. package/src/chat/ui/intelligent-ui/use-ui-queries.ts +4 -3
  281. package/src/chat/ui/markdown-blocks.ts +300 -12
  282. package/src/chat/ui/mermaid.ts +118 -0
  283. package/src/chat/ui/rows/ForksRow.tsx +5 -3
  284. package/src/chat/ui/rows/GeneratedImageRow.tsx +6 -4
  285. package/src/chat/ui/rows/MessageRows.tsx +73 -18
  286. package/src/chat/ui/rows/Rows.tsx +14 -1
  287. package/src/chat/ui/rows/SubagentRow.tsx +3 -2
  288. package/src/chat/ui/rows/VisualRow.tsx +3 -2
  289. package/src/chat/ui/rows/WorkRows.tsx +148 -47
  290. package/src/chat/ui/rows/WorkflowRow.tsx +3 -2
  291. package/src/chat/ui/timestamp-format.ts +2 -0
  292. package/src/chat/ui/use-diff-source-tokens.ts +10 -4
  293. package/src/chat/ui/visual-theme.ts +3 -2
  294. package/src/host.ts +31 -15
  295. package/src/index.ts +49 -0
  296. package/src/locales/en/agent-chat.ts +657 -0
  297. package/src/locales/en/agent-prompts.ts +43 -0
  298. package/src/locales/en/agent-providers.ts +131 -0
  299. package/src/locales/en/agent-usage.ts +131 -0
  300. package/src/locales/nl/agent-chat.ts +657 -0
  301. package/src/locales/nl/agent-prompts.ts +43 -0
  302. package/src/locales/nl/agent-providers.ts +131 -0
  303. package/src/locales/nl/agent-usage.ts +132 -0
  304. package/src/locales.ts +9 -8
  305. package/src/prompts/index.ts +35 -0
  306. package/src/prompts/logic/subjects.ts +12 -4
  307. package/src/prompts/ui/ApprovalBody.tsx +6 -4
  308. package/src/prompts/ui/PromptCard.tsx +11 -4
  309. package/src/prompts/ui/PromptView.tsx +3 -2
  310. package/src/prompts/ui/QuestionBody.tsx +3 -2
  311. package/src/providers/AccountColors.tsx +2 -2
  312. package/src/providers/AccountDetail.tsx +13 -7
  313. package/src/providers/AccountVariables.tsx +3 -1
  314. package/src/providers/AddAccountForm.tsx +3 -2
  315. package/src/providers/ProvidersPane.tsx +4 -3
  316. package/src/providers/account-actions.ts +7 -7
  317. package/src/providers/index.ts +17 -0
  318. package/src/providers/provider-abilities.ts +6 -1
  319. package/src/state/chats.ts +4 -2
  320. package/src/state/index.ts +39 -0
  321. package/src/testing/index.ts +2 -0
  322. package/src/{prompts/logic/prompts.fixtures.ts → testing/prompts.ts} +1 -1
  323. package/src/theme.css +13 -3
  324. package/src/usage/UsageBreakdown.tsx +3 -2
  325. package/src/usage/UsageLimits.tsx +4 -3
  326. package/src/usage/UsagePage.tsx +3 -2
  327. package/src/usage/index.ts +16 -0
  328. package/dist/locales/en/agent-chat.json +0 -597
  329. package/dist/locales/en/agent-prompts.json +0 -43
  330. package/dist/locales/en/agent-providers.json +0 -131
  331. package/dist/locales/en/agent-usage.json +0 -131
  332. package/dist/locales/nl/agent-chat.json +0 -597
  333. package/dist/locales/nl/agent-prompts.json +0 -43
  334. package/dist/locales/nl/agent-providers.json +0 -131
  335. package/dist/locales/nl/agent-usage.json +0 -131
  336. package/src/locales/en/agent-chat.json +0 -597
  337. package/src/locales/en/agent-prompts.json +0 -43
  338. package/src/locales/en/agent-providers.json +0 -131
  339. package/src/locales/en/agent-usage.json +0 -131
  340. package/src/locales/nl/agent-chat.json +0 -597
  341. package/src/locales/nl/agent-prompts.json +0 -43
  342. package/src/locales/nl/agent-providers.json +0 -131
  343. package/src/locales/nl/agent-usage.json +0 -131
  344. /package/dist/{prompts/logic/prompts.fixtures.js → testing/prompts.js} +0 -0
@@ -1,11 +1,15 @@
1
1
  import type { SyntaxNode, Tree } from '@lezer/common';
2
+ import { modSends, type ChatSendKey } from '../../send-key';
2
3
 
3
- export type EnterAction = 'send' | 'newline' | 'continue-list' | 'leave-list';
4
+ /* `send-alternate` sends with the delivery a running turn does not get by default; `send-and-new` also opens a new chat once it went. */
5
+ export type EnterAction = 'send' | 'send-alternate' | 'send-and-new' | 'newline' | 'continue-list' | 'leave-list';
4
6
 
5
7
  export interface EnterKeys {
6
8
  shift: boolean;
7
9
  /* Cmd on macOS, Ctrl elsewhere. */
8
10
  mod: boolean;
11
+ /* Option on macOS. */
12
+ alt?: boolean;
9
13
  }
10
14
 
11
15
  export interface ListItem {
@@ -23,6 +27,12 @@ export interface EnterContext {
23
27
  list: ListItem | null;
24
28
  /* The caret's offset in its line. */
25
29
  column: number;
30
+ /* Which key sends; `enter` when left out. */
31
+ sendKey?: ChatSendKey;
32
+ /* The message runs over more than one line, where `mod-enter-multiline` lets Enter add a line. */
33
+ multiline?: boolean;
34
+ /* The host opens a new chat after a send, which Mod+Alt+Enter asks for. */
35
+ startsNewChat?: boolean;
26
36
  }
27
37
 
28
38
  const LIST_ITEM = /^([ \t]*)(?:([-*+])|(\d{1,9})([.)]))([ \t]+)(\[[ xX]\](?:[ \t]+|$))?/;
@@ -41,23 +51,35 @@ export function listItemAt(line: string): ListItem | null {
41
51
  /*
42
52
  * Enter sends, except where whoever types is still writing: inside a fence nobody has closed yet
43
53
  * it adds a line, and in a list it starts the next item, or leaves the list from an empty one, so
44
- * a second Enter breaks out. Shift adds a plain line and Mod sends from anywhere.
54
+ * a second Enter breaks out. Shift adds a plain line and Mod sends from anywhere. Where the send key
55
+ * is Mod+Enter, Enter adds a line instead of sending. Alt sends the other way (queue or steer), and so
56
+ * does Mod+Shift+Enter where Mod+Enter is the send key; Mod+Alt+Enter is the send that opens a new chat.
45
57
  */
46
- export function enterAction(keys: EnterKeys, { inOpenFence, list, column }: EnterContext): EnterAction {
58
+ export function enterAction(
59
+ keys: EnterKeys,
60
+ { inOpenFence, list, column, sendKey = 'enter', multiline = false, startsNewChat = false }: EnterContext
61
+ ): EnterAction {
62
+ const modOnly = modSends(sendKey, multiline);
47
63
  if (keys.mod) {
48
- return 'send';
64
+ if (keys.alt && startsNewChat) {
65
+ return 'send-and-new';
66
+ }
67
+ return keys.alt || (modOnly && keys.shift) ? 'send-alternate' : 'send';
49
68
  }
50
69
  if (keys.shift || inOpenFence) {
51
70
  return 'newline';
52
71
  }
53
- if (list === null) {
54
- return 'send';
72
+ if (list !== null) {
73
+ // A caret in front of the marker moves the item down rather than splitting its marker.
74
+ if (column < list.prefix.length) {
75
+ return 'newline';
76
+ }
77
+ return list.empty ? 'leave-list' : 'continue-list';
55
78
  }
56
- // A caret in front of the marker moves the item down rather than splitting its marker.
57
- if (column < list.prefix.length) {
58
- return 'newline';
79
+ if (keys.alt) {
80
+ return 'send-alternate';
59
81
  }
60
- return list.empty ? 'leave-list' : 'continue-list';
82
+ return modOnly ? 'newline' : 'send';
61
83
  }
62
84
 
63
85
  /* The innermost fenced code block around `pos`, if any. */
@@ -0,0 +1,48 @@
1
+ import { useMemo } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useChatHost } from '../../../host';
4
+ import { useChatScope } from '../../../scope';
5
+
6
+ /* The empty box names its sigils as key caps, so they read as keys to press rather than as punctuation. */
7
+ function hintedPlaceholder(lead: string, joiner: string, hints: ReadonlyArray<{ key: string; label: string }>): HTMLElement {
8
+ const root = document.createElement('span');
9
+ root.className = 'composer-hints';
10
+ const extra = document.createElement('span');
11
+ extra.className = 'composer-hints-extra';
12
+ extra.append(joiner);
13
+ for (const hint of hints) {
14
+ const cap = document.createElement('kbd');
15
+ cap.textContent = hint.key;
16
+ extra.append(cap, hint.label);
17
+ }
18
+ root.append(lead, extra);
19
+ return root;
20
+ }
21
+
22
+ interface PlaceholderInput {
23
+ chatId: string;
24
+ disabled: boolean;
25
+ readOnly: boolean;
26
+ mentionable: boolean;
27
+ hasSkills: boolean;
28
+ }
29
+
30
+ /* What the empty box says: why nothing can be written, or the host's words and the keys that open a picker. */
31
+ export function useHintedPlaceholder({ chatId, disabled, readOnly, mentionable, hasSkills }: PlaceholderInput): string | HTMLElement {
32
+ const { t } = useTranslation('agent-chat');
33
+ const scope = useChatScope();
34
+ const lead = useChatHost().useComposerPlaceholder(scope.id, chatId);
35
+ return useMemo(() => {
36
+ if (disabled) {
37
+ return t('composer.placeholder.disconnected');
38
+ }
39
+ if (readOnly) {
40
+ return t('composer.placeholder.readOnly');
41
+ }
42
+ return hintedPlaceholder(lead ?? t('composer.placeholder.lead'), t('composer.placeholder.joiner'), [
43
+ { key: '/', label: t('composer.placeholder.commands') },
44
+ ...(mentionable ? [{ key: '@', label: t('composer.placeholder.files') }] : []),
45
+ ...(hasSkills ? [{ key: '$', label: t('composer.placeholder.skills') }] : [])
46
+ ]);
47
+ }, [disabled, readOnly, lead, mentionable, hasSkills, t]);
48
+ }
@@ -0,0 +1,45 @@
1
+ /* Anything with an action of its own; `data-composer-action` marks one a role cannot name, such as a control of the host's. */
2
+ const ACTIONS = [
3
+ 'a',
4
+ 'button',
5
+ 'input',
6
+ 'select',
7
+ 'textarea',
8
+ 'label',
9
+ 'summary',
10
+ '[contenteditable]:not([contenteditable="false"])',
11
+ '[tabindex]:not([tabindex="-1"])',
12
+ '[role="button"]',
13
+ '[role="link"]',
14
+ '[role="menuitem"]',
15
+ '[role="menuitemcheckbox"]',
16
+ '[role="menuitemradio"]',
17
+ '[role="option"]',
18
+ '[role="listbox"]',
19
+ '[role="checkbox"]',
20
+ '[role="radio"]',
21
+ '[role="switch"]',
22
+ '[role="tab"]',
23
+ '[role="slider"]',
24
+ '[role="combobox"]',
25
+ '[data-composer-action]'
26
+ ].join(', ');
27
+
28
+ /*
29
+ * Where a pointer is on the composer: in the text field, on an action, or on the space around them,
30
+ * which stands in for the text field. A target outside the surface is an action, as an event from a
31
+ * popup portaled out of it still reaches the surface through React.
32
+ */
33
+ export function surfacePartOf(target: EventTarget | null, surface: Element): 'input' | 'action' | 'surface' {
34
+ // Not `instanceof Element`, which fails for an element of another window.
35
+ const element = target as Element | null;
36
+ if (typeof element?.closest !== 'function' || !surface.contains(element)) {
37
+ return 'action';
38
+ }
39
+ const input = element.closest('.cm-editor');
40
+ if (input !== null && surface.contains(input)) {
41
+ return 'input';
42
+ }
43
+ const action = element.closest(ACTIONS);
44
+ return action !== null && surface.contains(action) ? 'action' : 'surface';
45
+ }
@@ -0,0 +1,134 @@
1
+ import { useRef, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import type { AgentKind, ChatInfo, ModelSelection, RuntimeMode } from '@adecore/agent-contracts';
4
+ import { useChatHost } from '../../../host';
5
+ import { useChatScope } from '../../../scope';
6
+ import { errorCode } from '../../../transport';
7
+ import { useChatActions } from '../../actions';
8
+ import { rememberChatAccount, rememberChatPreferences, rememberChatSelection } from '../../preferences';
9
+ import { composerStopOf } from '../../subagent-list';
10
+ import type { ComposerNotice } from './use-notice';
11
+
12
+ interface ControlsInput {
13
+ chatId: string;
14
+ info: ChatInfo;
15
+ notice: ComposerNotice;
16
+ onRetarget(provider: AgentKind, selection: ModelSelection): Promise<void>;
17
+ }
18
+
19
+ /* What the composer does to the chat rather than to its draft: its settings, a stop, a clear and a compaction. */
20
+ export function useChatControls({ chatId, info, notice: { setNotice, showError }, onRetarget }: ControlsInput) {
21
+ const { t } = useTranslation('agent-chat');
22
+ const host = useChatHost();
23
+ const scope = useChatScope();
24
+ const actions = useChatActions();
25
+ const configuring = useRef(false);
26
+ const [configurationPending, setConfigurationPending] = useState(false);
27
+ const [modelPickerOpen, setModelPickerOpen] = useState(false);
28
+ const [confirmClear, setConfirmClear] = useState(false);
29
+
30
+ /* One configuration at a time; a second pick while one is on its way is dropped. */
31
+ const runConfiguration = (work: () => Promise<void>): void => {
32
+ if (configuring.current) {
33
+ return;
34
+ }
35
+ configuring.current = true;
36
+ setConfigurationPending(true);
37
+ void work()
38
+ .catch(showError)
39
+ .finally(() => {
40
+ configuring.current = false;
41
+ setConfigurationPending(false);
42
+ });
43
+ };
44
+
45
+ const configure = (patch: { selection?: ModelSelection; runtimeMode?: RuntimeMode; account?: string }): void => {
46
+ runConfiguration(() =>
47
+ actions.configure(chatId, patch).then(() => {
48
+ if (patch.selection) {
49
+ rememberChatSelection(info.provider, patch.selection);
50
+ }
51
+ if (patch.runtimeMode) {
52
+ rememberChatPreferences({ runtimeMode: patch.runtimeMode });
53
+ }
54
+ if (patch.account) {
55
+ rememberChatAccount(scope.id, info.provider, patch.account);
56
+ }
57
+ })
58
+ );
59
+ };
60
+
61
+ /* A model of another CLI re-points the whole chat; one of this CLI's own is a configure. */
62
+ const chooseModel = (provider: AgentKind, slug: string): void => {
63
+ const selection: ModelSelection = { model: slug, options: {} };
64
+ if (provider !== info.provider) {
65
+ runConfiguration(() => onRetarget(provider, selection).then(() => rememberChatSelection(provider, selection)));
66
+ return;
67
+ }
68
+ configure({ selection });
69
+ };
70
+
71
+ const stop = (shiftKey: boolean): void => {
72
+ if (composerStopOf(shiftKey) === 'turn') {
73
+ void actions.stopTurn(chatId, false).catch(showError);
74
+ return;
75
+ }
76
+ host.confirm.stopSubagents(scope.id, chatId, () => void actions.stopTurn(chatId, true).catch(showError));
77
+ };
78
+
79
+ /* The host decides whether a turn is in the way; only its refusal asks the person first. */
80
+ const clearThread = async (): Promise<void> => {
81
+ try {
82
+ await actions.clear(chatId, false);
83
+ } catch (e) {
84
+ if (errorCode(e) === 'chat-busy') {
85
+ setConfirmClear(true);
86
+ return;
87
+ }
88
+ setNotice(t('composer.notice.clearFailed'));
89
+ }
90
+ };
91
+
92
+ const forceClearThread = async (): Promise<void> => {
93
+ await actions.clear(chatId, true);
94
+ setConfirmClear(false);
95
+ };
96
+
97
+ const compact = (): void => {
98
+ void actions.compact(chatId).catch(() => setNotice(t('composer.notice.compactFailed')));
99
+ };
100
+
101
+ /* Runs one of the composer's own commands; false for a name it does not handle. */
102
+ const runCommand = (name: string): boolean => {
103
+ switch (name) {
104
+ case 'model':
105
+ setModelPickerOpen(true);
106
+ return true;
107
+ case 'compact':
108
+ void actions.compact(chatId).catch(() => undefined);
109
+ return true;
110
+ case 'clear':
111
+ void clearThread();
112
+ return true;
113
+ default:
114
+ return false;
115
+ }
116
+ };
117
+
118
+ return {
119
+ configurationPending,
120
+ configure,
121
+ chooseModel,
122
+ chooseAccount: (account: string): void => configure({ account }),
123
+ stop,
124
+ compact,
125
+ runCommand,
126
+ modelPickerOpen,
127
+ setModelPickerOpen,
128
+ confirmClear,
129
+ cancelClear: (): void => setConfirmClear(false),
130
+ forceClearThread
131
+ };
132
+ }
133
+
134
+ export type ChatControls = ReturnType<typeof useChatControls>;
@@ -0,0 +1,25 @@
1
+ import type { ChatInfo, ChatItem, ProviderCapabilities } from '@adecore/agent-contracts';
2
+ import { useNow } from '@adecore/ui';
3
+ import { useChatRow } from '../../../state/chats';
4
+ import { RESUME_COMPACTION_TOKENS, resumeCompactionOffer } from '../../logic/resume-compaction';
5
+ import { useResumeCompactionDismissal } from '../../resume-compaction-dismissals';
6
+
7
+ /* The offer to fold a long context before a chat that sat idle goes on, or null when there is none. */
8
+ export function useCompactionOffer(chatId: string, info: ChatInfo, compaction: ProviderCapabilities['compaction'] | undefined) {
9
+ const order = useChatRow(chatId, (row) => row?.order);
10
+ const items = useChatRow(chatId, (row) => row?.structure);
11
+ const dismissedTurnId = useResumeCompactionDismissal(chatId);
12
+ // The cheap half of the offer, so a chat that can never make one keeps no timer.
13
+ const couldOffer = compaction !== undefined && compaction !== 'none' && info.usage.contextTokens >= RESUME_COMPACTION_TOKENS;
14
+ const now = useNow(60_000, couldOffer);
15
+ if (!couldOffer) {
16
+ return null;
17
+ }
18
+ return resumeCompactionOffer({
19
+ info,
20
+ compaction,
21
+ items: (order ?? []).map((id) => items?.[id]).filter((item): item is ChatItem => item !== undefined),
22
+ dismissedTurnId,
23
+ now
24
+ });
25
+ }
@@ -0,0 +1,71 @@
1
+ import { useContext, useEffect, useRef, useState, type Dispatch, type RefObject, type SetStateAction } from 'react';
2
+ import { EMPTY_DRAFT, joinDraftText, readDraft, takeDraftOffers, writeDraft, type ChatDraft } from '../../drafts';
3
+ import type { ComposerInputHandle } from '../ComposerInput';
4
+ import { QuoteTakerContext } from '../quote-selection';
5
+
6
+ export interface ComposerDraft {
7
+ draft: ChatDraft;
8
+ setDraft: Dispatch<SetStateAction<ChatDraft>>;
9
+ /* Taking a queued message back waits on the machine, and what was typed meanwhile is what it merges with. */
10
+ latest: RefObject<ChatDraft>;
11
+ /* The mentions and skills default to the draft's own as last rendered. */
12
+ setText(next: string, mentions?: string[], skills?: string[]): void;
13
+ clear(): void;
14
+ removeQuote(): void;
15
+ removeChat(id: string): void;
16
+ removeAttachment(index: number): void;
17
+ }
18
+
19
+ /* The chat's unsent prompt, kept in storage as it changes and open to text and quotes handed in from outside. */
20
+ export function useComposerDraft(chatId: string, inputRef: RefObject<ComposerInputHandle | null>): ComposerDraft {
21
+ const [draft, setDraft] = useState<ChatDraft>(() => readDraft(chatId));
22
+ const latest = useRef(draft);
23
+ const registerQuoteTaker = useContext(QuoteTakerContext);
24
+
25
+ useEffect(() => {
26
+ latest.current = draft;
27
+ writeDraft(chatId, draft);
28
+ }, [chatId, draft]);
29
+
30
+ useEffect(
31
+ () =>
32
+ takeDraftOffers(chatId, (offered) => {
33
+ setDraft((current) => ({ ...current, text: joinDraftText(current.text, offered) }));
34
+ inputRef.current?.focus();
35
+ }),
36
+ [chatId, inputRef]
37
+ );
38
+
39
+ useEffect(
40
+ () =>
41
+ registerQuoteTaker?.((selected, itemId) => {
42
+ setDraft((current) => ({ ...current, quote: selected, quoteSource: itemId }));
43
+ inputRef.current?.focus();
44
+ }),
45
+ [registerQuoteTaker, inputRef]
46
+ );
47
+
48
+ const setText = (next: string, mentions = draft.mentions, chosen = draft.skills): void => {
49
+ setDraft((current) => ({ ...current, text: next, mentions, skills: chosen }));
50
+ };
51
+
52
+ const clear = (): void => {
53
+ setDraft(EMPTY_DRAFT);
54
+ };
55
+
56
+ const removeQuote = (): void => {
57
+ setDraft((current) => ({ ...current, quote: '', quoteSource: null }));
58
+ inputRef.current?.focus();
59
+ };
60
+
61
+ const removeChat = (id: string): void => {
62
+ setDraft((current) => ({ ...current, chats: current.chats.filter((entry) => entry !== id) }));
63
+ inputRef.current?.focus();
64
+ };
65
+
66
+ const removeAttachment = (index: number): void => {
67
+ setDraft((current) => ({ ...current, attachments: current.attachments.filter((_, i) => i !== index) }));
68
+ };
69
+
70
+ return { draft, setDraft, latest, setText, clear, removeQuote, removeChat, removeAttachment };
71
+ }