@antelopejs/dms-ai 0.1.6 → 0.2.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 (560) hide show
  1. package/README.md +48 -12
  2. package/dist/channels/bridge.d.ts +6 -1
  3. package/dist/channels/bridge.js +29 -1
  4. package/dist/channels/bridge.js.map +1 -1
  5. package/dist/channels/channel-service.d.ts +2 -1
  6. package/dist/channels/channel-service.js +3 -2
  7. package/dist/channels/channel-service.js.map +1 -1
  8. package/dist/channels/sse-stream.d.ts +3 -2
  9. package/dist/config.d.ts +0 -2
  10. package/dist/config.js +0 -7
  11. package/dist/config.js.map +1 -1
  12. package/dist/constants/http.d.ts +9 -0
  13. package/dist/constants/http.js +14 -0
  14. package/dist/constants/http.js.map +1 -0
  15. package/dist/constants/i18n.d.ts +11 -0
  16. package/dist/constants/i18n.js +15 -0
  17. package/dist/constants/i18n.js.map +1 -0
  18. package/dist/constants/pages.d.ts +50 -0
  19. package/dist/constants/pages.js +58 -0
  20. package/dist/constants/pages.js.map +1 -0
  21. package/dist/constants/sidecar.d.ts +0 -1
  22. package/dist/constants/sidecar.js +1 -2
  23. package/dist/constants/sidecar.js.map +1 -1
  24. package/dist/index.js +0 -8
  25. package/dist/index.js.map +1 -1
  26. package/dist/lifecycle/sidecar-owner.d.ts +1 -0
  27. package/dist/lifecycle/sidecar-owner.js +13 -0
  28. package/dist/lifecycle/sidecar-owner.js.map +1 -1
  29. package/dist/lifecycle/spawn-sidecar.d.ts +1 -0
  30. package/dist/lifecycle/spawn-sidecar.js +10 -10
  31. package/dist/lifecycle/spawn-sidecar.js.map +1 -1
  32. package/dist/logging/log-buffer.d.ts +0 -6
  33. package/dist/logging/log-buffer.js +0 -1
  34. package/dist/logging/log-buffer.js.map +1 -1
  35. package/dist/pages/activity/columns.d.ts +2 -0
  36. package/dist/pages/activity/columns.js +103 -0
  37. package/dist/pages/activity/columns.js.map +1 -0
  38. package/dist/pages/activity/page.d.ts +1 -2
  39. package/dist/pages/activity/page.js +79 -44
  40. package/dist/pages/activity/page.js.map +1 -1
  41. package/dist/pages/all.d.ts +1 -0
  42. package/dist/pages/all.js +1 -0
  43. package/dist/pages/all.js.map +1 -1
  44. package/dist/pages/changes/page.d.ts +9 -0
  45. package/dist/pages/changes/page.js +22 -0
  46. package/dist/pages/changes/page.js.map +1 -0
  47. package/dist/pages/meta.d.ts +9 -0
  48. package/dist/pages/meta.js +31 -0
  49. package/dist/pages/meta.js.map +1 -0
  50. package/dist/pages/module.js +9 -5
  51. package/dist/pages/module.js.map +1 -1
  52. package/dist/pages/overview/insights.d.ts +3 -0
  53. package/dist/pages/overview/insights.js +77 -0
  54. package/dist/pages/overview/insights.js.map +1 -0
  55. package/dist/pages/overview/kpis.d.ts +2 -0
  56. package/dist/pages/overview/kpis.js +39 -0
  57. package/dist/pages/overview/kpis.js.map +1 -0
  58. package/dist/pages/overview/page.d.ts +6 -3
  59. package/dist/pages/overview/page.js +19 -62
  60. package/dist/pages/overview/page.js.map +1 -1
  61. package/dist/pages/overview/recent-changes.d.ts +2 -0
  62. package/dist/pages/overview/recent-changes.js +144 -0
  63. package/dist/pages/overview/recent-changes.js.map +1 -0
  64. package/dist/pages/overview/status.d.ts +3 -0
  65. package/dist/pages/overview/status.js +36 -0
  66. package/dist/pages/overview/status.js.map +1 -0
  67. package/dist/pages/settings/availability.d.ts +2 -0
  68. package/dist/pages/settings/availability.js +46 -0
  69. package/dist/pages/settings/availability.js.map +1 -0
  70. package/dist/pages/settings/options.d.ts +10 -0
  71. package/dist/pages/settings/options.js +58 -0
  72. package/dist/pages/settings/options.js.map +1 -0
  73. package/dist/pages/settings/page.d.ts +2 -1
  74. package/dist/pages/settings/page.js +39 -13
  75. package/dist/pages/settings/page.js.map +1 -1
  76. package/dist/pages/settings/sections.d.ts +2 -0
  77. package/dist/pages/settings/sections.js +164 -0
  78. package/dist/pages/settings/sections.js.map +1 -0
  79. package/dist/pages/skills/page.d.ts +2 -1
  80. package/dist/pages/skills/page.js +122 -12
  81. package/dist/pages/skills/page.js.map +1 -1
  82. package/dist/routes/activity-csv.d.ts +2 -0
  83. package/dist/routes/activity-csv.js +42 -0
  84. package/dist/routes/activity-csv.js.map +1 -0
  85. package/dist/routes/activity.d.ts +8 -0
  86. package/dist/routes/activity.js +105 -0
  87. package/dist/routes/activity.js.map +1 -0
  88. package/dist/routes/actor.d.ts +2 -0
  89. package/dist/routes/actor.js +8 -0
  90. package/dist/routes/actor.js.map +1 -0
  91. package/dist/routes/banner.d.ts +3 -0
  92. package/dist/routes/banner.js +9 -0
  93. package/dist/routes/banner.js.map +1 -0
  94. package/dist/routes/builder.js +1 -5
  95. package/dist/routes/builder.js.map +1 -1
  96. package/dist/routes/changes.d.ts +17 -0
  97. package/dist/routes/changes.js +152 -0
  98. package/dist/routes/changes.js.map +1 -0
  99. package/dist/routes/channels.js +2 -1
  100. package/dist/routes/channels.js.map +1 -1
  101. package/dist/routes/index.d.ts +3 -0
  102. package/dist/routes/index.js +3 -0
  103. package/dist/routes/index.js.map +1 -1
  104. package/dist/routes/list-query.d.ts +9 -0
  105. package/dist/routes/list-query.js +34 -0
  106. package/dist/routes/list-query.js.map +1 -0
  107. package/dist/routes/metric-shapes.d.ts +8 -0
  108. package/dist/routes/metric-shapes.js +107 -0
  109. package/dist/routes/metric-shapes.js.map +1 -0
  110. package/dist/routes/metrics.d.ts +5 -48
  111. package/dist/routes/metrics.js +52 -42
  112. package/dist/routes/metrics.js.map +1 -1
  113. package/dist/routes/settings.d.ts +3 -16
  114. package/dist/routes/settings.js +40 -14
  115. package/dist/routes/settings.js.map +1 -1
  116. package/dist/routes/sidecar-results.d.ts +6 -0
  117. package/dist/routes/sidecar-results.js +44 -0
  118. package/dist/routes/sidecar-results.js.map +1 -0
  119. package/dist/routes/skills.d.ts +4 -14
  120. package/dist/routes/skills.js +91 -6
  121. package/dist/routes/skills.js.map +1 -1
  122. package/dist/routes/status-shapes.d.ts +5 -0
  123. package/dist/routes/status-shapes.js +176 -0
  124. package/dist/routes/status-shapes.js.map +1 -0
  125. package/dist/routes/status.d.ts +9 -0
  126. package/dist/routes/status.js +92 -0
  127. package/dist/routes/status.js.map +1 -0
  128. package/dist/routes/undo-confirm.d.ts +3 -0
  129. package/dist/routes/undo-confirm.js +51 -0
  130. package/dist/routes/undo-confirm.js.map +1 -0
  131. package/dist/sidecar/http-client.d.ts +11 -0
  132. package/dist/sidecar/http-client.js +59 -0
  133. package/dist/sidecar/http-client.js.map +1 -0
  134. package/dist/sidecar/index.d.ts +2 -0
  135. package/dist/sidecar/index.js +19 -0
  136. package/dist/sidecar/index.js.map +1 -0
  137. package/dist/sidecar/query.d.ts +3 -0
  138. package/dist/sidecar/query.js +25 -0
  139. package/dist/sidecar/query.js.map +1 -0
  140. package/dist/types/activity.d.ts +31 -0
  141. package/dist/types/activity.js +3 -0
  142. package/dist/types/activity.js.map +1 -0
  143. package/dist/types/changes.d.ts +45 -0
  144. package/dist/types/changes.js +3 -0
  145. package/dist/types/changes.js.map +1 -0
  146. package/dist/types/index.d.ts +5 -0
  147. package/dist/types/index.js +5 -0
  148. package/dist/types/index.js.map +1 -1
  149. package/dist/types/metrics.d.ts +76 -0
  150. package/dist/types/metrics.js +3 -0
  151. package/dist/types/metrics.js.map +1 -0
  152. package/dist/types/skills.d.ts +51 -0
  153. package/dist/types/skills.js +3 -0
  154. package/dist/types/skills.js.map +1 -0
  155. package/dist/types/status.d.ts +16 -0
  156. package/dist/types/status.js +3 -0
  157. package/dist/types/status.js.map +1 -0
  158. package/dist/vocabulary/enumerations.d.ts +9 -0
  159. package/dist/vocabulary/enumerations.js +52 -0
  160. package/dist/vocabulary/enumerations.js.map +1 -0
  161. package/dist/vocabulary/index.d.ts +5 -0
  162. package/dist/vocabulary/index.js +22 -0
  163. package/dist/vocabulary/index.js.map +1 -0
  164. package/dist/vocabulary/keys.d.ts +1 -0
  165. package/dist/vocabulary/keys.js +8 -0
  166. package/dist/vocabulary/keys.js.map +1 -0
  167. package/dist/vocabulary/options.d.ts +7 -0
  168. package/dist/vocabulary/options.js +33 -0
  169. package/dist/vocabulary/options.js.map +1 -0
  170. package/dist/vocabulary/tools.d.ts +7 -0
  171. package/dist/vocabulary/tools.js +99 -0
  172. package/dist/vocabulary/tools.js.map +1 -0
  173. package/dist/vocabulary/types.d.ts +20 -0
  174. package/dist/vocabulary/types.js +3 -0
  175. package/dist/vocabulary/types.js.map +1 -0
  176. package/frontend-vue/app/chat/components/AnswerRecord.vue +95 -0
  177. package/frontend-vue/app/chat/components/ApprovalDock.vue +371 -0
  178. package/frontend-vue/app/chat/components/ChangeSetCard.vue +297 -0
  179. package/frontend-vue/app/chat/components/ChatEmpty.vue +142 -0
  180. package/frontend-vue/app/chat/components/ChatView.vue +664 -406
  181. package/frontend-vue/app/chat/components/Composer.vue +589 -0
  182. package/frontend-vue/app/chat/components/ConnectionBanner.vue +41 -65
  183. package/frontend-vue/app/chat/components/ConversationDrawer.vue +387 -177
  184. package/frontend-vue/app/chat/components/DiffView.vue +131 -0
  185. package/frontend-vue/app/chat/components/FullAutoBanner.vue +76 -0
  186. package/frontend-vue/app/chat/components/FullAutoDialog.vue +103 -0
  187. package/frontend-vue/app/chat/components/MarkdownContent.vue +15 -15
  188. package/frontend-vue/app/chat/components/MessageList.vue +389 -295
  189. package/frontend-vue/app/chat/components/NoticeCard.vue +193 -0
  190. package/frontend-vue/app/chat/components/PanelHeader.vue +242 -0
  191. package/frontend-vue/app/chat/components/PermissionCard.vue +470 -0
  192. package/frontend-vue/app/chat/components/PlanCard.vue +115 -0
  193. package/frontend-vue/app/chat/components/QuestionDock.vue +407 -0
  194. package/frontend-vue/app/chat/components/QueueDock.vue +310 -0
  195. package/frontend-vue/app/chat/components/RulesList.vue +97 -0
  196. package/frontend-vue/app/chat/components/StepsDock.vue +181 -0
  197. package/frontend-vue/app/chat/components/ToolCluster.vue +186 -178
  198. package/frontend-vue/app/chat/components/ToolRow.vue +251 -0
  199. package/frontend-vue/app/chat/components/TurnErrorCard.vue +135 -0
  200. package/frontend-vue/app/chat/composables/conversation-events.ts +404 -0
  201. package/frontend-vue/app/chat/composables/useChangeSetActions.ts +135 -0
  202. package/frontend-vue/app/chat/composables/useChatChannel.ts +11 -3
  203. package/frontend-vue/app/chat/composables/useChatI18n.ts +35 -0
  204. package/frontend-vue/app/chat/composables/useComposerAttachments.ts +111 -0
  205. package/frontend-vue/app/chat/composables/useConversation.ts +149 -651
  206. package/frontend-vue/app/chat/composables/useConversationId.ts +2 -10
  207. package/frontend-vue/app/chat/composables/useConversationList.ts +77 -21
  208. package/frontend-vue/app/chat/composables/useConversationMode.ts +73 -0
  209. package/frontend-vue/app/chat/composables/usePaletteTurn.ts +124 -0
  210. package/frontend-vue/app/chat/composables/usePermissionQueue.ts +211 -34
  211. package/frontend-vue/app/chat/composables/useQuestionQueue.ts +103 -21
  212. package/frontend-vue/app/chat/composables/useQueueActions.ts +55 -0
  213. package/frontend-vue/app/chat/composables/useSettings.ts +17 -34
  214. package/frontend-vue/app/chat/constants/attachments.ts +2 -1
  215. package/frontend-vue/app/chat/constants/conversation.ts +18 -32
  216. package/frontend-vue/app/chat/constants/protocol.ts +25 -2
  217. package/frontend-vue/app/chat/constants/run-status.ts +8 -14
  218. package/frontend-vue/app/chat/constants/settings.ts +5 -47
  219. package/frontend-vue/app/chat/types/conversation.ts +72 -2
  220. package/frontend-vue/app/chat/types/permission.ts +31 -0
  221. package/frontend-vue/app/chat/types/protocol.ts +226 -0
  222. package/frontend-vue/app/chat/types/question.ts +10 -1
  223. package/frontend-vue/app/chat/types/settings.ts +9 -5
  224. package/frontend-vue/app/chat/utils/approval-keyboard.ts +49 -0
  225. package/frontend-vue/app/chat/utils/arrays.ts +10 -0
  226. package/frontend-vue/app/chat/utils/conversation-groups.ts +96 -0
  227. package/frontend-vue/app/chat/utils/conversation-messages.ts +251 -0
  228. package/frontend-vue/app/chat/utils/diff.ts +78 -0
  229. package/frontend-vue/app/chat/utils/format.ts +43 -0
  230. package/frontend-vue/app/chat/utils/markdown.ts +1 -1
  231. package/frontend-vue/app/chat/utils/permission-view.ts +159 -0
  232. package/frontend-vue/app/chat/utils/platform.ts +34 -0
  233. package/frontend-vue/app/chat/utils/queue.ts +18 -0
  234. package/frontend-vue/app/chat/utils/render-items.ts +164 -0
  235. package/frontend-vue/app/chat/utils/run-status.ts +19 -23
  236. package/frontend-vue/app/chat/utils/suggestions.ts +101 -0
  237. package/frontend-vue/app/chat/utils/todos.ts +2 -2
  238. package/frontend-vue/app/chat/utils/tool-lexicon.ts +540 -0
  239. package/frontend-vue/app/chat/utils/tool-state.ts +60 -0
  240. package/frontend-vue/app/components/ActivityDetail.vue +235 -0
  241. package/frontend-vue/app/components/ChangesView.vue +249 -0
  242. package/frontend-vue/app/components/ChatPanel.vue +141 -196
  243. package/frontend-vue/app/components/PaletteAnswer.vue +185 -0
  244. package/frontend-vue/app/components/SkillCard.vue +77 -0
  245. package/frontend-vue/app/components/SkillDetail.vue +188 -0
  246. package/frontend-vue/app/plugins/ai.client.ts +349 -57
  247. package/frontend-vue/app/plugins/side-panel.ts +13 -0
  248. package/frontend-vue/app/runtime/assistant-activity.ts +105 -0
  249. package/frontend-vue/app/runtime/assistant-commands.ts +210 -0
  250. package/frontend-vue/app/runtime/assistant-notifications.ts +181 -0
  251. package/frontend-vue/app/runtime/assistant-session.ts +49 -6
  252. package/frontend-vue/app/runtime/channel-client.ts +3 -6
  253. package/frontend-vue/app/runtime/constants.ts +29 -35
  254. package/frontend-vue/app/runtime/host-commands.ts +4 -4
  255. package/frontend-vue/app/runtime/listeners.ts +1 -1
  256. package/frontend-vue/app/runtime/navigation-complete.ts +1 -1
  257. package/frontend-vue/app/runtime/panel-intents.ts +55 -0
  258. package/frontend-vue/app/runtime/shortcuts.ts +3 -1
  259. package/frontend-vue/app/runtime/sidecar-status.ts +9 -1
  260. package/frontend-vue/app/runtime/stream-holds.ts +24 -0
  261. package/frontend-vue/app/views/ChangeSetPanel.vue +222 -0
  262. package/frontend-vue/app/views/DecisionLabel.vue +30 -0
  263. package/frontend-vue/app/views/DiffView.vue +215 -0
  264. package/frontend-vue/app/views/ResultPill.vue +32 -0
  265. package/frontend-vue/app/views/RowStepper.vue +48 -0
  266. package/frontend-vue/app/views/UnavailableState.vue +66 -0
  267. package/frontend-vue/app/views/composables/useAiRequest.ts +89 -0
  268. package/frontend-vue/app/views/composables/useAssistant.ts +33 -0
  269. package/frontend-vue/app/views/composables/useChangeSetActions.ts +102 -0
  270. package/frontend-vue/app/views/composables/useViewFormat.ts +55 -0
  271. package/frontend-vue/app/views/constants.ts +43 -0
  272. package/frontend-vue/app/views/types.ts +189 -0
  273. package/frontend-vue/app/views/utils/activity.ts +77 -0
  274. package/frontend-vue/app/views/utils/change-sets.ts +44 -0
  275. package/frontend-vue/app/views/utils/diff.ts +98 -0
  276. package/frontend-vue/app/views/utils/moment.ts +92 -0
  277. package/frontend-vue/app/views/utils/skills.ts +27 -0
  278. package/frontend-vue/app/views/utils/tools.ts +73 -0
  279. package/frontend-vue/dms.frontend.ts +17 -5
  280. package/frontend-vue/i18n/locales/dms-ai-pages-en-GB.json +607 -0
  281. package/frontend-vue/i18n/locales/dms-ai-pages-fr-FR.json +607 -0
  282. package/frontend-vue/i18n/locales/dms-ai-panel-en-GB.json +425 -0
  283. package/frontend-vue/i18n/locales/dms-ai-panel-fr-FR.json +425 -0
  284. package/frontend-vue/i18n/locales/dms-ai-views-en-GB.json +142 -0
  285. package/frontend-vue/i18n/locales/dms-ai-views-fr-FR.json +142 -0
  286. package/frontend-vue/package.json +1 -1
  287. package/frontend-vue/tests/chat/conversation-events.test.ts +590 -0
  288. package/frontend-vue/tests/chat/diff-and-keys.test.ts +178 -0
  289. package/frontend-vue/tests/chat/tool-lexicon.test.ts +188 -0
  290. package/frontend-vue/tests/chat/useConversation.test.ts +36 -33
  291. package/frontend-vue/tests/chat-panel.test.ts +78 -131
  292. package/frontend-vue/tests/i18n-panel.test.ts +118 -0
  293. package/frontend-vue/tests/palette-assistant.test.ts +220 -0
  294. package/frontend-vue/tests/panel-states.test.ts +806 -0
  295. package/frontend-vue/tests/sidecar-guest.test.ts +35 -3
  296. package/frontend-vue/tests/support/i18n.ts +49 -0
  297. package/frontend-vue/tests/support/panel-harness.ts +198 -0
  298. package/frontend-vue/tests/support/stubs.ts +201 -0
  299. package/frontend-vue/tests/views/diff-view.test.ts +149 -0
  300. package/frontend-vue/tests/views/view-format.test.ts +59 -0
  301. package/package.json +4 -3
  302. package/sidecar/dist/agent/attachment-files.d.ts +0 -1
  303. package/sidecar/dist/agent/attachment-files.js +1 -1
  304. package/sidecar/dist/agent/attachment-files.js.map +1 -1
  305. package/sidecar/dist/agent/call-ledger.d.ts +6 -0
  306. package/sidecar/dist/agent/call-ledger.js +41 -0
  307. package/sidecar/dist/agent/call-ledger.js.map +1 -0
  308. package/sidecar/dist/agent/command-analysis.d.ts +9 -0
  309. package/sidecar/dist/agent/command-analysis.js +104 -0
  310. package/sidecar/dist/agent/command-analysis.js.map +1 -0
  311. package/sidecar/dist/agent/conversation-modes.d.ts +32 -0
  312. package/sidecar/dist/agent/conversation-modes.js +122 -0
  313. package/sidecar/dist/agent/conversation-modes.js.map +1 -0
  314. package/sidecar/dist/agent/edit-targets.d.ts +5 -0
  315. package/sidecar/dist/agent/edit-targets.js +41 -0
  316. package/sidecar/dist/agent/edit-targets.js.map +1 -0
  317. package/sidecar/dist/agent/effective-mode.d.ts +9 -2
  318. package/sidecar/dist/agent/effective-mode.js +14 -16
  319. package/sidecar/dist/agent/effective-mode.js.map +1 -1
  320. package/sidecar/dist/agent/host-context.js +2 -2
  321. package/sidecar/dist/agent/host-context.js.map +1 -1
  322. package/sidecar/dist/agent/line-diff.d.ts +8 -0
  323. package/sidecar/dist/agent/line-diff.js +204 -0
  324. package/sidecar/dist/agent/line-diff.js.map +1 -0
  325. package/sidecar/dist/agent/permission-bus.d.ts +55 -10
  326. package/sidecar/dist/agent/permission-bus.js +130 -100
  327. package/sidecar/dist/agent/permission-bus.js.map +1 -1
  328. package/sidecar/dist/agent/permission-preview.d.ts +20 -0
  329. package/sidecar/dist/agent/permission-preview.js +203 -0
  330. package/sidecar/dist/agent/permission-preview.js.map +1 -0
  331. package/sidecar/dist/agent/permission-rules.d.ts +17 -0
  332. package/sidecar/dist/agent/permission-rules.js +95 -0
  333. package/sidecar/dist/agent/permission-rules.js.map +1 -0
  334. package/sidecar/dist/agent/provider.d.ts +12 -4
  335. package/sidecar/dist/agent/question-bus.d.ts +14 -2
  336. package/sidecar/dist/agent/question-bus.js +30 -11
  337. package/sidecar/dist/agent/question-bus.js.map +1 -1
  338. package/sidecar/dist/agent/runner-events.d.ts +3 -1
  339. package/sidecar/dist/agent/runner.d.ts +6 -4
  340. package/sidecar/dist/agent/runner.js +24 -7
  341. package/sidecar/dist/agent/runner.js.map +1 -1
  342. package/sidecar/dist/agent/switching-runner.js +1 -0
  343. package/sidecar/dist/agent/switching-runner.js.map +1 -1
  344. package/sidecar/dist/agent/tool-kinds.d.ts +12 -0
  345. package/sidecar/dist/agent/tool-kinds.js +50 -0
  346. package/sidecar/dist/agent/tool-kinds.js.map +1 -0
  347. package/sidecar/dist/agent/typecheck.d.ts +2 -6
  348. package/sidecar/dist/audit/activity-query.d.ts +37 -0
  349. package/sidecar/dist/audit/activity-query.js +111 -0
  350. package/sidecar/dist/audit/activity-query.js.map +1 -0
  351. package/sidecar/dist/audit/activity-target.d.ts +2 -0
  352. package/sidecar/dist/audit/activity-target.js +46 -0
  353. package/sidecar/dist/audit/activity-target.js.map +1 -0
  354. package/sidecar/dist/audit/activity.d.ts +45 -0
  355. package/sidecar/dist/audit/activity.js +255 -0
  356. package/sidecar/dist/audit/activity.js.map +1 -0
  357. package/sidecar/dist/audit/call-audit.d.ts +11 -0
  358. package/sidecar/dist/audit/call-audit.js +23 -0
  359. package/sidecar/dist/audit/call-audit.js.map +1 -0
  360. package/sidecar/dist/checkpoints/checkpoints.d.ts +69 -0
  361. package/sidecar/dist/checkpoints/checkpoints.js +244 -0
  362. package/sidecar/dist/checkpoints/checkpoints.js.map +1 -0
  363. package/sidecar/dist/checkpoints/shadow-git.d.ts +23 -0
  364. package/sidecar/dist/checkpoints/shadow-git.js +173 -0
  365. package/sidecar/dist/checkpoints/shadow-git.js.map +1 -0
  366. package/sidecar/dist/constants/agent.d.ts +2 -0
  367. package/sidecar/dist/constants/agent.js +4 -0
  368. package/sidecar/dist/constants/agent.js.map +1 -1
  369. package/sidecar/dist/constants/audit.d.ts +22 -0
  370. package/sidecar/dist/constants/audit.js +49 -0
  371. package/sidecar/dist/constants/audit.js.map +1 -0
  372. package/sidecar/dist/constants/builder.d.ts +3 -0
  373. package/sidecar/dist/constants/builder.js +2 -0
  374. package/sidecar/dist/constants/builder.js.map +1 -1
  375. package/sidecar/dist/constants/checkpoints.d.ts +15 -0
  376. package/sidecar/dist/constants/checkpoints.js +26 -0
  377. package/sidecar/dist/constants/checkpoints.js.map +1 -0
  378. package/sidecar/dist/constants/claude.d.ts +1 -0
  379. package/sidecar/dist/constants/claude.js +1 -0
  380. package/sidecar/dist/constants/claude.js.map +1 -1
  381. package/sidecar/dist/constants/codex.d.ts +2 -4
  382. package/sidecar/dist/constants/codex.js +2 -4
  383. package/sidecar/dist/constants/codex.js.map +1 -1
  384. package/sidecar/dist/constants/http.d.ts +1 -0
  385. package/sidecar/dist/constants/http.js +1 -0
  386. package/sidecar/dist/constants/http.js.map +1 -1
  387. package/sidecar/dist/constants/mcp.d.ts +3 -0
  388. package/sidecar/dist/constants/mcp.js +9 -0
  389. package/sidecar/dist/constants/mcp.js.map +1 -1
  390. package/sidecar/dist/constants/permissions.d.ts +9 -3
  391. package/sidecar/dist/constants/permissions.js +9 -2
  392. package/sidecar/dist/constants/permissions.js.map +1 -1
  393. package/sidecar/dist/constants/settings.d.ts +2 -1
  394. package/sidecar/dist/constants/settings.js +7 -1
  395. package/sidecar/dist/constants/settings.js.map +1 -1
  396. package/sidecar/dist/constants/tool-kinds.d.ts +14 -0
  397. package/sidecar/dist/constants/tool-kinds.js +65 -0
  398. package/sidecar/dist/constants/tool-kinds.js.map +1 -0
  399. package/sidecar/dist/index.js +28 -2
  400. package/sidecar/dist/index.js.map +1 -1
  401. package/sidecar/dist/mcp/define-tool.d.ts +3 -2
  402. package/sidecar/dist/mcp/tool-definitions.js +4 -1
  403. package/sidecar/dist/mcp/tool-definitions.js.map +1 -1
  404. package/sidecar/dist/mcp/tools/ask-user.d.ts +2 -2
  405. package/sidecar/dist/mcp/tools/ask-user.js +7 -4
  406. package/sidecar/dist/mcp/tools/ask-user.js.map +1 -1
  407. package/sidecar/dist/mcp/tools/builder-catalog.d.ts +3 -0
  408. package/sidecar/dist/mcp/tools/builder-catalog.js +86 -0
  409. package/sidecar/dist/mcp/tools/builder-catalog.js.map +1 -0
  410. package/sidecar/dist/mcp/tools/builder-gate.d.ts +8 -0
  411. package/sidecar/dist/mcp/tools/builder-gate.js +22 -0
  412. package/sidecar/dist/mcp/tools/builder-gate.js.map +1 -0
  413. package/sidecar/dist/mcp/tools/builder.d.ts +7 -2
  414. package/sidecar/dist/mcp/tools/builder.js +48 -7
  415. package/sidecar/dist/mcp/tools/builder.js.map +1 -1
  416. package/sidecar/dist/mcp/types.d.ts +2 -0
  417. package/sidecar/dist/metrics/aggregate.d.ts +13 -10
  418. package/sidecar/dist/metrics/aggregate.js +140 -143
  419. package/sidecar/dist/metrics/aggregate.js.map +1 -1
  420. package/sidecar/dist/metrics/types.d.ts +36 -23
  421. package/sidecar/dist/metrics/types.js +3 -1
  422. package/sidecar/dist/metrics/types.js.map +1 -1
  423. package/sidecar/dist/pages/imports-scanner.d.ts +1 -1
  424. package/sidecar/dist/pages/imports-scanner.js +2 -5
  425. package/sidecar/dist/pages/imports-scanner.js.map +1 -1
  426. package/sidecar/dist/prompts/agent.d.ts +1 -3
  427. package/sidecar/dist/prompts/agent.js +4 -4
  428. package/sidecar/dist/prompts/agent.js.map +1 -1
  429. package/sidecar/dist/prompts/builder.d.ts +2 -2
  430. package/sidecar/dist/prompts/builder.js +2 -2
  431. package/sidecar/dist/protocol/events.d.ts +1084 -18
  432. package/sidecar/dist/protocol/events.js +239 -5
  433. package/sidecar/dist/protocol/events.js.map +1 -1
  434. package/sidecar/dist/protocol/messages.d.ts +273 -19
  435. package/sidecar/dist/protocol/messages.js +107 -7
  436. package/sidecar/dist/protocol/messages.js.map +1 -1
  437. package/sidecar/dist/providers/claude/config.d.ts +3 -2
  438. package/sidecar/dist/providers/claude/config.js +10 -4
  439. package/sidecar/dist/providers/claude/config.js.map +1 -1
  440. package/sidecar/dist/providers/claude/provider.d.ts +2 -8
  441. package/sidecar/dist/providers/claude/provider.js +37 -35
  442. package/sidecar/dist/providers/claude/provider.js.map +1 -1
  443. package/sidecar/dist/providers/claude/safe-mode.d.ts +6 -1
  444. package/sidecar/dist/providers/claude/safe-mode.js +13 -5
  445. package/sidecar/dist/providers/claude/safe-mode.js.map +1 -1
  446. package/sidecar/dist/providers/codex/adapter.d.ts +6 -0
  447. package/sidecar/dist/providers/codex/adapter.js +14 -4
  448. package/sidecar/dist/providers/codex/adapter.js.map +1 -1
  449. package/sidecar/dist/providers/codex/client.d.ts +0 -11
  450. package/sidecar/dist/providers/codex/config.d.ts +1 -3
  451. package/sidecar/dist/providers/codex/config.js +5 -11
  452. package/sidecar/dist/providers/codex/config.js.map +1 -1
  453. package/sidecar/dist/providers/codex/permissions.d.ts +7 -4
  454. package/sidecar/dist/providers/codex/permissions.js +32 -16
  455. package/sidecar/dist/providers/codex/permissions.js.map +1 -1
  456. package/sidecar/dist/providers/codex/process.js +1 -5
  457. package/sidecar/dist/providers/codex/process.js.map +1 -1
  458. package/sidecar/dist/providers/codex/provider.js +14 -3
  459. package/sidecar/dist/providers/codex/provider.js.map +1 -1
  460. package/sidecar/dist/providers/codex/skills.d.ts +0 -1
  461. package/sidecar/dist/providers/codex/skills.js +1 -1
  462. package/sidecar/dist/providers/codex/skills.js.map +1 -1
  463. package/sidecar/dist/providers/codex/stop.js +1 -10
  464. package/sidecar/dist/providers/codex/stop.js.map +1 -1
  465. package/sidecar/dist/server/change-set-actions.d.ts +10 -0
  466. package/sidecar/dist/server/change-set-actions.js +14 -0
  467. package/sidecar/dist/server/change-set-actions.js.map +1 -0
  468. package/sidecar/dist/server/chat-events.d.ts +15 -0
  469. package/sidecar/dist/server/chat-events.js +115 -0
  470. package/sidecar/dist/server/chat-events.js.map +1 -0
  471. package/sidecar/dist/server/chat-socket-registry.d.ts +2 -0
  472. package/sidecar/dist/server/chat-socket-registry.js +48 -37
  473. package/sidecar/dist/server/chat-socket-registry.js.map +1 -1
  474. package/sidecar/dist/server/conversation-runs.d.ts +13 -0
  475. package/sidecar/dist/server/conversation-runs.js +114 -0
  476. package/sidecar/dist/server/conversation-runs.js.map +1 -0
  477. package/sidecar/dist/server/http-io.d.ts +4 -0
  478. package/sidecar/dist/server/http-io.js +31 -0
  479. package/sidecar/dist/server/http-io.js.map +1 -0
  480. package/sidecar/dist/server/http-params.d.ts +9 -0
  481. package/sidecar/dist/server/http-params.js +79 -0
  482. package/sidecar/dist/server/http-params.js.map +1 -0
  483. package/sidecar/dist/server/http-routes.d.ts +27 -0
  484. package/sidecar/dist/server/http-routes.js +281 -0
  485. package/sidecar/dist/server/http-routes.js.map +1 -0
  486. package/sidecar/dist/server/http.d.ts +6 -1
  487. package/sidecar/dist/server/http.js +76 -164
  488. package/sidecar/dist/server/http.js.map +1 -1
  489. package/sidecar/dist/server/pending-queue.d.ts +2 -0
  490. package/sidecar/dist/server/pending-queue.js +16 -0
  491. package/sidecar/dist/server/pending-queue.js.map +1 -1
  492. package/sidecar/dist/server/permission-events.d.ts +15 -0
  493. package/sidecar/dist/server/permission-events.js +163 -0
  494. package/sidecar/dist/server/permission-events.js.map +1 -0
  495. package/sidecar/dist/server/routing.d.ts +4 -52
  496. package/sidecar/dist/server/routing.js +190 -501
  497. package/sidecar/dist/server/routing.js.map +1 -1
  498. package/sidecar/dist/server/safety-net.d.ts +7 -0
  499. package/sidecar/dist/server/safety-net.js +34 -6
  500. package/sidecar/dist/server/safety-net.js.map +1 -1
  501. package/sidecar/dist/server/services.d.ts +55 -0
  502. package/sidecar/dist/server/services.js +2 -0
  503. package/sidecar/dist/server/services.js.map +1 -0
  504. package/sidecar/dist/server/tool-calls.d.ts +6 -0
  505. package/sidecar/dist/server/tool-calls.js +134 -0
  506. package/sidecar/dist/server/tool-calls.js.map +1 -0
  507. package/sidecar/dist/server/turn-registry.d.ts +44 -0
  508. package/sidecar/dist/server/turn-registry.js +40 -0
  509. package/sidecar/dist/server/turn-registry.js.map +1 -0
  510. package/sidecar/dist/server/turns.d.ts +17 -0
  511. package/sidecar/dist/server/turns.js +335 -0
  512. package/sidecar/dist/server/turns.js.map +1 -0
  513. package/sidecar/dist/server/ws.d.ts +4 -1
  514. package/sidecar/dist/server/ws.js +102 -62
  515. package/sidecar/dist/server/ws.js.map +1 -1
  516. package/sidecar/dist/skills/build-catalog.d.ts +1 -0
  517. package/sidecar/dist/skills/build-catalog.js +14 -1
  518. package/sidecar/dist/skills/build-catalog.js.map +1 -1
  519. package/sidecar/dist/skills/skill-usage.d.ts +22 -0
  520. package/sidecar/dist/skills/skill-usage.js +97 -0
  521. package/sidecar/dist/skills/skill-usage.js.map +1 -0
  522. package/sidecar/dist/state/change-sets.d.ts +12 -0
  523. package/sidecar/dist/state/change-sets.js +77 -0
  524. package/sidecar/dist/state/change-sets.js.map +1 -0
  525. package/sidecar/dist/state/conversations.d.ts +19 -7
  526. package/sidecar/dist/state/conversations.js +61 -20
  527. package/sidecar/dist/state/conversations.js.map +1 -1
  528. package/sidecar/dist/state/host-state.d.ts +2 -1
  529. package/sidecar/dist/state/settings-store.d.ts +1 -0
  530. package/sidecar/dist/state/settings-store.js +27 -26
  531. package/sidecar/dist/state/settings-store.js.map +1 -1
  532. package/sidecar/dist/state/settings-types.d.ts +11 -1
  533. package/sidecar/dist/state/settings-types.js +3 -1
  534. package/sidecar/dist/state/settings-types.js.map +1 -1
  535. package/sidecar/dist/state/types.d.ts +114 -8
  536. package/sidecar/dist/state/types.js +6 -3
  537. package/sidecar/dist/state/types.js.map +1 -1
  538. package/skills/dms-builder-safe/REFERENCE.md +1 -1
  539. package/skills/dms-builder-safe/SKILL.md +12 -7
  540. package/dist/routes/proxy.d.ts +0 -4
  541. package/dist/routes/proxy.js +0 -55
  542. package/dist/routes/proxy.js.map +0 -1
  543. package/frontend-vue/app/chat/components/ComposerInput.vue +0 -742
  544. package/frontend-vue/app/chat/components/PermissionRequests.vue +0 -323
  545. package/frontend-vue/app/chat/components/QuestionPrompt.vue +0 -275
  546. package/frontend-vue/app/chat/components/QueuedMessages.vue +0 -109
  547. package/frontend-vue/app/chat/components/TodoList.vue +0 -291
  548. package/frontend-vue/app/chat/components/ToolCallEntry.vue +0 -218
  549. package/frontend-vue/app/chat/constants/connection-banner.ts +0 -7
  550. package/frontend-vue/app/chat/constants/conversation-drawer.ts +0 -13
  551. package/frontend-vue/app/chat/constants/permissions.ts +0 -50
  552. package/frontend-vue/app/chat/utils/tool-summary.ts +0 -53
  553. package/frontend-vue/app/components/ActivityView.vue +0 -94
  554. package/frontend-vue/app/components/SettingsView.vue +0 -387
  555. package/frontend-vue/app/components/SkillsView.vue +0 -230
  556. package/frontend-vue/app/runtime/header-action.ts +0 -64
  557. package/frontend-vue/app/runtime/overlay-prefs.ts +0 -89
  558. package/frontend-vue/app/runtime/panel-state.ts +0 -88
  559. package/frontend-vue/tests/overlay-prefs.test.ts +0 -91
  560. package/frontend-vue/tests/panel-state.test.ts +0 -58
