@adecore/agents-react 0.31.12 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/dist/agents/AccountDot.js +57 -6
  2. package/dist/agents/AgentIcon.js +88 -12
  3. package/dist/agents/ModelOptionControl.js +153 -18
  4. package/dist/agents/ProviderLogo.js +49 -4
  5. package/dist/agents/account-limits.js +17 -14
  6. package/dist/agents/accounts.js +99 -67
  7. package/dist/agents/agent-marks.js +5 -3
  8. package/dist/agents/model-name.js +42 -31
  9. package/dist/agents/model-options.js +8 -8
  10. package/dist/agents/model-requirement.js +17 -14
  11. package/dist/agents/option-words.d.ts +7 -0
  12. package/dist/agents/option-words.js +35 -0
  13. package/dist/agents/provider-paths.js +6 -6
  14. package/dist/agents/status-look.js +32 -12
  15. package/dist/chat/account-choice.d.ts +13 -0
  16. package/dist/chat/account-choice.js +90 -20
  17. package/dist/chat/actions.js +126 -59
  18. package/dist/chat/activity.js +5 -5
  19. package/dist/chat/attachments.js +74 -53
  20. package/dist/chat/bookmarks.js +58 -48
  21. package/dist/chat/chat-client.js +344 -263
  22. package/dist/chat/chat-references.js +3 -3
  23. package/dist/chat/composer-effort.d.ts +5 -0
  24. package/dist/chat/composer-effort.js +26 -0
  25. package/dist/chat/composer-send.js +13 -13
  26. package/dist/chat/drafts.js +115 -79
  27. package/dist/chat/forks.js +81 -24
  28. package/dist/chat/guards.js +15 -43
  29. package/dist/chat/index.d.ts +3 -1
  30. package/dist/chat/index.js +3 -2
  31. package/dist/chat/logic/ansi.js +170 -167
  32. package/dist/chat/logic/answers.js +2 -2
  33. package/dist/chat/logic/bookmarks.js +19 -19
  34. package/dist/chat/logic/command-looks.js +138 -96
  35. package/dist/chat/logic/context-usage.js +13 -9
  36. package/dist/chat/logic/continue-after-stop.js +15 -19
  37. package/dist/chat/logic/effort.d.ts +14 -0
  38. package/dist/chat/logic/effort.js +34 -0
  39. package/dist/chat/logic/embedded-code.js +387 -326
  40. package/dist/chat/logic/fork.js +134 -110
  41. package/dist/chat/logic/generated-image.js +54 -23
  42. package/dist/chat/logic/goal.js +28 -20
  43. package/dist/chat/logic/handback.js +6 -6
  44. package/dist/chat/logic/json.js +2 -2
  45. package/dist/chat/logic/limit.js +46 -30
  46. package/dist/chat/logic/picker-entries.d.ts +5 -3
  47. package/dist/chat/logic/picker-entries.js +83 -43
  48. package/dist/chat/logic/resume-compaction.d.ts +14 -1
  49. package/dist/chat/logic/resume-compaction.js +93 -24
  50. package/dist/chat/logic/scrubber.js +188 -136
  51. package/dist/chat/logic/thought.js +13 -16
  52. package/dist/chat/logic/thread-cards.js +60 -48
  53. package/dist/chat/logic/timeline-copy.js +30 -38
  54. package/dist/chat/logic/timeline-target.js +92 -63
  55. package/dist/chat/logic/timeline.js +499 -355
  56. package/dist/chat/logic/tool-catalog.js +54 -34
  57. package/dist/chat/logic/tools.js +106 -82
  58. package/dist/chat/logic/visual-height.js +18 -18
  59. package/dist/chat/logic/visual-viewport.js +6 -3
  60. package/dist/chat/logic/welcome.js +9 -9
  61. package/dist/chat/logic/workflow.js +45 -34
  62. package/dist/chat/mentions.js +149 -109
  63. package/dist/chat/persisted-json.js +51 -54
  64. package/dist/chat/preferences.d.ts +4 -0
  65. package/dist/chat/preferences.js +162 -84
  66. package/dist/chat/prompt-hold.js +9 -9
  67. package/dist/chat/quote.js +21 -30
  68. package/dist/chat/reading-width.js +12 -10
  69. package/dist/chat/recent-messages.js +34 -21
  70. package/dist/chat/resume-compaction-dismissals.js +25 -5
  71. package/dist/chat/runtime-modes.js +3 -3
  72. package/dist/chat/send-key.js +11 -7
  73. package/dist/chat/stash.js +89 -69
  74. package/dist/chat/subagent-conversation.js +181 -139
  75. package/dist/chat/subagent-list.js +65 -67
  76. package/dist/chat/subagent-support.js +12 -7
  77. package/dist/chat/subagent-view.js +132 -44
  78. package/dist/chat/thumbnails.js +88 -60
  79. package/dist/chat/timeline-flash.js +24 -12
  80. package/dist/chat/timeline-scroll.js +116 -86
  81. package/dist/chat/ui/AccountPill.js +126 -15
  82. package/dist/chat/ui/AnsiOutput.js +62 -6
  83. package/dist/chat/ui/BookmarkMarker.js +231 -41
  84. package/dist/chat/ui/BookmarkSubmenu.js +165 -18
  85. package/dist/chat/ui/ChatActivity.js +649 -70
  86. package/dist/chat/ui/ChatReferenceChip.js +104 -9
  87. package/dist/chat/ui/CodeBlock.js +132 -58
  88. package/dist/chat/ui/Composer.js +866 -132
  89. package/dist/chat/ui/ComposerInput.js +309 -120
  90. package/dist/chat/ui/DiffPool.js +75 -14
  91. package/dist/chat/ui/EditDiff.js +160 -21
  92. package/dist/chat/ui/FadingWords.js +32 -3
  93. package/dist/chat/ui/GoalDock.js +235 -42
  94. package/dist/chat/ui/ImageView.js +617 -61
  95. package/dist/chat/ui/LimitState.js +446 -72
  96. package/dist/chat/ui/Markdown.js +991 -173
  97. package/dist/chat/ui/MermaidBlock.js +238 -68
  98. package/dist/chat/ui/MessageActions.js +251 -39
  99. package/dist/chat/ui/ModelMarks.js +55 -5
  100. package/dist/chat/ui/Pickers.js +664 -113
  101. package/dist/chat/ui/PromptComposer.js +281 -51
  102. package/dist/chat/ui/QuoteButton.js +151 -57
  103. package/dist/chat/ui/ResumeCompactionDock.d.ts +6 -2
  104. package/dist/chat/ui/ResumeCompactionDock.js +141 -6
  105. package/dist/chat/ui/RowTime.js +59 -5
  106. package/dist/chat/ui/RunSettings.js +1744 -154
  107. package/dist/chat/ui/Scrubber.js +517 -88
  108. package/dist/chat/ui/ShellCommand.js +183 -107
  109. package/dist/chat/ui/SubagentControls.js +212 -24
  110. package/dist/chat/ui/SubagentInfo.js +170 -13
  111. package/dist/chat/ui/SubagentStopButton.js +115 -24
  112. package/dist/chat/ui/SubagentTimeline.js +357 -91
  113. package/dist/chat/ui/Timeline.js +988 -476
  114. package/dist/chat/ui/TimelineMenu.js +552 -37
  115. package/dist/chat/ui/UnifiedDiff.js +234 -27
  116. package/dist/chat/ui/UploadThumb.js +37 -7
  117. package/dist/chat/ui/VisualDialogs.js +251 -20
  118. package/dist/chat/ui/VisualFrame.js +321 -95
  119. package/dist/chat/ui/Welcome.js +72 -7
  120. package/dist/chat/ui/chips.js +1 -1
  121. package/dist/chat/ui/code-lines.js +36 -36
  122. package/dist/chat/ui/code-streaming.js +1 -1
  123. package/dist/chat/ui/code-theme.js +7 -7
  124. package/dist/chat/ui/composer/ComposerControls.js +329 -21
  125. package/dist/chat/ui/composer/ComposerMenu.js +358 -30
  126. package/dist/chat/ui/composer/DraftParts.js +185 -11
  127. package/dist/chat/ui/composer/QueuedMessages.js +138 -13
  128. package/dist/chat/ui/composer/chips.js +29 -19
  129. package/dist/chat/ui/composer/editor.js +79 -63
  130. package/dist/chat/ui/composer/insert.js +26 -12
  131. package/dist/chat/ui/composer/key-handler.js +180 -127
  132. package/dist/chat/ui/composer/keys.js +90 -73
  133. package/dist/chat/ui/composer/menu-aria.js +18 -9
  134. package/dist/chat/ui/composer/placeholder.js +78 -31
  135. package/dist/chat/ui/composer/surface.js +13 -37
  136. package/dist/chat/ui/composer/use-chat-controls.js +230 -90
  137. package/dist/chat/ui/composer/use-compaction-offer.js +50 -18
  138. package/dist/chat/ui/composer/use-composer-draft.js +65 -34
  139. package/dist/chat/ui/composer/use-composer-menus.js +478 -193
  140. package/dist/chat/ui/composer/use-composer-submit.js +251 -109
  141. package/dist/chat/ui/composer/use-continuable-turn.js +33 -6
  142. package/dist/chat/ui/composer/use-draft-files.js +245 -93
  143. package/dist/chat/ui/composer/use-effort-stepper.d.ts +13 -0
  144. package/dist/chat/ui/composer/use-effort-stepper.js +88 -0
  145. package/dist/chat/ui/composer/use-notice.js +61 -16
  146. package/dist/chat/ui/composer/use-pending-requests.js +38 -17
  147. package/dist/chat/ui/composer/use-prompt-history.js +117 -45
  148. package/dist/chat/ui/composer/use-prompt-hold.js +119 -35
  149. package/dist/chat/ui/composer/use-take-back.js +94 -72
  150. package/dist/chat/ui/diff/ApprovalReview.js +101 -23
  151. package/dist/chat/ui/diff/DiffFallbackBoundary.js +21 -13
  152. package/dist/chat/ui/diff/DiffOmitted.js +56 -6
  153. package/dist/chat/ui/diff/DiffStack.js +92 -8
  154. package/dist/chat/ui/diff/DiffUnavailable.js +56 -6
  155. package/dist/chat/ui/diff/EditorEditDiff.js +263 -51
  156. package/dist/chat/ui/diff/EditorPatchDiff.js +39 -14
  157. package/dist/chat/ui/diff/LegacyDiffPool.js +27 -10
  158. package/dist/chat/ui/diff/LegacyEditDiff.js +97 -20
  159. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +172 -42
  160. package/dist/chat/ui/diff/RawDiff.js +65 -5
  161. package/dist/chat/ui/diff/ReviewDiff.js +77 -5
  162. package/dist/chat/ui/diff/diff-props.js +1 -1
  163. package/dist/chat/ui/diff/diff-source-budget.js +46 -35
  164. package/dist/chat/ui/diff/editor-edit-model.js +18 -14
  165. package/dist/chat/ui/diff/review-plan.js +63 -40
  166. package/dist/chat/ui/diff/review-settle.js +24 -9
  167. package/dist/chat/ui/diff/syntax-runtime.js +236 -201
  168. package/dist/chat/ui/diff/use-review-stack.js +146 -25
  169. package/dist/chat/ui/diff-syntax.js +70 -58
  170. package/dist/chat/ui/diff-theme.js +31 -12
  171. package/dist/chat/ui/file-links.js +39 -10
  172. package/dist/chat/ui/find-reveal.js +29 -8
  173. package/dist/chat/ui/full-diff.js +17 -12
  174. package/dist/chat/ui/highlighter.js +143 -113
  175. package/dist/chat/ui/icons.js +16 -7
  176. package/dist/chat/ui/index.js +1 -1
  177. package/dist/chat/ui/intelligent-ui/UiBlockFrame.js +556 -82
  178. package/dist/chat/ui/intelligent-ui/UiFallbackPart.js +73 -5
  179. package/dist/chat/ui/intelligent-ui/UiReply.js +666 -262
  180. package/dist/chat/ui/intelligent-ui/block-local.js +59 -31
  181. package/dist/chat/ui/intelligent-ui/chart-data.js +77 -67
  182. package/dist/chat/ui/intelligent-ui/node-text.js +77 -91
  183. package/dist/chat/ui/intelligent-ui/registry.js +46 -46
  184. package/dist/chat/ui/intelligent-ui/render-context.js +1 -1
  185. package/dist/chat/ui/intelligent-ui/renderers/base-land.js +1 -1
  186. package/dist/chat/ui/intelligent-ui/renderers/binding.js +3 -3
  187. package/dist/chat/ui/intelligent-ui/renderers/chart.js +1223 -123
  188. package/dist/chat/ui/intelligent-ui/renderers/choices.js +312 -34
  189. package/dist/chat/ui/intelligent-ui/renderers/content.js +1241 -86
  190. package/dist/chat/ui/intelligent-ui/renderers/data.js +619 -54
  191. package/dist/chat/ui/intelligent-ui/renderers/inputs.js +868 -67
  192. package/dist/chat/ui/intelligent-ui/renderers/links.js +366 -62
  193. package/dist/chat/ui/intelligent-ui/renderers/map-slots.js +118 -60
  194. package/dist/chat/ui/intelligent-ui/renderers/map-style.js +85 -78
  195. package/dist/chat/ui/intelligent-ui/renderers/map-view.js +282 -217
  196. package/dist/chat/ui/intelligent-ui/renderers/map.js +621 -69
  197. package/dist/chat/ui/intelligent-ui/renderers/place-point.js +15 -8
  198. package/dist/chat/ui/intelligent-ui/renderers/structure.js +262 -20
  199. package/dist/chat/ui/intelligent-ui/renderers/text.js +674 -49
  200. package/dist/chat/ui/intelligent-ui/reply-parts.js +24 -15
  201. package/dist/chat/ui/intelligent-ui/table-data.js +97 -57
  202. package/dist/chat/ui/intelligent-ui/tones.js +31 -31
  203. package/dist/chat/ui/intelligent-ui/use-in-view.js +30 -12
  204. package/dist/chat/ui/intelligent-ui/use-later.js +28 -13
  205. package/dist/chat/ui/intelligent-ui/use-truncated.js +45 -21
  206. package/dist/chat/ui/intelligent-ui/use-ui-links.js +296 -109
  207. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +256 -246
  208. package/dist/chat/ui/markdown-blocks.js +296 -262
  209. package/dist/chat/ui/mermaid.js +60 -72
  210. package/dist/chat/ui/quote-selection.js +32 -29
  211. package/dist/chat/ui/rehype-chips.js +35 -23
  212. package/dist/chat/ui/rehype-fade.js +28 -17
  213. package/dist/chat/ui/remark-html-as-text.js +22 -15
  214. package/dist/chat/ui/reply-context.js +1 -1
  215. package/dist/chat/ui/reveal.js +161 -72
  216. package/dist/chat/ui/rows/ForksRow.js +226 -24
  217. package/dist/chat/ui/rows/GeneratedImageRow.js +541 -87
  218. package/dist/chat/ui/rows/MessageRows.js +1706 -159
  219. package/dist/chat/ui/rows/RowContainer.js +57 -7
  220. package/dist/chat/ui/rows/Rows.js +463 -54
  221. package/dist/chat/ui/rows/SubagentRow.js +577 -60
  222. package/dist/chat/ui/rows/TaskRow.js +359 -40
  223. package/dist/chat/ui/rows/VisualRow.js +233 -11
  224. package/dist/chat/ui/rows/WorkRows.js +1945 -164
  225. package/dist/chat/ui/rows/WorkflowRow.js +293 -34
  226. package/dist/chat/ui/rows/row-rhythm.js +27 -17
  227. package/dist/chat/ui/theme-watch.js +26 -23
  228. package/dist/chat/ui/timestamp-format.js +4 -1
  229. package/dist/chat/ui/use-diff-source-tokens.js +70 -34
  230. package/dist/chat/ui/useToggleSet.js +51 -19
  231. package/dist/chat/ui/visual-theme.js +153 -128
  232. package/dist/chat/visual-bridge.js +123 -123
  233. package/dist/chat/visual-viewport.js +94 -83
  234. package/dist/chat/visuals.js +13 -5
  235. package/dist/host-hooks.d.ts +29 -0
  236. package/dist/host-hooks.js +78 -0
  237. package/dist/host.js +120 -48
  238. package/dist/index.js +1 -1
  239. package/dist/lazy.js +38 -32
  240. package/dist/locales/en/agent-chat.d.ts +34 -0
  241. package/dist/locales/en/agent-chat.js +747 -713
  242. package/dist/locales/en/agent-prompts.js +42 -42
  243. package/dist/locales/en/agent-providers.d.ts +1 -0
  244. package/dist/locales/en/agent-providers.js +166 -165
  245. package/dist/locales/en/agent-usage.d.ts +6 -0
  246. package/dist/locales/en/agent-usage.js +129 -123
  247. package/dist/locales/nl/agent-chat.d.ts +34 -0
  248. package/dist/locales/nl/agent-chat.js +747 -713
  249. package/dist/locales/nl/agent-prompts.js +42 -42
  250. package/dist/locales/nl/agent-providers.d.ts +1 -0
  251. package/dist/locales/nl/agent-providers.js +166 -165
  252. package/dist/locales/nl/agent-usage.d.ts +6 -0
  253. package/dist/locales/nl/agent-usage.js +129 -123
  254. package/dist/locales.js +14 -14
  255. package/dist/mounted-registry.js +31 -30
  256. package/dist/port-transport.js +122 -111
  257. package/dist/prompts/index.js +1 -1
  258. package/dist/prompts/logic/focus.js +15 -14
  259. package/dist/prompts/logic/keys.js +93 -59
  260. package/dist/prompts/logic/prompts.js +27 -14
  261. package/dist/prompts/logic/subjects.js +60 -46
  262. package/dist/prompts/logic/useFocusAfterAnswer.js +60 -20
  263. package/dist/prompts/logic/usePromptSession.js +88 -77
  264. package/dist/prompts/ui/ApprovalBody.js +246 -27
  265. package/dist/prompts/ui/PromptActions.js +215 -9
  266. package/dist/prompts/ui/PromptCard.js +215 -36
  267. package/dist/prompts/ui/PromptView.js +372 -34
  268. package/dist/prompts/ui/QuestionBody.js +269 -73
  269. package/dist/providers/AccountColors.js +36 -5
  270. package/dist/providers/AccountDetail.js +683 -50
  271. package/dist/providers/AccountVariables.js +139 -32
  272. package/dist/providers/AddAccountForm.js +125 -38
  273. package/dist/providers/CliDetail.js +343 -36
  274. package/dist/providers/InstallPage.js +644 -59
  275. package/dist/providers/ProviderList.d.ts +2 -1
  276. package/dist/providers/ProviderList.js +215 -23
  277. package/dist/providers/ProvidersPane.d.ts +4 -2
  278. package/dist/providers/ProvidersPane.js +244 -64
  279. package/dist/providers/account-actions.js +54 -30
  280. package/dist/providers/index.js +1 -1
  281. package/dist/providers/install-steps.js +12 -9
  282. package/dist/providers/pane-target.d.ts +3 -0
  283. package/dist/providers/pane-target.js +34 -13
  284. package/dist/providers/parts.js +62 -12
  285. package/dist/providers/provider-abilities.js +5 -5
  286. package/dist/providers/provider-groups.js +75 -40
  287. package/dist/providers/variables.js +73 -39
  288. package/dist/scope.js +6 -6
  289. package/dist/settings/sections.js +18 -18
  290. package/dist/state/chats.js +404 -192
  291. package/dist/state/index.js +1 -1
  292. package/dist/state/provider-accounts.js +70 -47
  293. package/dist/state/providers.js +45 -16
  294. package/dist/state/usage.js +154 -77
  295. package/dist/storage.js +69 -68
  296. package/dist/testing/index.js +1 -1
  297. package/dist/testing/prompts.js +105 -67
  298. package/dist/transport.js +10 -10
  299. package/dist/ui/PlainTextarea.js +27 -3
  300. package/dist/usage/LimitsList.js +646 -40
  301. package/dist/usage/UsageBreakdown.js +879 -38
  302. package/dist/usage/UsageChart.js +311 -32
  303. package/dist/usage/UsageDialog.js +46 -4
  304. package/dist/usage/UsageLimits.js +467 -34
  305. package/dist/usage/UsageLimitsCard.js +95 -11
  306. package/dist/usage/UsagePage.js +817 -96
  307. package/dist/usage/UsagePane.js +164 -10
  308. package/dist/usage/UsageSummary.js +151 -6
  309. package/dist/usage/UsageTiles.js +164 -14
  310. package/dist/usage/format.js +32 -32
  311. package/dist/usage/index.d.ts +1 -1
  312. package/dist/usage/index.js +2 -1
  313. package/dist/usage/limit-groups.d.ts +2 -0
  314. package/dist/usage/limit-groups.js +77 -59
  315. package/dist/usage/limits.js +78 -43
  316. package/dist/usage/money.js +20 -4
  317. package/dist/usage/summary.js +85 -64
  318. package/package.json +8 -8
  319. package/src/agents/ModelOptionControl.tsx +3 -1
  320. package/src/agents/option-words.ts +27 -0
  321. package/src/chat/account-choice.ts +41 -1
  322. package/src/chat/composer-effort.ts +32 -0
  323. package/src/chat/forks.ts +4 -5
  324. package/src/chat/index.ts +3 -1
  325. package/src/chat/logic/effort.ts +32 -0
  326. package/src/chat/logic/picker-entries.ts +45 -10
  327. package/src/chat/logic/resume-compaction.ts +95 -17
  328. package/src/chat/logic/timeline.ts +11 -3
  329. package/src/chat/preferences.ts +35 -0
  330. package/src/chat/subagent-view.ts +2 -3
  331. package/src/chat/ui/AnsiOutput.tsx +1 -2
  332. package/src/chat/ui/BookmarkSubmenu.tsx +3 -3
  333. package/src/chat/ui/ChatActivity.tsx +14 -22
  334. package/src/chat/ui/ChatReferenceChip.tsx +2 -3
  335. package/src/chat/ui/Composer.tsx +15 -7
  336. package/src/chat/ui/EditDiff.tsx +2 -3
  337. package/src/chat/ui/LimitState.tsx +2 -2
  338. package/src/chat/ui/Markdown.tsx +10 -8
  339. package/src/chat/ui/MermaidBlock.tsx +2 -3
  340. package/src/chat/ui/Pickers.tsx +49 -29
  341. package/src/chat/ui/PromptComposer.tsx +7 -9
  342. package/src/chat/ui/ResumeCompactionDock.tsx +16 -4
  343. package/src/chat/ui/RunSettings.tsx +67 -28
  344. package/src/chat/ui/Scrubber.tsx +3 -3
  345. package/src/chat/ui/ShellCommand.tsx +2 -0
  346. package/src/chat/ui/SubagentInfo.tsx +2 -3
  347. package/src/chat/ui/SubagentTimeline.tsx +12 -16
  348. package/src/chat/ui/Timeline.tsx +6 -6
  349. package/src/chat/ui/UnifiedDiff.tsx +3 -4
  350. package/src/chat/ui/VisualFrame.tsx +5 -8
  351. package/src/chat/ui/code-theme.ts +4 -4
  352. package/src/chat/ui/composer/placeholder.ts +2 -2
  353. package/src/chat/ui/composer/use-compaction-offer.ts +36 -16
  354. package/src/chat/ui/composer/use-composer-menus.ts +4 -9
  355. package/src/chat/ui/composer/use-composer-submit.ts +2 -1
  356. package/src/chat/ui/composer/use-effort-stepper.ts +56 -0
  357. package/src/chat/ui/composer/use-notice.ts +2 -2
  358. package/src/chat/ui/diff/EditorEditDiff.tsx +9 -13
  359. package/src/chat/ui/diff/LegacyEditDiff.tsx +12 -17
  360. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +13 -21
  361. package/src/chat/ui/diff/use-review-stack.ts +4 -4
  362. package/src/chat/ui/diff-theme.ts +3 -3
  363. package/src/chat/ui/file-links.ts +2 -2
  364. package/src/chat/ui/intelligent-ui/UiReply.tsx +2 -0
  365. package/src/chat/ui/intelligent-ui/renderers/chart.tsx +3 -3
  366. package/src/chat/ui/intelligent-ui/renderers/content.tsx +5 -6
  367. package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +2 -1
  368. package/src/chat/ui/intelligent-ui/renderers/map.tsx +2 -1
  369. package/src/chat/ui/intelligent-ui/use-truncated.ts +16 -19
  370. package/src/chat/ui/intelligent-ui/use-ui-links.ts +3 -3
  371. package/src/chat/ui/rows/ForksRow.tsx +3 -5
  372. package/src/chat/ui/rows/GeneratedImageRow.tsx +2 -1
  373. package/src/chat/ui/rows/MessageRows.tsx +12 -21
  374. package/src/chat/ui/rows/SubagentRow.tsx +3 -3
  375. package/src/chat/ui/rows/TaskRow.tsx +1 -1
  376. package/src/chat/ui/rows/WorkRows.tsx +10 -5
  377. package/src/chat/ui/useToggleSet.ts +15 -18
  378. package/src/chat/ui/visual-theme.ts +2 -3
  379. package/src/host-hooks.ts +113 -0
  380. package/src/lazy.tsx +2 -0
  381. package/src/locales/en/agent-chat.ts +134 -108
  382. package/src/locales/en/agent-prompts.ts +7 -7
  383. package/src/locales/en/agent-providers.ts +35 -34
  384. package/src/locales/en/agent-usage.ts +26 -20
  385. package/src/locales/nl/agent-chat.ts +126 -100
  386. package/src/locales/nl/agent-prompts.ts +5 -5
  387. package/src/locales/nl/agent-providers.ts +33 -32
  388. package/src/locales/nl/agent-usage.ts +25 -20
  389. package/src/providers/CliDetail.tsx +2 -1
  390. package/src/providers/InstallPage.tsx +2 -4
  391. package/src/providers/ProviderList.tsx +12 -2
  392. package/src/providers/ProvidersPane.tsx +45 -15
  393. package/src/providers/pane-target.ts +20 -4
  394. package/src/state/chats.ts +2 -2
  395. package/src/usage/LimitsList.tsx +12 -13
  396. package/src/usage/UsageBreakdown.tsx +17 -6
  397. package/src/usage/UsageLimits.tsx +2 -1
  398. package/src/usage/UsagePage.tsx +3 -3
  399. package/src/usage/index.ts +1 -1
  400. package/src/usage/limit-groups.ts +12 -0
  401. package/src/usage/limits.ts +2 -2
  402. package/src/usage/money.ts +1 -2
