@antelopejs/dms-ai 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. package/README.md +50 -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 +120 -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/markdown.test.ts +1 -0
  290. package/frontend-vue/tests/chat/tool-lexicon.test.ts +188 -0
  291. package/frontend-vue/tests/chat/useConversation.test.ts +36 -33
  292. package/frontend-vue/tests/chat-panel.test.ts +79 -131
  293. package/frontend-vue/tests/host-commands.test.ts +1 -0
  294. package/frontend-vue/tests/i18n-panel.test.ts +118 -0
  295. package/frontend-vue/tests/navigation.test.ts +1 -0
  296. package/frontend-vue/tests/palette-assistant.test.ts +221 -0
  297. package/frontend-vue/tests/panel-states.test.ts +811 -0
  298. package/frontend-vue/tests/sidecar-guest.test.ts +35 -3
  299. package/frontend-vue/tests/support/i18n.ts +49 -0
  300. package/frontend-vue/tests/support/panel-harness.ts +198 -0
  301. package/frontend-vue/tests/support/stubs.ts +201 -0
  302. package/frontend-vue/tests/views/diff-view.test.ts +150 -0
  303. package/frontend-vue/tests/views/view-format.test.ts +59 -0
  304. package/frontend-vue/vitest.config.ts +4 -1
  305. package/package.json +5 -4
  306. package/sidecar/dist/agent/attachment-files.d.ts +0 -1
  307. package/sidecar/dist/agent/attachment-files.js +1 -1
  308. package/sidecar/dist/agent/attachment-files.js.map +1 -1
  309. package/sidecar/dist/agent/call-ledger.d.ts +6 -0
  310. package/sidecar/dist/agent/call-ledger.js +41 -0
  311. package/sidecar/dist/agent/call-ledger.js.map +1 -0
  312. package/sidecar/dist/agent/command-analysis.d.ts +9 -0
  313. package/sidecar/dist/agent/command-analysis.js +104 -0
  314. package/sidecar/dist/agent/command-analysis.js.map +1 -0
  315. package/sidecar/dist/agent/conversation-modes.d.ts +32 -0
  316. package/sidecar/dist/agent/conversation-modes.js +122 -0
  317. package/sidecar/dist/agent/conversation-modes.js.map +1 -0
  318. package/sidecar/dist/agent/edit-targets.d.ts +5 -0
  319. package/sidecar/dist/agent/edit-targets.js +41 -0
  320. package/sidecar/dist/agent/edit-targets.js.map +1 -0
  321. package/sidecar/dist/agent/effective-mode.d.ts +9 -2
  322. package/sidecar/dist/agent/effective-mode.js +14 -16
  323. package/sidecar/dist/agent/effective-mode.js.map +1 -1
  324. package/sidecar/dist/agent/host-context.js +2 -2
  325. package/sidecar/dist/agent/host-context.js.map +1 -1
  326. package/sidecar/dist/agent/line-diff.d.ts +8 -0
  327. package/sidecar/dist/agent/line-diff.js +204 -0
  328. package/sidecar/dist/agent/line-diff.js.map +1 -0
  329. package/sidecar/dist/agent/permission-bus.d.ts +55 -10
  330. package/sidecar/dist/agent/permission-bus.js +130 -100
  331. package/sidecar/dist/agent/permission-bus.js.map +1 -1
  332. package/sidecar/dist/agent/permission-preview.d.ts +20 -0
  333. package/sidecar/dist/agent/permission-preview.js +203 -0
  334. package/sidecar/dist/agent/permission-preview.js.map +1 -0
  335. package/sidecar/dist/agent/permission-rules.d.ts +17 -0
  336. package/sidecar/dist/agent/permission-rules.js +95 -0
  337. package/sidecar/dist/agent/permission-rules.js.map +1 -0
  338. package/sidecar/dist/agent/provider.d.ts +12 -4
  339. package/sidecar/dist/agent/question-bus.d.ts +14 -2
  340. package/sidecar/dist/agent/question-bus.js +30 -11
  341. package/sidecar/dist/agent/question-bus.js.map +1 -1
  342. package/sidecar/dist/agent/runner-events.d.ts +3 -1
  343. package/sidecar/dist/agent/runner.d.ts +6 -4
  344. package/sidecar/dist/agent/runner.js +24 -7
  345. package/sidecar/dist/agent/runner.js.map +1 -1
  346. package/sidecar/dist/agent/switching-runner.js +1 -0
  347. package/sidecar/dist/agent/switching-runner.js.map +1 -1
  348. package/sidecar/dist/agent/tool-kinds.d.ts +12 -0
  349. package/sidecar/dist/agent/tool-kinds.js +50 -0
  350. package/sidecar/dist/agent/tool-kinds.js.map +1 -0
  351. package/sidecar/dist/agent/typecheck.d.ts +2 -6
  352. package/sidecar/dist/audit/activity-query.d.ts +37 -0
  353. package/sidecar/dist/audit/activity-query.js +111 -0
  354. package/sidecar/dist/audit/activity-query.js.map +1 -0
  355. package/sidecar/dist/audit/activity-target.d.ts +2 -0
  356. package/sidecar/dist/audit/activity-target.js +46 -0
  357. package/sidecar/dist/audit/activity-target.js.map +1 -0
  358. package/sidecar/dist/audit/activity.d.ts +45 -0
  359. package/sidecar/dist/audit/activity.js +255 -0
  360. package/sidecar/dist/audit/activity.js.map +1 -0
  361. package/sidecar/dist/audit/call-audit.d.ts +11 -0
  362. package/sidecar/dist/audit/call-audit.js +23 -0
  363. package/sidecar/dist/audit/call-audit.js.map +1 -0
  364. package/sidecar/dist/checkpoints/checkpoints.d.ts +69 -0
  365. package/sidecar/dist/checkpoints/checkpoints.js +244 -0
  366. package/sidecar/dist/checkpoints/checkpoints.js.map +1 -0
  367. package/sidecar/dist/checkpoints/shadow-git.d.ts +23 -0
  368. package/sidecar/dist/checkpoints/shadow-git.js +173 -0
  369. package/sidecar/dist/checkpoints/shadow-git.js.map +1 -0
  370. package/sidecar/dist/constants/agent.d.ts +2 -0
  371. package/sidecar/dist/constants/agent.js +4 -0
  372. package/sidecar/dist/constants/agent.js.map +1 -1
  373. package/sidecar/dist/constants/audit.d.ts +22 -0
  374. package/sidecar/dist/constants/audit.js +49 -0
  375. package/sidecar/dist/constants/audit.js.map +1 -0
  376. package/sidecar/dist/constants/builder.d.ts +3 -0
  377. package/sidecar/dist/constants/builder.js +2 -0
  378. package/sidecar/dist/constants/builder.js.map +1 -1
  379. package/sidecar/dist/constants/checkpoints.d.ts +15 -0
  380. package/sidecar/dist/constants/checkpoints.js +26 -0
  381. package/sidecar/dist/constants/checkpoints.js.map +1 -0
  382. package/sidecar/dist/constants/claude.d.ts +1 -0
  383. package/sidecar/dist/constants/claude.js +1 -0
  384. package/sidecar/dist/constants/claude.js.map +1 -1
  385. package/sidecar/dist/constants/codex.d.ts +2 -4
  386. package/sidecar/dist/constants/codex.js +2 -4
  387. package/sidecar/dist/constants/codex.js.map +1 -1
  388. package/sidecar/dist/constants/http.d.ts +1 -0
  389. package/sidecar/dist/constants/http.js +1 -0
  390. package/sidecar/dist/constants/http.js.map +1 -1
  391. package/sidecar/dist/constants/mcp.d.ts +3 -0
  392. package/sidecar/dist/constants/mcp.js +9 -0
  393. package/sidecar/dist/constants/mcp.js.map +1 -1
  394. package/sidecar/dist/constants/permissions.d.ts +9 -3
  395. package/sidecar/dist/constants/permissions.js +9 -2
  396. package/sidecar/dist/constants/permissions.js.map +1 -1
  397. package/sidecar/dist/constants/settings.d.ts +2 -1
  398. package/sidecar/dist/constants/settings.js +7 -1
  399. package/sidecar/dist/constants/settings.js.map +1 -1
  400. package/sidecar/dist/constants/tool-kinds.d.ts +14 -0
  401. package/sidecar/dist/constants/tool-kinds.js +65 -0
  402. package/sidecar/dist/constants/tool-kinds.js.map +1 -0
  403. package/sidecar/dist/index.js +28 -2
  404. package/sidecar/dist/index.js.map +1 -1
  405. package/sidecar/dist/mcp/define-tool.d.ts +3 -2
  406. package/sidecar/dist/mcp/tool-definitions.js +4 -1
  407. package/sidecar/dist/mcp/tool-definitions.js.map +1 -1
  408. package/sidecar/dist/mcp/tools/ask-user.d.ts +2 -2
  409. package/sidecar/dist/mcp/tools/ask-user.js +7 -4
  410. package/sidecar/dist/mcp/tools/ask-user.js.map +1 -1
  411. package/sidecar/dist/mcp/tools/builder-catalog.d.ts +3 -0
  412. package/sidecar/dist/mcp/tools/builder-catalog.js +86 -0
  413. package/sidecar/dist/mcp/tools/builder-catalog.js.map +1 -0
  414. package/sidecar/dist/mcp/tools/builder-gate.d.ts +8 -0
  415. package/sidecar/dist/mcp/tools/builder-gate.js +22 -0
  416. package/sidecar/dist/mcp/tools/builder-gate.js.map +1 -0
  417. package/sidecar/dist/mcp/tools/builder.d.ts +7 -2
  418. package/sidecar/dist/mcp/tools/builder.js +48 -7
  419. package/sidecar/dist/mcp/tools/builder.js.map +1 -1
  420. package/sidecar/dist/mcp/types.d.ts +2 -0
  421. package/sidecar/dist/metrics/aggregate.d.ts +13 -10
  422. package/sidecar/dist/metrics/aggregate.js +140 -143
  423. package/sidecar/dist/metrics/aggregate.js.map +1 -1
  424. package/sidecar/dist/metrics/types.d.ts +36 -23
  425. package/sidecar/dist/metrics/types.js +3 -1
  426. package/sidecar/dist/metrics/types.js.map +1 -1
  427. package/sidecar/dist/pages/imports-scanner.d.ts +1 -1
  428. package/sidecar/dist/pages/imports-scanner.js +2 -5
  429. package/sidecar/dist/pages/imports-scanner.js.map +1 -1
  430. package/sidecar/dist/prompts/agent.d.ts +1 -3
  431. package/sidecar/dist/prompts/agent.js +4 -4
  432. package/sidecar/dist/prompts/agent.js.map +1 -1
  433. package/sidecar/dist/prompts/builder.d.ts +2 -2
  434. package/sidecar/dist/prompts/builder.js +2 -2
  435. package/sidecar/dist/protocol/events.d.ts +1084 -18
  436. package/sidecar/dist/protocol/events.js +239 -5
  437. package/sidecar/dist/protocol/events.js.map +1 -1
  438. package/sidecar/dist/protocol/messages.d.ts +273 -19
  439. package/sidecar/dist/protocol/messages.js +107 -7
  440. package/sidecar/dist/protocol/messages.js.map +1 -1
  441. package/sidecar/dist/providers/claude/config.d.ts +3 -2
  442. package/sidecar/dist/providers/claude/config.js +10 -4
  443. package/sidecar/dist/providers/claude/config.js.map +1 -1
  444. package/sidecar/dist/providers/claude/provider.d.ts +2 -8
  445. package/sidecar/dist/providers/claude/provider.js +37 -35
  446. package/sidecar/dist/providers/claude/provider.js.map +1 -1
  447. package/sidecar/dist/providers/claude/safe-mode.d.ts +6 -1
  448. package/sidecar/dist/providers/claude/safe-mode.js +13 -5
  449. package/sidecar/dist/providers/claude/safe-mode.js.map +1 -1
  450. package/sidecar/dist/providers/codex/adapter.d.ts +6 -0
  451. package/sidecar/dist/providers/codex/adapter.js +14 -4
  452. package/sidecar/dist/providers/codex/adapter.js.map +1 -1
  453. package/sidecar/dist/providers/codex/client.d.ts +0 -11
  454. package/sidecar/dist/providers/codex/config.d.ts +1 -3
  455. package/sidecar/dist/providers/codex/config.js +5 -11
  456. package/sidecar/dist/providers/codex/config.js.map +1 -1
  457. package/sidecar/dist/providers/codex/permissions.d.ts +7 -4
  458. package/sidecar/dist/providers/codex/permissions.js +32 -16
  459. package/sidecar/dist/providers/codex/permissions.js.map +1 -1
  460. package/sidecar/dist/providers/codex/process.js +1 -5
  461. package/sidecar/dist/providers/codex/process.js.map +1 -1
  462. package/sidecar/dist/providers/codex/provider.js +14 -3
  463. package/sidecar/dist/providers/codex/provider.js.map +1 -1
  464. package/sidecar/dist/providers/codex/skills.d.ts +0 -1
  465. package/sidecar/dist/providers/codex/skills.js +1 -1
  466. package/sidecar/dist/providers/codex/skills.js.map +1 -1
  467. package/sidecar/dist/providers/codex/stop.js +1 -10
  468. package/sidecar/dist/providers/codex/stop.js.map +1 -1
  469. package/sidecar/dist/server/change-set-actions.d.ts +10 -0
  470. package/sidecar/dist/server/change-set-actions.js +14 -0
  471. package/sidecar/dist/server/change-set-actions.js.map +1 -0
  472. package/sidecar/dist/server/chat-events.d.ts +15 -0
  473. package/sidecar/dist/server/chat-events.js +115 -0
  474. package/sidecar/dist/server/chat-events.js.map +1 -0
  475. package/sidecar/dist/server/chat-socket-registry.d.ts +2 -0
  476. package/sidecar/dist/server/chat-socket-registry.js +48 -37
  477. package/sidecar/dist/server/chat-socket-registry.js.map +1 -1
  478. package/sidecar/dist/server/conversation-runs.d.ts +13 -0
  479. package/sidecar/dist/server/conversation-runs.js +114 -0
  480. package/sidecar/dist/server/conversation-runs.js.map +1 -0
  481. package/sidecar/dist/server/http-io.d.ts +4 -0
  482. package/sidecar/dist/server/http-io.js +31 -0
  483. package/sidecar/dist/server/http-io.js.map +1 -0
  484. package/sidecar/dist/server/http-params.d.ts +9 -0
  485. package/sidecar/dist/server/http-params.js +79 -0
  486. package/sidecar/dist/server/http-params.js.map +1 -0
  487. package/sidecar/dist/server/http-routes.d.ts +27 -0
  488. package/sidecar/dist/server/http-routes.js +281 -0
  489. package/sidecar/dist/server/http-routes.js.map +1 -0
  490. package/sidecar/dist/server/http.d.ts +6 -1
  491. package/sidecar/dist/server/http.js +76 -164
  492. package/sidecar/dist/server/http.js.map +1 -1
  493. package/sidecar/dist/server/pending-queue.d.ts +2 -0
  494. package/sidecar/dist/server/pending-queue.js +16 -0
  495. package/sidecar/dist/server/pending-queue.js.map +1 -1
  496. package/sidecar/dist/server/permission-events.d.ts +15 -0
  497. package/sidecar/dist/server/permission-events.js +163 -0
  498. package/sidecar/dist/server/permission-events.js.map +1 -0
  499. package/sidecar/dist/server/routing.d.ts +4 -52
  500. package/sidecar/dist/server/routing.js +190 -501
  501. package/sidecar/dist/server/routing.js.map +1 -1
  502. package/sidecar/dist/server/safety-net.d.ts +7 -0
  503. package/sidecar/dist/server/safety-net.js +34 -6
  504. package/sidecar/dist/server/safety-net.js.map +1 -1
  505. package/sidecar/dist/server/services.d.ts +55 -0
  506. package/sidecar/dist/server/services.js +2 -0
  507. package/sidecar/dist/server/services.js.map +1 -0
  508. package/sidecar/dist/server/tool-calls.d.ts +6 -0
  509. package/sidecar/dist/server/tool-calls.js +134 -0
  510. package/sidecar/dist/server/tool-calls.js.map +1 -0
  511. package/sidecar/dist/server/turn-registry.d.ts +44 -0
  512. package/sidecar/dist/server/turn-registry.js +40 -0
  513. package/sidecar/dist/server/turn-registry.js.map +1 -0
  514. package/sidecar/dist/server/turns.d.ts +17 -0
  515. package/sidecar/dist/server/turns.js +335 -0
  516. package/sidecar/dist/server/turns.js.map +1 -0
  517. package/sidecar/dist/server/ws.d.ts +4 -1
  518. package/sidecar/dist/server/ws.js +102 -62
  519. package/sidecar/dist/server/ws.js.map +1 -1
  520. package/sidecar/dist/skills/build-catalog.d.ts +1 -0
  521. package/sidecar/dist/skills/build-catalog.js +14 -1
  522. package/sidecar/dist/skills/build-catalog.js.map +1 -1
  523. package/sidecar/dist/skills/skill-usage.d.ts +22 -0
  524. package/sidecar/dist/skills/skill-usage.js +97 -0
  525. package/sidecar/dist/skills/skill-usage.js.map +1 -0
  526. package/sidecar/dist/state/change-sets.d.ts +12 -0
  527. package/sidecar/dist/state/change-sets.js +77 -0
  528. package/sidecar/dist/state/change-sets.js.map +1 -0
  529. package/sidecar/dist/state/conversations.d.ts +19 -7
  530. package/sidecar/dist/state/conversations.js +61 -20
  531. package/sidecar/dist/state/conversations.js.map +1 -1
  532. package/sidecar/dist/state/host-state.d.ts +2 -1
  533. package/sidecar/dist/state/settings-store.d.ts +1 -0
  534. package/sidecar/dist/state/settings-store.js +27 -26
  535. package/sidecar/dist/state/settings-store.js.map +1 -1
  536. package/sidecar/dist/state/settings-types.d.ts +11 -1
  537. package/sidecar/dist/state/settings-types.js +3 -1
  538. package/sidecar/dist/state/settings-types.js.map +1 -1
  539. package/sidecar/dist/state/types.d.ts +114 -8
  540. package/sidecar/dist/state/types.js +6 -3
  541. package/sidecar/dist/state/types.js.map +1 -1
  542. package/sidecar/package.json +2 -1
  543. package/skills/dms-builder-safe/REFERENCE.md +1 -1
  544. package/skills/dms-builder-safe/SKILL.md +12 -7
  545. package/dist/routes/proxy.d.ts +0 -4
  546. package/dist/routes/proxy.js +0 -55
  547. package/dist/routes/proxy.js.map +0 -1
  548. package/frontend-vue/app/chat/components/ComposerInput.vue +0 -742
  549. package/frontend-vue/app/chat/components/PermissionRequests.vue +0 -323
  550. package/frontend-vue/app/chat/components/QuestionPrompt.vue +0 -275
  551. package/frontend-vue/app/chat/components/QueuedMessages.vue +0 -109
  552. package/frontend-vue/app/chat/components/TodoList.vue +0 -291
  553. package/frontend-vue/app/chat/components/ToolCallEntry.vue +0 -218
  554. package/frontend-vue/app/chat/constants/connection-banner.ts +0 -7
  555. package/frontend-vue/app/chat/constants/conversation-drawer.ts +0 -13
  556. package/frontend-vue/app/chat/constants/permissions.ts +0 -50
  557. package/frontend-vue/app/chat/utils/tool-summary.ts +0 -53
  558. package/frontend-vue/app/components/ActivityView.vue +0 -94
  559. package/frontend-vue/app/components/SettingsView.vue +0 -387
  560. package/frontend-vue/app/components/SkillsView.vue +0 -230
  561. package/frontend-vue/app/runtime/header-action.ts +0 -64
  562. package/frontend-vue/app/runtime/overlay-prefs.ts +0 -89
  563. package/frontend-vue/app/runtime/panel-state.ts +0 -88
  564. package/frontend-vue/tests/overlay-prefs.test.ts +0 -91
  565. package/frontend-vue/tests/panel-state.test.ts +0 -58