@@ -1,43 +1,36 @@
1
1
  import { type Ref, ref } from "vue";
2
- import {
3
- MESSAGE_ROLES,
4
- NOT_SENT_MESSAGE,
5
- RETRY_NEEDS_FILES_MESSAGE,
6
- STOP_NOT_DELIVERED_MESSAGE,
7
- STORED_ERROR_ROLE,
8
- STORED_TOOL_RESULT_ROLE,
9
- STORED_TOOL_USE_ROLE,
10
- TOOL_CUT_SHORT_RESULT,
11
- TOOL_STATUS,
12
- } from "../constants/conversation";
13
- import {
14
- CLIENT_MESSAGE_TYPES,
15
- SERVER_EVENT_TYPES,
16
- } from "../constants/protocol";
2
+ import { LOCAL_ERROR_KEYS, MESSAGE_ROLES } from "../constants/conversation";
3
+ import { CLIENT_MESSAGE_TYPES } from "../constants/protocol";
17
4
  import type {
18
- AssistantMessage,
19
5
  ConversationMessage,
20
- ErrorMessage,
21
6
  MessageAttachment,
22
7
  QueuedMessage,
23
8
  RunProgress,
24
- ToolCallMessage,
25
- ToolStatus,
26
9
  UserMessage,
27
10
  } from "../types/conversation";