@@ -4,91 +4,125 @@ import { matchesShortcut, shortcut } from '@adecore/ui';
4
4
  * is a widget the keyboard is already in. They only mean something while the focus is inside one.
5
5
  */
6
6
  export const PROMPT_SHORTCUTS = {
7
- primary: shortcut('Mod+Enter'),
8
- previousPrompt: shortcut('Mod+Shift+ArrowLeft'),
9
- nextPrompt: shortcut('Mod+Shift+ArrowRight')
7
+ primary: shortcut('Mod+Enter'),
8
+ previousPrompt: shortcut('Mod+Shift+ArrowLeft'),
9
+ nextPrompt: shortcut('Mod+Shift+ArrowRight')
10
10
  };
11
11
  function isPlain(event) {
12
- return !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && !event.isComposing;
12
+ return !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && !event.isComposing;
13
13
  }
14
- const LIST_KEYS = { ArrowUp: 'previous', ArrowDown: 'next', Home: 'first', End: 'last' };
15
- const TOOLBAR_KEYS = { ArrowLeft: 'previous', ArrowRight: 'next', Home: 'first', End: 'last' };
14
+ const LIST_KEYS = {
15
+ ArrowUp: 'previous',
16
+ ArrowDown: 'next',
17
+ Home: 'first',
18
+ End: 'last'
19
+ };
20
+ const TOOLBAR_KEYS = {
21
+ ArrowLeft: 'previous',
22
+ ArrowRight: 'next',
23
+ Home: 'first',
24
+ End: 'last'
25
+ };
16
26
  /* Both lists wrap, the way a radio group does. */