@@ -1,13 +1,36 @@
1
1
  import {
2
2
  type DmsAppContext,
3
+ type DmsI18n,
3
4
  defineDmsPlugin,
4
5
  useDmsRouter,
5
- useDmsState,
6
6
  } from "#dms/frontend-module";
7
- import { type Ref, readonly, ref, watch } from "vue";
7
+ import {
8
+ computed,
9
+ type Ref,
10
+ readonly,
11
+ ref,
12
+ shallowRef,
13
+ type ShallowRef,
14
+ watch,
15
+ } from "vue";
16
+ import { CHAT_I18N_KEY, type ChatI18n } from "../chat/composables/useChatI18n";
17
+ import type { ChatApi } from "../chat/composables/useChangeSetActions";
18
+ import type { CurrentPage } from "../chat/types/conversation";
19
+ import {
20
+ type AssistantActivity,
21
+ type AssistantStatusPayload,
22
+ createAssistantActivity,
23
+ } from "../runtime/assistant-activity";
24
+ import {
25
+ launcherAction,
26
+ paletteAssistant,
27
+ paletteSource,
28
+ } from "../runtime/assistant-commands";
29
+ import { installAssistantNotifications } from "../runtime/assistant-notifications";
8
30
  import {
9
31
  ASSISTANT_SESSION_KEY,
10
32
  type AssistantSession,
33
+ type ChatPanelState,
11
34
  } from "../runtime/assistant-session";
