@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.
- package/README.md +48 -12
- package/dist/channels/bridge.d.ts +6 -1
- package/dist/channels/bridge.js +29 -1
- package/dist/channels/bridge.js.map +1 -1
- package/dist/channels/channel-service.d.ts +2 -1
- package/dist/channels/channel-service.js +3 -2
- package/dist/channels/channel-service.js.map +1 -1
- package/dist/channels/sse-stream.d.ts +3 -2
- package/dist/config.d.ts +0 -2
- package/dist/config.js +0 -7
- package/dist/config.js.map +1 -1
- package/dist/constants/http.d.ts +9 -0
- package/dist/constants/http.js +14 -0
- package/dist/constants/http.js.map +1 -0
- package/dist/constants/i18n.d.ts +11 -0
- package/dist/constants/i18n.js +15 -0
- package/dist/constants/i18n.js.map +1 -0
- package/dist/constants/pages.d.ts +50 -0
- package/dist/constants/pages.js +58 -0
- package/dist/constants/pages.js.map +1 -0
- package/dist/constants/sidecar.d.ts +0 -1
- package/dist/constants/sidecar.js +1 -2
- package/dist/constants/sidecar.js.map +1 -1
- package/dist/index.js +0 -8
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/sidecar-owner.d.ts +1 -0
- package/dist/lifecycle/sidecar-owner.js +13 -0
- package/dist/lifecycle/sidecar-owner.js.map +1 -1
- package/dist/lifecycle/spawn-sidecar.d.ts +1 -0
- package/dist/lifecycle/spawn-sidecar.js +10 -10
- package/dist/lifecycle/spawn-sidecar.js.map +1 -1
- package/dist/logging/log-buffer.d.ts +0 -6
- package/dist/logging/log-buffer.js +0 -1
- package/dist/logging/log-buffer.js.map +1 -1
- package/dist/pages/activity/columns.d.ts +2 -0
- package/dist/pages/activity/columns.js +103 -0
- package/dist/pages/activity/columns.js.map +1 -0
- package/dist/pages/activity/page.d.ts +1 -2
- package/dist/pages/activity/page.js +79 -44
- package/dist/pages/activity/page.js.map +1 -1
- package/dist/pages/all.d.ts +1 -0
- package/dist/pages/all.js +1 -0
- package/dist/pages/all.js.map +1 -1
- package/dist/pages/changes/page.d.ts +9 -0
- package/dist/pages/changes/page.js +22 -0
- package/dist/pages/changes/page.js.map +1 -0
- package/dist/pages/meta.d.ts +9 -0
- package/dist/pages/meta.js +31 -0
- package/dist/pages/meta.js.map +1 -0
- package/dist/pages/module.js +9 -5
- package/dist/pages/module.js.map +1 -1
- package/dist/pages/overview/insights.d.ts +3 -0
- package/dist/pages/overview/insights.js +77 -0
- package/dist/pages/overview/insights.js.map +1 -0
- package/dist/pages/overview/kpis.d.ts +2 -0
- package/dist/pages/overview/kpis.js +39 -0
- package/dist/pages/overview/kpis.js.map +1 -0
- package/dist/pages/overview/page.d.ts +6 -3
- package/dist/pages/overview/page.js +19 -62
- package/dist/pages/overview/page.js.map +1 -1
- package/dist/pages/overview/recent-changes.d.ts +2 -0
- package/dist/pages/overview/recent-changes.js +144 -0
- package/dist/pages/overview/recent-changes.js.map +1 -0
- package/dist/pages/overview/status.d.ts +3 -0
- package/dist/pages/overview/status.js +36 -0
- package/dist/pages/overview/status.js.map +1 -0
- package/dist/pages/settings/availability.d.ts +2 -0
- package/dist/pages/settings/availability.js +46 -0
- package/dist/pages/settings/availability.js.map +1 -0
- package/dist/pages/settings/options.d.ts +10 -0
- package/dist/pages/settings/options.js +58 -0
- package/dist/pages/settings/options.js.map +1 -0
- package/dist/pages/settings/page.d.ts +2 -1
- package/dist/pages/settings/page.js +39 -13
- package/dist/pages/settings/page.js.map +1 -1
- package/dist/pages/settings/sections.d.ts +2 -0
- package/dist/pages/settings/sections.js +164 -0
- package/dist/pages/settings/sections.js.map +1 -0
- package/dist/pages/skills/page.d.ts +2 -1
- package/dist/pages/skills/page.js +122 -12
- package/dist/pages/skills/page.js.map +1 -1
- package/dist/routes/activity-csv.d.ts +2 -0
- package/dist/routes/activity-csv.js +42 -0
- package/dist/routes/activity-csv.js.map +1 -0
- package/dist/routes/activity.d.ts +8 -0
- package/dist/routes/activity.js +105 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/actor.d.ts +2 -0
- package/dist/routes/actor.js +8 -0
- package/dist/routes/actor.js.map +1 -0
- package/dist/routes/banner.d.ts +3 -0
- package/dist/routes/banner.js +9 -0
- package/dist/routes/banner.js.map +1 -0
- package/dist/routes/builder.js +1 -5
- package/dist/routes/builder.js.map +1 -1
- package/dist/routes/changes.d.ts +17 -0
- package/dist/routes/changes.js +152 -0
- package/dist/routes/changes.js.map +1 -0
- package/dist/routes/channels.js +2 -1
- package/dist/routes/channels.js.map +1 -1
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.js +3 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/list-query.d.ts +9 -0
- package/dist/routes/list-query.js +34 -0
- package/dist/routes/list-query.js.map +1 -0
- package/dist/routes/metric-shapes.d.ts +8 -0
- package/dist/routes/metric-shapes.js +107 -0
- package/dist/routes/metric-shapes.js.map +1 -0
- package/dist/routes/metrics.d.ts +5 -48
- package/dist/routes/metrics.js +52 -42
- package/dist/routes/metrics.js.map +1 -1
- package/dist/routes/settings.d.ts +3 -16
- package/dist/routes/settings.js +40 -14
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/sidecar-results.d.ts +6 -0
- package/dist/routes/sidecar-results.js +44 -0
- package/dist/routes/sidecar-results.js.map +1 -0
- package/dist/routes/skills.d.ts +4 -14
- package/dist/routes/skills.js +91 -6
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/status-shapes.d.ts +5 -0
- package/dist/routes/status-shapes.js +176 -0
- package/dist/routes/status-shapes.js.map +1 -0
- package/dist/routes/status.d.ts +9 -0
- package/dist/routes/status.js +92 -0
- package/dist/routes/status.js.map +1 -0
- package/dist/routes/undo-confirm.d.ts +3 -0
- package/dist/routes/undo-confirm.js +51 -0
- package/dist/routes/undo-confirm.js.map +1 -0
- package/dist/sidecar/http-client.d.ts +11 -0
- package/dist/sidecar/http-client.js +59 -0
- package/dist/sidecar/http-client.js.map +1 -0
- package/dist/sidecar/index.d.ts +2 -0
- package/dist/sidecar/index.js +19 -0
- package/dist/sidecar/index.js.map +1 -0
- package/dist/sidecar/query.d.ts +3 -0
- package/dist/sidecar/query.js +25 -0
- package/dist/sidecar/query.js.map +1 -0
- package/dist/types/activity.d.ts +31 -0
- package/dist/types/activity.js +3 -0
- package/dist/types/activity.js.map +1 -0
- package/dist/types/changes.d.ts +45 -0
- package/dist/types/changes.js +3 -0
- package/dist/types/changes.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/metrics.d.ts +76 -0
- package/dist/types/metrics.js +3 -0
- package/dist/types/metrics.js.map +1 -0
- package/dist/types/skills.d.ts +51 -0
- package/dist/types/skills.js +3 -0
- package/dist/types/skills.js.map +1 -0
- package/dist/types/status.d.ts +16 -0
- package/dist/types/status.js +3 -0
- package/dist/types/status.js.map +1 -0
- package/dist/vocabulary/enumerations.d.ts +9 -0
- package/dist/vocabulary/enumerations.js +52 -0
- package/dist/vocabulary/enumerations.js.map +1 -0
- package/dist/vocabulary/index.d.ts +5 -0
- package/dist/vocabulary/index.js +22 -0
- package/dist/vocabulary/index.js.map +1 -0
- package/dist/vocabulary/keys.d.ts +1 -0
- package/dist/vocabulary/keys.js +8 -0
- package/dist/vocabulary/keys.js.map +1 -0
- package/dist/vocabulary/options.d.ts +7 -0
- package/dist/vocabulary/options.js +33 -0
- package/dist/vocabulary/options.js.map +1 -0
- package/dist/vocabulary/tools.d.ts +7 -0
- package/dist/vocabulary/tools.js +99 -0
- package/dist/vocabulary/tools.js.map +1 -0
- package/dist/vocabulary/types.d.ts +20 -0
- package/dist/vocabulary/types.js +3 -0
- package/dist/vocabulary/types.js.map +1 -0
- package/frontend-vue/app/chat/components/AnswerRecord.vue +95 -0
- package/frontend-vue/app/chat/components/ApprovalDock.vue +371 -0
- package/frontend-vue/app/chat/components/ChangeSetCard.vue +297 -0
- package/frontend-vue/app/chat/components/ChatEmpty.vue +142 -0
- package/frontend-vue/app/chat/components/ChatView.vue +664 -406
- package/frontend-vue/app/chat/components/Composer.vue +589 -0
- package/frontend-vue/app/chat/components/ConnectionBanner.vue +41 -65
- package/frontend-vue/app/chat/components/ConversationDrawer.vue +387 -177
- package/frontend-vue/app/chat/components/DiffView.vue +131 -0
- package/frontend-vue/app/chat/components/FullAutoBanner.vue +76 -0
- package/frontend-vue/app/chat/components/FullAutoDialog.vue +103 -0
- package/frontend-vue/app/chat/components/MarkdownContent.vue +15 -15
- package/frontend-vue/app/chat/components/MessageList.vue +389 -295
- package/frontend-vue/app/chat/components/NoticeCard.vue +193 -0
- package/frontend-vue/app/chat/components/PanelHeader.vue +242 -0
- package/frontend-vue/app/chat/components/PermissionCard.vue +470 -0
- package/frontend-vue/app/chat/components/PlanCard.vue +115 -0
- package/frontend-vue/app/chat/components/QuestionDock.vue +407 -0
- package/frontend-vue/app/chat/components/QueueDock.vue +310 -0
- package/frontend-vue/app/chat/components/RulesList.vue +97 -0
- package/frontend-vue/app/chat/components/StepsDock.vue +181 -0
- package/frontend-vue/app/chat/components/ToolCluster.vue +186 -178
- package/frontend-vue/app/chat/components/ToolRow.vue +251 -0
- package/frontend-vue/app/chat/components/TurnErrorCard.vue +135 -0
- package/frontend-vue/app/chat/composables/conversation-events.ts +404 -0
- package/frontend-vue/app/chat/composables/useChangeSetActions.ts +135 -0
- package/frontend-vue/app/chat/composables/useChatChannel.ts +11 -3
- package/frontend-vue/app/chat/composables/useChatI18n.ts +35 -0
- package/frontend-vue/app/chat/composables/useComposerAttachments.ts +111 -0
- package/frontend-vue/app/chat/composables/useConversation.ts +149 -651
- package/frontend-vue/app/chat/composables/useConversationId.ts +2 -10
- package/frontend-vue/app/chat/composables/useConversationList.ts +77 -21
- package/frontend-vue/app/chat/composables/useConversationMode.ts +73 -0
- package/frontend-vue/app/chat/composables/usePaletteTurn.ts +124 -0
- package/frontend-vue/app/chat/composables/usePermissionQueue.ts +211 -34
- package/frontend-vue/app/chat/composables/useQuestionQueue.ts +103 -21
- package/frontend-vue/app/chat/composables/useQueueActions.ts +55 -0
- package/frontend-vue/app/chat/composables/useSettings.ts +17 -34
- package/frontend-vue/app/chat/constants/attachments.ts +2 -1
- package/frontend-vue/app/chat/constants/conversation.ts +18 -32
- package/frontend-vue/app/chat/constants/protocol.ts +25 -2
- package/frontend-vue/app/chat/constants/run-status.ts +8 -14
- package/frontend-vue/app/chat/constants/settings.ts +5 -47
- package/frontend-vue/app/chat/types/conversation.ts +72 -2
- package/frontend-vue/app/chat/types/permission.ts +31 -0
- package/frontend-vue/app/chat/types/protocol.ts +226 -0
- package/frontend-vue/app/chat/types/question.ts +10 -1
- package/frontend-vue/app/chat/types/settings.ts +9 -5
- package/frontend-vue/app/chat/utils/approval-keyboard.ts +49 -0
- package/frontend-vue/app/chat/utils/arrays.ts +10 -0
- package/frontend-vue/app/chat/utils/conversation-groups.ts +96 -0
- package/frontend-vue/app/chat/utils/conversation-messages.ts +251 -0
- package/frontend-vue/app/chat/utils/diff.ts +78 -0
- package/frontend-vue/app/chat/utils/format.ts +43 -0
- package/frontend-vue/app/chat/utils/markdown.ts +1 -1
- package/frontend-vue/app/chat/utils/permission-view.ts +159 -0
- package/frontend-vue/app/chat/utils/platform.ts +34 -0
- package/frontend-vue/app/chat/utils/queue.ts +18 -0
- package/frontend-vue/app/chat/utils/render-items.ts +164 -0
- package/frontend-vue/app/chat/utils/run-status.ts +19 -23
- package/frontend-vue/app/chat/utils/suggestions.ts +101 -0
- package/frontend-vue/app/chat/utils/todos.ts +2 -2
- package/frontend-vue/app/chat/utils/tool-lexicon.ts +540 -0
- package/frontend-vue/app/chat/utils/tool-state.ts +60 -0
- package/frontend-vue/app/components/ActivityDetail.vue +235 -0
- package/frontend-vue/app/components/ChangesView.vue +249 -0
- package/frontend-vue/app/components/ChatPanel.vue +141 -196
- package/frontend-vue/app/components/PaletteAnswer.vue +185 -0
- package/frontend-vue/app/components/SkillCard.vue +77 -0
- package/frontend-vue/app/components/SkillDetail.vue +188 -0
- package/frontend-vue/app/plugins/ai.client.ts +349 -57
- package/frontend-vue/app/plugins/side-panel.ts +13 -0
- package/frontend-vue/app/runtime/assistant-activity.ts +105 -0
- package/frontend-vue/app/runtime/assistant-commands.ts +210 -0
- package/frontend-vue/app/runtime/assistant-notifications.ts +181 -0
- package/frontend-vue/app/runtime/assistant-session.ts +49 -6
- package/frontend-vue/app/runtime/channel-client.ts +3 -6
- package/frontend-vue/app/runtime/constants.ts +29 -35
- package/frontend-vue/app/runtime/host-commands.ts +4 -4
- package/frontend-vue/app/runtime/listeners.ts +1 -1
- package/frontend-vue/app/runtime/navigation-complete.ts +1 -1
- package/frontend-vue/app/runtime/panel-intents.ts +55 -0
- package/frontend-vue/app/runtime/shortcuts.ts +3 -1
- package/frontend-vue/app/runtime/sidecar-status.ts +9 -1
- package/frontend-vue/app/runtime/stream-holds.ts +24 -0
- package/frontend-vue/app/views/ChangeSetPanel.vue +222 -0
- package/frontend-vue/app/views/DecisionLabel.vue +30 -0
- package/frontend-vue/app/views/DiffView.vue +215 -0
- package/frontend-vue/app/views/ResultPill.vue +32 -0
- package/frontend-vue/app/views/RowStepper.vue +48 -0
- package/frontend-vue/app/views/UnavailableState.vue +66 -0
- package/frontend-vue/app/views/composables/useAiRequest.ts +89 -0
- package/frontend-vue/app/views/composables/useAssistant.ts +33 -0
- package/frontend-vue/app/views/composables/useChangeSetActions.ts +102 -0
- package/frontend-vue/app/views/composables/useViewFormat.ts +55 -0
- package/frontend-vue/app/views/constants.ts +43 -0
- package/frontend-vue/app/views/types.ts +189 -0
- package/frontend-vue/app/views/utils/activity.ts +77 -0
- package/frontend-vue/app/views/utils/change-sets.ts +44 -0
- package/frontend-vue/app/views/utils/diff.ts +98 -0
- package/frontend-vue/app/views/utils/moment.ts +92 -0
- package/frontend-vue/app/views/utils/skills.ts +27 -0
- package/frontend-vue/app/views/utils/tools.ts +73 -0
- package/frontend-vue/dms.frontend.ts +17 -5
- package/frontend-vue/i18n/locales/dms-ai-pages-en-GB.json +607 -0
- package/frontend-vue/i18n/locales/dms-ai-pages-fr-FR.json +607 -0
- package/frontend-vue/i18n/locales/dms-ai-panel-en-GB.json +425 -0
- package/frontend-vue/i18n/locales/dms-ai-panel-fr-FR.json +425 -0
- package/frontend-vue/i18n/locales/dms-ai-views-en-GB.json +142 -0
- package/frontend-vue/i18n/locales/dms-ai-views-fr-FR.json +142 -0
- package/frontend-vue/package.json +1 -1
- package/frontend-vue/tests/chat/conversation-events.test.ts +590 -0
- package/frontend-vue/tests/chat/diff-and-keys.test.ts +178 -0
- package/frontend-vue/tests/chat/tool-lexicon.test.ts +188 -0
- package/frontend-vue/tests/chat/useConversation.test.ts +36 -33
- package/frontend-vue/tests/chat-panel.test.ts +78 -131
- package/frontend-vue/tests/i18n-panel.test.ts +118 -0
- package/frontend-vue/tests/palette-assistant.test.ts +220 -0
- package/frontend-vue/tests/panel-states.test.ts +806 -0
- package/frontend-vue/tests/sidecar-guest.test.ts +35 -3
- package/frontend-vue/tests/support/i18n.ts +49 -0
- package/frontend-vue/tests/support/panel-harness.ts +198 -0
- package/frontend-vue/tests/support/stubs.ts +201 -0
- package/frontend-vue/tests/views/diff-view.test.ts +149 -0
- package/frontend-vue/tests/views/view-format.test.ts +59 -0
- package/package.json +4 -3
- package/sidecar/dist/agent/attachment-files.d.ts +0 -1
- package/sidecar/dist/agent/attachment-files.js +1 -1
- package/sidecar/dist/agent/attachment-files.js.map +1 -1
- package/sidecar/dist/agent/call-ledger.d.ts +6 -0
- package/sidecar/dist/agent/call-ledger.js +41 -0
- package/sidecar/dist/agent/call-ledger.js.map +1 -0
- package/sidecar/dist/agent/command-analysis.d.ts +9 -0
- package/sidecar/dist/agent/command-analysis.js +104 -0
- package/sidecar/dist/agent/command-analysis.js.map +1 -0
- package/sidecar/dist/agent/conversation-modes.d.ts +32 -0
- package/sidecar/dist/agent/conversation-modes.js +122 -0
- package/sidecar/dist/agent/conversation-modes.js.map +1 -0
- package/sidecar/dist/agent/edit-targets.d.ts +5 -0
- package/sidecar/dist/agent/edit-targets.js +41 -0
- package/sidecar/dist/agent/edit-targets.js.map +1 -0
- package/sidecar/dist/agent/effective-mode.d.ts +9 -2
- package/sidecar/dist/agent/effective-mode.js +14 -16
- package/sidecar/dist/agent/effective-mode.js.map +1 -1
- package/sidecar/dist/agent/host-context.js +2 -2
- package/sidecar/dist/agent/host-context.js.map +1 -1
- package/sidecar/dist/agent/line-diff.d.ts +8 -0
- package/sidecar/dist/agent/line-diff.js +204 -0
- package/sidecar/dist/agent/line-diff.js.map +1 -0
- package/sidecar/dist/agent/permission-bus.d.ts +55 -10
- package/sidecar/dist/agent/permission-bus.js +130 -100
- package/sidecar/dist/agent/permission-bus.js.map +1 -1
- package/sidecar/dist/agent/permission-preview.d.ts +20 -0
- package/sidecar/dist/agent/permission-preview.js +203 -0
- package/sidecar/dist/agent/permission-preview.js.map +1 -0
- package/sidecar/dist/agent/permission-rules.d.ts +17 -0
- package/sidecar/dist/agent/permission-rules.js +95 -0
- package/sidecar/dist/agent/permission-rules.js.map +1 -0
- package/sidecar/dist/agent/provider.d.ts +12 -4
- package/sidecar/dist/agent/question-bus.d.ts +14 -2
- package/sidecar/dist/agent/question-bus.js +30 -11
- package/sidecar/dist/agent/question-bus.js.map +1 -1
- package/sidecar/dist/agent/runner-events.d.ts +3 -1
- package/sidecar/dist/agent/runner.d.ts +6 -4
- package/sidecar/dist/agent/runner.js +24 -7
- package/sidecar/dist/agent/runner.js.map +1 -1
- package/sidecar/dist/agent/switching-runner.js +1 -0
- package/sidecar/dist/agent/switching-runner.js.map +1 -1
- package/sidecar/dist/agent/tool-kinds.d.ts +12 -0
- package/sidecar/dist/agent/tool-kinds.js +50 -0
- package/sidecar/dist/agent/tool-kinds.js.map +1 -0
- package/sidecar/dist/agent/typecheck.d.ts +2 -6
- package/sidecar/dist/audit/activity-query.d.ts +37 -0
- package/sidecar/dist/audit/activity-query.js +111 -0
- package/sidecar/dist/audit/activity-query.js.map +1 -0
- package/sidecar/dist/audit/activity-target.d.ts +2 -0
- package/sidecar/dist/audit/activity-target.js +46 -0
- package/sidecar/dist/audit/activity-target.js.map +1 -0
- package/sidecar/dist/audit/activity.d.ts +45 -0
- package/sidecar/dist/audit/activity.js +255 -0
- package/sidecar/dist/audit/activity.js.map +1 -0
- package/sidecar/dist/audit/call-audit.d.ts +11 -0
- package/sidecar/dist/audit/call-audit.js +23 -0
- package/sidecar/dist/audit/call-audit.js.map +1 -0
- package/sidecar/dist/checkpoints/checkpoints.d.ts +69 -0
- package/sidecar/dist/checkpoints/checkpoints.js +244 -0
- package/sidecar/dist/checkpoints/checkpoints.js.map +1 -0
- package/sidecar/dist/checkpoints/shadow-git.d.ts +23 -0
- package/sidecar/dist/checkpoints/shadow-git.js +173 -0
- package/sidecar/dist/checkpoints/shadow-git.js.map +1 -0
- package/sidecar/dist/constants/agent.d.ts +2 -0
- package/sidecar/dist/constants/agent.js +4 -0
- package/sidecar/dist/constants/agent.js.map +1 -1
- package/sidecar/dist/constants/audit.d.ts +22 -0
- package/sidecar/dist/constants/audit.js +49 -0
- package/sidecar/dist/constants/audit.js.map +1 -0
- package/sidecar/dist/constants/builder.d.ts +3 -0
- package/sidecar/dist/constants/builder.js +2 -0
- package/sidecar/dist/constants/builder.js.map +1 -1
- package/sidecar/dist/constants/checkpoints.d.ts +15 -0
- package/sidecar/dist/constants/checkpoints.js +26 -0
- package/sidecar/dist/constants/checkpoints.js.map +1 -0
- package/sidecar/dist/constants/claude.d.ts +1 -0
- package/sidecar/dist/constants/claude.js +1 -0
- package/sidecar/dist/constants/claude.js.map +1 -1
- package/sidecar/dist/constants/codex.d.ts +2 -4
- package/sidecar/dist/constants/codex.js +2 -4
- package/sidecar/dist/constants/codex.js.map +1 -1
- package/sidecar/dist/constants/http.d.ts +1 -0
- package/sidecar/dist/constants/http.js +1 -0
- package/sidecar/dist/constants/http.js.map +1 -1
- package/sidecar/dist/constants/mcp.d.ts +3 -0
- package/sidecar/dist/constants/mcp.js +9 -0
- package/sidecar/dist/constants/mcp.js.map +1 -1
- package/sidecar/dist/constants/permissions.d.ts +9 -3
- package/sidecar/dist/constants/permissions.js +9 -2
- package/sidecar/dist/constants/permissions.js.map +1 -1
- package/sidecar/dist/constants/settings.d.ts +2 -1
- package/sidecar/dist/constants/settings.js +7 -1
- package/sidecar/dist/constants/settings.js.map +1 -1
- package/sidecar/dist/constants/tool-kinds.d.ts +14 -0
- package/sidecar/dist/constants/tool-kinds.js +65 -0
- package/sidecar/dist/constants/tool-kinds.js.map +1 -0
- package/sidecar/dist/index.js +28 -2
- package/sidecar/dist/index.js.map +1 -1
- package/sidecar/dist/mcp/define-tool.d.ts +3 -2
- package/sidecar/dist/mcp/tool-definitions.js +4 -1
- package/sidecar/dist/mcp/tool-definitions.js.map +1 -1
- package/sidecar/dist/mcp/tools/ask-user.d.ts +2 -2
- package/sidecar/dist/mcp/tools/ask-user.js +7 -4
- package/sidecar/dist/mcp/tools/ask-user.js.map +1 -1
- package/sidecar/dist/mcp/tools/builder-catalog.d.ts +3 -0
- package/sidecar/dist/mcp/tools/builder-catalog.js +86 -0
- package/sidecar/dist/mcp/tools/builder-catalog.js.map +1 -0
- package/sidecar/dist/mcp/tools/builder-gate.d.ts +8 -0
- package/sidecar/dist/mcp/tools/builder-gate.js +22 -0
- package/sidecar/dist/mcp/tools/builder-gate.js.map +1 -0
- package/sidecar/dist/mcp/tools/builder.d.ts +7 -2
- package/sidecar/dist/mcp/tools/builder.js +48 -7
- package/sidecar/dist/mcp/tools/builder.js.map +1 -1
- package/sidecar/dist/mcp/types.d.ts +2 -0
- package/sidecar/dist/metrics/aggregate.d.ts +13 -10
- package/sidecar/dist/metrics/aggregate.js +140 -143
- package/sidecar/dist/metrics/aggregate.js.map +1 -1
- package/sidecar/dist/metrics/types.d.ts +36 -23
- package/sidecar/dist/metrics/types.js +3 -1
- package/sidecar/dist/metrics/types.js.map +1 -1
- package/sidecar/dist/pages/imports-scanner.d.ts +1 -1
- package/sidecar/dist/pages/imports-scanner.js +2 -5
- package/sidecar/dist/pages/imports-scanner.js.map +1 -1
- package/sidecar/dist/prompts/agent.d.ts +1 -3
- package/sidecar/dist/prompts/agent.js +4 -4
- package/sidecar/dist/prompts/agent.js.map +1 -1
- package/sidecar/dist/prompts/builder.d.ts +2 -2
- package/sidecar/dist/prompts/builder.js +2 -2
- package/sidecar/dist/protocol/events.d.ts +1084 -18
- package/sidecar/dist/protocol/events.js +239 -5
- package/sidecar/dist/protocol/events.js.map +1 -1
- package/sidecar/dist/protocol/messages.d.ts +273 -19
- package/sidecar/dist/protocol/messages.js +107 -7
- package/sidecar/dist/protocol/messages.js.map +1 -1
- package/sidecar/dist/providers/claude/config.d.ts +3 -2
- package/sidecar/dist/providers/claude/config.js +10 -4
- package/sidecar/dist/providers/claude/config.js.map +1 -1
- package/sidecar/dist/providers/claude/provider.d.ts +2 -8
- package/sidecar/dist/providers/claude/provider.js +37 -35
- package/sidecar/dist/providers/claude/provider.js.map +1 -1
- package/sidecar/dist/providers/claude/safe-mode.d.ts +6 -1
- package/sidecar/dist/providers/claude/safe-mode.js +13 -5
- package/sidecar/dist/providers/claude/safe-mode.js.map +1 -1
- package/sidecar/dist/providers/codex/adapter.d.ts +6 -0
- package/sidecar/dist/providers/codex/adapter.js +14 -4
- package/sidecar/dist/providers/codex/adapter.js.map +1 -1
- package/sidecar/dist/providers/codex/client.d.ts +0 -11
- package/sidecar/dist/providers/codex/config.d.ts +1 -3
- package/sidecar/dist/providers/codex/config.js +5 -11
- package/sidecar/dist/providers/codex/config.js.map +1 -1
- package/sidecar/dist/providers/codex/permissions.d.ts +7 -4
- package/sidecar/dist/providers/codex/permissions.js +32 -16
- package/sidecar/dist/providers/codex/permissions.js.map +1 -1
- package/sidecar/dist/providers/codex/process.js +1 -5
- package/sidecar/dist/providers/codex/process.js.map +1 -1
- package/sidecar/dist/providers/codex/provider.js +14 -3
- package/sidecar/dist/providers/codex/provider.js.map +1 -1
- package/sidecar/dist/providers/codex/skills.d.ts +0 -1
- package/sidecar/dist/providers/codex/skills.js +1 -1
- package/sidecar/dist/providers/codex/skills.js.map +1 -1
- package/sidecar/dist/providers/codex/stop.js +1 -10
- package/sidecar/dist/providers/codex/stop.js.map +1 -1
- package/sidecar/dist/server/change-set-actions.d.ts +10 -0
- package/sidecar/dist/server/change-set-actions.js +14 -0
- package/sidecar/dist/server/change-set-actions.js.map +1 -0
- package/sidecar/dist/server/chat-events.d.ts +15 -0
- package/sidecar/dist/server/chat-events.js +115 -0
- package/sidecar/dist/server/chat-events.js.map +1 -0
- package/sidecar/dist/server/chat-socket-registry.d.ts +2 -0
- package/sidecar/dist/server/chat-socket-registry.js +48 -37
- package/sidecar/dist/server/chat-socket-registry.js.map +1 -1
- package/sidecar/dist/server/conversation-runs.d.ts +13 -0
- package/sidecar/dist/server/conversation-runs.js +114 -0
- package/sidecar/dist/server/conversation-runs.js.map +1 -0
- package/sidecar/dist/server/http-io.d.ts +4 -0
- package/sidecar/dist/server/http-io.js +31 -0
- package/sidecar/dist/server/http-io.js.map +1 -0
- package/sidecar/dist/server/http-params.d.ts +9 -0
- package/sidecar/dist/server/http-params.js +79 -0
- package/sidecar/dist/server/http-params.js.map +1 -0
- package/sidecar/dist/server/http-routes.d.ts +27 -0
- package/sidecar/dist/server/http-routes.js +281 -0
- package/sidecar/dist/server/http-routes.js.map +1 -0
- package/sidecar/dist/server/http.d.ts +6 -1
- package/sidecar/dist/server/http.js +76 -164
- package/sidecar/dist/server/http.js.map +1 -1
- package/sidecar/dist/server/pending-queue.d.ts +2 -0
- package/sidecar/dist/server/pending-queue.js +16 -0
- package/sidecar/dist/server/pending-queue.js.map +1 -1
- package/sidecar/dist/server/permission-events.d.ts +15 -0
- package/sidecar/dist/server/permission-events.js +163 -0
- package/sidecar/dist/server/permission-events.js.map +1 -0
- package/sidecar/dist/server/routing.d.ts +4 -52
- package/sidecar/dist/server/routing.js +190 -501
- package/sidecar/dist/server/routing.js.map +1 -1
- package/sidecar/dist/server/safety-net.d.ts +7 -0
- package/sidecar/dist/server/safety-net.js +34 -6
- package/sidecar/dist/server/safety-net.js.map +1 -1
- package/sidecar/dist/server/services.d.ts +55 -0
- package/sidecar/dist/server/services.js +2 -0
- package/sidecar/dist/server/services.js.map +1 -0
- package/sidecar/dist/server/tool-calls.d.ts +6 -0
- package/sidecar/dist/server/tool-calls.js +134 -0
- package/sidecar/dist/server/tool-calls.js.map +1 -0
- package/sidecar/dist/server/turn-registry.d.ts +44 -0
- package/sidecar/dist/server/turn-registry.js +40 -0
- package/sidecar/dist/server/turn-registry.js.map +1 -0
- package/sidecar/dist/server/turns.d.ts +17 -0
- package/sidecar/dist/server/turns.js +335 -0
- package/sidecar/dist/server/turns.js.map +1 -0
- package/sidecar/dist/server/ws.d.ts +4 -1
- package/sidecar/dist/server/ws.js +102 -62
- package/sidecar/dist/server/ws.js.map +1 -1
- package/sidecar/dist/skills/build-catalog.d.ts +1 -0
- package/sidecar/dist/skills/build-catalog.js +14 -1
- package/sidecar/dist/skills/build-catalog.js.map +1 -1
- package/sidecar/dist/skills/skill-usage.d.ts +22 -0
- package/sidecar/dist/skills/skill-usage.js +97 -0
- package/sidecar/dist/skills/skill-usage.js.map +1 -0
- package/sidecar/dist/state/change-sets.d.ts +12 -0
- package/sidecar/dist/state/change-sets.js +77 -0
- package/sidecar/dist/state/change-sets.js.map +1 -0
- package/sidecar/dist/state/conversations.d.ts +19 -7
- package/sidecar/dist/state/conversations.js +61 -20
- package/sidecar/dist/state/conversations.js.map +1 -1
- package/sidecar/dist/state/host-state.d.ts +2 -1
- package/sidecar/dist/state/settings-store.d.ts +1 -0
- package/sidecar/dist/state/settings-store.js +27 -26
- package/sidecar/dist/state/settings-store.js.map +1 -1
- package/sidecar/dist/state/settings-types.d.ts +11 -1
- package/sidecar/dist/state/settings-types.js +3 -1
- package/sidecar/dist/state/settings-types.js.map +1 -1
- package/sidecar/dist/state/types.d.ts +114 -8
- package/sidecar/dist/state/types.js +6 -3
- package/sidecar/dist/state/types.js.map +1 -1
- package/skills/dms-builder-safe/REFERENCE.md +1 -1
- package/skills/dms-builder-safe/SKILL.md +12 -7
- package/dist/routes/proxy.d.ts +0 -4
- package/dist/routes/proxy.js +0 -55
- package/dist/routes/proxy.js.map +0 -1
- package/frontend-vue/app/chat/components/ComposerInput.vue +0 -742
- package/frontend-vue/app/chat/components/PermissionRequests.vue +0 -323
- package/frontend-vue/app/chat/components/QuestionPrompt.vue +0 -275
- package/frontend-vue/app/chat/components/QueuedMessages.vue +0 -109
- package/frontend-vue/app/chat/components/TodoList.vue +0 -291
- package/frontend-vue/app/chat/components/ToolCallEntry.vue +0 -218
- package/frontend-vue/app/chat/constants/connection-banner.ts +0 -7
- package/frontend-vue/app/chat/constants/conversation-drawer.ts +0 -13
- package/frontend-vue/app/chat/constants/permissions.ts +0 -50
- package/frontend-vue/app/chat/utils/tool-summary.ts +0 -53
- package/frontend-vue/app/components/ActivityView.vue +0 -94
- package/frontend-vue/app/components/SettingsView.vue +0 -387
- package/frontend-vue/app/components/SkillsView.vue +0 -230
- package/frontend-vue/app/runtime/header-action.ts +0 -64
- package/frontend-vue/app/runtime/overlay-prefs.ts +0 -89
- package/frontend-vue/app/runtime/panel-state.ts +0 -88
- package/frontend-vue/tests/overlay-prefs.test.ts +0 -91
- package/frontend-vue/tests/panel-state.test.ts +0 -58
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { MESSAGE_ROLES } from "../constants/conversation";
|
|
2
|
+
import { SERVER_EVENT_TYPES } from "../constants/protocol";
|
|
3
|
+
import type {
|
|
4
|
+
ConversationMessage,
|
|
5
|
+
ToolCallMessage,
|
|
6
|
+
} from "../types/conversation";
|
|
7
|
+
import type {
|
|
8
|
+
AllowedBy,
|
|
9
|
+
AttachmentMeta,
|
|
10
|
+
ChangeSetSummary,
|
|
11
|
+
ConversationModeState,
|
|
12
|
+
FullAutoState,
|
|
13
|
+
Notice,
|
|
14
|
+
QueuedItemWire,
|
|
15
|
+
SnapshotMessage,
|
|
16
|
+
ToolOutcome,
|
|
17
|
+
WireAttachment,
|
|
18
|
+
} from "../types/protocol";
|
|
19
|
+
import type { PendingAttachment } from "../utils/attachments";
|
|
20
|
+
import {
|
|
21
|
+
buildAssistantMessage,
|
|
22
|
+
buildErrorMessage,
|
|
23
|
+
buildUserMessage,
|
|
24
|
+
closedStatus,
|
|
25
|
+
settleOpenTools,
|
|
26
|
+
snapshotToMessages,
|
|
27
|
+
} from "../utils/conversation-messages";
|
|
28
|
+
import { newUuid } from "../utils/ids";
|
|
29
|
+
import { toActivityKind } from "../utils/run-status";
|
|
30
|
+
import type { ConversationState } from "./useConversation";
|
|
31
|
+
|
|
32
|
+
interface ChunkEvent {
|
|
33
|
+
text: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ToolStartEvent {
|
|
37
|
+
callId: string;
|
|
38
|
+
toolName: string;
|
|
39
|
+
args: unknown;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface ToolEndEvent {
|
|
43
|
+
callId: string;
|
|
44
|
+
status?: string;
|
|
45
|
+
result: unknown;
|
|
46
|
+
outcome?: ToolOutcome;
|
|
47
|
+
allowedBy?: AllowedBy;
|
|
48
|
+
changeSetId?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface RunErrorEvent {
|
|
52
|
+
error: string;
|
|
53
|
+
isRetryable?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface RunProgressEvent {
|
|
57
|
+
activity: string;
|
|
58
|
+
detail?: string;
|
|
59
|
+
elapsedMs: number;
|
|
60
|
+
idleMs: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface SnapshotModeWire {
|
|
64
|
+
mode?: ConversationModeState["mode"];
|
|
65
|
+
generationMode?: ConversationModeState["generationMode"];
|
|
66
|
+
fullAuto?: FullAutoState | null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface SnapshotEvent {
|
|
70
|
+
messages?: SnapshotMessage[];
|
|
71
|
+
changeSets?: ChangeSetSummary[];
|
|
72
|
+
mode?: SnapshotModeWire;
|
|
73
|
+
totalTokens?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface QueueStateEvent {
|
|
77
|
+
items?: QueuedItemWire[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface UserMessageEchoEvent {
|
|
81
|
+
content: string;
|
|
82
|
+
attachments?: AttachmentMeta[];
|
|
83
|
+
timestampMs?: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface NoticeEvent {
|
|
87
|
+
notice?: Notice;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface ChangeSetEvent {
|
|
91
|
+
changeSet?: ChangeSetSummary;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface UsageEvent {
|
|
95
|
+
totalTokens?: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type EventHandler = (state: ConversationState, event: never) => void;
|
|
99
|
+
|
|
100
|
+
function setMessages(
|
|
101
|
+
state: ConversationState,
|
|
102
|
+
next: ConversationMessage[],
|
|
103
|
+
): void {
|
|
104
|
+
state.messages.value = next;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function appendMessage(
|
|
108
|
+
state: ConversationState,
|
|
109
|
+
message: ConversationMessage,
|
|
110
|
+
): void {
|
|
111
|
+
setMessages(state, [...state.messages.value, message]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function endTurn(state: ConversationState): void {
|
|
115
|
+
setMessages(state, settleOpenTools(state.messages.value));
|
|
116
|
+
state.progress.value = null;
|
|
117
|
+
state.isTurnInFlight.value = false;
|
|
118
|
+
state.isRunning.value = state.queued.value.length > 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function appendChunk(state: ConversationState, event: ChunkEvent): void {
|
|
122
|
+
const list = state.messages.value;
|
|
123
|
+
const last = list.at(-1);
|
|
124
|
+
if (last?.role !== MESSAGE_ROLES.ASSISTANT) {
|
|
125
|
+
appendMessage(state, buildAssistantMessage(event.text));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
setMessages(state, [
|
|
129
|
+
...list.slice(0, -1),
|
|
130
|
+
{ ...last, content: last.content + event.text },
|
|
131
|
+
]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isCall(msg: ConversationMessage, callId: string): boolean {
|
|
135
|
+
return msg.role === MESSAGE_ROLES.TOOL && msg.callId === callId;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function startTool(state: ConversationState, event: ToolStartEvent): void {
|
|
139
|
+
const list = state.messages.value;
|
|
140
|
+
if (list.some((msg) => isCall(msg, event.callId))) {
|
|
141
|
+
setMessages(
|
|
142
|
+
state,
|
|
143
|
+
list.map((msg) =>
|
|
144
|
+
isCall(msg, event.callId)
|
|
145
|
+
? { ...msg, toolName: event.toolName, args: event.args }
|
|
146
|
+
: msg,
|
|
147
|
+
),
|
|
148
|
+
);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const tool: ToolCallMessage = {
|
|
152
|
+
id: newUuid(),
|
|
153
|
+
role: MESSAGE_ROLES.TOOL,
|
|
154
|
+
callId: event.callId,
|
|
155
|
+
toolName: event.toolName,
|
|
156
|
+
args: event.args,
|
|
157
|
+
status: "pending",
|
|
158
|
+
timestampMs: state.callTimes.get(event.callId)?.startedAtMs ?? Date.now(),
|
|
159
|
+
};
|
|
160
|
+
appendMessage(state, tool);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function endTool(state: ConversationState, event: ToolEndEvent): void {
|
|
164
|
+
const endedAtMs = state.callTimes.get(event.callId)?.endedAtMs ?? Date.now();
|
|
165
|
+
setMessages(
|
|
166
|
+
state,
|
|
167
|
+
state.messages.value.map((msg) => {
|
|
168
|
+
if (!isCall(msg, event.callId) || msg.role !== MESSAGE_ROLES.TOOL)
|
|
169
|
+
return msg;
|
|
170
|
+
return {
|
|
171
|
+
...msg,
|
|
172
|
+
status: closedStatus(event.outcome, event.status),
|
|
173
|
+
result: event.result,
|
|
174
|
+
outcome: event.outcome,
|
|
175
|
+
allowedBy: event.allowedBy ?? msg.allowedBy,
|
|
176
|
+
changeSetId: event.changeSetId,
|
|
177
|
+
endedAtMs,
|
|
178
|
+
};
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function failRun(state: ConversationState, event: RunErrorEvent): void {
|
|
184
|
+
endTurn(state);
|
|
185
|
+
appendMessage(
|
|
186
|
+
state,
|
|
187
|
+
buildErrorMessage(event.error, event.isRetryable ?? true),
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function isTurnStart(msg: ConversationMessage): boolean {
|
|
192
|
+
if (msg.role === MESSAGE_ROLES.USER) return true;
|
|
193
|
+
return msg.role === MESSAGE_ROLES.NOTICE && msg.notice.kind === "autofix";
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Kept through a replay: stored outside the turn's own events. */
|
|
197
|
+
function isOutOfTurn(msg: ConversationMessage): boolean {
|
|
198
|
+
return (
|
|
199
|
+
msg.role === MESSAGE_ROLES.NOTICE ||
|
|
200
|
+
msg.role === MESSAGE_ROLES.QUESTION_ANSWER
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* The transcript up to where the running turn began. A re-attach sends the
|
|
206
|
+
* stored transcript, then `run_resumed` and every event of the running turn
|
|
207
|
+
* from its start: the turn's stored part makes way for that replay, or its
|
|
208
|
+
* texts would be appended twice.
|
|
209
|
+
*/
|
|
210
|
+
function withoutRunningTurn(
|
|
211
|
+
list: ConversationMessage[],
|
|
212
|
+
): ConversationMessage[] {
|
|
213
|
+
const start = lastIndexWhere(list, isTurnStart);
|
|
214
|
+
return [
|
|
215
|
+
...list.slice(0, start + 1),
|
|
216
|
+
...list.slice(start + 1).filter(isOutOfTurn),
|
|
217
|
+
];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function lastIndexWhere(
|
|
221
|
+
list: ConversationMessage[],
|
|
222
|
+
predicate: (msg: ConversationMessage) => boolean,
|
|
223
|
+
): number {
|
|
224
|
+
for (let index = list.length - 1; index >= 0; index -= 1)
|
|
225
|
+
if (predicate(list[index])) return index;
|
|
226
|
+
return -1;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function resumeRun(state: ConversationState): void {
|
|
230
|
+
setMessages(state, withoutRunningTurn(state.messages.value));
|
|
231
|
+
state.isRunning.value = true;
|
|
232
|
+
state.isTurnInFlight.value = true;
|
|
233
|
+
state.lastEventAtMs.value = Date.now();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function reportProgress(
|
|
237
|
+
state: ConversationState,
|
|
238
|
+
event: RunProgressEvent,
|
|
239
|
+
): void {
|
|
240
|
+
state.progress.value = {
|
|
241
|
+
activity: toActivityKind(event.activity),
|
|
242
|
+
detail: event.detail,
|
|
243
|
+
elapsedMs: event.elapsedMs,
|
|
244
|
+
idleMs: event.idleMs,
|
|
245
|
+
receivedAtMs: Date.now(),
|
|
246
|
+
};
|
|
247
|
+
state.isRunning.value = true;
|
|
248
|
+
state.isTurnInFlight.value = true;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function toModeState(wire: SnapshotModeWire | undefined) {
|
|
252
|
+
if (wire?.mode === undefined || wire.generationMode === undefined)
|
|
253
|
+
return null;
|
|
254
|
+
return {
|
|
255
|
+
mode: wire.mode,
|
|
256
|
+
generationMode: wire.generationMode,
|
|
257
|
+
fullAuto: wire.fullAuto ?? null,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function byId(sets: readonly ChangeSetSummary[]) {
|
|
262
|
+
return Object.fromEntries(sets.map((set) => [set.id, set]));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function rememberCallTimes(
|
|
266
|
+
state: ConversationState,
|
|
267
|
+
list: ConversationMessage[],
|
|
268
|
+
): void {
|
|
269
|
+
state.callTimes.clear();
|
|
270
|
+
for (const msg of list) {
|
|
271
|
+
if (msg.role !== MESSAGE_ROLES.TOOL) continue;
|
|
272
|
+
state.callTimes.set(msg.callId, {
|
|
273
|
+
startedAtMs: msg.timestampMs,
|
|
274
|
+
endedAtMs: msg.endedAtMs,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function applySnapshot(state: ConversationState, event: SnapshotEvent): void {
|
|
280
|
+
const messages = snapshotToMessages(event.messages ?? []);
|
|
281
|
+
rememberCallTimes(state, messages);
|
|
282
|
+
setMessages(state, messages);
|
|
283
|
+
state.changeSets.value = byId(event.changeSets ?? []);
|
|
284
|
+
state.mode.value = toModeState(event.mode) ?? state.mode.value;
|
|
285
|
+
state.totalTokens.value = event.totalTokens ?? state.totalTokens.value;
|
|
286
|
+
state.isRunning.value = false;
|
|
287
|
+
state.progress.value = null;
|
|
288
|
+
state.isTurnInFlight.value = false;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function toPendingAttachment(wire: WireAttachment): PendingAttachment {
|
|
292
|
+
return {
|
|
293
|
+
id: newUuid(),
|
|
294
|
+
name: wire.name,
|
|
295
|
+
mimeType: wire.mimeType,
|
|
296
|
+
size: wire.size,
|
|
297
|
+
data: wire.data,
|
|
298
|
+
dataUrl: `data:${wire.mimeType};base64,${wire.data}`,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function applyQueue(state: ConversationState, event: QueueStateEvent): void {
|
|
303
|
+
state.queued.value = (event.items ?? []).map((item) => ({
|
|
304
|
+
id: item.id,
|
|
305
|
+
content: item.content,
|
|
306
|
+
attachments: (item.attachments ?? []).map(toPendingAttachment),
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function echoUserMessage(
|
|
311
|
+
state: ConversationState,
|
|
312
|
+
event: UserMessageEchoEvent,
|
|
313
|
+
): void {
|
|
314
|
+
const attachments = (event.attachments ?? []).map((meta) => ({ ...meta }));
|
|
315
|
+
appendMessage(
|
|
316
|
+
state,
|
|
317
|
+
buildUserMessage(
|
|
318
|
+
event.content,
|
|
319
|
+
attachments.length > 0 ? attachments : undefined,
|
|
320
|
+
undefined,
|
|
321
|
+
event.timestampMs ?? Date.now(),
|
|
322
|
+
),
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function applyMode(state: ConversationState, event: SnapshotModeWire): void {
|
|
327
|
+
state.mode.value = toModeState(event) ?? state.mode.value;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function appendNotice(state: ConversationState, event: NoticeEvent): void {
|
|
331
|
+
if (event.notice === undefined) return;
|
|
332
|
+
appendMessage(state, {
|
|
333
|
+
id: newUuid(),
|
|
334
|
+
role: MESSAGE_ROLES.NOTICE,
|
|
335
|
+
notice: event.notice,
|
|
336
|
+
timestampMs: event.notice.timestampMs ?? Date.now(),
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function hasCardFor(state: ConversationState, changeSetId: string): boolean {
|
|
341
|
+
return state.messages.value.some(
|
|
342
|
+
(msg) =>
|
|
343
|
+
msg.role === MESSAGE_ROLES.CHANGE_SET && msg.changeSetId === changeSetId,
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function applyChangeSet(state: ConversationState, event: ChangeSetEvent): void {
|
|
348
|
+
const set = event.changeSet;
|
|
349
|
+
if (set === undefined) return;
|
|
350
|
+
state.changeSets.value = { ...state.changeSets.value, [set.id]: set };
|
|
351
|
+
if (hasCardFor(state, set.id)) return;
|
|
352
|
+
appendMessage(state, {
|
|
353
|
+
id: newUuid(),
|
|
354
|
+
role: MESSAGE_ROLES.CHANGE_SET,
|
|
355
|
+
changeSetId: set.id,
|
|
356
|
+
timestampMs: set.createdAtMs,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function applyUsage(state: ConversationState, event: UsageEvent): void {
|
|
361
|
+
if (typeof event.totalTokens !== "number") return;
|
|
362
|
+
state.totalTokens.value = event.totalTokens;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const EVENT_HANDLERS: Record<string, EventHandler> = {
|
|
366
|
+
[SERVER_EVENT_TYPES.ASSISTANT_MESSAGE_CHUNK]: appendChunk,
|
|
367
|
+
[SERVER_EVENT_TYPES.TOOL_CALL_START]: startTool,
|
|
368
|
+
[SERVER_EVENT_TYPES.TOOL_CALL_END]: endTool,
|
|
369
|
+
[SERVER_EVENT_TYPES.RUN_DONE]: endTurn,
|
|
370
|
+
[SERVER_EVENT_TYPES.RUN_ERROR]: failRun,
|
|
371
|
+
[SERVER_EVENT_TYPES.RUN_RESUMED]: resumeRun,
|
|
372
|
+
[SERVER_EVENT_TYPES.RUN_PROGRESS]: reportProgress,
|
|
373
|
+
[SERVER_EVENT_TYPES.CONVERSATION_SNAPSHOT]: applySnapshot,
|
|
374
|
+
[SERVER_EVENT_TYPES.QUEUE_STATE]: applyQueue,
|
|
375
|
+
[SERVER_EVENT_TYPES.USER_MESSAGE_ECHO]: echoUserMessage,
|
|
376
|
+
[SERVER_EVENT_TYPES.CONVERSATION_MODE]: applyMode,
|
|
377
|
+
[SERVER_EVENT_TYPES.NOTICE]: appendNotice,
|
|
378
|
+
[SERVER_EVENT_TYPES.CHANGE_SET]: applyChangeSet,
|
|
379
|
+
[SERVER_EVENT_TYPES.USAGE]: applyUsage,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
383
|
+
return value !== null && typeof value === "object";
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function isForActive(
|
|
387
|
+
state: ConversationState,
|
|
388
|
+
msg: Record<string, unknown>,
|
|
389
|
+
): boolean {
|
|
390
|
+
const id = msg.conversationId;
|
|
391
|
+
return typeof id !== "string" || id === state.options.activeId.value;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** Folds one sidecar event into the active conversation; others are ignored. */
|
|
395
|
+
export function dispatchConversationEvent(
|
|
396
|
+
state: ConversationState,
|
|
397
|
+
msg: unknown,
|
|
398
|
+
): void {
|
|
399
|
+
if (!isRecord(msg) || typeof msg.type !== "string") return;
|
|
400
|
+
const handler = EVENT_HANDLERS[msg.type];
|
|
401
|
+
if (handler === undefined || !isForActive(state, msg)) return;
|
|
402
|
+
state.lastEventAtMs.value = Date.now();
|
|
403
|
+
handler(state, msg as never);
|
|
404
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { type Ref, ref, watch } from "vue";
|
|
2
|
+
import { CLIENT_MESSAGE_TYPES } from "../constants/protocol";
|
|
3
|
+
import type { ChangeSetSummary } from "../types/protocol";
|
|
4
|
+
|
|
5
|
+
/** What the dashboard's authenticated fetch gives the chat. */
|
|
6
|
+
export interface ChatApi {
|
|
7
|
+
get: <T>(path: string) => Promise<T>;
|
|
8
|
+
post: <T>(path: string, body?: unknown) => Promise<T>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface UndoConflict {
|
|
12
|
+
changeSetId: string;
|
|
13
|
+
number: number;
|
|
14
|
+
title: string;
|
|
15
|
+
files: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface UndoPreview {
|
|
19
|
+
conflicts?: UndoConflict[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** An undo waiting on the user: later sets touch the same files. */
|
|
23
|
+
interface PendingUndo {
|
|
24
|
+
changeSetId: string;
|
|
25
|
+
number: number;
|
|
26
|
+
conflicts: UndoConflict[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface UseChangeSetActionsOptions {
|
|
30
|
+
activeId: Ref<string>;
|
|
31
|
+
changeSets: Ref<Record<string, ChangeSetSummary>>;
|
|
32
|
+
send: (msg: object) => boolean;
|
|
33
|
+
api: ChatApi | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface UseChangeSetActionsResult {
|
|
37
|
+
busyIds: Ref<ReadonlySet<string>>;
|
|
38
|
+
pendingUndo: Ref<PendingUndo | null>;
|
|
39
|
+
undo: (changeSetId: string) => Promise<void>;
|
|
40
|
+
redo: (changeSetId: string) => void;
|
|
41
|
+
/** Answers the conflict question: with the later sets, or this one alone. */
|
|
42
|
+
confirmUndo: (includeLater: boolean) => void;
|
|
43
|
+
cancelUndo: () => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const BUSY_TIMEOUT_MS = 10_000;
|
|
47
|
+
|
|
48
|
+
function undoPreviewPath(changeSetId: string): string {
|
|
49
|
+
return `/ai/changes/${encodeURIComponent(changeSetId)}/undo-preview`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Undo and Redo from the chat's change set cards. Undo first asks the backend
|
|
54
|
+
* which later sets touch the same files, and lets the user choose when some
|
|
55
|
+
* do, since undoing one alone may leave code that does not compile.
|
|
56
|
+
*/
|
|
57
|
+
export function useChangeSetActions(
|
|
58
|
+
options: UseChangeSetActionsOptions,
|
|
59
|
+
): UseChangeSetActionsResult {
|
|
60
|
+
const busyIds = ref<ReadonlySet<string>>(new Set());
|
|
61
|
+
const stateAtAction = new Map<string, string | undefined>();
|
|
62
|
+
const pendingUndo = ref<PendingUndo | null>(null);
|
|
63
|
+
|
|
64
|
+
const setBusy = (id: string, isBusy: boolean): void => {
|
|
65
|
+
const next = new Set(busyIds.value);
|
|
66
|
+
if (isBusy) next.add(id);
|
|
67
|
+
else next.delete(id);
|
|
68
|
+
busyIds.value = next;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const act = (
|
|
72
|
+
changeSetId: string,
|
|
73
|
+
action: "undo" | "redo",
|
|
74
|
+
includeLater = false,
|
|
75
|
+
): void => {
|
|
76
|
+
const isSent = options.send({
|
|
77
|
+
type: CLIENT_MESSAGE_TYPES.CHANGE_SET_ACTION,
|
|
78
|
+
conversationId: options.activeId.value,
|
|
79
|
+
changeSetId,
|
|
80
|
+
action,
|
|
81
|
+
...(includeLater ? { includeLater: true } : {}),
|
|
82
|
+
});
|
|
83
|
+
if (!isSent) return;
|
|
84
|
+
stateAtAction.set(
|
|
85
|
+
changeSetId,
|
|
86
|
+
options.changeSets.value[changeSetId]?.state,
|
|
87
|
+
);
|
|
88
|
+
setBusy(changeSetId, true);
|
|
89
|
+
setTimeout(() => setBusy(changeSetId, false), BUSY_TIMEOUT_MS);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
watch(options.changeSets, (sets) => {
|
|
93
|
+
const settled = [...busyIds.value].filter(
|
|
94
|
+
(id) => sets[id]?.state !== stateAtAction.get(id),
|
|
95
|
+
);
|
|
96
|
+
settled.forEach((id) => setBusy(id, false));
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const conflictsOf = async (changeSetId: string): Promise<UndoConflict[]> => {
|
|
100
|
+
if (options.api === null) return [];
|
|
101
|
+
try {
|
|
102
|
+
const preview = await options.api.get<UndoPreview>(
|
|
103
|
+
undoPreviewPath(changeSetId),
|
|
104
|
+
);
|
|
105
|
+
return preview.conflicts ?? [];
|
|
106
|
+
} catch {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const undo = async (changeSetId: string): Promise<void> => {
|
|
112
|
+
const conflicts = await conflictsOf(changeSetId);
|
|
113
|
+
if (conflicts.length === 0) {
|
|
114
|
+
act(changeSetId, "undo");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const number = options.changeSets.value[changeSetId]?.number ?? 0;
|
|
118
|
+
pendingUndo.value = { changeSetId, number, conflicts };
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
busyIds,
|
|
123
|
+
pendingUndo,
|
|
124
|
+
undo,
|
|
125
|
+
redo: (changeSetId) => act(changeSetId, "redo"),
|
|
126
|
+
confirmUndo: (includeLater) => {
|
|
127
|
+
const pending = pendingUndo.value;
|
|
128
|
+
pendingUndo.value = null;
|
|
129
|
+
if (pending !== null) act(pending.changeSetId, "undo", includeLater);
|
|
130
|
+
},
|
|
131
|
+
cancelUndo: () => {
|
|
132
|
+
pendingUndo.value = null;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -11,9 +11,15 @@ import {
|
|
|
11
11
|
export interface UseChatChannelOptions {
|
|
12
12
|
transport: ChatTransport;
|
|
13
13
|
getConversationId: () => string;
|
|
14
|
+
/**
|
|
15
|
+
* Follows the conversation next to the one the tab's stream shows, rather
|
|
16
|
+
* than switching it: the command palette's answer, while the panel keeps
|
|
17
|
+
* its own chat.
|
|
18
|
+
*/
|
|
19
|
+
isFollowing?: boolean;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
type ChannelMessageHandler = (msg: unknown) => void;
|
|
17
23
|
|
|
18
24
|
export interface UseChatChannelResult {
|
|
19
25
|
/** False when the message was dropped: the stream is not connected. */
|
|
@@ -43,10 +49,12 @@ function setStatus(state: ChannelState, status: string): void {
|
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
function sendHello(state: ChannelState): void {
|
|
46
|
-
state.options
|
|
52
|
+
const { transport, getConversationId, isFollowing } = state.options;
|
|
53
|
+
transport.send({
|
|
47
54
|
type: CLIENT_MESSAGE_TYPES.HELLO,
|
|
48
55
|
role: CHAT_ROLE,
|
|
49
|
-
conversationId:
|
|
56
|
+
conversationId: getConversationId(),
|
|
57
|
+
...(isFollowing === true ? { follow: true } : {}),
|
|
50
58
|
});
|
|
51
59
|
}
|
|
52
60
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type InjectionKey, inject, type Ref, ref } from "vue";
|
|
2
|
+
|
|
3
|
+
export type TranslateParams = Record<string, string | number>;
|
|
4
|
+
|
|
5
|
+
/** `t` of the dashboard's vue-i18n: a key, named parameters, a plural count. */
|
|
6
|
+
export type Translate = (
|
|
7
|
+
key: string,
|
|
8
|
+
params?: TranslateParams,
|
|
9
|
+
plural?: number,
|
|
10
|
+
) => string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The chat's view of the dashboard's i18n. The plugin provides it from the DMS
|
|
14
|
+
* runtime, so the chat itself imports nothing of the DMS and stays testable on
|
|
15
|
+
* its own.
|
|
16
|
+
*/
|
|
17
|
+
export interface ChatI18n {
|
|
18
|
+
t: Translate;
|
|
19
|
+
/** The interface language, for dates and numbers. */
|
|
20
|
+
locale: Readonly<Ref<string>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const CHAT_I18N_KEY: InjectionKey<ChatI18n> = Symbol("dms-ai:i18n");
|
|
24
|
+
|
|
25
|
+
const FALLBACK_LOCALE = "en-GB";
|
|
26
|
+
|
|
27
|
+
const keyOnly: ChatI18n = {
|
|
28
|
+
t: (key) => key,
|
|
29
|
+
locale: ref(FALLBACK_LOCALE),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** The chat's translator: the dashboard's when provided, the bare keys otherwise. */
|
|
33
|
+
export function useChatI18n(): ChatI18n {
|
|
34
|
+
return inject(CHAT_I18N_KEY, keyOnly);
|
|
35
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type Ref, ref } from "vue";
|
|
2
|
+
import {
|
|
3
|
+
MAX_ATTACHMENT_MEGABYTES,
|
|
4
|
+
MAX_ATTACHMENTS,
|
|
5
|
+
} from "../constants/attachments";
|
|
6
|
+
import {
|
|
7
|
+
exceedsSizeLimit,
|
|
8
|
+
type PendingAttachment,
|
|
9
|
+
readFileAsAttachment,
|
|
10
|
+
} from "../utils/attachments";
|
|
11
|
+
import type { Translate } from "./useChatI18n";
|
|
12
|
+
|
|
13
|
+
export interface UseComposerAttachmentsResult {
|
|
14
|
+
attachments: Ref<PendingAttachment[]>;
|
|
15
|
+
error: Ref<string>;
|
|
16
|
+
isDragging: Ref<boolean>;
|
|
17
|
+
add: (files: FileList | File[]) => Promise<void>;
|
|
18
|
+
remove: (id: string) => void;
|
|
19
|
+
clear: () => void;
|
|
20
|
+
onDragEnter: (event: DragEvent) => void;
|
|
21
|
+
onDragOver: (event: DragEvent) => void;
|
|
22
|
+
onDragLeave: () => void;
|
|
23
|
+
onDrop: (event: DragEvent) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hasFiles(event: DragEvent): boolean {
|
|
27
|
+
return event.dataTransfer?.types.includes("Files") ?? false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The files staged in the composer: picked, pasted or dropped, within the
|
|
32
|
+
* sidecar's limits, each problem said in the user's language.
|
|
33
|
+
*/
|
|
34
|
+
export function useComposerAttachments(
|
|
35
|
+
t: Translate,
|
|
36
|
+
isDisabled: () => boolean,
|
|
37
|
+
): UseComposerAttachmentsResult {
|
|
38
|
+
const attachments = ref<PendingAttachment[]>([]);
|
|
39
|
+
const error = ref("");
|
|
40
|
+
const isDragging = ref(false);
|
|
41
|
+
let dragDepth = 0;
|
|
42
|
+
|
|
43
|
+
async function readOne(file: File): Promise<void> {
|
|
44
|
+
if (exceedsSizeLimit(file)) {
|
|
45
|
+
error.value = t("dms_ai.panel.composer.file_too_large", {
|
|
46
|
+
name: file.name,
|
|
47
|
+
max: MAX_ATTACHMENT_MEGABYTES,
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
attachments.value = [
|
|
53
|
+
...attachments.value,
|
|
54
|
+
await readFileAsAttachment(file),
|
|
55
|
+
];
|
|
56
|
+
} catch {
|
|
57
|
+
error.value = t("dms_ai.panel.composer.file_unreadable", {
|
|
58
|
+
name: file.name,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function add(files: FileList | File[]): Promise<void> {
|
|
64
|
+
error.value = "";
|
|
65
|
+
const incoming = Array.from(files);
|
|
66
|
+
const room = MAX_ATTACHMENTS - attachments.value.length;
|
|
67
|
+
if (incoming.length > room)
|
|
68
|
+
error.value = t("dms_ai.panel.composer.too_many_files", {
|
|
69
|
+
max: MAX_ATTACHMENTS,
|
|
70
|
+
});
|
|
71
|
+
for (const file of incoming.slice(0, Math.max(room, 0)))
|
|
72
|
+
await readOne(file);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function onDrop(event: DragEvent): void {
|
|
76
|
+
dragDepth = 0;
|
|
77
|
+
isDragging.value = false;
|
|
78
|
+
const files = event.dataTransfer?.files;
|
|
79
|
+
if (isDisabled() || files === undefined || files.length === 0) return;
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
void add(files);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
attachments,
|
|
86
|
+
error,
|
|
87
|
+
isDragging,
|
|
88
|
+
add,
|
|
89
|
+
remove: (id) => {
|
|
90
|
+
attachments.value = attachments.value.filter((att) => att.id !== id);
|
|
91
|
+
},
|
|
92
|
+
clear: () => {
|
|
93
|
+
attachments.value = [];
|
|
94
|
+
error.value = "";
|
|
95
|
+
},
|
|
96
|
+
onDragEnter: (event) => {
|
|
97
|
+
if (isDisabled() || !hasFiles(event)) return;
|
|
98
|
+
dragDepth += 1;
|
|
99
|
+
isDragging.value = true;
|
|
100
|
+
},
|
|
101
|
+
onDragOver: (event) => {
|
|
102
|
+
if (!isDisabled() && hasFiles(event)) event.preventDefault();
|
|
103
|
+
},
|
|
104
|
+
onDragLeave: () => {
|
|
105
|
+
if (dragDepth === 0) return;
|
|
106
|
+
dragDepth -= 1;
|
|
107
|
+
if (dragDepth === 0) isDragging.value = false;
|
|
108
|
+
},
|
|
109
|
+
onDrop,
|
|
110
|
+
};
|
|
111
|
+
}
|