17
27
  export function stepIndex(index, count, to) {
18
- if (count === 0) {
19
- return -1;
20
- }
21
- switch (to) {
22
- case 'first':
23
- return 0;
24
- case 'last':
25
- return count - 1;
26
- case 'previous':
27
- return (index - 1 + count) % count;
28
- case 'next':
29
- return (index + 1) % count;
30
- }
28
+ if (count === 0) {
29
+ return -1;
30
+ }
31
+ switch (to) {
32
+ case 'first':
33
+ return 0;
34
+ case 'last':
35
+ return count - 1;
36
+ case 'previous':
37
+ return (index - 1 + count) % count;
38
+ case 'next':
39
+ return (index + 1) % count;
40
+ }
31
41
  }
32
42
  /*
33
43
  * A choice of a question. Enter on a multi select question only moves on once something is chosen, so
34
44
  * the first Enter on an empty question picks the choice instead of doing nothing.
35
45
  */
36
- export function choiceKey(event, { multiSelect, anyChosen }) {
37
- if (!isPlain(event)) {
38
- return null;
39
- }
40
- const step = LIST_KEYS[event.key];
41
- if (step) {
42
- return { kind: 'move', to: step };
43
- }
44
- if (event.code === 'Space') {
45
- return { kind: 'pick' };
46
- }
47
- if (event.key === 'Enter') {
48
- if (!multiSelect) {
49
- return { kind: 'pick-and-commit' };
50
- }
51
- return anyChosen ? { kind: 'commit' } : { kind: 'pick' };
52
- }
46
+ export function choiceKey(event, {
47
+ multiSelect,
48
+ anyChosen
49
+ }) {
50
+ if (!isPlain(event)) {
53
51
  return null;
52
+ }
53
+ const step = LIST_KEYS[event.key];
54
+ if (step) {
55
+ return {
56
+ kind: 'move',
57
+ to: step
58
+ };
59
+ }
60
+ if (event.code === 'Space') {
61
+ return {
62
+ kind: 'pick'
63
+ };
64
+ }
65
+ if (event.key === 'Enter') {
66
+ if (!multiSelect) {
67
+ return {
68
+ kind: 'pick-and-commit'
69
+ };
70
+ }
71
+ return anyChosen ? {
72
+ kind: 'commit'
73
+ } : {
74
+ kind: 'pick'
75
+ };
76
+ }
77
+ return null;
54
78
  }
55
79
  /* A written answer: under the choices ("Something else…") or the only field of a question without choices. */
56
- export function answerFieldKey(event, { belowChoices, caretAtStart, hasText }) {
57
- if (!isPlain(event)) {
58
- return null;
59
- }
60
- if (event.key === 'ArrowUp' && belowChoices && caretAtStart) {
61
- return { kind: 'to-last-choice' };
62
- }
63
- if (event.key === 'Enter') {
64
- // An empty answer is not sent, and an empty line in front of the answer is never what Enter meant.
65
- return hasText ? { kind: 'commit' } : { kind: 'ignore' };
66
- }
80
+ export function answerFieldKey(event, {
81
+ belowChoices,
82
+ caretAtStart,
83
+ hasText
84
+ }) {
85
+ if (!isPlain(event)) {
67
86
  return null;
87
+ }
88
+ if (event.key === 'ArrowUp' && belowChoices && caretAtStart) {
89
+ return {
90
+ kind: 'to-last-choice'
91
+ };
92
+ }
93
+ if (event.key === 'Enter') {
94
+ // An empty answer is not sent, and an empty line in front of the answer is never what Enter meant.
95
+ return hasText ? {
96
+ kind: 'commit'
97
+ } : {
98
+ kind: 'ignore'
99
+ };
100
+ }
101
+ return null;
68
102
  }
69
103
  export function headingKey(event) {
70
- return isPlain(event) && event.key === 'ArrowDown';
104
+ return isPlain(event) && event.key === 'ArrowDown';
71
105
  }
72
106
  export function toolbarKey(event) {
73
- return isPlain(event) ? (TOOLBAR_KEYS[event.key] ?? null) : null;
107
+ return isPlain(event) ? TOOLBAR_KEYS[event.key] ?? null : null;
74
108
  }
75
109
  export function isPrimaryKey(event, apple) {
76
- return !event.isComposing && matchesShortcut(PROMPT_SHORTCUTS.primary, event, apple);
110
+ return !event.isComposing && matchesShortcut(PROMPT_SHORTCUTS.primary, event, apple);
77
111
  }
78
112
  /* Paging through a stack. In a text field these keys select to the start or end of the line, so they stay there. */
79
113
  export function pageKey(event, apple, typing) {
80
- if (typing || event.isComposing) {
81
- return null;
82
- }
83
- if (matchesShortcut(PROMPT_SHORTCUTS.previousPrompt, event, apple)) {
84
- return -1;
85
- }
86
- return matchesShortcut(PROMPT_SHORTCUTS.nextPrompt, event, apple) ? 1 : null;
114
+ if (typing || event.isComposing) {
115
+ return null;
116
+ }
117
+ if (matchesShortcut(PROMPT_SHORTCUTS.previousPrompt, event, apple)) {
118
+ return -1;
119
+ }
120
+ return matchesShortcut(PROMPT_SHORTCUTS.nextPrompt, event, apple) ? 1 : null;
87
121
  }
88
122
  /*
89
123
  * A key without Ctrl, Cmd or Alt never leaves a card: arrows would reach the canvas, Space would start a
90
124
  * pan and Backspace would delete the selected nodes. Escape and Tab still go on, since they leave the card.
91
125
  */
92
126
  export function staysInCard(event) {
93
- return !event.ctrlKey && !event.metaKey && !event.altKey && event.key !== 'Escape' && event.key !== 'Tab';
94
- }
127
+ return !event.ctrlKey && !event.metaKey && !event.altKey && event.key !== 'Escape' && event.key !== 'Tab';
128
+ }
@@ -1,32 +1,45 @@
1
1
  import { toggleChoice } from '../../chat/logic/answers.js';
2
2
  export function emptyPromptDraft() {
3
- return { index: 0, answers: {}, reason: '', showReason: false };
3
+ return {
4
+ index: 0,
5
+ answers: {},
6
+ reason: '',
7
+ showReason: false
8
+ };
4
9
  }
5
10
  export function answerValue(answer) {
6
- return answer.custom ? answer.text.trim() : answer.choices.join(', ');
11
+ return answer.custom ? answer.text.trim() : answer.choices.join(', ');
7
12
  }
8
13
  export function questionAnswer(draft, question) {
9
- return draft.answers[question.id] ?? { choices: [], text: '', custom: question.choices.length === 0 };
14
+ return draft.answers[question.id] ?? {
15
+ choices: [],
16
+ text: '',
17
+ custom: question.choices.length === 0
18
+ };
10
19
  }
11
20
  export function pickPromptChoice(answer, question, label) {
12
- return { ...answer, custom: false, choices: question.multiSelect ? toggleChoice(answer.choices, label) : [label] };
21
+ return {
22
+ ...answer,
23
+ custom: false,
24
+ choices: question.multiSelect ? toggleChoice(answer.choices, label) : [label]
25
+ };
13
26
  }
14
27
  /* An optional question never stands in front of a request that holds the agent up. */
15
28
  export function isBlockingPrompt(item) {
16
- return item.kind === 'approval' || !item.async;
29
+ return item.kind === 'approval' || !item.async;
17
30
  }
18
31
  /* Blocking prompts first and optional ones after, each oldest first. The chat and a canvas's stack both follow it. */
19
32
  export function orderPrompts(prompts, blocking, createdAt) {
20
- return [...prompts].sort((a, b) => Number(blocking(b)) - Number(blocking(a)) || createdAt(a) - createdAt(b));
33
+ return [...prompts].sort((a, b) => Number(blocking(b)) - Number(blocking(a)) || createdAt(a) - createdAt(b));
21
34
  }
22
35
  export function nextPrompt(items, activeId) {
23
- const active = items.find((item) => item.requestId === activeId);
24
- if (active) {
25
- return active;
26
- }
27
- return orderPrompts(items, isBlockingPrompt, (item) => item.createdAt)[0] ?? null;
36
+ const active = items.find(item => item.requestId === activeId);
37
+ if (active) {
38
+ return active;
39
+ }
40
+ return orderPrompts(items, isBlockingPrompt, item => item.createdAt)[0] ?? null;
28
41
  }
29
42
  export function promptAnswers(item, draft) {
30
- const answers = Object.fromEntries(item.questions.map((question) => [question.id, answerValue(questionAnswer(draft, question))]));
31
- return Object.values(answers).every((answer) => answer !== '') ? answers : null;
32
- }
43
+ const answers = Object.fromEntries(item.questions.map(question => [question.id, answerValue(questionAnswer(draft, question))]));
44
+ return Object.values(answers).every(answer => answer !== '') ? answers : null;
45
+ }
@@ -2,64 +2,78 @@ import i18next from 'i18next';
2
2
  import { isBlockingPrompt } from './prompts.js';