12
35
  import {
13
36
  type ChannelClient,
@@ -18,15 +41,18 @@ import {
18
41
  createChatTransport,
19
42
  } from "../runtime/chat-transport";
20
43
  import {
21
- APP_OVERLAYS_STATE_KEY,
44
+ CHANGES_PATH,
22
45
  CHANNEL_IDLE_STOP_MS,
23
46
  CHANNEL_STATUS_RECONNECTING,
24
- CHAT_PANEL_COMPONENT_NAME,
25
47
  HELLO_MESSAGE_TYPE,
26
48
  HOST_ROLE,
27
49
  JSON_CONTENT_TYPE,
50
+ RESTART_PATH,
28
51
  SIDECAR_INFO_PATH,
29
52
  SIDECAR_STATUS_CONNECTED,
53
+ SIDECAR_STATUS_REVIVING,
54
+ SIDE_PANEL_ID,
55
+ STATUS_PATH,
30
56
  VISIBILITY_CHANGE_EVENT,
31
57
  } from "../runtime/constants";
32
58
  import {
@@ -34,16 +60,12 @@ import {
34
60
  installCurrentPageTracker,
35
61
  } from "../runtime/current-page";
36
62
  import { createFrameRouter } from "../runtime/frame-router";
37
- import { registerLauncherAction } from "../runtime/header-action";
38
63
  import {
39
64
  createHostCommandDispatcher,
40
65
  type HostCommandDispatcher,
41
66
  } from "../runtime/host-commands";
42
67
  import { installNavigationCompleteEmitter } from "../runtime/navigation-complete";
43
- import {
44
- type ChatPanelState,
45
- createChatPanelState,
46
- } from "../runtime/panel-state";
68
+ import { createPanelIntents } from "../runtime/panel-intents";
47
69
  import { runWhenLoggedIn } from "../runtime/session-gate";
48
70
  import { installToggleShortcut } from "../runtime/shortcuts";
49
71
  import {
@@ -51,8 +73,10 @@ import {
51
73
  type SidecarStatus,
52
74
  type SidecarStatusController,
53
75
  } from "../runtime/sidecar-status";
76
+ import { createStreamHolds, type StreamHolds } from "../runtime/stream-holds";
54
77
 
55
78
  type AuthFetch = ReturnType<typeof useAuthFetch>["$authFetch"];
79
+ type Toaster = ReturnType<typeof useToast>;
56
80
 
57
81
  interface ChannelDeps {
58
82
  $authFetch: AuthFetch;
@@ -65,6 +89,26 @@ interface AssistantChannel {
65
89
  chat: ChatTransportHub;
66
90
  }
67
91
 
92
+ /** What the plugin takes from the DMS before its first await, while in context. */
93
+ interface DashboardDeps {
94
+ $authFetch: AuthFetch;
95
+ toaster: Toaster;
96
+ devReload: ReturnType<typeof useDevReload>;
97
+ router: ReturnType<typeof useDmsRouter>;
98
+ }
99
+
100
+ function postJson(
101
+ $authFetch: AuthFetch,
102
+ path: string,
103
+ body?: unknown,
104
+ ): Promise<unknown> {
105
+ return $authFetch(path, {
106
+ method: "POST",
107
+ body: JSON.stringify(body ?? {}),
108
+ headers: { "content-type": JSON_CONTENT_TYPE },
109
+ });
110
+ }
111
+
68
112
  function createAssistantChannel(deps: ChannelDeps): AssistantChannel {
69
113
  const chat = createChatTransport({
70
114
  send: (msg) => client.send(msg),
@@ -72,12 +116,7 @@ function createAssistantChannel(deps: ChannelDeps): AssistantChannel {
72
116
  getStatus: () => client.getStatus(),
73
117
  });
74
118
  const client = createChannelClient({
75
- post: (path, body) =>
76
- deps.$authFetch(path, {
77
- method: "POST",
78
- body: JSON.stringify(body),
79
- headers: { "content-type": JSON_CONTENT_TYPE },
80
- }),
119
+ post: (path, body) => postJson(deps.$authFetch, path, body),
81
120
  onReady: () => {
82
121
  client.send({ type: HELLO_MESSAGE_TYPE, role: HOST_ROLE });
83
122
  client.send(buildCurrentPageUpdate(window.location.href));
@@ -96,7 +135,21 @@ function createAssistantChannel(deps: ChannelDeps): AssistantChannel {
96
135
  return { client, chat };
97
136
  }
98
137
 
99
- function followPanel(panel: ChatPanelState, client: ChannelClient): () => void {
138
+ /** What keeps the tab's stream open. */
139
+ interface StreamNeeds {
140
+ panel: ChatPanelState;
141
+ activity: AssistantActivity;
142
+ holds: StreamHolds;
143
+ }
144
+
145
+ /**
146
+ * The stream is open while the panel is, while the tab shows a chat that
147
+ * works or waits, so its events (and their toasts) still arrive, and while the
148
+ * command palette streams an answer; otherwise it gives its connection back
149
+ * shortly after.
150
+ */
151
+ function followPanel(needs: StreamNeeds, client: ChannelClient): () => void {
152
+ const { panel, activity, holds } = needs;
100
153
  let stopTimer: ReturnType<typeof setTimeout> | null = null;
101
154
  const clearStopTimer = (): void => {
102
155
  if (stopTimer !== null) clearTimeout(stopTimer);
@@ -104,17 +157,21 @@ function followPanel(panel: ChatPanelState, client: ChannelClient): () => void {
104
157
  };
105
158
  const follow = (): void => {
106
159
  clearStopTimer();
107
- const isNeeded =
108
- panel.isOpen.value && document.visibilityState === "visible";
109
- if (isNeeded) client.start();
160
+ const isVisible = document.visibilityState === "visible";
161
+ const isWanted =
162
+ panel.isOpen.value || activity.isBusy.value || holds.isHeld.value;
163
+ if (isVisible && isWanted) client.start();
110
164
  else stopTimer = setTimeout(() => client.stop(), CHANNEL_IDLE_STOP_MS);
111
165
  };
112
- const stopWatchingPanel = watch(panel.isOpen, follow);
166
+ const stopWatching = watch(
167
+ [panel.isOpen, activity.isBusy, holds.isHeld],
168
+ follow,
169
+ );
113
170
  document.addEventListener(VISIBILITY_CHANGE_EVENT, follow);
114
171
  follow();
115
172
  return () => {
116
173
  clearStopTimer();
117
- stopWatchingPanel();
174
+ stopWatching();
118
175
  document.removeEventListener(VISIBILITY_CHANGE_EVENT, follow);
119
176
  };
120
177
  }
@@ -129,22 +186,33 @@ function followSidecarStatus(
129
186
  client: ChannelClient,
130
187
  ): FollowedSidecarStatus {
131
188
  const status = ref<SidecarStatus>(controller.getStatus());
132
- let isFirstReport = true;
189
+ // Only a sidecar coming back needs a fresh stream: replacing the one that
190
+ // just opened would re-attach every chat and replay its running turn.
133
191
  const stop = controller.subscribe((next) => {
134
- if (next === SIDECAR_STATUS_CONNECTED && !isFirstReport)
192
+ if (
193
+ next === SIDECAR_STATUS_CONNECTED &&
194
+ status.value === SIDECAR_STATUS_REVIVING
195
+ )
135
196
  client.reconnectNow();
136
197
  status.value = next;
137
- isFirstReport = false;
138
198
  });
139
199
  return { status: readonly(status), stop };
140
200
  }
141
201
 
142
- function installHostState(client: ChannelClient): () => void {
202
+ function installHostState(
203
+ client: ChannelClient,
204
+ currentPage: Ref<CurrentPage | null>,
205
+ ): () => void {
143
206
  const sendWhenConnected = (msg: unknown): void => {
144
207
  if (!client.isConnected()) return;
145
208
  client.send(msg);
146
209
  };
147
- const stopTracking = installCurrentPageTracker({ send: sendWhenConnected });
210
+ const stopTracking = installCurrentPageTracker({
211
+ send: (msg) => {
212
+ currentPage.value = msg.currentPage;
213
+ sendWhenConnected(msg);
214
+ },
215
+ });
148
216
  const stopNavigation = installNavigationCompleteEmitter({
149
217
  send: sendWhenConnected,
150
218
  });
@@ -154,63 +222,287 @@ function installHostState(client: ChannelClient): () => void {
154
222
  };
155
223
  }
156
224
 
157
- function registerChatPanel(): void {
158
- const overlays = useDmsState<string[]>(APP_OVERLAYS_STATE_KEY, () => []);
159
- if (overlays.value.includes(CHAT_PANEL_COMPONENT_NAME)) return;
160
- overlays.value = [...overlays.value, CHAT_PANEL_COMPONENT_NAME];
225
+ function createChatI18n(i18n: DmsI18n): ChatI18n {
226
+ return {
227
+ t: (key, params, plural) =>
228
+ plural === undefined
229
+ ? i18n.t(key, params ?? {})
230
+ : i18n.t(key, params ?? {}, plural),
231
+ locale: computed(() => String(i18n.locale.value)),
232
+ };
161
233
  }
162
234
 
163
- async function startAssistant({ vueApp }: DmsAppContext): Promise<void> {
164
- const { $authFetch } = useAuthFetch();
165
- const controller = createSidecarStatusController(() =>
166
- $authFetch(SIDECAR_INFO_PATH),
235
+ function createApi($authFetch: AuthFetch): ChatApi {
236
+ return {
237
+ get: <T>(path: string) => $authFetch(path) as Promise<T>,
238
+ post: <T>(path: string, body?: unknown) =>
239
+ postJson($authFetch, path, body) as Promise<T>,
240
+ };
241
+ }
242
+
243
+ interface SessionParts {
244
+ deps: DashboardDeps;
245
+ controller: SidecarStatusController;
246
+ chat: ChatTransportHub;
247
+ panel: ChatPanelState;
248
+ holds: StreamHolds;
249
+ status: Readonly<Ref<SidecarStatus>>;
250
+ activity: AssistantActivity;
251
+ currentPage: Ref<CurrentPage | null>;
252
+ }
253
+
254
+ function createSession(parts: SessionParts): AssistantSession {
255
+ const { deps, panel, activity } = parts;
256
+ const intents = createPanelIntents();
257
+ return {
258
+ status: parts.status,
259
+ chat: parts.chat.transport,
260
+ panel,
261
+ navigate: (path) => void deps.router.push(path),
262
+ openConversation: (conversationId) => {
263
+ intents.push({ kind: "open", conversationId });
264
+ panel.open();
265
+ },
266
+ startConversation: (prompt) => {
267
+ intents.push({ kind: "start", prompt });
268
+ panel.open();
269
+ },
270
+ holdStream: parts.holds.hold,
271
+ pendingApprovals: activity.pendingApprovals,
272
+ intents,
273
+ currentPage: readonly(parts.currentPage),
274
+ api: createApi(deps.$authFetch),
275
+ lastError: activity.lastError,
276
+ restart: async () => {
277
+ try {
278
+ await postJson(deps.$authFetch, RESTART_PATH);
279
+ } finally {
280
+ parts.controller.retry();
281
+ void activity.refresh();
282
+ }
283
+ },
284
+ };
285
+ }
286
+
287
+ function registerDashboardEntries(
288
+ session: AssistantSession,
289
+ i18n: ChatI18n,
290
+ ): () => void {
291
+ const register = (): void => registerHeaderAction(launcherAction(i18n.t));
292
+ register();
293
+ const stopWatchingLocale = watch(i18n.locale, register);
294
+ registerCommandPaletteSource(
295
+ paletteSource(i18n.t, session.pendingApprovals, {
296
+ ask: () => {
297
+ session.intents.push({ kind: "focus" });
298
+ session.panel.open();
299
+ },
300
+ startConversation: () => session.startConversation(),
301
+ reviewApprovals: () => {
302
+ session.intents.push({ kind: "approvals" });
303
+ session.panel.open();
304
+ },
305
+ openChanges: () => session.navigate(CHANGES_PATH),
306
+ }),
307
+ );
308
+ registerCommandPaletteAssistant(
309
+ paletteAssistant(i18n.t, session.currentPage),
167
310
  );
168
- if (!(await controller.init())) return;
169
- const router = useDmsRouter();
311
+ return stopWatchingLocale;
312
+ }
313
+
314
+ function installToasts(
315
+ session: AssistantSession,
316
+ i18n: ChatI18n,
317
+ toaster: Toaster,
318
+ ): () => void {
319
+ return installAssistantNotifications({
320
+ chat: session.chat,
321
+ isPanelOpen: session.panel.isOpen,
322
+ pendingApprovals: session.pendingApprovals,
323
+ t: i18n.t,
324
+ toast: (input) => void toaster.add(input),
325
+ reviewApprovals: (conversationId) => {
326
+ if (conversationId !== undefined)
327
+ session.openConversation(conversationId);
328
+ session.intents.push({ kind: "approvals" });
329
+ session.panel.open();
330
+ },
331
+ undoChangeSet: (set) =>
332
+ session.chat.send({
333
+ type: "change_set_action",
334
+ conversationId: set.conversationId,
335
+ changeSetId: set.id,
336
+ action: "undo",
337
+ }),
338
+ reviewChangeSet: (id) =>
339
+ session.navigate(`${CHANGES_PATH}?set=${encodeURIComponent(id)}`),
340
+ });
341
+ }
342
+
343
+ /**
344
+ * The launcher and the palette entries join the dashboard only once the app is
345
+ * mounted: the server renders neither, and anything added before hydration
346
+ * would make the client's tree, and the ids its tooltips and menus draw,
347
+ * differ from the server's. The panel itself is registered on the server too
348
+ * (`side-panel.ts`).
349
+ */
350
+ function registerOnceMounted(
351
+ context: DmsAppContext,
352
+ appMounted: Promise<void>,
353
+ session: AssistantSession,
354
+ i18n: ChatI18n,
355
+ ): () => void {
356
+ let stop: (() => void) | null = null;
357
+ let isActive = true;
358
+ void appMounted.then(() => {
359
+ if (!isActive) return;
360
+ context.runWithContext(() => {
361
+ stop = registerDashboardEntries(session, i18n);
362
+ });
363
+ });
364
+ return () => {
365
+ isActive = false;
366
+ stop?.();
367
+ };
368
+ }
369
+
370
+ /** What the plugin provides the app before the assistant runs. */
371
+ interface ProvidedAssistant {
372
+ session: ShallowRef<AssistantSession | null>;
373
+ i18n: ChatI18n;
374
+ }
375
+
376
+ interface AssistantRuntime {
377
+ session: AssistantSession;
378
+ stops: Array<() => void>;
379
+ }
380
+
381
+ function createRuntime(
382
+ deps: DashboardDeps,
383
+ controller: SidecarStatusController,
384
+ ): AssistantRuntime {
170
385
  const dispatchHostCommand = createHostCommandDispatcher({
171
- router,
172
- devReload: useDmsDevReload(),
386
+ router: deps.router,
387
+ devReload: deps.devReload,
173
388
  });
174
389
  const { client, chat } = createAssistantChannel({
175
- $authFetch,
390
+ $authFetch: deps.$authFetch,
176
391
  controller,
177
392
  dispatchHostCommand,
178
393
  });
179
- const panel = createChatPanelState();
394
+ const panel: ChatPanelState = useSidePanel(SIDE_PANEL_ID);
395
+ const holds = createStreamHolds();
180
396
  const sidecarStatus = followSidecarStatus(controller, client);
181
- const session: AssistantSession = {
182
- status: sidecarStatus.status,
397
+ const activity = createAssistantActivity({
398
+ fetchStatus: () =>
399
+ deps.$authFetch(STATUS_PATH) as Promise<AssistantStatusPayload>,
183
400
  chat: chat.transport,
401
+ shouldPoll: () =>
402
+ !panel.isOpen.value ||
403
+ sidecarStatus.status.value !== SIDECAR_STATUS_CONNECTED,
404
+ });
405
+ const currentPage = ref<CurrentPage | null>(null);
406
+ const session = createSession({
407
+ deps,
408
+ controller,
409
+ chat,
184
410
  panel,
185
- navigate: (path) => void router.push(path),
411
+ holds,
412
+ status: sidecarStatus.status,
413
+ activity,
414
+ currentPage,
415
+ });
416
+ void activity.refresh();
417
+ const stops = [
418
+ installToggleShortcut({ onToggle: panel.toggle }),
419
+ followPanel({ panel, activity, holds }, client),
420
+ installHostState(client, currentPage),
421
+ sidecarStatus.stop,
422
+ activity.stop,
423
+ controller.dispose,
424
+ client.stop,
425
+ ];
426
+ return { session, stops };
427
+ }
428
+
429
+ interface WireOptions {
430
+ context: DmsAppContext;
431
+ appMounted: Promise<void>;
432
+ provided: ProvidedAssistant;
433
+ toaster: Toaster;
434
+ }
435
+
436
+ function wireAssistant(
437
+ options: WireOptions,
438
+ runtime: AssistantRuntime,
439
+ ): () => void {
440
+ const { context, appMounted, provided } = options;
441
+ const { session } = runtime;
442
+ provided.session.value = session;
443
+ const stops = [
444
+ registerOnceMounted(context, appMounted, session, provided.i18n),
445
+ installToasts(session, provided.i18n, options.toaster),
446
+ ...runtime.stops,
447
+ ];
448
+ return () => {
449
+ provided.session.value = null;
450
+ stops.forEach((stop) => stop());
186
451
  };
187
- vueApp.provide(ASSISTANT_SESSION_KEY, session);
188
- registerChatPanel();
189
- installToggleShortcut({ onToggle: panel.toggle });
190
- registerLauncherAction(panel.toggleFromLauncher);
191
- const stopFollowing = followPanel(panel, client);
192
- const stopHostState = installHostState(client);
193
- const teardown = (): void => {
194
- stopFollowing();
195
- stopHostState();
196
- sidecarStatus.stop();
197
- controller.dispose();
198
- client.stop();
452
+ }
453
+
454
+ async function startAssistant(
455
+ context: DmsAppContext,
456
+ appMounted: Promise<void>,
457
+ provided: ProvidedAssistant,
458
+ ): Promise<void> {
459
+ const deps: DashboardDeps = {
460
+ $authFetch: useAuthFetch().$authFetch,
461
+ toaster: useToast(),
462
+ devReload: useDevReload(),
463
+ router: useDmsRouter(),
199
464
  };
200
- vueApp.onUnmount(teardown);
465
+ const controller = createSidecarStatusController(() =>
466
+ deps.$authFetch(SIDECAR_INFO_PATH),
467
+ );
468
+ if (!(await controller.init())) {
469
+ context.runWithContext(() => unregisterSidePanel(SIDE_PANEL_ID));
470
+ return;
471
+ }
472
+ const teardown = context.runWithContext(() =>
473
+ wireAssistant(
474
+ { context, appMounted, provided, toaster: deps.toaster },
475
+ createRuntime(deps, controller),
476
+ ),
477
+ );
478
+ context.vueApp.onUnmount(teardown);
201
479
  import.meta.hot?.dispose(teardown);
202
480
  }
203
481
 
204
482
  /**
205
483
  * The assistant appears for a signed-in owner in development only: a first
206
484
  * probe that finds no dms-ai backend, or a disabled sidecar, leaves no trace.
485
+ * The session is provided at once, empty until that probe answers, so the
486
+ * panel the server rendered open and the workspace pages follow it.
207
487
  */
208
488
  export default defineDmsPlugin((context) => {
209
489
  if (!import.meta.env.DEV) return;
490
+ const provided: ProvidedAssistant = {
491
+ session: shallowRef<AssistantSession | null>(null),
492
+ i18n: createChatI18n(context.$i18n),
493
+ };
494
+ context.vueApp.provide(ASSISTANT_SESSION_KEY, provided.session);
495
+ context.vueApp.provide(CHAT_I18N_KEY, provided.i18n);
496
+ const appMounted = new Promise<void>((resolve) =>
497
+ context.hook("app:mounted", resolve),
498
+ );
210
499
  const { loggedIn } = useUserSession();
211
500
  const stopGate = runWhenLoggedIn(
212
501
  () => loggedIn.value,
213
- () => void context.runWithContext(() => startAssistant(context)),
502
+ () =>
503
+ void context.runWithContext(() =>
504
+ startAssistant(context, appMounted, provided),
505
+ ),
214
506
  );
215
507
  context.vueApp.onUnmount(stopGate);
216
508
  });
@@ -0,0 +1,13 @@
1
+ import { defineDmsPlugin } from "#dms/frontend-module";
2
+ import { assistantSidePanel } from "../runtime/assistant-commands";
3
+
4
+ /**
5
+ * The panel's place in the dashboard, registered on the server as well: a
6
+ * panel left open renders docked at its width on the first paint, without the
7
+ * page jumping. The client plugin withdraws it where the assistant does not
8
+ * run (no dms-ai backend, the sidecar disabled).
9
+ */
10
+ export default defineDmsPlugin(() => {
11
+ if (!import.meta.env.DEV) return;
12
+ registerSidePanel(assistantSidePanel());
13
+ });
@@ -0,0 +1,105 @@
1
+ import { computed, type ComputedRef, type Ref, ref } from "vue";
2
+ import type { ChatTransport } from "./chat-transport";
3
+ import { STATUS_POLL_MS } from "./constants";
4
+ import { isTypedMessage } from "./typed-message";
5
+
6
+ /** The backend's `/ai/status`, as far as the tab reads it. */
7
+ export interface AssistantStatusPayload {
8
+ pendingApprovals?: number;
9
+ workingConversations?: number;
10
+ lastError?: string;
11
+ }
12
+
13
+ interface ConversationListItem {
14
+ isRunning?: boolean;
15
+ pendingApprovals?: number;
16
+ }
17
+
18
+ interface ConversationListFrame {
19
+ type: "conversation_list";
20
+ conversations?: ConversationListItem[];
21
+ }
22
+
23
+ const CONVERSATION_LIST_TYPE = "conversation_list";
24
+
25
+ export interface AssistantActivity {
26
+ /** Requests waiting for an answer, across every chat. */
27
+ pendingApprovals: Readonly<Ref<number>>;
28
+ /** Chats running a turn now. */
29
+ workingConversations: Readonly<Ref<number>>;
30
+ /** A chat works or waits: the stream is worth keeping while the tab shows. */
31
+ isBusy: ComputedRef<boolean>;
32
+ lastError: Readonly<Ref<string | null>>;
33
+ /** Re-reads the backend's status now. */
34
+ refresh: () => Promise<void>;
35
+ stop: () => void;
36
+ }
37
+
38
+ export interface AssistantActivityOptions {
39
+ fetchStatus: () => Promise<AssistantStatusPayload>;
40
+ chat: ChatTransport;
41
+ /** Whether polling is useful now: the tab shows and the panel is closed. */
42
+ shouldPoll: () => boolean;
43
+ }
44
+
45
+ function isListFrame(msg: object): msg is ConversationListFrame {
46
+ return isTypedMessage(msg) && msg.type === CONVERSATION_LIST_TYPE;
47
+ }
48
+
49
+ function sum(
50
+ items: ConversationListItem[],
51
+ read: (item: ConversationListItem) => number,
52
+ ): number {
53
+ return items.reduce((total, item) => total + read(item), 0);
54
+ }
55
+
56
+ /**
57
+ * What the tab knows of the assistant's work across chats, from the backend's
58
+ * status (polled while the panel is closed) and from the conversation lists
59
+ * the sidecar broadcasts while the stream is open.
60
+ */
61
+ export function createAssistantActivity(
62
+ options: AssistantActivityOptions,
63
+ ): AssistantActivity {
64
+ const pendingApprovals = ref(0);
65
+ const workingConversations = ref(0);
66
+ const lastError = ref<string | null>(null);
67
+
68
+ const refresh = async (): Promise<void> => {
69
+ try {
70
+ const status = await options.fetchStatus();
71
+ pendingApprovals.value = status.pendingApprovals ?? 0;
72
+ workingConversations.value = status.workingConversations ?? 0;
73
+ lastError.value = status.lastError ?? null;
74
+ } catch {
75
+ return;
76
+ }
77
+ };
78
+
79
+ const stopListening = options.chat.onMessage((msg) => {
80
+ if (!isListFrame(msg)) return;
81
+ const items = msg.conversations ?? [];
82
+ pendingApprovals.value = sum(items, (item) => item.pendingApprovals ?? 0);
83
+ workingConversations.value = sum(items, (item) =>
84
+ item.isRunning === true ? 1 : 0,
85
+ );
86
+ });
87
+
88
+ const timer = setInterval(() => {
89
+ if (options.shouldPoll()) void refresh();
90
+ }, STATUS_POLL_MS);
91
+
92
+ return {
93
+ pendingApprovals,
94
+ workingConversations,
95
+ isBusy: computed(
96
+ () => pendingApprovals.value > 0 || workingConversations.value > 0,
97
+ ),
98
+ lastError,
99
+ refresh,
100
+ stop: () => {
101
+ clearInterval(timer);
102
+ stopListening();
103
+ },
104
+ };
105
+ }