@antelopejs/dms-ai 0.6.0 → 0.7.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 +2 -2
- 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 +35 -22
- 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.d.ts +1 -1
- package/dist/pages/settings/availability.js +19 -5
- package/dist/pages/settings/availability.js.map +1 -1
- package/dist/pages/settings/page.js +1 -1
- package/dist/pages/settings/page.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/changes.d.ts +6 -4
- package/dist/routes/changes.js.map +1 -1
- package/dist/routes/codex-account.d.ts +5 -1
- 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 +4 -3
- package/dist/routes/settings.js +4 -15
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/sidecar-info.js.map +1 -1
- package/dist/routes/sidecar-results.d.ts +2 -2
- 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/undo-confirm.js.map +1 -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/settings-values.d.ts +3 -0
- package/dist/sidecar/settings-values.js +21 -0
- package/dist/sidecar/settings-values.js.map +1 -0
- 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/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/build/backend-boundary.ts +89 -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/panel-fixtures.ts +110 -0
- package/frontend-vue/tests/support/panel-harness.ts +2 -2
- package/frontend-vue/vitest.config.ts +2 -1
- package/package.json +21 -10
- 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 +12 -2
- package/sidecar/dist/logs/logs-client.js.map +1 -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-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.js +8 -9
- 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/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 +5 -0
- package/sidecar/dist/protocol/json.js +3 -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.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-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 +1 -1
- 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 +15 -8
- package/sidecar/dist/server/http-routes.js.map +1 -1
- package/sidecar/dist/server/http.js +21 -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/raw-data.js +2 -1
- package/sidecar/dist/server/raw-data.js.map +1 -1
- package/sidecar/dist/server/routing.js +1 -1
- 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.js +7 -5
- package/sidecar/dist/server/tool-calls.js.map +1 -1
- package/sidecar/dist/server/turns.js +2 -1
- 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/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 +1 -1
- 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/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,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>
|
|
@@ -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. */
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
3
|
+
import type { Plugin } from "vite";
|
|
4
|
+
|
|
5
|
+
const BACKEND_PACKAGE = "@antelopejs/dms-ai";
|
|
6
|
+
const BACKEND_SOURCE = "src";
|
|
7
|
+
const QUERY_OR_HASH = /[?#].*$/;
|
|
8
|
+
|
|
9
|
+
const backendRoots = new Map<string, string | null>();
|
|
10
|
+
|
|
11
|
+
function packageName(manifest: string): string | undefined {
|
|
12
|
+
try {
|
|
13
|
+
const parsed: { name?: string } = JSON.parse(
|
|
14
|
+
readFileSync(manifest, "utf8"),
|
|
15
|
+
);
|
|
16
|
+
return parsed.name;
|
|
17
|
+
} catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function backendRoot(directory: string): string | null {
|
|
23
|
+
const known = backendRoots.get(directory);
|
|
24
|
+
if (known !== undefined) return known;
|
|
25
|
+
const manifest = join(directory, "package.json");
|
|
26
|
+
const parent = dirname(directory);
|
|
27
|
+
let root: string | null = null;
|
|
28
|
+
if (existsSync(manifest)) {
|
|
29
|
+
root = packageName(manifest) === BACKEND_PACKAGE ? directory : null;
|
|
30
|
+
} else if (parent !== directory) {
|
|
31
|
+
root = backendRoot(parent);
|
|
32
|
+
}
|
|
33
|
+
backendRoots.set(directory, root);
|
|
34
|
+
return root;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The real path of a resolved module id when it lies under the `src`
|
|
39
|
+
* directory of the backend package, or `undefined`. The package that owns the
|
|
40
|
+
* file decides, not a path, so the answer is the same in the repository and in
|
|
41
|
+
* the workspace the DMS builds the frontend in. Virtual ids and ids that are
|
|
42
|
+
* not files are ignored.
|
|
43
|
+
*/
|
|
44
|
+
function backendSourceFile(id: string): string | undefined {
|
|
45
|
+
const path = id.replace(QUERY_OR_HASH, "");
|
|
46
|
+
if (!isAbsolute(path)) return undefined;
|
|
47
|
+
let real: string;
|
|
48
|
+
try {
|
|
49
|
+
real = realpathSync(path);
|
|
50
|
+
} catch {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const root = backendRoot(dirname(real));
|
|
54
|
+
if (root === null) return undefined;
|
|
55
|
+
return relative(root, real).split(sep)[0] === BACKEND_SOURCE
|
|
56
|
+
? real
|
|
57
|
+
: undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Fails the build, the dev server and the tests when a module of the frontend
|
|
62
|
+
* resolves to a file under the backend's `src`: the browser reaches the
|
|
63
|
+
* backend only through its HTTP routes. It checks what the whole resolution
|
|
64
|
+
* chain returns, so an alias is seen through and a symlink the resolver
|
|
65
|
+
* returns is followed to its real path, and it runs before the other plugins
|
|
66
|
+
* (`enforce: "pre"`).
|
|
67
|
+
*/
|
|
68
|
+
export function backendBoundary(): Plugin {
|
|
69
|
+
return {
|
|
70
|
+
name: "dms-ai:backend-boundary",
|
|
71
|
+
enforce: "pre",
|
|
72
|
+
async resolveId(source, importer, options) {
|
|
73
|
+
const resolved = await this.resolve(source, importer, {
|
|
74
|
+
...options,
|
|
75
|
+
skipSelf: true,
|
|
76
|
+
});
|
|
77
|
+
if (resolved === null || resolved.external) return resolved;
|
|
78
|
+
const file = backendSourceFile(resolved.id);
|
|
79
|
+
if (file === undefined) return resolved;
|
|
80
|
+
const from =
|
|
81
|
+
importer === undefined
|
|
82
|
+
? "an entry point"
|
|
83
|
+
: importer.replace(QUERY_OR_HASH, "");
|
|
84
|
+
return this.error(
|
|
85
|
+
`Backend boundary: ${from} imports ${file}, which is under src of ${BACKEND_PACKAGE}. The frontend reaches the backend only through its HTTP routes.`,
|
|
86
|
+
);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -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
|
+
"@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
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mkdirSync,
|
|
3
|
+
mkdtempSync,
|
|
4
|
+
realpathSync,
|
|
5
|
+
rmSync,
|
|
6
|
+
symlinkSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { build, type Plugin } from "vite";
|
|
12
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
13
|
+
import { backendBoundary } from "../build/backend-boundary.ts";
|
|
14
|
+
|
|
15
|
+
let root: string;
|
|
16
|
+
|
|
17
|
+
function write(file: string, text: string): void {
|
|
18
|
+
const path = join(root, file);
|
|
19
|
+
mkdirSync(join(path, ".."), { recursive: true });
|
|
20
|
+
writeFileSync(path, text);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function manifest(directory: string, name: string): void {
|
|
24
|
+
write(`${directory}/package.json`, JSON.stringify({ name }));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** A frontend entry with `source` as its only import, built for real. */
|
|
28
|
+
async function buildEntry(source: string, extra: Plugin[] = []): Promise<void> {
|
|
29
|
+
write(
|
|
30
|
+
"frontend/entry.ts",
|
|
31
|
+
`import "${source}";\nexport const frontend = 1;\n`,
|
|
32
|
+
);
|
|
33
|
+
await build({
|
|
34
|
+
root: join(root, "frontend"),
|
|
35
|
+
configFile: false,
|
|
36
|
+
logLevel: "silent",
|
|
37
|
+
plugins: [backendBoundary(), ...extra],
|
|
38
|
+
build: {
|
|
39
|
+
write: false,
|
|
40
|
+
lib: { entry: join(root, "frontend/entry.ts"), formats: ["es"] },
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
root = realpathSync(mkdtempSync(join(tmpdir(), "dms-ai-boundary-")));
|
|
47
|
+
manifest("backend", "@antelopejs/dms-ai");
|
|
48
|
+
write("backend/src/routes/status.ts", "export const status = 1;\n");
|
|
49
|
+
write("backend/dist/index.js", "export const built = 1;\n");
|
|
50
|
+
write("backend/srcfoo/index.ts", "export const sibling = 1;\n");
|
|
51
|
+
manifest("other", "another-package");
|
|
52
|
+
write("other/src/index.ts", "export const other = 1;\n");
|
|
53
|
+
manifest("frontend", "@antelopejs/dms-ai-frontend-vue");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
rmSync(root, { recursive: true, force: true });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe("the backend boundary of a real build", () => {
|
|
61
|
+
it("fails when the frontend imports a file under the backend's src", async () => {
|
|
62
|
+
await expect(buildEntry("../backend/src/routes/status.ts")).rejects.toThrow(
|
|
63
|
+
/frontend\/entry\.ts imports .*backend\/src\/routes\/status\.ts/,
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("fails when the import carries a query", async () => {
|
|
68
|
+
await expect(
|
|
69
|
+
buildEntry("../backend/src/routes/status.ts?raw"),
|
|
70
|
+
).rejects.toThrow(/Backend boundary/);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("follows a symlink a resolver returns to the file it points at", async () => {
|
|
74
|
+
symlinkSync(
|
|
75
|
+
join(root, "backend/src/routes"),
|
|
76
|
+
join(root, "frontend/routes"),
|
|
77
|
+
);
|
|
78
|
+
const linked: Plugin = {
|
|
79
|
+
name: "test:linked",
|
|
80
|
+
enforce: "pre",
|
|
81
|
+
resolveId: (source) =>
|
|
82
|
+
source === "@linked/status"
|
|
83
|
+
? join(root, "frontend/routes/status.ts")
|
|
84
|
+
: null,
|
|
85
|
+
};
|
|
86
|
+
await expect(buildEntry("@linked/status", [linked])).rejects.toThrow(
|
|
87
|
+
/backend\/src\/routes\/status\.ts/,
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("sees through an alias another plugin resolves", async () => {
|
|
92
|
+
const alias: Plugin = {
|
|
93
|
+
name: "test:alias",
|
|
94
|
+
enforce: "pre",
|
|
95
|
+
resolveId: (source) =>
|
|
96
|
+
source === "@backend/status"
|
|
97
|
+
? join(root, "backend/src/routes/status.ts")
|
|
98
|
+
: null,
|
|
99
|
+
};
|
|
100
|
+
await expect(buildEntry("@backend/status", [alias])).rejects.toThrow(
|
|
101
|
+
/Backend boundary/,
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("lets the backend's built output through", async () => {
|
|
106
|
+
await expect(
|
|
107
|
+
buildEntry("../backend/dist/index.js"),
|
|
108
|
+
).resolves.toBeUndefined();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("lets a sibling directory whose name starts with src through", async () => {
|
|
112
|
+
await expect(
|
|
113
|
+
buildEntry("../backend/srcfoo/index.ts"),
|
|
114
|
+
).resolves.toBeUndefined();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("lets the src of another package through", async () => {
|
|
118
|
+
await expect(buildEntry("../other/src/index.ts")).resolves.toBeUndefined();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("ignores a virtual module", async () => {
|
|
122
|
+
const virtual: Plugin = {
|
|
123
|
+
name: "test:virtual",
|
|
124
|
+
enforce: "pre",
|
|
125
|
+
resolveId: (source) => (source === "virtual:ok" ? "\0virtual:ok" : null),
|
|
126
|
+
load: (id) => (id === "\0virtual:ok" ? "export const v = 1;" : null),
|
|
127
|
+
};
|
|
128
|
+
await expect(buildEntry("virtual:ok", [virtual])).resolves.toBeUndefined();
|
|
129
|
+
});
|
|
130
|
+
});
|