3
3
  /* Unique across the chats of a surface and the app's own prompts, and stable while the prompt waits. */
4
4
  export function promptIdOf(subject) {
5
- return subject.kind === 'chat' ? `agent-chat:${subject.nodeId}:${subject.item.requestId}` : subject.prompt.id;
5
+ return subject.kind === 'chat' ? `agent-chat:${subject.nodeId}:${subject.item.requestId}` : subject.prompt.id;
6
6
  }
7
7
  export function promptCreatedAt(subject) {
8
- return subject.kind === 'chat' ? subject.item.createdAt : subject.prompt.createdAt;
8
+ return subject.kind === 'chat' ? subject.item.createdAt : subject.prompt.createdAt;
9
9
  }
10
10
  /* Only a chat's optional question does not hold anything up; the app says so of its own. */
11
11
  export function isBlockingSubject(subject) {
12
- return subject.kind === 'chat' ? isBlockingPrompt(subject.item) : subject.prompt.blocking;
12
+ return subject.kind === 'chat' ? isBlockingPrompt(subject.item) : subject.prompt.blocking;
13
13
  }
14
14
  /* The buttons of a chat's permission request in the order it draws them: a remembered rule, Deny, then Allow as the primary. */
15
15
  export function approvalButtons(subject, reason) {
16
- if (subject.kind !== 'chat' || subject.item.kind !== 'approval') {
17
- return [];
16
+ if (subject.kind !== 'chat' || subject.item.kind !== 'approval') {
17
+ return [];
18
+ }
19
+ const {
20
+ item
21
+ } = subject;
22
+ const message = reason.trim();
23
+ return [...(item.canAllowAlways && item.allowAlways ? [{
24
+ id: 'allow-always',
25
+ label: item.allowAlways.label,
26
+ description: item.allowAlways.description,
27
+ primary: false,
28
+ lasting: true,
29
+ action: {
30
+ kind: 'approve',
31
+ decision: 'allow-always'
18
32
  }
19
- const { item } = subject;
20
- const message = reason.trim();
21
- return [
22
- ...(item.canAllowAlways && item.allowAlways
23
- ? [
24
- {
25
- id: 'allow-always',
26
- label: item.allowAlways.label,
27
- description: item.allowAlways.description,
28
- primary: false,
29
- lasting: true,
30
- action: { kind: 'approve', decision: 'allow-always' }
31
- }
32
- ]
33
- : []),
34
- {
35
- id: 'deny',
36
- label: i18next.t('agent-prompts:approval.deny'),
37
- primary: false,
38
- action: { kind: 'approve', decision: 'deny', ...(message ? { message } : {}) }
39
- },
40
- { id: 'allow', label: i18next.t('agent-prompts:approval.allow'), primary: true, action: { kind: 'approve', decision: 'allow' } }
41
- ];
33
+ }] : []), {
34
+ id: 'deny',
35
+ label: i18next.t('agent-prompts:approval.deny'),
36
+ primary: false,
37
+ action: {
38
+ kind: 'approve',
39
+ decision: 'deny',
40
+ ...(message ? {
41
+ message
42
+ } : {})
43
+ }
44
+ }, {
45
+ id: 'allow',
46
+ label: i18next.t('agent-prompts:approval.allow'),
47
+ primary: true,
48
+ action: {
49
+ kind: 'approve',
50
+ decision: 'allow'
51
+ }
52
+ }];
42
53
  }
43
54
  /*
44
55
  * Sends a card's action as the request its subject is answered with, or to `host` for a prompt it raised.
45
56
  * A refusal comes back as an error for the card to show.
46
57
  */
47
58
  export async function answerPrompt(subject, action, chat, host) {
48
- if (subject.kind === 'host') {
49
- return host.prompts.answer(subject.prompt, action);
50
- }
51
- if (chat === null) {
52
- throw new Error(i18next.t('agent-prompts:error.notConnected'));
53
- }
54
- const { item, nodeId } = subject;
55
- if (action.kind === 'approve') {
56
- return chat.approve(nodeId, item.requestId, action.decision, action.message);
57
- }
58
- if (action.kind === 'answer') {
59
- return chat.answer(nodeId, item.requestId, action.answers);
60
- }
61
- if (action.kind === 'dismiss') {
62
- return chat.dismiss(nodeId, item.id);
63
- }
64
- throw new Error(i18next.t('agent-prompts:error.noChoices'));
65
- }
59
+ if (subject.kind === 'host') {
60
+ return host.prompts.answer(subject.prompt, action);
61
+ }
62
+ if (chat === null) {
63
+ throw new Error(i18next.t('agent-prompts:error.notConnected'));
64
+ }
65
+ const {
66
+ item,
67
+ nodeId
68
+ } = subject;
69
+ if (action.kind === 'approve') {
70
+ return chat.approve(nodeId, item.requestId, action.decision, action.message);
71
+ }
72
+ if (action.kind === 'answer') {
73
+ return chat.answer(nodeId, item.requestId, action.answers);
74
+ }
75
+ if (action.kind === 'dismiss') {
76
+ return chat.dismiss(nodeId, item.id);
77
+ }
78
+ throw new Error(i18next.t('agent-prompts:error.noChoices'));
79
+ }
@@ -1,3 +1,4 @@
1
+ import { c as _c } from "react/compiler-runtime";
1
2
  import { useEffect, useRef } from 'react';