28
- import type { PermissionRequestData } from "../types/permission";
29
- import type { QuestionData, QuestionRequestData } from "../types/question";
30
- import { type PendingAttachment, splitDataUrl } from "../utils/attachments";
11
+ import type {
12
+ ChangeSetSummary,
13
+ ConversationModeState,
14
+ QuestionAnswerRecord,
15
+ WireAttachment,
16
+ } from "../types/protocol";
17
+ import type { PendingAttachment } from "../utils/attachments";
18
+ import { splitDataUrl } from "../utils/attachments";
19
+ import {
20
+ buildLocalError,
21
+ buildUserMessage,
22
+ settleOpenTools,
23
+ } from "../utils/conversation-messages";
31
24
  import { newUuid } from "../utils/ids";
32
- import { toActivityKind } from "../utils/run-status";
25
+ import { dispatchConversationEvent } from "./conversation-events";
33
26
 
34
27
  export interface UseConversationOptions {
35
28
  activeId: Ref<string>;
36
29
  /** Returns false when the message could not leave the chat. */
37
30
  send: (msg: object) => boolean;
38
31
  onMessage: (handler: (msg: unknown) => void) => () => void;
39
- onPermissionRequest?: (req: PermissionRequestData) => void;
40
- onQuestionRequest?: (req: QuestionRequestData) => void;
32
+ /** The page the dashboard shows, stamped on the messages sent from it. */
33
+ getPagePath?: () => string | undefined;
41
34
  }
