@antelopejs/dms-ai 0.6.1 → 0.8.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 +17 -7
- package/dist/builder/presence.js.map +1 -1
- package/dist/channels/bridge.js +4 -2
- package/dist/channels/bridge.js.map +1 -1
- package/dist/channels/sse-stream.d.ts +1 -1
- package/dist/config.d.ts +6 -1
- package/dist/config.js +9 -21
- package/dist/config.js.map +1 -1
- package/dist/constants/channels.d.ts +5 -1
- package/dist/constants/channels.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/build-id.js +1 -1
- package/dist/lifecycle/build-id.js.map +1 -1
- package/dist/lifecycle/module-roots.js +12 -14
- package/dist/lifecycle/module-roots.js.map +1 -1
- package/dist/lifecycle/sidecar-owner.js.map +1 -1
- package/dist/lifecycle/skill-sources.js +45 -32
- package/dist/lifecycle/skill-sources.js.map +1 -1
- package/dist/lifecycle/spawn-sidecar.js +11 -6
- package/dist/lifecycle/spawn-sidecar.js.map +1 -1
- package/dist/logging/log-buffer.js +6 -2
- package/dist/logging/log-buffer.js.map +1 -1
- package/dist/pages/activity/columns.d.ts +66 -2
- package/dist/pages/activity/columns.js.map +1 -1
- package/dist/pages/activity/page.js.map +1 -1
- package/dist/pages/index.js.map +1 -1
- package/dist/pages/overview/page.js.map +1 -1
- package/dist/pages/overview/recent-changes.js.map +1 -1
- package/dist/pages/settings/availability.js.map +1 -1
- package/dist/pages/skills/page.js.map +1 -1
- package/dist/pages-registry.js +9 -10
- package/dist/pages-registry.js.map +1 -1
- package/dist/routes/activity.d.ts +5 -4
- package/dist/routes/activity.js.map +1 -1
- package/dist/routes/builder.d.ts +7 -1
- package/dist/routes/builder.js.map +1 -1
- package/dist/routes/changes.d.ts +11 -8
- package/dist/routes/changes.js.map +1 -1
- package/dist/routes/codex-account.d.ts +7 -2
- package/dist/routes/codex-account.js +2 -2
- package/dist/routes/codex-account.js.map +1 -1
- package/dist/routes/database.d.ts +21 -4
- package/dist/routes/database.js.map +1 -1
- package/dist/routes/metric-shapes.js +8 -5
- package/dist/routes/metric-shapes.js.map +1 -1
- package/dist/routes/metrics.d.ts +4 -2
- package/dist/routes/metrics.js +2 -2
- package/dist/routes/metrics.js.map +1 -1
- package/dist/routes/pages-registry.js.map +1 -1
- package/dist/routes/settings.d.ts +3 -2
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/sidecar-info.js.map +1 -1
- package/dist/routes/sidecar-results.d.ts +4 -4
- package/dist/routes/sidecar-results.js +10 -10
- package/dist/routes/sidecar-results.js.map +1 -1
- package/dist/routes/skills.d.ts +2 -1
- package/dist/routes/skills.js +6 -4
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/status-shapes.js +12 -12
- package/dist/routes/status-shapes.js.map +1 -1
- package/dist/routes/status.js.map +1 -1
- package/dist/routes/undo-confirm.js.map +1 -1
- package/dist/sidecar/http-client.js +3 -1
- package/dist/sidecar/http-client.js.map +1 -1
- package/dist/sidecar/index.d.ts +1 -0
- package/dist/sidecar/index.js +1 -0
- package/dist/sidecar/index.js.map +1 -1
- package/dist/sidecar/json-body.d.ts +4 -0
- package/dist/sidecar/json-body.js +33 -0
- package/dist/sidecar/json-body.js.map +1 -0
- package/dist/sidecar/settings-values.d.ts +5 -2
- package/dist/sidecar/settings-values.js.map +1 -1
- package/dist/vocabulary/tools.js.map +1 -1
- package/frontend-vue/app/chat/components/ChatView.vue +33 -133
- package/frontend-vue/app/chat/components/ProviderNotice.vue +77 -0
- package/frontend-vue/app/chat/components/UndoConflictModal.vue +98 -0
- package/frontend-vue/app/chat/composables/useChangeSetActions.ts +1 -1
- package/frontend-vue/app/components/SkillDetail.vue +1 -1
- package/frontend-vue/app/plugins/ai.client.ts +10 -2
- package/frontend-vue/app/runtime/assistant-actions.ts +41 -0
- package/frontend-vue/app/runtime/assistant-session.ts +8 -2
- package/frontend-vue/app/runtime/panel-intents.ts +3 -1
- package/frontend-vue/app/views/ChangeSetPanel.vue +1 -1
- package/frontend-vue/app/views/composables/useAiData.ts +10 -18
- package/frontend-vue/app/views/composables/useChangeSetActions.ts +5 -15
- package/frontend-vue/app/views/constants.ts +1 -1
- package/frontend-vue/app/views/types.ts +1 -1
- package/frontend-vue/build/backend-boundary.ts +122 -0
- package/frontend-vue/dms.frontend.build.ts +6 -0
- package/frontend-vue/package.json +2 -1
- package/frontend-vue/pnpm-lock.yaml +3 -0
- package/frontend-vue/tests/assistant-actions.test.ts +72 -0
- package/frontend-vue/tests/backend-boundary.test.ts +130 -0
- package/frontend-vue/tests/panel-approvals.test.ts +190 -0
- package/frontend-vue/tests/panel-questions.test.ts +169 -0
- package/frontend-vue/tests/panel-states.test.ts +1 -556
- package/frontend-vue/tests/panel-tools.test.ts +165 -0
- package/frontend-vue/tests/sidecar-guest.test.ts +39 -71
- package/frontend-vue/tests/support/api-error-presenter.ts +28 -0
- package/frontend-vue/tests/support/panel-fixtures.ts +110 -0
- package/frontend-vue/tests/support/panel-harness.ts +2 -2
- package/frontend-vue/tests/views/api-data-reads.test.ts +2 -0
- package/frontend-vue/tests/views/api-error-presentation.test.ts +89 -0
- package/frontend-vue/vitest.config.ts +2 -1
- package/package.json +21 -9
- package/sidecar/dist/agent/attachment-files.js.map +1 -1
- package/sidecar/dist/agent/call-ledger.d.ts +3 -2
- package/sidecar/dist/agent/call-ledger.js +1 -1
- package/sidecar/dist/agent/call-ledger.js.map +1 -1
- package/sidecar/dist/agent/command-analysis.js +13 -14
- package/sidecar/dist/agent/command-analysis.js.map +1 -1
- package/sidecar/dist/agent/conversation-modes.js.map +1 -1
- package/sidecar/dist/agent/edit-targets.d.ts +5 -1
- package/sidecar/dist/agent/edit-targets.js +8 -6
- package/sidecar/dist/agent/edit-targets.js.map +1 -1
- package/sidecar/dist/agent/edit-tracker.d.ts +2 -1
- package/sidecar/dist/agent/edit-tracker.js +3 -4
- package/sidecar/dist/agent/edit-tracker.js.map +1 -1
- package/sidecar/dist/agent/effective-mode.js.map +1 -1
- package/sidecar/dist/agent/line-diff.js +10 -8
- package/sidecar/dist/agent/line-diff.js.map +1 -1
- package/sidecar/dist/agent/permission-bus.js +2 -1
- package/sidecar/dist/agent/permission-bus.js.map +1 -1
- package/sidecar/dist/agent/permission-preview.d.ts +1 -1
- package/sidecar/dist/agent/permission-preview.js +54 -37
- package/sidecar/dist/agent/permission-preview.js.map +1 -1
- package/sidecar/dist/agent/permission-rules.js +4 -6
- package/sidecar/dist/agent/permission-rules.js.map +1 -1
- package/sidecar/dist/agent/provider.d.ts +2 -1
- package/sidecar/dist/agent/question-bus.js.map +1 -1
- package/sidecar/dist/agent/read-access.d.ts +2 -1
- package/sidecar/dist/agent/read-access.js +4 -7
- package/sidecar/dist/agent/read-access.js.map +1 -1
- package/sidecar/dist/agent/runner.js.map +1 -1
- package/sidecar/dist/agent/session.js +2 -6
- package/sidecar/dist/agent/session.js.map +1 -1
- package/sidecar/dist/agent/switching-runner.js.map +1 -1
- package/sidecar/dist/agent/system-prompt.js.map +1 -1
- package/sidecar/dist/agent/tool-summary.d.ts +2 -1
- package/sidecar/dist/agent/tool-summary.js +26 -13
- package/sidecar/dist/agent/tool-summary.js.map +1 -1
- package/sidecar/dist/agent/typecheck.d.ts +1 -4
- package/sidecar/dist/agent/typecheck.js +3 -2
- package/sidecar/dist/agent/typecheck.js.map +1 -1
- package/sidecar/dist/audit/activity-query.js +4 -8
- package/sidecar/dist/audit/activity-query.js.map +1 -1
- package/sidecar/dist/audit/activity-target.d.ts +4 -2
- package/sidecar/dist/audit/activity-target.js +10 -9
- package/sidecar/dist/audit/activity-target.js.map +1 -1
- package/sidecar/dist/audit/activity.js +4 -3
- package/sidecar/dist/audit/activity.js.map +1 -1
- package/sidecar/dist/audit/call-audit.js.map +1 -1
- package/sidecar/dist/builder/builder-client.d.ts +2 -1
- package/sidecar/dist/builder/builder-client.js +6 -8
- package/sidecar/dist/builder/builder-client.js.map +1 -1
- package/sidecar/dist/builder/capability.js.map +1 -1
- package/sidecar/dist/checkpoints/checkpoints.js.map +1 -1
- package/sidecar/dist/checkpoints/shadow-git.js +6 -2
- package/sidecar/dist/checkpoints/shadow-git.js.map +1 -1
- package/sidecar/dist/constants/agent.js.map +1 -1
- package/sidecar/dist/constants/attachments.js.map +1 -1
- package/sidecar/dist/constants/builder.js.map +1 -1
- package/sidecar/dist/constants/chatgpt.js.map +1 -1
- package/sidecar/dist/constants/checkpoints.d.ts +1 -1
- package/sidecar/dist/constants/checkpoints.js +6 -6
- package/sidecar/dist/constants/checkpoints.js.map +1 -1
- package/sidecar/dist/constants/claude.d.ts +3 -4
- package/sidecar/dist/constants/claude.js +16 -16
- package/sidecar/dist/constants/claude.js.map +1 -1
- package/sidecar/dist/constants/cli.js.map +1 -1
- package/sidecar/dist/constants/codex.d.ts +4 -5
- package/sidecar/dist/constants/codex.js +25 -25
- package/sidecar/dist/constants/codex.js.map +1 -1
- package/sidecar/dist/constants/database.js.map +1 -1
- package/sidecar/dist/constants/mcp.js.map +1 -1
- package/sidecar/dist/constants/paths.js.map +1 -1
- package/sidecar/dist/constants/project.d.ts +1 -1
- package/sidecar/dist/constants/project.js.map +1 -1
- package/sidecar/dist/constants/providers.js.map +1 -1
- package/sidecar/dist/constants/questions.js.map +1 -1
- package/sidecar/dist/constants/read-access.d.ts +1 -1
- package/sidecar/dist/constants/read-access.js +7 -7
- package/sidecar/dist/constants/read-access.js.map +1 -1
- package/sidecar/dist/constants/timing.js.map +1 -1
- package/sidecar/dist/database/database-client.d.ts +3 -2
- package/sidecar/dist/database/database-client.js +13 -9
- package/sidecar/dist/database/database-client.js.map +1 -1
- package/sidecar/dist/host/project-info.js +13 -7
- package/sidecar/dist/host/project-info.js.map +1 -1
- package/sidecar/dist/index.d.ts +1 -1
- package/sidecar/dist/index.js +60 -34
- package/sidecar/dist/index.js.map +1 -1
- package/sidecar/dist/logs/logs-client.js +13 -2
- package/sidecar/dist/logs/logs-client.js.map +1 -1
- package/sidecar/dist/logs/types.d.ts +2 -1
- package/sidecar/dist/mcp/define-tool.d.ts +9 -8
- package/sidecar/dist/mcp/define-tool.js.map +1 -1
- package/sidecar/dist/mcp/http-binding.js.map +1 -1
- package/sidecar/dist/mcp/tools/ask-user.js.map +1 -1
- package/sidecar/dist/mcp/tools/builder-catalog.d.ts +6 -1
- package/sidecar/dist/mcp/tools/builder-catalog.js +32 -24
- package/sidecar/dist/mcp/tools/builder-catalog.js.map +1 -1
- package/sidecar/dist/mcp/tools/builder-expr.d.ts +5 -0
- package/sidecar/dist/mcp/tools/builder-expr.js +25 -0
- package/sidecar/dist/mcp/tools/builder-expr.js.map +1 -0
- package/sidecar/dist/mcp/tools/builder-gate.js +2 -2
- package/sidecar/dist/mcp/tools/builder-gate.js.map +1 -1
- package/sidecar/dist/mcp/tools/builder-project.d.ts +2 -1
- package/sidecar/dist/mcp/tools/builder-project.js +60 -43
- package/sidecar/dist/mcp/tools/builder-project.js.map +1 -1
- package/sidecar/dist/mcp/tools/builder-queries.d.ts +34 -0
- package/sidecar/dist/mcp/tools/builder-queries.js +56 -0
- package/sidecar/dist/mcp/tools/builder-queries.js.map +1 -0
- package/sidecar/dist/mcp/tools/builder.d.ts +31 -19
- package/sidecar/dist/mcp/tools/builder.js +5 -72
- package/sidecar/dist/mcp/tools/builder.js.map +1 -1
- package/sidecar/dist/mcp/tools/database.js +5 -9
- package/sidecar/dist/mcp/tools/database.js.map +1 -1
- package/sidecar/dist/mcp/tools/find-pages-using.js.map +1 -1
- package/sidecar/dist/mcp/tools/get-current-page.js.map +1 -1
- package/sidecar/dist/mcp/tools/list-pages.js.map +1 -1
- package/sidecar/dist/mcp/tools/navigate-to-page.js +6 -6
- package/sidecar/dist/mcp/tools/navigate-to-page.js.map +1 -1
- package/sidecar/dist/mcp/tools/preview-blocks.js +15 -11
- package/sidecar/dist/mcp/tools/preview-blocks.js.map +1 -1
- package/sidecar/dist/mcp/tools/query-logs.js.map +1 -1
- package/sidecar/dist/mcp/tools/typecheck.js.map +1 -1
- package/sidecar/dist/mcp/types.d.ts +2 -1
- package/sidecar/dist/metrics/aggregate.js.map +1 -1
- package/sidecar/dist/metrics/types.js.map +1 -1
- package/sidecar/dist/pages/registry-client.js +14 -5
- package/sidecar/dist/pages/registry-client.js.map +1 -1
- package/sidecar/dist/pages/route-match.js.map +1 -1
- package/sidecar/dist/protocol/events.d.ts +7 -7
- package/sidecar/dist/protocol/events.js.map +1 -1
- package/sidecar/dist/protocol/json.d.ts +9 -0
- package/sidecar/dist/protocol/json.js +32 -0
- package/sidecar/dist/protocol/json.js.map +1 -0
- package/sidecar/dist/protocol/messages.d.ts +4 -4
- package/sidecar/dist/protocol/messages.js +3 -3
- package/sidecar/dist/protocol/messages.js.map +1 -1
- package/sidecar/dist/providers/claude/activity.d.ts +4 -2
- package/sidecar/dist/providers/claude/activity.js +29 -38
- package/sidecar/dist/providers/claude/activity.js.map +1 -1
- package/sidecar/dist/providers/claude/adapter.js +62 -91
- package/sidecar/dist/providers/claude/adapter.js.map +1 -1
- package/sidecar/dist/providers/claude/attachments.js +4 -4
- package/sidecar/dist/providers/claude/attachments.js.map +1 -1
- package/sidecar/dist/providers/claude/config.d.ts +4 -1
- package/sidecar/dist/providers/claude/config.js.map +1 -1
- package/sidecar/dist/providers/claude/module.js.map +1 -1
- package/sidecar/dist/providers/claude/provider.d.ts +4 -2
- package/sidecar/dist/providers/claude/provider.js.map +1 -1
- package/sidecar/dist/providers/claude/resolve-binary.js +6 -4
- package/sidecar/dist/providers/claude/resolve-binary.js.map +1 -1
- package/sidecar/dist/providers/claude/safe-mode.js +14 -3
- package/sidecar/dist/providers/claude/safe-mode.js.map +1 -1
- package/sidecar/dist/providers/codex/adapter.js +124 -46
- package/sidecar/dist/providers/codex/adapter.js.map +1 -1
- package/sidecar/dist/providers/codex/attachments.js +1 -1
- package/sidecar/dist/providers/codex/attachments.js.map +1 -1
- package/sidecar/dist/providers/codex/chatgpt/credentials.js.map +1 -1
- package/sidecar/dist/providers/codex/chatgpt/http.js +8 -5
- package/sidecar/dist/providers/codex/chatgpt/http.js.map +1 -1
- package/sidecar/dist/providers/codex/chatgpt/lock.js +3 -3
- package/sidecar/dist/providers/codex/chatgpt/lock.js.map +1 -1
- package/sidecar/dist/providers/codex/chatgpt/login.js.map +1 -1
- package/sidecar/dist/providers/codex/chatgpt/oauth.js +51 -8
- package/sidecar/dist/providers/codex/chatgpt/oauth.js.map +1 -1
- package/sidecar/dist/providers/codex/chatgpt/store.js +23 -23
- package/sidecar/dist/providers/codex/chatgpt/store.js.map +1 -1
- package/sidecar/dist/providers/codex/client.d.ts +4 -3
- package/sidecar/dist/providers/codex/client.js +10 -3
- package/sidecar/dist/providers/codex/client.js.map +1 -1
- package/sidecar/dist/providers/codex/config.js.map +1 -1
- package/sidecar/dist/providers/codex/module.js.map +1 -1
- package/sidecar/dist/providers/codex/permissions.d.ts +2 -2
- package/sidecar/dist/providers/codex/permissions.js +20 -6
- package/sidecar/dist/providers/codex/permissions.js.map +1 -1
- package/sidecar/dist/providers/codex/process.d.ts +3 -1
- package/sidecar/dist/providers/codex/process.js +35 -36
- package/sidecar/dist/providers/codex/process.js.map +1 -1
- package/sidecar/dist/providers/codex/provider.d.ts +2 -0
- package/sidecar/dist/providers/codex/provider.js +23 -7
- package/sidecar/dist/providers/codex/provider.js.map +1 -1
- package/sidecar/dist/providers/codex/resolve-binary.js +2 -2
- package/sidecar/dist/providers/codex/resolve-binary.js.map +1 -1
- package/sidecar/dist/providers/codex/stop.d.ts +6 -1
- package/sidecar/dist/providers/codex/stop.js +29 -22
- package/sidecar/dist/providers/codex/stop.js.map +1 -1
- package/sidecar/dist/providers/registry.js +4 -5
- package/sidecar/dist/providers/registry.js.map +1 -1
- package/sidecar/dist/server/chat-events.d.ts +16 -3
- package/sidecar/dist/server/chat-events.js.map +1 -1
- package/sidecar/dist/server/chat-socket-registry.d.ts +6 -6
- package/sidecar/dist/server/chat-socket-registry.js.map +1 -1
- package/sidecar/dist/server/conversation-runs.d.ts +1 -1
- package/sidecar/dist/server/conversation-runs.js +4 -5
- package/sidecar/dist/server/conversation-runs.js.map +1 -1
- package/sidecar/dist/server/host-socket-registry.d.ts +4 -3
- package/sidecar/dist/server/host-socket-registry.js.map +1 -1
- package/sidecar/dist/server/http-io.d.ts +3 -2
- package/sidecar/dist/server/http-io.js +2 -3
- package/sidecar/dist/server/http-io.js.map +1 -1
- package/sidecar/dist/server/http-params.js.map +1 -1
- package/sidecar/dist/server/http-routes.d.ts +9 -2
- package/sidecar/dist/server/http-routes.js +19 -15
- package/sidecar/dist/server/http-routes.js.map +1 -1
- package/sidecar/dist/server/http.js +19 -10
- package/sidecar/dist/server/http.js.map +1 -1
- package/sidecar/dist/server/pending-queue.js +4 -1
- package/sidecar/dist/server/pending-queue.js.map +1 -1
- package/sidecar/dist/server/permission-events.d.ts +8 -4
- package/sidecar/dist/server/permission-events.js.map +1 -1
- package/sidecar/dist/server/raw-data.js +2 -1
- package/sidecar/dist/server/raw-data.js.map +1 -1
- package/sidecar/dist/server/routing.js +5 -2
- package/sidecar/dist/server/routing.js.map +1 -1
- package/sidecar/dist/server/safety-net.js +20 -9
- package/sidecar/dist/server/safety-net.js.map +1 -1
- package/sidecar/dist/server/tool-calls.d.ts +13 -4
- package/sidecar/dist/server/tool-calls.js +7 -5
- package/sidecar/dist/server/tool-calls.js.map +1 -1
- package/sidecar/dist/server/turns.d.ts +16 -2
- package/sidecar/dist/server/turns.js +7 -4
- package/sidecar/dist/server/turns.js.map +1 -1
- package/sidecar/dist/server/ws.js +2 -6
- package/sidecar/dist/server/ws.js.map +1 -1
- package/sidecar/dist/skills/build-catalog.js.map +1 -1
- package/sidecar/dist/skills/frontmatter.js.map +1 -1
- package/sidecar/dist/skills/plugin-wrapper.js.map +1 -1
- package/sidecar/dist/skills/resolve-sources.js.map +1 -1
- package/sidecar/dist/skills/skill-usage.js +18 -12
- package/sidecar/dist/skills/skill-usage.js.map +1 -1
- package/sidecar/dist/state/change-sets.js +4 -1
- package/sidecar/dist/state/change-sets.js.map +1 -1
- package/sidecar/dist/state/conversations.js.map +1 -1
- package/sidecar/dist/state/lock.js +6 -2
- package/sidecar/dist/state/lock.js.map +1 -1
- package/sidecar/dist/state/settings-store.d.ts +31 -1
- package/sidecar/dist/state/settings-store.js +23 -24
- package/sidecar/dist/state/settings-store.js.map +1 -1
- package/sidecar/dist/state/settings-types.js.map +1 -1
- package/sidecar/dist/state/sidecar-version.js +3 -1
- package/sidecar/dist/state/sidecar-version.js.map +1 -1
- package/sidecar/dist/state/store.js +9 -3
- package/sidecar/dist/state/store.js.map +1 -1
- package/sidecar/dist/state/types.js.map +1 -1
- package/sidecar/package.json +1 -7
- package/skills/dms-ai/SKILL.md +1 -1
- package/skills/dms-ai/cases.json +47 -0
- package/skills/dms-ai-code-mode/cases.json +38 -0
- package/skills/dms-builder-safe/cases.json +67 -0
- package/skills/dms-external-database/REFERENCE.md +34 -9
- package/skills/dms-external-database/SKILL.md +24 -11
- package/skills/dms-external-database/cases.json +47 -0
- package/frontend-vue/tests/i18n-panel.test.ts +0 -118
- package/frontend-vue/tests/i18n-views.test.ts +0 -63
- package/frontend-vue/tests/panel-header-height.test.ts +0 -40
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useChatI18n } from "../composables/useChatI18n";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
agentName: string;
|
|
6
|
+
/** Why the provider cannot run, as the sidecar reported it. */
|
|
7
|
+
reason: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Emits {
|
|
11
|
+
openSettings: [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
defineProps<Props>();
|
|
15
|
+
const emit = defineEmits<Emits>();
|
|
16
|
+
const { t } = useChatI18n();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<div class="chat-view-provider">
|
|
21
|
+
<div class="cb-provider" role="alert">
|
|
22
|
+
<UIcon name="i-ph-key" class="cb-provider__icon" />
|
|
23
|
+
<div>
|
|
24
|
+
<b>
|
|
25
|
+
{{ t("dms_ai.panel.errors.agent_cant_run", { agent: agentName }) }}
|
|
26
|
+
</b>
|
|
27
|
+
{{ reason }}
|
|
28
|
+
{{ t("dms_ai.panel.errors.agent_no_fallback") }}
|
|
29
|
+
<div class="cb-provider__row">
|
|
30
|
+
<UButton
|
|
31
|
+
size="xs"
|
|
32
|
+
color="neutral"
|
|
33
|
+
variant="outline"
|
|
34
|
+
icon="i-ph-gear-six"
|
|
35
|
+
:label="t('dms_ai.panel.errors.open_settings')"
|
|
36
|
+
@click="emit('openSettings')"
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<style scoped>
|
|
45
|
+
.chat-view-provider {
|
|
46
|
+
padding: 0 14px 16px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.cb-provider {
|
|
50
|
+
display: flex;
|
|
51
|
+
gap: 10px;
|
|
52
|
+
padding: 10px 12px;
|
|
53
|
+
border: 1px solid var(--dms-error-line);
|
|
54
|
+
border-radius: var(--ai-radius-md);
|
|
55
|
+
background: var(--dms-error-tint);
|
|
56
|
+
font-size: 12.5px;
|
|
57
|
+
line-height: 1.5;
|
|
58
|
+
color: var(--ui-text-toned);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.cb-provider__icon {
|
|
62
|
+
width: 16px;
|
|
63
|
+
height: 16px;
|
|
64
|
+
flex: none;
|
|
65
|
+
margin-top: 1px;
|
|
66
|
+
color: var(--ui-error);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.cb-provider b {
|
|
70
|
+
font-weight: 600;
|
|
71
|
+
color: var(--ui-text-highlighted);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.cb-provider__row {
|
|
75
|
+
margin-top: 8px;
|
|
76
|
+
}
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PendingUndo } from "../composables/useChangeSetActions";
|
|
3
|
+
import { useChatI18n } from "../composables/useChatI18n";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
/** The undo waiting on the user; the modal is open while there is one. */
|
|
7
|
+
pending: PendingUndo | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Emits {
|
|
11
|
+
confirm: [includeLater: boolean];
|
|
12
|
+
cancel: [];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
defineProps<Props>();
|
|
16
|
+
const emit = defineEmits<Emits>();
|
|
17
|
+
const { t } = useChatI18n();
|
|
18
|
+
|
|
19
|
+
function onOpenChange(isOpen: boolean): void {
|
|
20
|
+
if (!isOpen) emit("cancel");
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<UModal
|
|
26
|
+
:open="pending !== null"
|
|
27
|
+
:title="t('dms_ai.panel.change.conflict_title')"
|
|
28
|
+
@update:open="onOpenChange"
|
|
29
|
+
>
|
|
30
|
+
<template #body>
|
|
31
|
+
<p class="chat-view-conflict">
|
|
32
|
+
{{
|
|
33
|
+
t("dms_ai.panel.change.conflict_text", {
|
|
34
|
+
number: pending?.number ?? 0,
|
|
35
|
+
})
|
|
36
|
+
}}
|
|
37
|
+
</p>
|
|
38
|
+
<ul class="chat-view-conflicts">
|
|
39
|
+
<li
|
|
40
|
+
v-for="conflict in pending?.conflicts ?? []"
|
|
41
|
+
:key="conflict.changeSetId"
|
|
42
|
+
>
|
|
43
|
+
<b>#{{ conflict.number }}</b>
|
|
44
|
+
{{ conflict.title }}
|
|
45
|
+
<span>{{ conflict.files.join(", ") }}</span>
|
|
46
|
+
</li>
|
|
47
|
+
</ul>
|
|
48
|
+
</template>
|
|
49
|
+
<template #footer>
|
|
50
|
+
<div class="chat-view-conflict-foot">
|
|
51
|
+
<UButton
|
|
52
|
+
color="neutral"
|
|
53
|
+
variant="ghost"
|
|
54
|
+
:label="t('dms_ai.panel.change.undo_only')"
|
|
55
|
+
@click="emit('confirm', false)"
|
|
56
|
+
/>
|
|
57
|
+
<UButton
|
|
58
|
+
color="secondary"
|
|
59
|
+
:label="t('dms_ai.panel.change.undo_together')"
|
|
60
|
+
@click="emit('confirm', true)"
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
</UModal>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<style scoped>
|
|
68
|
+
.chat-view-conflict {
|
|
69
|
+
margin: 0 0 10px;
|
|
70
|
+
font-size: 13px;
|
|
71
|
+
line-height: 1.5;
|
|
72
|
+
color: var(--ui-text-muted);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.chat-view-conflicts {
|
|
76
|
+
display: grid;
|
|
77
|
+
gap: 6px;
|
|
78
|
+
margin: 0;
|
|
79
|
+
padding: 0;
|
|
80
|
+
list-style: none;
|
|
81
|
+
font-size: 12.5px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.chat-view-conflicts span {
|
|
85
|
+
display: block;
|
|
86
|
+
font-family: var(--ai-font-mono, ui-monospace, monospace);
|
|
87
|
+
font-size: 11px;
|
|
88
|
+
color: var(--ui-text-muted);
|
|
89
|
+
overflow-wrap: anywhere;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.chat-view-conflict-foot {
|
|
93
|
+
display: flex;
|
|
94
|
+
justify-content: flex-end;
|
|
95
|
+
gap: 8px;
|
|
96
|
+
width: 100%;
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type { Tone } from "#dms-
|
|
2
|
+
import type { Tone } from "#dms-core/app/types/tone";
|
|
3
3
|
import { computed } from "vue";
|
|
4
4
|
import { renderDocument } from "../chat/utils/markdown";
|
|
5
5
|
import { useAssistant } from "../views/composables/useAssistant";
|
|
@@ -26,6 +26,10 @@ import {
|
|
|
26
26
|
paletteAssistant,
|
|
27
27
|
paletteSource,
|
|
28
28
|
} from "../runtime/assistant-commands";
|
|
29
|
+
import {
|
|
30
|
+
ASSISTANT_ACTIONS_KEY,
|
|
31
|
+
publicAssistantActions,
|
|
32
|
+
} from "../runtime/assistant-actions";
|
|
29
33
|
import { installAssistantNotifications } from "../runtime/assistant-notifications";
|
|
30
34
|
import {
|
|
31
35
|
ASSISTANT_SESSION_KEY,
|
|
@@ -264,8 +268,8 @@ function createSession(parts: SessionParts): AssistantSession {
|
|
|
264
268
|
intents.push({ kind: "open", conversationId });
|
|
265
269
|
panel.open();
|
|
266
270
|
},
|
|
267
|
-
startConversation: (prompt) => {
|
|
268
|
-
intents.push({ kind: "start", prompt });
|
|
271
|
+
startConversation: (prompt, mode) => {
|
|
272
|
+
intents.push({ kind: "start", prompt, mode });
|
|
269
273
|
panel.open();
|
|
270
274
|
},
|
|
271
275
|
holdStream: parts.holds.hold,
|
|
@@ -502,6 +506,10 @@ export default defineDmsPlugin((context) => {
|
|
|
502
506
|
i18n: createChatI18n(context.$i18n),
|
|
503
507
|
};
|
|
504
508
|
context.vueApp.provide(ASSISTANT_SESSION_KEY, provided.session);
|
|
509
|
+
context.vueApp.provide(
|
|
510
|
+
ASSISTANT_ACTIONS_KEY,
|
|
511
|
+
publicAssistantActions(provided.session),
|
|
512
|
+
);
|
|
505
513
|
context.vueApp.provide(CHAT_I18N_KEY, provided.i18n);
|
|
506
514
|
const appMounted = new Promise<void>((resolve) =>
|
|
507
515
|
context.hook("app:mounted", resolve),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AssistantSessionRef,
|
|
3
|
+
ConversationStartMode,
|
|
4
|
+
} from "./assistant-session";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The assistant as another module's layer may use it, without depending on dms-ai: injected under
|
|
8
|
+
* {@link ASSISTANT_ACTIONS_KEY} with a `null` default, which is what a project without dms-ai, or
|
|
9
|
+
* outside development, answers.
|
|
10
|
+
*/
|
|
11
|
+
export interface PublicAssistantActions {
|
|
12
|
+
/** The assistant runs in this tab, so a button that starts a conversation can be offered. Reactive. */
|
|
13
|
+
readonly isAvailable: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Opens the assistant panel on a new conversation with `prompt` in the composer, unsent. With
|
|
16
|
+
* `mode`, the conversation is set to it first: `plan` makes the agent end with a plan to approve.
|
|
17
|
+
*/
|
|
18
|
+
startConversation: (
|
|
19
|
+
prompt: string,
|
|
20
|
+
options?: { mode?: ConversationStartMode },
|
|
21
|
+
) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The global key of {@link PublicAssistantActions}: `Symbol.for` resolves to the same symbol in
|
|
26
|
+
* every layer, so another module's layer injects it without importing dms-ai.
|
|
27
|
+
*/
|
|
28
|
+
export const ASSISTANT_ACTIONS_KEY = Symbol.for("dms-ai:assistant-actions");
|
|
29
|
+
|
|
30
|
+
/** The public actions over the tab's assistant session, which may not run yet, or ever. */
|
|
31
|
+
export function publicAssistantActions(
|
|
32
|
+
session: AssistantSessionRef,
|
|
33
|
+
): PublicAssistantActions {
|
|
34
|
+
return {
|
|
35
|
+
get isAvailable() {
|
|
36
|
+
return session.value !== null;
|
|
37
|
+
},
|
|
38
|
+
startConversation: (prompt, options) =>
|
|
39
|
+
session.value?.startConversation(prompt, options?.mode),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -17,6 +17,9 @@ export interface ChatPanelState {
|
|
|
17
17
|
toggle: () => void;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** The approval modes a conversation can be started in from outside the panel. */
|
|
21
|
+
export type ConversationStartMode = "plan" | "normal";
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* The tab's assistant, as the plugin that owns it hands it to the panel, the
|
|
22
25
|
* command palette's answer and the workspace pages: the sidecar's
|
|
@@ -31,8 +34,11 @@ export interface AssistantSession {
|
|
|
31
34
|
navigate: (path: string) => void;
|
|
32
35
|
/** Opens the panel on that conversation. */
|
|
33
36
|
openConversation: (conversationId: string) => void;
|
|
34
|
-
/**
|
|
35
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Opens the panel on a new conversation, the composer optionally prefilled, and the
|
|
39
|
+
* conversation set to `mode` first when one is given.
|
|
40
|
+
*/
|
|
41
|
+
startConversation: (prompt?: string, mode?: ConversationStartMode) => void;
|
|
36
42
|
/**
|
|
37
43
|
* Keeps the tab's stream open while the panel is closed, until the returned
|
|
38
44
|
* function releases it: the command palette's answer streams through it.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Ref, ref } from "vue";
|
|
2
|
+
import type { ConversationStartMode } from "./assistant-session";
|
|
2
3
|
|
|
3
4
|
/** Opens the panel on a stored conversation. */
|
|
4
5
|
interface OpenConversationIntent {
|
|
@@ -6,10 +7,11 @@ interface OpenConversationIntent {
|
|
|
6
7
|
conversationId: string;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
/** Opens the panel on a new conversation, the composer optionally prefilled. */
|
|
10
|
+
/** Opens the panel on a new conversation, the composer optionally prefilled, in `mode` when given. */
|
|
10
11
|
interface StartConversationIntent {
|
|
11
12
|
kind: "start";
|
|
12
13
|
prompt?: string;
|
|
14
|
+
mode?: ConversationStartMode;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/** Puts the caret in the composer of the current conversation. */
|
|
@@ -7,7 +7,7 @@ import { useAssistant } from "./composables/useAssistant";
|
|
|
7
7
|
import { useChangeSetActions } from "./composables/useChangeSetActions";
|
|
8
8
|
import { useViewFormat } from "./composables/useViewFormat";
|
|
9
9
|
import { AI_ROUTES } from "./constants";
|
|
10
|
-
import type { Tone } from "#dms-
|
|
10
|
+
import type { Tone } from "#dms-core/app/types/tone";
|
|
11
11
|
import type {
|
|
12
12
|
ChangeSetDetail,
|
|
13
13
|
ChangeSetSummary,
|
|
@@ -40,16 +40,10 @@ interface FetchErrorResponse {
|
|
|
40
40
|
status?: number;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
interface FetchErrorBody {
|
|
44
|
-
message?: unknown;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
43
|
interface FetchErrorLike {
|
|
48
44
|
status?: number;
|
|
49
45
|
statusCode?: number;
|
|
50
46
|
response?: FetchErrorResponse;
|
|
51
|
-
data?: FetchErrorBody;
|
|
52
|
-
message?: string;
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
/** The HTTP status of a `$authFetch` rejection, if it got an answer. */
|
|
@@ -60,14 +54,6 @@ function errorStatus(error: unknown): number | undefined {
|
|
|
60
54
|
);
|
|
61
55
|
}
|
|
62
56
|
|
|
63
|
-
/** The server's `{ message }`, else the error's own text. */
|
|
64
|
-
export function errorMessage(error: unknown): string {
|
|
65
|
-
const candidate = error as FetchErrorLike | null;
|
|
66
|
-
const serverMessage = candidate?.data?.message;
|
|
67
|
-
if (typeof serverMessage === "string") return serverMessage;
|
|
68
|
-
return candidate?.message ?? String(error);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
57
|
export function classifyFailure(error: unknown): RequestFailure {
|
|
72
58
|
return errorStatus(error) === HTTP_SERVICE_UNAVAILABLE
|
|
73
59
|
? "unavailable"
|
|
@@ -80,15 +66,21 @@ export function classifyFailure(error: unknown): RequestFailure {
|
|
|
80
66
|
* whether the assistant isn't running (503) rather than an error.
|
|
81
67
|
*/
|
|
82
68
|
function describeFailure(result: FailingRead): FailureDescription {
|
|
69
|
+
const { resolveError } = useApiErrorPresenter();
|
|
70
|
+
const notice = computed(() =>
|
|
71
|
+
result.error.value
|
|
72
|
+
? resolveError(result.error.value, {
|
|
73
|
+
fallbackKey: `dms_ai.views.${classifyFailure(result.error.value)}.description`,
|
|
74
|
+
})
|
|
75
|
+
: null,
|
|
76
|
+
);
|
|
83
77
|
return {
|
|
84
78
|
failure: computed(() =>
|
|
85
|
-
|
|
79
|
+
notice.value && result.status.value !== "pending"
|
|
86
80
|
? classifyFailure(result.error.value)
|
|
87
81
|
: null,
|
|
88
82
|
),
|
|
89
|
-
message: computed(() =>
|
|
90
|
-
result.error.value ? errorMessage(result.error.value) : "",
|
|
91
|
-
),
|
|
83
|
+
message: computed(() => notice.value?.message ?? ""),
|
|
92
84
|
};
|
|
93
85
|
}
|
|
94
86
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ref, type Ref } from "vue";
|
|
2
2
|
import { AI_ROUTES } from "../constants";
|
|
3
3
|
import type { ChangeSetSummary } from "../types";
|
|
4
|
-
import { classifyFailure
|
|
4
|
+
import { classifyFailure } from "./useAiData";
|
|
5
5
|
|
|
6
6
|
export interface ChangeSetActions {
|
|
7
7
|
isBusy: Ref<boolean>;
|
|
@@ -28,23 +28,11 @@ function changeSetPath(changeSetId: string, action: string): string {
|
|
|
28
28
|
export function useChangeSetActions(): ChangeSetActions {
|
|
29
29
|
const { t } = useI18n();
|
|
30
30
|
const toast = useToast();
|
|
31
|
+
const { presentError } = useApiErrorPresenter();
|
|
31
32
|
const { $authFetch } = useAuthFetch();
|
|
32
33
|
const { confirmFrom } = useConfirmFrom();
|
|
33
34
|
const isBusy = ref(false);
|
|
34
35
|
|
|
35
|
-
function failureToast(error: unknown): void {
|
|
36
|
-
const failure = classifyFailure(error);
|
|
37
|
-
toast.add({
|
|
38
|
-
title: t(`dms_ai.views.${failure}.title`),
|
|
39
|
-
description:
|
|
40
|
-
failure === "error"
|
|
41
|
-
? errorMessage(error)
|
|
42
|
-
: t("dms_ai.views.unavailable.description"),
|
|
43
|
-
color: "error",
|
|
44
|
-
icon: "i-ph-warning-circle",
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
36
|
async function redo(changeSet: ChangeSetSummary): Promise<void> {
|
|
49
37
|
isBusy.value = true;
|
|
50
38
|
try {
|
|
@@ -59,7 +47,9 @@ export function useChangeSetActions(): ChangeSetActions {
|
|
|
59
47
|
});
|
|
60
48
|
await refreshPageBlocks();
|
|
61
49
|
} catch (error) {
|
|
62
|
-
|
|
50
|
+
presentError(error, {
|
|
51
|
+
fallbackKey: `dms_ai.views.${classifyFailure(error)}.description`,
|
|
52
|
+
});
|
|
63
53
|
} finally {
|
|
64
54
|
isBusy.value = false;
|
|
65
55
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
3
|
+
import type { DmsVitePluginEntry } from "#dms/frontend-build";
|
|
4
|
+
|
|
5
|
+
type VitePlugin = Extract<DmsVitePluginEntry, { name: string }>;
|
|
6
|
+
|
|
7
|
+
const BACKEND_PACKAGE = "@antelopejs/dms-ai";
|
|
8
|
+
const BACKEND_SOURCE = "src";
|
|
9
|
+
const QUERY_OR_HASH = /[?#].*$/;
|
|
10
|
+
|
|
11
|
+
const backendRoots = new Map<string, string | null>();
|
|
12
|
+
|
|
13
|
+
/** Whether a parsed manifest names its package. */
|
|
14
|
+
function isNamedManifest(value: unknown): value is { name: string } {
|
|
15
|
+
return (
|
|
16
|
+
typeof value === "object" &&
|
|
17
|
+
value !== null &&
|
|
18
|
+
"name" in value &&
|
|
19
|
+
typeof value.name === "string"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The package name a `package.json` declares, or `undefined`. */
|
|
24
|
+
function packageName(manifest: string): string | undefined {
|
|
25
|
+
try {
|
|
26
|
+
const parsed: unknown = JSON.parse(readFileSync(manifest, "utf8"));
|
|
27
|
+
return isNamedManifest(parsed) ? parsed.name : undefined;
|
|
28
|
+
} catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The directory of the backend package that holds `directory`, or null. */
|
|
34
|
+
function backendRoot(directory: string): string | null {
|
|
35
|
+
const known = backendRoots.get(directory);
|
|
36
|
+
if (known !== undefined) {
|
|
37
|
+
return known;
|
|
38
|
+
}
|
|
39
|
+
const manifest = join(directory, "package.json");
|
|
40
|
+
const parent = dirname(directory);
|
|
41
|
+
let root: string | null = null;
|
|
42
|
+
if (existsSync(manifest)) {
|
|
43
|
+
root = packageName(manifest) === BACKEND_PACKAGE ? directory : null;
|
|
44
|
+
} else if (parent !== directory) {
|
|
45
|
+
root = backendRoot(parent);
|
|
46
|
+
}
|
|
47
|
+
backendRoots.set(directory, root);
|
|
48
|
+
return root;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The real path of a resolved module id when it lies under the `src`
|
|
53
|
+
* directory of the backend package, or `undefined`. The package that owns the
|
|
54
|
+
* file decides, not a path, so the answer is the same in the repository and in
|
|
55
|
+
* the build workspace. Virtual ids and ids that are not files are ignored.
|
|
56
|
+
*/
|
|
57
|
+
function backendSourceFile(id: string): string | undefined {
|
|
58
|
+
const path = id.replace(QUERY_OR_HASH, "");
|
|
59
|
+
if (!isAbsolute(path)) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
let real: string;
|
|
63
|
+
try {
|
|
64
|
+
real = realpathSync(path);
|
|
65
|
+
} catch {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const root = backendRoot(dirname(real));
|
|
69
|
+
if (root === null) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
return relative(root, real).split(sep)[0] === BACKEND_SOURCE
|
|
73
|
+
? real
|
|
74
|
+
: undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Fails the build and the dev server when a module of the frontend resolves to
|
|
79
|
+
* a file under the `src` of the backend package: the browser reaches the
|
|
80
|
+
* backend only through its HTTP interface. It checks what the whole resolution
|
|
81
|
+
* chain returns, an id marked external included, so an alias is seen through
|
|
82
|
+
* and a symlink the resolver returns is followed to its real path, and it runs
|
|
83
|
+
* before the other plugins (`enforce: "pre"`). Vite builds workers with their
|
|
84
|
+
* own plugin list, so the plugin adds itself there too.
|
|
85
|
+
*
|
|
86
|
+
* antelopejs-sync writes this file from `@antelopejs/tooling-configs` and
|
|
87
|
+
* restores it on every run: change the plugin in the pack, not here.
|
|
88
|
+
*/
|
|
89
|
+
export function backendBoundary(): VitePlugin {
|
|
90
|
+
return {
|
|
91
|
+
...boundaryCheck(),
|
|
92
|
+
config: () => ({ worker: { plugins: () => [boundaryCheck()] } }),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The check alone, as a worker build runs it. */
|
|
97
|
+
function boundaryCheck(): VitePlugin {
|
|
98
|
+
return {
|
|
99
|
+
name: `${BACKEND_PACKAGE}:backend-boundary`,
|
|
100
|
+
enforce: "pre",
|
|
101
|
+
async resolveId(source, importer, options) {
|
|
102
|
+
const resolved = await this.resolve(source, importer, {
|
|
103
|
+
...options,
|
|
104
|
+
skipSelf: true,
|
|
105
|
+
});
|
|
106
|
+
if (resolved === null) {
|
|
107
|
+
return resolved;
|
|
108
|
+
}
|
|
109
|
+
const file = backendSourceFile(resolved.id);
|
|
110
|
+
if (file === undefined) {
|
|
111
|
+
return resolved;
|
|
112
|
+
}
|
|
113
|
+
const from =
|
|
114
|
+
importer === undefined
|
|
115
|
+
? "an entry point"
|
|
116
|
+
: importer.replace(QUERY_OR_HASH, "");
|
|
117
|
+
return this.error(
|
|
118
|
+
`Backend boundary: ${from} imports ${file}, which is under the src of ${BACKEND_PACKAGE}. The frontend reaches the backend only through its HTTP interface.`,
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"packageManager": "pnpm@10.6.5",
|
|
8
8
|
"engines": {
|
|
9
|
-
"@antelopejs/dms-frontend": ">=0.9.
|
|
9
|
+
"@antelopejs/dms-frontend": ">=0.9.1 <0.10.0"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "pnpm --dir \"${DMS_FRONTEND_WORKSPACE:?Set DMS_FRONTEND_WORKSPACE to the generated Inertia workspace}\" build",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
38
38
|
"typescript": "^5.8.2",
|
|
39
39
|
"typescript-eslint": "^8.0.0",
|
|
40
|
+
"vite": "^7.3.2",
|
|
40
41
|
"vitest": "^4.1.5",
|
|
41
42
|
"vue-tsc": "^3.1.1"
|
|
42
43
|
}
|
|
@@ -60,6 +60,9 @@ importers:
|
|
|
60
60
|
typescript-eslint:
|
|
61
61
|
specifier: ^8.0.0
|
|
62
62
|
version: 8.70.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)
|
|
63
|
+
vite:
|
|
64
|
+
specifier: ^7.3.2
|
|
65
|
+
version: 7.3.2(jiti@2.7.0)(terser@5.46.2)(yaml@2.8.4)
|
|
63
66
|
vitest:
|
|
64
67
|
specifier: ^4.1.5
|
|
65
68
|
version: 4.1.5(jsdom@29.1.1)(vite@7.3.2(jiti@2.7.0)(terser@5.46.2)(yaml@2.8.4))
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { flushPromises } from "@vue/test-utils";
|
|
3
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { shallowRef } from "vue";
|
|
5
|
+
import { publicAssistantActions } from "../app/runtime/assistant-actions";
|
|
6
|
+
import {
|
|
7
|
+
createHarness,
|
|
8
|
+
openPanel,
|
|
9
|
+
sentOfType,
|
|
10
|
+
unmountPanel,
|
|
11
|
+
} from "./support/panel-harness";
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
unmountPanel();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const PROMPT =
|
|
18
|
+
"Use dms-external-database on connection roaster, module builder-db-roaster-tables.";
|
|
19
|
+
|
|
20
|
+
describe("the assistant actions another module's layer injects", () => {
|
|
21
|
+
it("start a new conversation with the composer prefilled and nothing sent", async () => {
|
|
22
|
+
const harness = createHarness();
|
|
23
|
+
const panel = await openPanel(harness);
|
|
24
|
+
const actions = publicAssistantActions(shallowRef(harness.session));
|
|
25
|
+
expect(actions.isAvailable).toBe(true);
|
|
26
|
+
actions.startConversation(PROMPT);
|
|
27
|
+
await flushPromises();
|
|
28
|
+
expect((panel.find("textarea").element as HTMLTextAreaElement).value).toBe(
|
|
29
|
+
PROMPT,
|
|
30
|
+
);
|
|
31
|
+
expect(sentOfType(harness, "user_message")).toEqual([]);
|
|
32
|
+
expect(sentOfType(harness, "set_conversation_mode")).toEqual([]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("set the new conversation to plan mode before prefilling it, when asked", async () => {
|
|
36
|
+
const harness = createHarness();
|
|
37
|
+
const panel = await openPanel(harness);
|
|
38
|
+
const actions = publicAssistantActions(shallowRef(harness.session));
|
|
39
|
+
actions.startConversation(PROMPT, { mode: "plan" });
|
|
40
|
+
await flushPromises();
|
|
41
|
+
const started = sentOfType(harness, "hello").at(-1)?.conversationId;
|
|
42
|
+
expect(sentOfType(harness, "set_conversation_mode")).toEqual([
|
|
43
|
+
expect.objectContaining({ conversationId: started, mode: "plan" }),
|
|
44
|
+
]);
|
|
45
|
+
expect((panel.find("textarea").element as HTMLTextAreaElement).value).toBe(
|
|
46
|
+
PROMPT,
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("set plan mode once the stream is up, when the panel opens before it", async () => {
|
|
51
|
+
const harness = createHarness();
|
|
52
|
+
await openPanel(harness);
|
|
53
|
+
harness.setChannelStatus("disconnected");
|
|
54
|
+
publicAssistantActions(shallowRef(harness.session)).startConversation(
|
|
55
|
+
PROMPT,
|
|
56
|
+
{ mode: "plan" },
|
|
57
|
+
);
|
|
58
|
+
await flushPromises();
|
|
59
|
+
expect(sentOfType(harness, "set_conversation_mode")).toEqual([]);
|
|
60
|
+
harness.setChannelStatus("connected");
|
|
61
|
+
await flushPromises();
|
|
62
|
+
expect(sentOfType(harness, "set_conversation_mode")).toEqual([
|
|
63
|
+
expect.objectContaining({ mode: "plan" }),
|
|
64
|
+
]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("are unavailable without a session, and starting then does nothing", () => {
|
|
68
|
+
const actions = publicAssistantActions(shallowRef(null));
|
|
69
|
+
expect(actions.isAvailable).toBe(false);
|
|
70
|
+
expect(() => actions.startConversation(PROMPT)).not.toThrow();
|
|
71
|
+
});
|
|
72
|
+
});
|