2
3
  import { focusPromptStart } from './focus.js';
3
4
  /*
@@ -5,24 +6,63 @@ import { focusPromptStart } from './focus.js';
5
6
  * wherever `onEmpty` puts it once none is left. A card answered with the keyboard elsewhere takes nothing.
6
7
  */
7
8
  export function useFocusAfterAnswer(activeId, container, onEmpty) {
8
- const pending = useRef(false);
9
- useEffect(() => {
10
- if (!pending.current) {
11
- return;
12
- }
13
- pending.current = false;
14
- if (!focusPromptStart(container.current)) {
15
- onEmpty();
16
- }
17
- // Only a change of the front card is news; a new `onEmpty` each render is not.
18
- // oxlint-disable-next-line react-hooks/exhaustive-deps
19
- }, [activeId]);
20
- return {
21
- hold: () => {
22
- pending.current = container.current?.contains(document.activeElement) === true;
23
- },
24
- release: () => {
25
- pending.current = false;
26
- }
9
+ const $ = _c(10);
10
+ const pending = useRef(false);
11
+ let t0;
12
+ if ($[0] !== container || $[1] !== onEmpty) {
13
+ t0 = () => {
14
+ if (!pending.current) {
15
+ return;
16
+ }
17
+ pending.current = false;
18
+ if (!focusPromptStart(container.current)) {
19
+ onEmpty();
20
+ }
27
21
  };
28
- }
22
+ $[0] = container;
23
+ $[1] = onEmpty;
24
+ $[2] = t0;
25
+ } else {
26
+ t0 = $[2];
27
+ }
28
+ let t1;
29
+ if ($[3] !== activeId) {
30
+ t1 = [activeId];
31
+ $[3] = activeId;
32
+ $[4] = t1;
33
+ } else {
34
+ t1 = $[4];
35
+ }
36
+ useEffect(t0, t1);
37
+ let t2;
38
+ if ($[5] !== container) {
39
+ t2 = () => {
40
+ pending.current = container.current?.contains(document.activeElement) === true;
41
+ };
42
+ $[5] = container;
43
+ $[6] = t2;
44
+ } else {
45
+ t2 = $[6];
46
+ }
47
+ let t3;
48
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
49
+ t3 = () => {
50
+ pending.current = false;
51
+ };
52
+ $[7] = t3;
53
+ } else {
54
+ t3 = $[7];
55
+ }
56
+ let t4;
57
+ if ($[8] !== t2) {
58
+ t4 = {
59
+ hold: t2,
60
+ release: t3
61
+ };
62
+ $[8] = t2;
63
+ $[9] = t4;
64
+ } else {
65
+ t4 = $[9];
66
+ }
67
+ return t4;
68
+ }
@@ -5,83 +5,94 @@ import { emptyPromptDraft } from './prompts.js';
5
5
  * paging, one send at a time, the error of the request that failed, and the requests answered here