42
35
 
43
36
  export interface UseConversationResult {
@@ -50,432 +43,29 @@ export interface UseConversationResult {
50
43
  isTurnInFlight: Ref<boolean>;
51
44
  /** Local time of the last event the sidecar sent about this conversation. */
52
45
  lastEventAtMs: Ref<number>;
53
- sendUserMessage: (content: string, attachments?: PendingAttachment[]) => void;
54
- /** Sends the last user message again, with its files when still at hand. */
46
+ /** The change sets of this conversation, by id. */
47
+ changeSets: Ref<Record<string, ChangeSetSummary>>;
48
+ /** The chat's own approval mode and scope; null until the sidecar says. */
49
+ mode: Ref<ConversationModeState | null>;
50
+ /** Tokens this chat has used so far; null until the sidecar says. */
51
+ totalTokens: Ref<number | null>;
52
+ sendUserMessage: (
53
+ content: string,
54
+ attachments?: PendingAttachment[],
55
+ extra?: Record<string, unknown>,
56
+ ) => void;
57
+ /**
58
+ * Runs the last turn again: the sidecar re-runs a stored message, the chat
59
+ * resends one that never left.
60
+ */
55
61
  retry: () => void;
56
- cancelQueued: (id: string) => void;
57
62
  interrupt: () => void;
63
+ recordAnswers: (answers: QuestionAnswerRecord[]) => void;
58
64
  reset: () => void;
59
65
  }
60
66
 
61
- interface SnapshotMessage {
62
- role: string;
63
- content: string;
64
- toolName?: string;
65
- callId?: string;
66
- status?: string;
67
- attachments?: MessageAttachment[];
68
- isRetryable?: boolean;
69
- timestampMs: number;
70
- }
71
-
72
- interface ChunkEvent {
73
- type: typeof SERVER_EVENT_TYPES.ASSISTANT_MESSAGE_CHUNK;
74
- conversationId: string;
75
- text: string;
76
- }
77
-
78
- interface ToolStartEvent {
79
- type: typeof SERVER_EVENT_TYPES.TOOL_CALL_START;
80
- conversationId: string;
81
- callId: string;
82
- toolName: string;
83
- args: unknown;
84
- }
85
-
86
- interface ToolEndEvent {
87
- type: typeof SERVER_EVENT_TYPES.TOOL_CALL_END;
88
- conversationId: string;
89
- callId: string;
90
- status: "success" | "error";
91
- result: unknown;
92
- }
93
-
94
- interface RunDoneEvent {
95
- type: typeof SERVER_EVENT_TYPES.RUN_DONE;
96
- conversationId: string;
97
- }
98
-
99
- interface RunResumedEvent {
100
- type: typeof SERVER_EVENT_TYPES.RUN_RESUMED;
101
- conversationId: string;
102
- }
103
-
104
- interface RunErrorEvent {
105
- type: typeof SERVER_EVENT_TYPES.RUN_ERROR;
106
- conversationId: string;
107
- error: string;
108
- isRetryable?: boolean;
109
- }
110
-
111
- interface RunProgressEvent {
112
- type: typeof SERVER_EVENT_TYPES.RUN_PROGRESS;
113
- conversationId: string;
114
- activity: string;
115
- detail?: string;
116
- elapsedMs: number;
117
- idleMs: number;
118
- }
119
-
120
- interface SnapshotEvent {
121
- type: typeof SERVER_EVENT_TYPES.CONVERSATION_SNAPSHOT;
122
- conversationId: string;
123
- messages: SnapshotMessage[];
124
- }
125
-
126
- interface PermissionRequestEvent {
127
- type: typeof SERVER_EVENT_TYPES.PERMISSION_REQUEST;
128
- conversationId: string;
129
- requestId: string;
130
- toolName: string;
131
- args: unknown;
132
- summary: string;
133
- }
134
-
135
- interface AskQuestionEvent {
136
- type: typeof SERVER_EVENT_TYPES.ASK_QUESTION;
137
- conversationId: string;
138
- requestId: string;
139
- questions: QuestionData[];
140
- }
141
-
142
- interface WireAttachment {
143
- name: string;
144
- mimeType: string;
145
- size: number;
146
- data: string;
147
- }
148
-
149
- interface AttachmentMeta {
150
- name: string;
151
- mimeType: string;
152
- size: number;
153
- }
154
-
155
- interface QueuedItemWire {
156
- id: string;
157
- content: string;
158
- attachments?: WireAttachment[];
159
- }
160
-
161
- interface QueueStateEvent {
162
- type: typeof SERVER_EVENT_TYPES.QUEUE_STATE;
163
- conversationId: string;
164
- items: QueuedItemWire[];
165
- }
166
-
167
- interface UserMessageEchoEvent {
168
- type: typeof SERVER_EVENT_TYPES.USER_MESSAGE_ECHO;
169
- conversationId: string;
170
- content: string;
171
- attachments?: AttachmentMeta[];
172
- timestampMs: number;
173
- }
174
-
175
- function newId(): string {
176
- return newUuid();
177
- }
178
-
179
- function buildUserMessage(
180
- content: string,
181
- attachments?: MessageAttachment[],
182
- ): UserMessage {
183
- return {
184
- id: newId(),
185
- role: MESSAGE_ROLES.USER,
186
- content,
187
- attachments,
188
- timestampMs: Date.now(),
189
- };
190
- }
191
-
192
- function markUnsent(message: UserMessage, isSent: boolean): UserMessage {
193
- return isSent ? message : { ...message, isUnsent: true };
194
- }
195
-
196
- function buildAssistantMessage(text: string): AssistantMessage {
197
- return {
198
- id: newId(),
199
- role: MESSAGE_ROLES.ASSISTANT,
200
- content: text,
201
- timestampMs: Date.now(),
202
- };
203
- }
204
-
205
- function buildToolCallMessage(event: ToolStartEvent): ToolCallMessage {
206
- return {
207
- id: newId(),
208
- role: MESSAGE_ROLES.TOOL,
209
- callId: event.callId,
210
- toolName: event.toolName,
211
- args: event.args,
212
- status: TOOL_STATUS.PENDING,
213
- timestampMs: Date.now(),
214
- };
215
- }
216
-
217
- function appendChunk(
218
- list: ConversationMessage[],
219
- text: string,
220
- ): ConversationMessage[] {
221
- const last = list.at(-1);
222
- if (last !== undefined && last.role === MESSAGE_ROLES.ASSISTANT) {
223
- const updated: AssistantMessage = { ...last, content: last.content + text };
224
- return [...list.slice(0, -1), updated];
225
- }
226
- return [...list, buildAssistantMessage(text)];
227
- }
228
-
229
- function upsertToolCall(
230
- list: ConversationMessage[],
231
- event: ToolStartEvent,
232
- ): ConversationMessage[] {
233
- const exists = list.some(
234
- (msg) => msg.role === MESSAGE_ROLES.TOOL && msg.callId === event.callId,
235
- );
236
- if (!exists) return [...list, buildToolCallMessage(event)];
237
- return list.map((msg) => {
238
- if (msg.role !== MESSAGE_ROLES.TOOL || msg.callId !== event.callId) {
239
- return msg;
240
- }
241
- return {
242
- ...msg,
243
- toolName: event.toolName,
244
- args: event.args,
245
- status: TOOL_STATUS.PENDING,
246
- };
247
- });
248
- }
249
-
250
- function applyToolEnd(
251
- list: ConversationMessage[],
252
- event: ToolEndEvent,
253
- ): ConversationMessage[] {
254
- return list.map((msg) => {
255
- if (msg.role !== MESSAGE_ROLES.TOOL) return msg;
256
- if (msg.callId !== event.callId) return msg;
257
- return { ...msg, status: event.status, result: event.result };
258
- });
259
- }
260
-
261
- function normalizeToolStatus(raw: string | undefined): ToolStatus {
262
- if (raw === TOOL_STATUS.SUCCESS) return TOOL_STATUS.SUCCESS;
263
- if (raw === TOOL_STATUS.ERROR) return TOOL_STATUS.ERROR;
264
- return TOOL_STATUS.PENDING;
265
- }
266
-
267
- function safeParse(raw: string): unknown {
268
- try {
269
- return JSON.parse(raw);
270
- } catch {
271
- return raw;
272
- }
273
- }
274
-
275
- function buildUserSnapshot(snap: SnapshotMessage): UserMessage {
276
- return {
277
- id: newId(),
278
- role: MESSAGE_ROLES.USER,
279
- content: snap.content,
280
- attachments: snap.attachments,
281
- timestampMs: snap.timestampMs,
282
- };
283
- }
284
-
285
- function buildAssistantSnapshot(snap: SnapshotMessage): AssistantMessage {
286
- return {
287
- id: newId(),
288
- role: MESSAGE_ROLES.ASSISTANT,
289
- content: snap.content,
290
- timestampMs: snap.timestampMs,
291
- };
292
- }
293
-
294
- function buildToolUseSnapshot(snap: SnapshotMessage): ToolCallMessage | null {
295
- if (snap.callId === undefined || snap.toolName === undefined) return null;
296
- return {
297
- id: newId(),
298
- role: MESSAGE_ROLES.TOOL,
299
- callId: snap.callId,
300
- toolName: snap.toolName,
301
- args: safeParse(snap.content),
302
- status: TOOL_STATUS.PENDING,
303
- timestampMs: snap.timestampMs,
304
- };
305
- }
306
-
307
- function applyToolResultSnapshot(
308
- out: ConversationMessage[],
309
- toolByCallId: Map<string, ToolCallMessage>,
310
- snap: SnapshotMessage,
311
- ): void {
312
- if (snap.callId === undefined) return;
313
- const result = safeParse(snap.content);
314
- const status = normalizeToolStatus(snap.status);
315
- const existing = toolByCallId.get(snap.callId);
316
- if (existing !== undefined) {
317
- existing.result = result;
318
- existing.status = status;
319
- return;
320
- }
321
- out.push({
322
- id: newId(),
323
- role: MESSAGE_ROLES.TOOL,
324
- callId: snap.callId,
325
- toolName: "",
326
- args: undefined,
327
- result,
328
- status,
329
- timestampMs: snap.timestampMs,
330
- });
331
- }
332
-
333
- function appendSnapshotItem(
334
- out: ConversationMessage[],
335
- toolByCallId: Map<string, ToolCallMessage>,
336
- item: SnapshotMessage,
337
- ): void {
338
- if (item.role === MESSAGE_ROLES.USER) {
339
- out.push(buildUserSnapshot(item));
340
- return;
341
- }
342
- if (item.role === STORED_ERROR_ROLE) {
343
- out.push(
344
- buildErrorMessage(
345
- item.content,
346
- item.isRetryable ?? true,
347
- item.timestampMs,
348
- ),
349
- );
350
- return;
351
- }
352
- if (item.role === MESSAGE_ROLES.ASSISTANT) {
353
- out.push(buildAssistantSnapshot(item));
354
- return;
355
- }
356
- if (item.role === STORED_TOOL_USE_ROLE) {
357
- const message = buildToolUseSnapshot(item);
358
- if (message === null) return;
359
- out.push(message);
360
- toolByCallId.set(message.callId, message);
361
- return;
362
- }
363
- if (item.role === STORED_TOOL_RESULT_ROLE) {
364
- applyToolResultSnapshot(out, toolByCallId, item);
365
- }
366
- }
367
-
368
- function snapshotToMessages(snap: SnapshotMessage[]): ConversationMessage[] {
369
- const out: ConversationMessage[] = [];
370
- const toolByCallId = new Map<string, ToolCallMessage>();
371
- for (const item of snap) {
372
- appendSnapshotItem(out, toolByCallId, item);
373
- }
374
- return settlePendingTools(out);
375
- }
376
-
377
- function buildErrorMessage(
378
- error: string,
379
- isRetryable: boolean,
380
- timestampMs: number = Date.now(),
381
- ): ErrorMessage {
382
- return {
383
- id: newId(),
384
- role: MESSAGE_ROLES.ERROR,
385
- content: error,
386
- isRetryable,
387
- timestampMs,
388
- };
389
- }
390
-
391
- function isPendingTool(msg: ConversationMessage): msg is ToolCallMessage {
392
- return msg.role === MESSAGE_ROLES.TOOL && msg.status === TOOL_STATUS.PENDING;
393
- }
394
-
395
- function settlePendingTools(
396
- list: ConversationMessage[],
397
- ): ConversationMessage[] {
398
- if (!list.some(isPendingTool)) return list;
399
- return list.map((msg) => {
400
- if (!isPendingTool(msg)) return msg;
401
- return { ...msg, status: TOOL_STATUS.ERROR, result: TOOL_CUT_SHORT_RESULT };
402
- });
403
- }
404
-
405
- function toRunProgress(event: RunProgressEvent): RunProgress {
406
- return {
407
- activity: toActivityKind(event.activity),
408
- detail: event.detail,
409
- elapsedMs: event.elapsedMs,
410
- idleMs: event.idleMs,
411
- receivedAtMs: Date.now(),
412
- };
413
- }
414
-
415
- function isUserMessage(msg: ConversationMessage): msg is UserMessage {
416
- return msg.role === MESSAGE_ROLES.USER;
417
- }
418
-
419
- function lastUserMessage(list: ConversationMessage[]): UserMessage | undefined {
420
- for (let index = list.length - 1; index >= 0; index -= 1) {
421
- const message = list[index];
422
- if (isUserMessage(message)) return message;
423
- }
424
- return undefined;
425
- }
426
-
427
- function toResendableAttachments(
428
- attachments: MessageAttachment[] | undefined,
429
- ): PendingAttachment[] | null {
430
- const list = attachments ?? [];
431
- if (list.some((att) => !att.dataUrl)) return null;
432
- return list.map((att) => ({
433
- id: newId(),
434
- name: att.name,
435
- mimeType: att.mimeType,
436
- size: att.size,
437
- data: splitDataUrl(att.dataUrl ?? ""),
438
- dataUrl: att.dataUrl ?? "",
439
- }));
440
- }
441
-
442
- function isObject(value: unknown): value is Record<string, unknown> {
443
- return value !== null && typeof value === "object";
444
- }
445
-
446
- function getEventType(msg: unknown): string | null {
447
- if (!isObject(msg)) return null;
448
- const t = msg.type;
449
- return typeof t === "string" ? t : null;
450
- }
451
-
452
- function getConversationId(msg: unknown): string | null {
453
- if (!isObject(msg)) return null;
454
- const id = msg.conversationId;
455
- return typeof id === "string" ? id : null;
456
- }
457
-
458
- function toPermissionRequestData(
459
- event: PermissionRequestEvent,
460
- ): PermissionRequestData {
461
- return {
462
- requestId: event.requestId,
463
- conversationId: event.conversationId,
464
- toolName: event.toolName,
465
- args: event.args,
466
- summary: event.summary,
467
- };
468
- }
469
-
470
- function toQuestionRequestData(event: AskQuestionEvent): QuestionRequestData {
471
- return {
472
- requestId: event.requestId,
473
- conversationId: event.conversationId,
474
- questions: event.questions,
475
- };
476
- }
477
-
478
- interface ConversationState {
67
+ /** Every piece of a conversation the event handlers write. */
68
+ export interface ConversationState {
479
69
  options: UseConversationOptions;
480
70
  messages: Ref<ConversationMessage[]>;
481
71
  isRunning: Ref<boolean>;
@@ -483,40 +73,23 @@ interface ConversationState {
483
73
  progress: Ref<RunProgress | null>;
484
74
  isTurnInFlight: Ref<boolean>;
485
75
  lastEventAtMs: Ref<number>;
76
+ changeSets: Ref<Record<string, ChangeSetSummary>>;
77
+ mode: Ref<ConversationModeState | null>;
78
+ totalTokens: Ref<number | null>;
79
+ /**
80
+ * When the calls of the stored transcript started and ended. A re-attach
81
+ * replays the running turn's events, and the replayed calls take their
82
+ * times from here rather than from the moment of the replay.
83
+ */
84
+ callTimes: Map<string, CallTimes>;
486
85
  }
487
86
 
488
- type ConversationEvent =
489
- | ChunkEvent
490
- | ToolStartEvent
491
- | ToolEndEvent
492
- | RunDoneEvent
493
- | RunResumedEvent
494
- | RunErrorEvent
495
- | RunProgressEvent
496
- | SnapshotEvent
497
- | PermissionRequestEvent
498
- | AskQuestionEvent
499
- | QueueStateEvent
500
- | UserMessageEchoEvent;
501
-
502
- type ConversationEventType = ConversationEvent["type"];
503
-
504
- interface EventTypeTag<K extends ConversationEventType> {
505
- type: K;
87
+ /** When a call started and, once it did, ended, in sidecar time. */
88
+ interface CallTimes {
89
+ startedAtMs: number;
90
+ endedAtMs?: number;
506
91
  }
507
92
 
508
- type EventOfType<K extends ConversationEventType> = Extract<
509
- ConversationEvent,
510
- EventTypeTag<K>
511
- >;
512
-
513
- type EventHandlers = {
514
- [K in ConversationEventType]: (
515
- state: ConversationState,
516
- event: EventOfType<K>,
517
- ) => void;
518
- };
519
-
520
93
  function appendMessage(
521
94
  state: ConversationState,
522
95
  message: ConversationMessage,
@@ -524,12 +97,12 @@ function appendMessage(
524
97
  state.messages.value = [...state.messages.value, message];
525
98
  }
526
99
 
527
- function appendError(
100
+ function appendLocalError(
528
101
  state: ConversationState,
529
- error: string,
102
+ key: string,
530
103
  isRetryable = true,
531
104
  ): void {
532
- appendMessage(state, buildErrorMessage(error, isRetryable));
105
+ appendMessage(state, buildLocalError(key, isRetryable));
533
106
  }
534
107
 
535
108
  function expectTurn(state: ConversationState): void {
@@ -538,149 +111,11 @@ function expectTurn(state: ConversationState): void {
538
111
  }
539
112
 
540
113
  function endTurn(state: ConversationState): void {
541
- state.messages.value = settlePendingTools(state.messages.value);
542
- state.progress.value = null;
543
- state.isTurnInFlight.value = false;
544
- }
545
-
546
- function settleOrKeepRunning(state: ConversationState): void {
547
- state.isRunning.value = state.queued.value.length > 0;
548
- }
549
-
550
- function applySnapshot(state: ConversationState, event: SnapshotEvent): void {
551
- state.messages.value = snapshotToMessages(event.messages);
552
- state.isRunning.value = false;
114
+ state.messages.value = settleOpenTools(state.messages.value);
553
115
  state.progress.value = null;
554
116
  state.isTurnInFlight.value = false;
555
117
  }
556
118
 
557
- function toPendingAttachment(wire: WireAttachment): PendingAttachment {
558
- return {
559
- id: newId(),
560
- name: wire.name,
561
- mimeType: wire.mimeType,
562
- size: wire.size,
563
- data: wire.data,
564
- dataUrl: `data:${wire.mimeType};base64,${wire.data}`,
565
- };
566
- }
567
-
568
- function applyQueueState(
569
- state: ConversationState,
570
- event: QueueStateEvent,
571
- ): void {
572
- state.queued.value = event.items.map((item) => ({
573
- id: item.id,
574
- content: item.content,
575
- attachments: (item.attachments ?? []).map(toPendingAttachment),
576
- }));
577
- }
578
-
579
- function withAttachments(
580
- attachments: MessageAttachment[],
581
- ): MessageAttachment[] | undefined {
582
- return attachments.length > 0 ? attachments : undefined;
583
- }
584
-
585
- function applyUserEcho(
586
- state: ConversationState,
587
- event: UserMessageEchoEvent,
588
- ): void {
589
- const attachments = (event.attachments ?? []).map((a) => ({
590
- ...a,
591
- dataUrl: "",
592
- }));
593
- appendMessage(
594
- state,
595
- buildUserMessage(event.content, withAttachments(attachments)),
596
- );
597
- }
598
-
599
- function forwardPermissionRequest(
600
- state: ConversationState,
601
- event: PermissionRequestEvent,
602
- ): void {
603
- state.options.onPermissionRequest?.(toPermissionRequestData(event));
604
- }
605
-
606
- function forwardQuestion(
607
- state: ConversationState,
608
- event: AskQuestionEvent,
609
- ): void {
610
- state.options.onQuestionRequest?.(toQuestionRequestData(event));
611
- }
612
-
613
- function applyProgress(
614
- state: ConversationState,
615
- event: RunProgressEvent,
616
- ): void {
617
- state.progress.value = toRunProgress(event);
618
- state.isRunning.value = true;
619
- state.isTurnInFlight.value = true;
620
- }
621
-
622
- const EVENT_HANDLERS: EventHandlers = {
623
- [SERVER_EVENT_TYPES.ASSISTANT_MESSAGE_CHUNK]: (state, event) => {
624
- state.messages.value = appendChunk(state.messages.value, event.text);
625
- },
626
- [SERVER_EVENT_TYPES.TOOL_CALL_START]: (state, event) => {
627
- state.messages.value = upsertToolCall(state.messages.value, event);
628
- },
629
- [SERVER_EVENT_TYPES.TOOL_CALL_END]: (state, event) => {
630
- state.messages.value = applyToolEnd(state.messages.value, event);
631
- },
632
- [SERVER_EVENT_TYPES.RUN_DONE]: (state) => {
633
- endTurn(state);
634
- settleOrKeepRunning(state);
635
- },
636
- [SERVER_EVENT_TYPES.RUN_RESUMED]: (state) => {
637
- state.isRunning.value = true;
638
- expectTurn(state);
639
- },
640
- [SERVER_EVENT_TYPES.RUN_ERROR]: (state, event) => {
641
- endTurn(state);
642
- appendError(state, event.error, event.isRetryable ?? true);
643
- settleOrKeepRunning(state);
644
- },
645
- [SERVER_EVENT_TYPES.RUN_PROGRESS]: applyProgress,
646
- [SERVER_EVENT_TYPES.CONVERSATION_SNAPSHOT]: applySnapshot,
647
- [SERVER_EVENT_TYPES.PERMISSION_REQUEST]: forwardPermissionRequest,
648
- [SERVER_EVENT_TYPES.ASK_QUESTION]: forwardQuestion,
649
- [SERVER_EVENT_TYPES.QUEUE_STATE]: applyQueueState,
650
- [SERVER_EVENT_TYPES.USER_MESSAGE_ECHO]: applyUserEcho,
651
- };
652
-
653
- function isForActiveConversation(
654
- state: ConversationState,
655
- msg: unknown,
656
- ): boolean {
657
- const eventId = getConversationId(msg);
658
- return eventId === null || eventId === state.options.activeId.value;
659
- }
660
-
661
- function isHandledEventType(
662
- type: string | null,
663
- ): type is ConversationEventType {
664
- return type !== null && Object.hasOwn(EVENT_HANDLERS, type);
665
- }
666
-
667
- function runHandler<K extends ConversationEventType>(
668
- state: ConversationState,
669
- type: K,
670
- event: EventOfType<K>,
671
- ): void {
672
- const handler: EventHandlers[K] = EVENT_HANDLERS[type];
673
- handler(state, event);
674
- }
675
-
676
- function dispatch(state: ConversationState, msg: unknown): void {
677
- const type = getEventType(msg);
678
- if (!isHandledEventType(type)) return;
679
- if (!isForActiveConversation(state, msg)) return;
680
- state.lastEventAtMs.value = Date.now();
681
- runHandler(state, type, msg as EventOfType<typeof type>);
682
- }
683
-
684
119
  function toWireAttachments(attachments: PendingAttachment[]): WireAttachment[] {
685
120
  return attachments.map((a) => ({
686
121
  name: a.name,
@@ -692,7 +127,8 @@ function toWireAttachments(attachments: PendingAttachment[]): WireAttachment[] {
692
127
 
693
128
  function toLocalAttachments(
694
129
  attachments: PendingAttachment[],
695
- ): MessageAttachment[] {
130
+ ): MessageAttachment[] | undefined {
131
+ if (attachments.length === 0) return undefined;
696
132
  return attachments.map((a) => ({
697
133
  name: a.name,
698
134
  mimeType: a.mimeType,
@@ -701,43 +137,46 @@ function toLocalAttachments(
701
137
  }));
702
138
  }
703
139
 
140
+ function withWire(attachments: PendingAttachment[]): Record<string, unknown> {
141
+ const wire = toWireAttachments(attachments);
142
+ return wire.length > 0 ? { attachments: wire } : {};
143
+ }
144
+
704
145
  function queueFollowUp(
705
146
  state: ConversationState,
706
147
  content: string,
707
148
  attachments: PendingAttachment[],
708
149
  ): void {
709
- const wire = toWireAttachments(attachments);
710
150
  const isQueued = state.options.send({
711
151
  type: CLIENT_MESSAGE_TYPES.QUEUE_ENQUEUE,
712
152
  conversationId: state.options.activeId.value,
713
- item: {
714
- id: newId(),
715
- content,
716
- ...(wire.length > 0 ? { attachments: wire } : {}),
717
- },
153
+ item: { id: newUuid(), content, ...withWire(attachments) },
718
154
  });
719
- if (!isQueued) appendError(state, NOT_SENT_MESSAGE);
155
+ if (!isQueued) appendLocalError(state, LOCAL_ERROR_KEYS.NOT_SENT);
720
156
  }
721
157
 
722
158
  function startTurn(
723
159
  state: ConversationState,
724
160
  content: string,
725
161
  attachments: PendingAttachment[],
162
+ extra: Record<string, unknown>,
726
163
  ): void {
727
- const wire = toWireAttachments(attachments);
728
164
  const isSent = state.options.send({
729
165
  type: CLIENT_MESSAGE_TYPES.USER_MESSAGE,
730
166
  conversationId: state.options.activeId.value,
731
167
  content,
732
- ...(wire.length > 0 ? { attachments: wire } : {}),
168
+ ...withWire(attachments),
169
+ ...extra,
733
170
  });
171
+ state.messages.value = settleOpenTools(state.messages.value);
734
172
  const message = buildUserMessage(
735
173
  content,
736
- withAttachments(toLocalAttachments(attachments)),
174
+ toLocalAttachments(attachments),
175
+ state.options.getPagePath?.(),
737
176
  );
738
- appendMessage(state, markUnsent(message, isSent));
177
+ appendMessage(state, isSent ? message : { ...message, isUnsent: true });
739
178
  if (!isSent) {
740
- appendError(state, NOT_SENT_MESSAGE);
179
+ appendLocalError(state, LOCAL_ERROR_KEYS.NOT_SENT);
741
180
  return;
742
181
  }
743
182
  state.isRunning.value = true;
@@ -748,6 +187,7 @@ function sendUserMessage(
748
187
  state: ConversationState,
749
188
  content: string,
750
189
  attachments: PendingAttachment[],
190
+ extra: Record<string, unknown>,
751
191
  ): void {
752
192
  const trimmed = content.trim();
753
193
  if (trimmed.length === 0 && attachments.length === 0) return;
@@ -755,31 +195,60 @@ function sendUserMessage(
755
195
  queueFollowUp(state, trimmed, attachments);
756
196
  return;
757
197
  }
758
- startTurn(state, trimmed, attachments);
198
+ startTurn(state, trimmed, attachments, extra);
759
199
  }
760
200
 
761
- function retry(state: ConversationState): void {
762
- const last = lastUserMessage(state.messages.value);
763
- if (last === undefined) return;
201
+ function lastUserMessage(list: ConversationMessage[]): UserMessage | undefined {
202
+ const users = list.filter(
203
+ (msg): msg is UserMessage => msg.role === MESSAGE_ROLES.USER,
204
+ );
205
+ return users.at(-1);
206
+ }
207
+
208
+ function toResendableAttachments(
209
+ attachments: MessageAttachment[] | undefined,
210
+ ): PendingAttachment[] | null {
211
+ const list = attachments ?? [];
212
+ if (list.some((att) => !att.dataUrl)) return null;
213
+ return list.map((att) => ({
214
+ id: newUuid(),
215
+ name: att.name,
216
+ mimeType: att.mimeType,
217
+ size: att.size,
218
+ data: splitDataUrl(att.dataUrl ?? ""),
219
+ dataUrl: att.dataUrl ?? "",
220
+ }));
221
+ }
222
+
223
+ function resendLocally(state: ConversationState, last: UserMessage): void {
764
224
  const attachments = toResendableAttachments(last.attachments);
765
225
  if (attachments === null) {
766
- appendError(state, RETRY_NEEDS_FILES_MESSAGE, false);
226
+ appendLocalError(state, LOCAL_ERROR_KEYS.RETRY_NEEDS_FILES, false);
767
227
  return;
768
228
  }
769
- if (last.isUnsent === true) {
770
- state.messages.value = state.messages.value.filter(
771
- (msg) => msg.id !== last.id,
772
- );
773
- }
774
- sendUserMessage(state, last.content, attachments);
229
+ state.messages.value = state.messages.value.filter(
230
+ (msg) => msg.id !== last.id,
231
+ );
232
+ sendUserMessage(state, last.content, attachments, {});
775
233
  }
776
234
 
777
- function cancelQueued(state: ConversationState, id: string): void {
778
- state.options.send({
779
- type: CLIENT_MESSAGE_TYPES.QUEUE_CANCEL,
235
+ function retry(state: ConversationState): void {
236
+ const last = lastUserMessage(state.messages.value);
237
+ if (last === undefined || state.isRunning.value) return;
238
+ if (last.isUnsent === true) {
239
+ resendLocally(state, last);
240
+ return;
241
+ }
242
+ const isSent = state.options.send({
243
+ type: CLIENT_MESSAGE_TYPES.RETRY_TURN,
780
244
  conversationId: state.options.activeId.value,
781
- id,
782
245
  });
246
+ if (!isSent) {
247
+ appendLocalError(state, LOCAL_ERROR_KEYS.NOT_SENT);
248
+ return;
249
+ }
250
+ state.isRunning.value = true;
251
+ expectTurn(state);
783
252
  }
784
253
 
785
254
  function interrupt(state: ConversationState): void {
@@ -791,7 +260,20 @@ function interrupt(state: ConversationState): void {
791
260
  if (isSent) return;
792
261
  endTurn(state);
793
262
  state.isRunning.value = false;
794
- appendError(state, STOP_NOT_DELIVERED_MESSAGE);
263
+ appendLocalError(state, LOCAL_ERROR_KEYS.STOP_NOT_DELIVERED);
264
+ }
265
+
266
+ function recordAnswers(
267
+ state: ConversationState,
268
+ answers: QuestionAnswerRecord[],
269
+ ): void {
270
+ if (answers.length === 0) return;
271
+ appendMessage(state, {
272
+ id: newUuid(),
273
+ role: MESSAGE_ROLES.QUESTION_ANSWER,
274
+ answers,
275
+ timestampMs: Date.now(),
276
+ });
795
277
  }
796
278
 
797
279
  function reset(state: ConversationState): void {
@@ -800,6 +282,10 @@ function reset(state: ConversationState): void {
800
282
  state.queued.value = [];
801
283
  state.progress.value = null;
802
284
  state.isTurnInFlight.value = false;
285
+ state.changeSets.value = {};
286
+ state.mode.value = null;
287
+ state.totalTokens.value = null;
288
+ state.callTimes.clear();
803
289
  }
804
290
 
805
291
  function createConversationState(
@@ -813,14 +299,23 @@ function createConversationState(
813
299
  progress: ref<RunProgress | null>(null),
814
300
  isTurnInFlight: ref(false),
815
301
  lastEventAtMs: ref(Date.now()),
302
+ changeSets: ref<Record<string, ChangeSetSummary>>({}),
303
+ mode: ref<ConversationModeState | null>(null),
304
+ totalTokens: ref<number | null>(null),
305
+ callTimes: new Map(),
816
306
  };
817
307
  }
818
308
 
309
+ /**
310
+ * One conversation as the chat shows it: its transcript, its running turn,
311
+ * its queue, change sets, mode and token count, all folded from the
312
+ * sidecar's events for the active conversation.
313
+ */
819
314
  export function useConversation(
820
315
  options: UseConversationOptions,
821
316
  ): UseConversationResult {
822
317
  const state = createConversationState(options);
823
- options.onMessage((msg) => dispatch(state, msg));
318
+ options.onMessage((msg) => dispatchConversationEvent(state, msg));
824
319
  return {
825
320
  messages: state.messages,
826
321
  isRunning: state.isRunning,
@@ -828,11 +323,14 @@ export function useConversation(
828
323
  progress: state.progress,
829
324
  isTurnInFlight: state.isTurnInFlight,
830
325
  lastEventAtMs: state.lastEventAtMs,
831
- sendUserMessage: (content, attachments = []) =>
832
- sendUserMessage(state, content, attachments),
326
+ changeSets: state.changeSets,
327
+ mode: state.mode,
328
+ totalTokens: state.totalTokens,
329
+ sendUserMessage: (content, attachments = [], extra = {}) =>
330
+ sendUserMessage(state, content, attachments, extra),
833
331
  retry: () => retry(state),
834
- cancelQueued: (id) => cancelQueued(state, id),
835
332
  interrupt: () => interrupt(state),
333
+ recordAnswers: (answers) => recordAnswers(state, answers),
836
334
  reset: () => reset(state),
837
335
  };
838
336
  }