@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,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "ai-install-codex",
|
|
6
|
+
"area": "dms-ai",
|
|
7
|
+
"style": "clean",
|
|
8
|
+
"prompt": "Install dms-ai and make it use Codex instead of Claude Code.",
|
|
9
|
+
"expect": {
|
|
10
|
+
"skills": ["dms-ai"],
|
|
11
|
+
"acceptable": ["dms", "dms-project"]
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "ai-offline-casual",
|
|
16
|
+
"area": "dms-ai",
|
|
17
|
+
"style": "casual",
|
|
18
|
+
"prompt": "the ai assistant says offline",
|
|
19
|
+
"expect": {
|
|
20
|
+
"skills": ["dms-ai"],
|
|
21
|
+
"acceptable": ["dms", "dms-project"]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "dms-ai-disable-sidecar",
|
|
26
|
+
"area": "dms-ai",
|
|
27
|
+
"style": "clean",
|
|
28
|
+
"prompt": "How do I start the DMS backend without the dms-ai sidecar process, for example in a CI job?",
|
|
29
|
+
"expect": {
|
|
30
|
+
"skills": ["dms-ai"],
|
|
31
|
+
"acceptable": ["dms", "dms-project"],
|
|
32
|
+
"mustMention": ["DMS_AI"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "dms-ai-not-builder-editor",
|
|
37
|
+
"area": "dms-ai",
|
|
38
|
+
"style": "clean",
|
|
39
|
+
"prompt": "The Edit this page editor never opens and Ctrl+B does nothing. How do I set the projectRoot of the builder module?",
|
|
40
|
+
"expect": {
|
|
41
|
+
"skills": ["dms-builder"],
|
|
42
|
+
"acceptable": ["dms"],
|
|
43
|
+
"avoid": ["dms-ai"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "dms-ai-code-mode-edit-loop",
|
|
6
|
+
"area": "dms-ai",
|
|
7
|
+
"style": "clean",
|
|
8
|
+
"prompt": "The assistant is in Code mode and I want it to change the orders page and the two other pages that reuse the same custom block. How should it work so I can watch each page update in the dashboard?",
|
|
9
|
+
"expect": {
|
|
10
|
+
"skills": ["dms-ai-code-mode"],
|
|
11
|
+
"acceptable": ["dms-ai", "dms-pages", "dms-best-practices"],
|
|
12
|
+
"mustMention": ["FindPagesUsing", "NavigateToPage", "Typecheck"]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "dms-ai-code-mode-page-404-casual",
|
|
17
|
+
"area": "dms-ai",
|
|
18
|
+
"style": "casual",
|
|
19
|
+
"prompt": "ai edited my page in code mode and now it 404s, how do i see why",
|
|
20
|
+
"expect": {
|
|
21
|
+
"skills": ["dms-ai-code-mode"],
|
|
22
|
+
"acceptable": ["dms-ai", "dms-pages", "dms"],
|
|
23
|
+
"mustMention": ["QueryLogs"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "dms-ai-code-mode-not-safe-builder",
|
|
28
|
+
"area": "dms-ai",
|
|
29
|
+
"style": "clean",
|
|
30
|
+
"prompt": "We are in safe mode. Create a Reports page under the pages.reports category with BuilderCreatePage, then add a TableView on the orders resource.",
|
|
31
|
+
"expect": {
|
|
32
|
+
"skills": ["dms-builder-safe"],
|
|
33
|
+
"acceptable": ["dms-pages", "dms-best-practices"],
|
|
34
|
+
"avoid": ["dms-ai-code-mode"]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "ai-builder-add-chart",
|
|
6
|
+
"area": "dms-ai",
|
|
7
|
+
"style": "clean",
|
|
8
|
+
"prompt": "Using the Builder tools, add a revenue chart to the sales page.",
|
|
9
|
+
"expect": {
|
|
10
|
+
"skills": ["dms-builder-safe"],
|
|
11
|
+
"acceptable": [
|
|
12
|
+
"dms-pages",
|
|
13
|
+
"dms-best-practices",
|
|
14
|
+
"dms-builder-page",
|
|
15
|
+
"dms-builder"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "dms-builder-safe-table-casual",
|
|
21
|
+
"area": "dms-ai",
|
|
22
|
+
"style": "casual",
|
|
23
|
+
"prompt": "add a table of the books to the catalog page, safe mode",
|
|
24
|
+
"expect": {
|
|
25
|
+
"skills": ["dms-builder-safe"],
|
|
26
|
+
"acceptable": ["dms-pages", "dms-builder", "dms-best-practices"]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "dms-builder-safe-kpi-query",
|
|
31
|
+
"area": "dms-ai",
|
|
32
|
+
"style": "clean",
|
|
33
|
+
"prompt": "In safe mode, add a KpiCard to the /sales/overview page that shows the total number of orders. Which Builder tools do I call, in what order?",
|
|
34
|
+
"expect": {
|
|
35
|
+
"skills": ["dms-builder-safe"],
|
|
36
|
+
"acceptable": ["dms-pages", "dms-best-practices", "dms-builder"],
|
|
37
|
+
"mustMention": [
|
|
38
|
+
"BuilderQueryTemplates",
|
|
39
|
+
"BuilderAddQuery",
|
|
40
|
+
"BuilderAddBlock"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "dms-builder-safe-opaque-target",
|
|
46
|
+
"area": "dms-ai",
|
|
47
|
+
"style": "clean",
|
|
48
|
+
"prompt": "In safe mode the Builder answered opaque_target when I tried to configure the nested chart of a ChartCard. How should the agent proceed?",
|
|
49
|
+
"expect": {
|
|
50
|
+
"skills": ["dms-builder-safe"],
|
|
51
|
+
"acceptable": ["dms-ai-code-mode", "dms-best-practices", "dms-pages"],
|
|
52
|
+
"mustMention": ["AskUser"]
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "dms-builder-safe-not-code-mode",
|
|
57
|
+
"area": "dms-ai",
|
|
58
|
+
"style": "clean",
|
|
59
|
+
"prompt": "dms-ai is in Code mode. I changed a custom block by hand and want to show the three pages that render it, then check the Typecheck output.",
|
|
60
|
+
"expect": {
|
|
61
|
+
"skills": ["dms-ai-code-mode"],
|
|
62
|
+
"acceptable": ["dms-ai", "dms-pages"],
|
|
63
|
+
"avoid": ["dms-builder-safe"]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
@@ -11,7 +11,7 @@ integrator gave you:
|
|
|
11
11
|
"source": { "type": "package", "package": "@antelopejs/postgres", "version": "<version>" },
|
|
12
12
|
"config": { "mode": "external", "statementTimeoutMs": 30000 },
|
|
13
13
|
"env": { "url": "ERP_DATABASE_URL" } } },
|
|
14
|
-
{ "op": "CreateLocalModule", "id": "erp-tables", "path": "modules/erp-tables", "entry": {
|
|
14
|
+
{ "op": "CreateLocalModule", "id": "erp-tables", "path": "modules/erp-tables", "connection": "erp", "entry": {
|
|
15
15
|
"importOverrides": [{ "interface": "@antelopejs/interface-database", "source": "postgres-erp" }] } },
|
|
16
16
|
{ "op": "ConfigureModule", "id": "mongodb", "entry": {
|
|
17
17
|
"exportPriority": { "@antelopejs/interface-database": 1 } } },
|
|
@@ -22,13 +22,36 @@ integrator gave you:
|
|
|
22
22
|
] }
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
- **Step 1** is the client's database as an external
|
|
26
|
-
variable.
|
|
27
|
-
- **Step 2** is the module the tables are generated into. It is bound to that instance
|
|
25
|
+
- **Step 1** is the client's database as an external instance of its engine's module. Its URL
|
|
26
|
+
comes from the variable.
|
|
27
|
+
- **Step 2** is the module the tables are generated into. It is bound to that instance, and
|
|
28
|
+
`connection` records that it holds the tables of `erp`.
|
|
28
29
|
- **Step 3** keeps the DMS and its modules on the project's own database. Leave it out if the
|
|
29
30
|
project already pins them.
|
|
30
31
|
- **Steps 4 and 5** give the Builder and you the connection `erp`, the same id for both.
|
|
31
32
|
|
|
33
|
+
For MongoDB and RethinkDB, step 1 changes, and the other steps name its id in place of
|
|
34
|
+
`postgres-erp`. The `disabledExports` entry keeps the external instance from ever serving the raw
|
|
35
|
+
client other modules ask for:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{ "op": "AddModule", "id": "mongodb-erp", "entry": {
|
|
39
|
+
"source": { "type": "package", "package": "@antelopejs/mongodb", "version": "<version>" },
|
|
40
|
+
"config": { "mode": "external", "statementTimeoutMs": 30000 },
|
|
41
|
+
"env": { "url": "ERP_DATABASE_URL", "database": "ERP_DATABASE_NAME" },
|
|
42
|
+
"disabledExports": ["@antelopejs/interface-mongodb"] } }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{ "op": "AddModule", "id": "rethinkdb-erp", "entry": {
|
|
47
|
+
"source": { "type": "package", "package": "@antelopejs/rethinkdb", "version": "<version>" },
|
|
48
|
+
"config": { "mode": "external", "statementTimeoutMs": 30000 },
|
|
49
|
+
"env": { "url": "ERP_DATABASE_URL" },
|
|
50
|
+
"disabledExports": ["@antelopejs/interface-rethinkdb"] } }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The RethinkDB URL holds the database as its path: `rethinkdb://user:password@host:28015/erp`.
|
|
54
|
+
|
|
32
55
|
## The proposal
|
|
33
56
|
|
|
34
57
|
`BuilderAnalyseDatabase` answers it once the job is done:
|
|
@@ -53,7 +76,8 @@ integrator gave you:
|
|
|
53
76
|
"open": [
|
|
54
77
|
{ "id": "purpose:legacy.t_cst", "kind": "purpose", "relation": "legacy.t_cst",
|
|
55
78
|
"question": "What does legacy.t_cst hold?", "options": ["…"], "proposed": null,
|
|
56
|
-
"resource": { "relation": "legacy.t_cst", "…": "…" }
|
|
79
|
+
"resource": { "relation": "legacy.t_cst", "…": "…" },
|
|
80
|
+
"open": [ { "id": "reference:legacy.t_cst.c05", "kind": "reference", "…": "…" } ] } ] }
|
|
57
81
|
```
|
|
58
82
|
|
|
59
83
|
The rules, in the order they apply to a relation:
|
|
@@ -64,15 +88,15 @@ The rules, in the order they apply to a relation:
|
|
|
64
88
|
| R4 | a framework's or a migration tool's table | excluded |
|
|
65
89
|
| R3 | no rows | excluded |
|
|
66
90
|
| R2 | no key | stats only |
|
|
67
|
-
| R5 | keyed by its two
|
|
91
|
+
| R5 | keyed by its two references | stats only: a link table |
|
|
68
92
|
| R6 | keyed, with a label candidate | TableView |
|
|
69
93
|
| R7 | keyed, no label, referenced | TableView labelled by its key, and a `label` item |
|
|
70
94
|
| R8 | keyed, no label, not referenced, with a time axis | stats only: events or a log |
|
|
71
95
|
| R9 | anything else | a `purpose` item |
|
|
72
96
|
|
|
73
97
|
For columns: F1 and F2 leave out a column no type reads and one named like a secret, F3 proposes
|
|
74
|
-
the first accepted declaration, F4 makes a
|
|
75
|
-
whole by `CheckReference`. L1 chooses labels, L2 titles, FL the four flags, W1 read-only.
|
|
98
|
+
the first accepted declaration, F4 makes a reference the database declares a relation column
|
|
99
|
+
(PostgreSQL only), F5 one found whole by `CheckReference`. L1 chooses labels, L2 titles, FL the four flags, W1 read-only.
|
|
76
100
|
|
|
77
101
|
## Plan
|
|
78
102
|
|
|
@@ -119,7 +143,8 @@ The proposal's values, without their rules, plus what you changed:
|
|
|
119
143
|
```
|
|
120
144
|
|
|
121
145
|
- `declared` defaults to the column's `accepts[0]`. Set it only to take another accepted
|
|
122
|
-
declaration
|
|
146
|
+
declaration, and always for a column a `field-type` item asked about: give the answer as its
|
|
147
|
+
`declared`.
|
|
123
148
|
- Key columns are added for you.
|
|
124
149
|
- A relation column's target must be in the same call, with a `label`, or mapped in the module
|
|
125
150
|
before.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dms-external-database
|
|
3
|
-
description: Connects a DMS project to a client's existing database, runs the Builder's analysis of it, settles what the analysis could not decide from the catalog and aggregates, generates TableViews through the Builder, and adds stats pages over them. Use when the user wants pages over a database the project does not own ("plug in our client's Postgres", "generate the admin for this database", "finish the mapping the Builder proposed").
|
|
3
|
+
description: Connects a DMS project to a client's existing database, runs the Builder's analysis of it, settles what the analysis could not decide from the catalog and aggregates, generates TableViews through the Builder, and adds stats pages over them. Use when the user wants pages over a database the project does not own, PostgreSQL, MongoDB or RethinkDB ("plug in our client's Postgres", "map their Mongo database", "generate the admin for this database", "finish the mapping the Builder proposed").
|
|
4
4
|
icon: i-ph-database
|
|
5
5
|
category: Builder
|
|
6
6
|
tags: [Database, Builder, Pages, DMS]
|
|
@@ -28,16 +28,21 @@ Call `DatabaseConnections`.
|
|
|
28
28
|
- **A connection is listed** with an `engine`: use its id and go to 2.
|
|
29
29
|
- **An entry answers `error`**: say what it says (an owned instance, the catalog not enabled, a
|
|
30
30
|
role that cannot read) and stop.
|
|
31
|
-
- **Nothing is listed**: the project is not connected yet.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`erp
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
- **Nothing is listed**: the project is not connected yet. Ask the integrator which engine the
|
|
32
|
+
database runs: PostgreSQL, MongoDB or RethinkDB. Propose one `BuilderConfigureProject` call
|
|
33
|
+
with that engine's steps in REFERENCE.md *Connecting*. Pick the names with the integrator, for
|
|
34
|
+
example connection `erp`, provider module `postgres-erp` (`mongodb-erp`, `rethinkdb-erp`),
|
|
35
|
+
generated module `erp-tables`, variable `ERP_DATABASE_URL`, and for MongoDB
|
|
36
|
+
`ERP_DATABASE_NAME`. Ask the integrator for the version of the engine's module to install
|
|
37
|
+
(`@antelopejs/postgres`, `@antelopejs/mongodb`, `@antelopejs/rethinkdb`): you cannot look it
|
|
38
|
+
up. The user approves the diff.
|
|
39
|
+
- Then tell the integrator to put the URL in `.env` (`ERP_DATABASE_URL=postgres://…`,
|
|
40
|
+
`mongodb://…`, or `rethinkdb://…/<database>`; for MongoDB also `ERP_DATABASE_NAME`), or in the
|
|
41
|
+
Builder's *Database* workspace, which writes it there, and to restart the project. Every
|
|
42
|
+
deployed environment needs the same variables, set where that environment keeps its secrets,
|
|
39
43
|
never in git.
|
|
40
|
-
- Recommend
|
|
44
|
+
- Recommend an account that can only read for the analysis: a PostgreSQL role with SELECT, a
|
|
45
|
+
MongoDB user with the built-in `read` role, a RethinkDB user with `read` permission.
|
|
41
46
|
- Stop here: the connection exists only after the restart.
|
|
42
47
|
|
|
43
48
|
The Builder and you each have a connection to the database, under the same id: the Builder for
|
|
@@ -66,16 +71,24 @@ profile of the whole database again: the Builder did it.
|
|
|
66
71
|
- **Open items**, one by one:
|
|
67
72
|
- `purpose`: what a relation holds. Decide from its name, comment, columns and profile:
|
|
68
73
|
entities to list (a TableView), facts to count (stats only), or nothing to show (excluded).
|
|
69
|
-
The item carries the relation as it would be mapped
|
|
74
|
+
The item carries the relation as it would be mapped, and in its own `open` the questions
|
|
75
|
+
that mapping leaves. Answer those only when you map the relation.
|
|
70
76
|
- `label`: which column names a row. Prefer a name or title, then a code or number people
|
|
71
77
|
recognise.
|
|
72
78
|
- `reference`: a column found almost whole in another relation's key. Check it with
|
|
73
79
|
`CheckReference` on the column; make it a relation column only at containment 1.
|
|
80
|
+
- `field-type`: a field of a document database whose sampled values have several types, none
|
|
81
|
+
covering enough of them (`int 60% | string 40%`). Pick the declaration that reads what
|
|
82
|
+
the field means, from its name and its shares, or leave it out. Unanswered, it stays out.
|
|
74
83
|
- Where nothing tells you, say so and leave the item open: the integrator answers it in the
|
|
75
84
|
Builder. Do not guess.
|
|
76
85
|
- **Defaults worth revisiting.** For example a table rule R8 calls a log whose name and comment
|
|
77
86
|
say it holds entities, a label rule L1 chose that a comment contradicts, or a title taken from a
|
|
78
87
|
cryptic name.
|
|
88
|
+
- **Document databases** (MongoDB, RethinkDB) declare no field types and no references: the
|
|
89
|
+
catalog reads types from a sample, and every reference comes from a name and a `CheckReference`,
|
|
90
|
+
never from the database. An embedded document is one field: its subfields are not mappable, and
|
|
91
|
+
neither is an array of ids as a relation.
|
|
79
92
|
- **Editable.** Every TableView is proposed read-only. Make one editable only where the integrator
|
|
80
93
|
wants it; show `writes` beside it, so a read-only role in this environment is visible.
|
|
81
94
|
- **Stats pages,** which the analysis does not make, one per area:
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "dms-external-database-connect-erp",
|
|
6
|
+
"area": "dms-ai",
|
|
7
|
+
"style": "clean",
|
|
8
|
+
"prompt": "Our client already runs a PostgreSQL ERP database. I want admin pages over it in this DMS project without recreating the tables, and nothing is connected yet. How do we begin?",
|
|
9
|
+
"expect": {
|
|
10
|
+
"skills": ["dms-external-database"],
|
|
11
|
+
"acceptable": ["dms", "dms-builder", "dms-builder-safe"],
|
|
12
|
+
"mustMention": ["BuilderConfigureProject"]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "dms-external-database-finish-mapping",
|
|
17
|
+
"area": "dms-ai",
|
|
18
|
+
"style": "clean",
|
|
19
|
+
"prompt": "The Builder analysed the client's database and proposed a mapping with a few open items. Settle them, apply the mapping and add a page with monthly revenue.",
|
|
20
|
+
"expect": {
|
|
21
|
+
"skills": ["dms-external-database"],
|
|
22
|
+
"acceptable": ["dms-builder", "dms-builder-safe"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "dms-external-database-casual",
|
|
27
|
+
"area": "dms-ai",
|
|
28
|
+
"style": "casual",
|
|
29
|
+
"prompt": "need admin screens for the clients old postgres db, dont wanna recreate the tables",
|
|
30
|
+
"expect": {
|
|
31
|
+
"skills": ["dms-external-database"],
|
|
32
|
+
"acceptable": ["dms", "dms-builder", "dms-builder-safe", "dms-database"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "dms-external-database-not-console",
|
|
37
|
+
"area": "dms-ai",
|
|
38
|
+
"style": "clean",
|
|
39
|
+
"prompt": "Show me the schemas that my project's own modules registered as a diagram in the dashboard console.",
|
|
40
|
+
"expect": {
|
|
41
|
+
"skills": ["dms-database"],
|
|
42
|
+
"acceptable": ["dms"],
|
|
43
|
+
"avoid": ["dms-external-database"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
3
|
-
import { describe, expect, it } from "vitest";
|
|
4
|
-
import { TOOL_VERB_KEYS } from "../app/chat/utils/tool-lexicon";
|
|
5
|
-
import en from "../i18n/locales/dms-ai-panel-en-GB.json";
|
|
6
|
-
import fr from "../i18n/locales/dms-ai-panel-fr-FR.json";
|
|
7
|
-
|
|
8
|
-
type Tree = Record<string, unknown>;
|
|
9
|
-
|
|
10
|
-
const ROOT = resolve(__dirname, "..");
|
|
11
|
-
const SOURCES = [
|
|
12
|
-
"app/chat",
|
|
13
|
-
"app/runtime",
|
|
14
|
-
"app/plugins",
|
|
15
|
-
"app/components/ChatPanel.vue",
|
|
16
|
-
];
|
|
17
|
-
const LITERAL_KEY =
|
|
18
|
-
/["'`](dms_ai\.(?:panel|tools|common)\.[A-Za-z0-9_.]+[A-Za-z0-9_])["'`]/g;
|
|
19
|
-
const OWNED_NAMESPACES = ["panel", "tools", "common"];
|
|
20
|
-
|
|
21
|
-
/** Keys built at run time from a value, each with every value it can take. */
|
|
22
|
-
const DYNAMIC_FAMILIES: Record<string, readonly string[]> = {
|
|
23
|
-
"dms_ai.panel.tool.state": [
|
|
24
|
-
"done",
|
|
25
|
-
"running",
|
|
26
|
-
"waiting",
|
|
27
|
-
"denied",
|
|
28
|
-
"blocked",
|
|
29
|
-
"failed",
|
|
30
|
-
"stopped",
|
|
31
|
-
],
|
|
32
|
-
"dms_ai.panel.change.status": ["added", "modified", "deleted"],
|
|
33
|
-
"dms_ai.panel.change.typecheck": ["passed", "failed", "skipped"],
|
|
34
|
-
"dms_ai.common.scope": ["safe", "vibe"],
|
|
35
|
-
"dms_ai.common.agent": ["claude", "codex"],
|
|
36
|
-
"dms_ai.panel.composer.scope_desc": ["safe", "vibe"],
|
|
37
|
-
"dms_ai.panel.full_auto": [
|
|
38
|
-
"duration_turn",
|
|
39
|
-
"duration_30m",
|
|
40
|
-
"duration_chat",
|
|
41
|
-
"banner_turn",
|
|
42
|
-
"banner_30m",
|
|
43
|
-
"banner_chat",
|
|
44
|
-
],
|
|
45
|
-
"dms_ai.panel.drawer": [
|
|
46
|
-
"group_active",
|
|
47
|
-
"group_today",
|
|
48
|
-
"group_week",
|
|
49
|
-
"group_older",
|
|
50
|
-
],
|
|
51
|
-
"dms_ai.panel.empty": ["text_safe", "text_vibe"],
|
|
52
|
-
"dms_ai.panel.approvals": [
|
|
53
|
-
"why_deletes_data",
|
|
54
|
-
"why_removes_code",
|
|
55
|
-
"effect_adds_dependency",
|
|
56
|
-
"effect_removes_dependency",
|
|
57
|
-
],
|
|
58
|
-
"dms_ai.panel.rules": [
|
|
59
|
-
"kind_file",
|
|
60
|
-
"kind_directory",
|
|
61
|
-
"kind_command",
|
|
62
|
-
"kind_domain",
|
|
63
|
-
],
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
function files(path: string): string[] {
|
|
67
|
-
const full = join(ROOT, path);
|
|
68
|
-
if (!statSync(full).isDirectory()) return [full];
|
|
69
|
-
return readdirSync(full).flatMap((entry) => files(join(path, entry)));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function flatten(tree: Tree, prefix = ""): string[] {
|
|
73
|
-
return Object.entries(tree).flatMap(([key, value]) =>
|
|
74
|
-
value !== null && typeof value === "object"
|
|
75
|
-
? flatten(value as Tree, `${prefix}${key}.`)
|
|
76
|
-
: [`${prefix}${key}`],
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function usedKeys(): string[] {
|
|
81
|
-
const source = SOURCES.flatMap(files)
|
|
82
|
-
.map((file) => readFileSync(file, "utf8"))
|
|
83
|
-
.join("\n");
|
|
84
|
-
return [
|
|
85
|
-
...new Set([...source.matchAll(LITERAL_KEY)].map((match) => match[1])),
|
|
86
|
-
];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const dynamicKeys = Object.entries(DYNAMIC_FAMILIES).flatMap(
|
|
90
|
-
([prefix, values]) => values.map((value) => `${prefix}.${value}`),
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
describe("the panel's strings", () => {
|
|
94
|
-
const english = new Set(flatten(en));
|
|
95
|
-
const french = new Set(flatten(fr));
|
|
96
|
-
|
|
97
|
-
it("exist in English and French alike", () => {
|
|
98
|
-
expect([...english].sort()).toEqual([...french].sort());
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("cover every key the panel uses", () => {
|
|
102
|
-
const keys = [
|
|
103
|
-
...usedKeys(),
|
|
104
|
-
...dynamicKeys,
|
|
105
|
-
...TOOL_VERB_KEYS.map((verb) => `dms_ai.tools.${verb}`),
|
|
106
|
-
];
|
|
107
|
-
expect(keys.filter((key) => !english.has(key))).toEqual([]);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("stay in the panel's own namespaces", () => {
|
|
111
|
-
expect(Object.keys(en.dms_ai).sort()).toEqual([...OWNED_NAMESPACES].sort());
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("hold no character vue-i18n would read as syntax", () => {
|
|
115
|
-
const texts = [JSON.stringify(en), JSON.stringify(fr)];
|
|
116
|
-
for (const text of texts) expect(text).not.toMatch(/[@$]/);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
3
|
-
import { describe, expect, it } from "vitest";
|
|
4
|
-
import en from "../i18n/locales/dms-ai-views-en-GB.json";
|
|
5
|
-
import fr from "../i18n/locales/dms-ai-views-fr-FR.json";
|
|
6
|
-
|
|
7
|
-
type Tree = Record<string, unknown>;
|
|
8
|
-
|
|
9
|
-
const ROOT = resolve(__dirname, "..");
|
|
10
|
-
// The page components (the skill drawer and cards among them) and the view
|
|
11
|
-
// helpers they share; the chat panel has its own test.
|
|
12
|
-
const SOURCES = ["app/components", "app/views"];
|
|
13
|
-
const EXCLUDED = ["ChatPanel.vue"];
|
|
14
|
-
const LITERAL_KEY = /["'`](dms_ai\.views\.[A-Za-z0-9_.]+[A-Za-z0-9_])["'`]/g;
|
|
15
|
-
|
|
16
|
-
/** Keys built at run time from a value, each with every value it can take. */
|
|
17
|
-
const DYNAMIC_FAMILIES: Record<string, readonly string[]> = {
|
|
18
|
-
"dms_ai.views.skills.source": ["module", "local"],
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
function files(path: string): string[] {
|
|
22
|
-
const full = join(ROOT, path);
|
|
23
|
-
if (!statSync(full).isDirectory()) return [full];
|
|
24
|
-
return readdirSync(full)
|
|
25
|
-
.filter((entry) => !EXCLUDED.includes(entry))
|
|
26
|
-
.flatMap((entry) => files(join(path, entry)));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function flatten(tree: Tree, prefix = ""): string[] {
|
|
30
|
-
return Object.entries(tree).flatMap(([key, value]) =>
|
|
31
|
-
value !== null && typeof value === "object"
|
|
32
|
-
? flatten(value as Tree, `${prefix}${key}.`)
|
|
33
|
-
: [`${prefix}${key}`],
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function usedKeys(): string[] {
|
|
38
|
-
const source = SOURCES.flatMap(files)
|
|
39
|
-
.map((file) => readFileSync(file, "utf8"))
|
|
40
|
-
.join("\n");
|
|
41
|
-
return [
|
|
42
|
-
...new Set([...source.matchAll(LITERAL_KEY)].map((match) => match[1])),
|
|
43
|
-
];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const dynamicKeys = Object.entries(DYNAMIC_FAMILIES).flatMap(
|
|
47
|
-
([prefix, values]) => values.map((value) => `${prefix}.${value}`),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
describe("the views' strings", () => {
|
|
51
|
-
const english = new Set(flatten(en));
|
|
52
|
-
const french = new Set(flatten(fr));
|
|
53
|
-
|
|
54
|
-
it("exist in English and French alike", () => {
|
|
55
|
-
expect([...english].sort()).toEqual([...french].sort());
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("cover every key the views use", () => {
|
|
59
|
-
const keys = [...usedKeys(), ...dynamicKeys];
|
|
60
|
-
expect(keys.length).toBeGreaterThan(0);
|
|
61
|
-
expect(keys.filter((key) => !english.has(key))).toEqual([]);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { describe, expect, it } from "vitest";
|
|
4
|
-
|
|
5
|
-
// jsdom does not lay out, so these read the stylesheets: each panel header must
|
|
6
|
-
// take its height from the DMS navbar's variable, or their borders drift apart.
|
|
7
|
-
const HEADER_RULES = [
|
|
8
|
-
{ file: "../app/chat/components/PanelHeader.vue", selector: ".cb__head" },
|
|
9
|
-
{
|
|
10
|
-
file: "../app/chat/components/ConversationDrawer.vue",
|
|
11
|
-
selector: ".cb-drawer__head",
|
|
12
|
-
},
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
function ruleBody(source: string, selector: string): string {
|
|
16
|
-
const start = source.indexOf(`${selector} {`);
|
|
17
|
-
expect(start, `${selector} rule`).toBeGreaterThanOrEqual(0);
|
|
18
|
-
return source.slice(start, source.indexOf("}", start));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
describe("panel header height", () => {
|
|
22
|
-
it.each(HEADER_RULES)("$selector uses the DMS header height", (rule) => {
|
|
23
|
-
const source = readFileSync(resolve(__dirname, rule.file), "utf8");
|
|
24
|
-
|
|
25
|
-
expect(ruleBody(source, rule.selector)).toMatch(
|
|
26
|
-
/\bheight: var\(--ui-header-height\);/,
|
|
27
|
-
);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("centres the status overlay close button in that height", () => {
|
|
31
|
-
const source = readFileSync(
|
|
32
|
-
resolve(__dirname, "../app/components/ChatPanel.vue"),
|
|
33
|
-
"utf8",
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
expect(ruleBody(source, ".dms-ai-panel-close")).toContain(
|
|
37
|
-
"var(--ui-header-height)",
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
});
|