6
6
  * that the machine has not taken off yet.
7
7
  */
8
- export function usePromptSession({ prompts, idOf, pick, disabled }) {
9
- const [activeId, setActiveId] = useState(null);
10
- const [activeIndex, setActiveIndex] = useState(0);
11
- const [completed, setCompleted] = useState([]);
12
- const [drafts, setDrafts] = useState({});
13
- const [sending, setSending] = useState(false);
14
- const [error, setError] = useState(null);
15
- const busy = useRef(false);
16
- const pressedRequest = useRef(null);
17
- const stillCompleted = completed.filter((id) => prompts.some((prompt) => idOf(prompt) === id));
18
- if (stillCompleted.length !== completed.length) {
19
- setCompleted(stillCompleted);
8
+ export function usePromptSession({
9
+ prompts,
10
+ idOf,
11
+ pick,
12
+ disabled
13
+ }) {
14
+ const [activeId, setActiveId] = useState(null);
15
+ const [activeIndex, setActiveIndex] = useState(0);
16
+ const [completed, setCompleted] = useState([]);
17
+ const [drafts, setDrafts] = useState({});
18
+ const [sending, setSending] = useState(false);
19
+ const [error, setError] = useState(null);
20
+ const busy = useRef(false);
21
+ const pressedRequest = useRef(null);
22
+ const stillCompleted = completed.filter(id => prompts.some(prompt => idOf(prompt) === id));
23
+ if (stillCompleted.length !== completed.length) {
24
+ setCompleted(stillCompleted);
25
+ }
26
+ const waiting = prompts.filter(prompt_0 => !completed.includes(idOf(prompt_0)));
27
+ const active = pick(waiting, activeId, activeIndex);
28
+ const activeKey = active === null ? null : idOf(active);
29
+ const index = active === null ? 0 : waiting.indexOf(active);
30
+ if (index !== activeIndex) {
31
+ setActiveIndex(index);
32
+ }
33
+ if (activeKey !== activeId) {
34
+ setActiveId(activeKey);
35
+ setError(null);
36
+ }
37
+ const finish = id_0 => {
38
+ setCompleted(current => [...current, id_0]);
39
+ setDrafts(current_0 => {
40
+ const next = {
41
+ ...current_0
42
+ };
43
+ delete next[id_0];
44
+ return next;
45
+ });
46
+ };
47
+ const act = async (prompt_1, send) => {
48
+ if (busy.current || disabled) {
49
+ return 'busy';
20
50
  }
21
- const waiting = prompts.filter((prompt) => !completed.includes(idOf(prompt)));
22
- const active = pick(waiting, activeId, activeIndex);
23
- const activeKey = active === null ? null : idOf(active);
24
- const index = active === null ? 0 : waiting.indexOf(active);
25
- if (index !== activeIndex) {
26
- setActiveIndex(index);
51
+ const id_1 = idOf(prompt_1);
52
+ busy.current = true;
53
+ setSending(true);
54
+ setError(null);
55
+ try {
56
+ await send();
57
+ finish(id_1);
58
+ return 'sent';
59
+ } catch (cause) {
60
+ setError({
61
+ id: id_1,
62
+ message: cause instanceof Error ? cause.message : String(cause)
63
+ });
64
+ return 'failed';
65
+ } finally {
66
+ busy.current = false;
67
+ setSending(false);
27
68
  }
28
- if (activeKey !== activeId) {
29
- setActiveId(activeKey);
30
- setError(null);
69
+ };
70
+ return {
71
+ active,
72
+ activeId: activeKey,
73
+ index,
74
+ waiting,
75
+ setActive: id_2 => {
76
+ setActiveId(id_2);
77
+ setError(null);
78
+ },
79
+ draftOf: id_3 => drafts[id_3] ?? emptyPromptDraft(),
80
+ setDraft: (id_4, draft) => setDrafts(current_1 => ({
81
+ ...current_1,
82
+ [id_4]: draft
83
+ })),
84
+ sending,
85
+ errorOf: id_5 => error?.id === id_5 ? error.message : null,
86
+ act,
87
+ onPointerDownCapture: () => {
88
+ pressedRequest.current = activeKey;
89
+ },
90
+ onClickCapture: event => {
91
+ // A press that began on Send cannot become Allow when a request arrives underneath it.
92
+ if (event.detail > 0 && event.target.closest('.prompt-card') && pressedRequest.current !== activeKey) {
93
+ event.preventDefault();
94
+ event.stopPropagation();
95
+ }
31
96
  }
32
- const finish = (id) => {
33
- setCompleted((current) => [...current, id]);
34
- setDrafts((current) => {
35
- const next = { ...current };
36
- delete next[id];
37
- return next;
38
- });
39
- };
40
- const act = async (prompt, send) => {
41
- if (busy.current || disabled) {
42
- return 'busy';
43
- }
44
- const id = idOf(prompt);
45
- busy.current = true;
46
- setSending(true);
47
- setError(null);
48
- try {
49
- await send();
50
- finish(id);
51
- return 'sent';
52
- }
53
- catch (cause) {
54
- setError({ id, message: cause instanceof Error ? cause.message : String(cause) });
55
- return 'failed';
56
- }
57
- finally {
58
- busy.current = false;
59
- setSending(false);
60
- }
61
- };
62
- return {
63
- active,
64
- activeId: activeKey,
65
- index,
66
- waiting,
67
- setActive: (id) => {
68
- setActiveId(id);
69
- setError(null);
70
- },
71
- draftOf: (id) => drafts[id] ?? emptyPromptDraft(),
72
- setDraft: (id, draft) => setDrafts((current) => ({ ...current, [id]: draft })),
73
- sending,
74
- errorOf: (id) => (error?.id === id ? error.message : null),
75
- act,
76
- onPointerDownCapture: () => {
77
- pressedRequest.current = activeKey;
78
- },
79
- onClickCapture: (event) => {
80
- // A press that began on Send cannot become Allow when a request arrives underneath it.
81
- if (event.detail > 0 && event.target.closest('.prompt-card') && pressedRequest.current !== activeKey) {
82
- event.preventDefault();
83
- event.stopPropagation();
84
- }
85
- }
86
- };
87
- }
97
+ };
98
+ }