@vellumai/assistant 0.5.13 → 0.5.14
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/.env.example +1 -6
- package/AGENTS.md +4 -0
- package/ARCHITECTURE.md +0 -1
- package/bunfig.toml +1 -0
- package/docs/architecture/memory.md +3 -3
- package/openapi.yaml +127 -22
- package/package.json +1 -1
- package/src/__tests__/access-request-decision.test.ts +2 -32
- package/src/__tests__/actor-token-service.test.ts +1 -31
- package/src/__tests__/anthropic-provider.test.ts +53 -40
- package/src/__tests__/app-git-history.test.ts +9 -17
- package/src/__tests__/app-git-service.test.ts +14 -20
- package/src/__tests__/app-store-dir-names.test.ts +10 -20
- package/src/__tests__/approval-cascade.test.ts +2 -19
- package/src/__tests__/approval-primitive.test.ts +2 -27
- package/src/__tests__/approval-routes-http.test.ts +2 -30
- package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -28
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -45
- package/src/__tests__/attachments-store.test.ts +5 -32
- package/src/__tests__/audit-log-rotation.test.ts +5 -36
- package/src/__tests__/avatar-e2e.test.ts +1 -9
- package/src/__tests__/avatar-generator.test.ts +1 -7
- package/src/__tests__/browser-fill-credential.test.ts +0 -4
- package/src/__tests__/browser-manager.test.ts +0 -6
- package/src/__tests__/call-controller.test.ts +1 -22
- package/src/__tests__/call-conversation-messages.test.ts +0 -21
- package/src/__tests__/call-domain.test.ts +0 -25
- package/src/__tests__/call-pointer-messages.test.ts +0 -21
- package/src/__tests__/call-recovery.test.ts +0 -22
- package/src/__tests__/call-routes-http.test.ts +0 -24
- package/src/__tests__/call-store.test.ts +0 -21
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -24
- package/src/__tests__/canonical-guardian-store.test.ts +48 -21
- package/src/__tests__/channel-approval-routes.test.ts +6 -26
- package/src/__tests__/channel-approvals.test.ts +1 -38
- package/src/__tests__/channel-delivery-store.test.ts +0 -21
- package/src/__tests__/channel-guardian.test.ts +0 -26
- package/src/__tests__/channel-reply-delivery.test.ts +5 -0
- package/src/__tests__/channel-retry-sweep.test.ts +0 -21
- package/src/__tests__/checker.test.ts +26 -61
- package/src/__tests__/clawhub.test.ts +9 -25
- package/src/__tests__/cli-command-risk-guard.test.ts +0 -18
- package/src/__tests__/config-loader-backfill.test.ts +9 -28
- package/src/__tests__/config-schema-cmd.test.ts +5 -25
- package/src/__tests__/config-schema.test.ts +21 -40
- package/src/__tests__/config-watcher.test.ts +4 -91
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -21
- package/src/__tests__/contacts-tools.test.ts +0 -21
- package/src/__tests__/context-memory-e2e.test.ts +0 -21
- package/src/__tests__/context-window-manager.test.ts +130 -3
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -4
- package/src/__tests__/conversation-agent-loop.test.ts +0 -4
- package/src/__tests__/conversation-attachments.test.ts +1 -24
- package/src/__tests__/conversation-attention-store.test.ts +0 -21
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -22
- package/src/__tests__/conversation-clear-safety.test.ts +0 -22
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -21
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -24
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -23
- package/src/__tests__/conversation-disk-view.test.ts +5 -27
- package/src/__tests__/conversation-error.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +1 -33
- package/src/__tests__/conversation-fork-route.test.ts +0 -27
- package/src/__tests__/conversation-history-web-search.test.ts +23 -16
- package/src/__tests__/conversation-init.benchmark.test.ts +22 -43
- package/src/__tests__/conversation-key-store-disk-view.test.ts +8 -34
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -4
- package/src/__tests__/conversation-pre-run-repair.test.ts +0 -4
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -4
- package/src/__tests__/conversation-queue.test.ts +8 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +13 -51
- package/src/__tests__/conversation-runtime-assembly.test.ts +64 -38
- package/src/__tests__/conversation-slash-commands.test.ts +5 -0
- package/src/__tests__/conversation-slash-queue.test.ts +0 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -4
- package/src/__tests__/conversation-speed-override.test.ts +326 -0
- package/src/__tests__/conversation-starter-routes.test.ts +0 -23
- package/src/__tests__/conversation-store.test.ts +0 -21
- package/src/__tests__/conversation-unread-route.test.ts +0 -24
- package/src/__tests__/conversation-usage.test.ts +56 -21
- package/src/__tests__/conversation-wipe.test.ts +0 -21
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -4
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -4
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +8 -5
- package/src/__tests__/credential-vault-unit.test.ts +9 -428
- package/src/__tests__/credentials-cli.test.ts +10 -10
- package/src/__tests__/daemon-assistant-events.test.ts +0 -19
- package/src/__tests__/date-context.test.ts +77 -97
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +7 -24
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +29 -42
- package/src/__tests__/delete-managed-skill-tool.test.ts +2 -10
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -26
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +61 -15
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -36
- package/src/__tests__/email-cli.test.ts +6 -6
- package/src/__tests__/ephemeral-permissions.test.ts +5 -17
- package/src/__tests__/first-greeting.test.ts +4 -32
- package/src/__tests__/followup-tools.test.ts +0 -21
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -20
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -23
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -23
- package/src/__tests__/guardian-action-followup-store.test.ts +0 -21
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -21
- package/src/__tests__/guardian-action-late-reply.test.ts +0 -21
- package/src/__tests__/guardian-action-store.test.ts +0 -21
- package/src/__tests__/guardian-action-sweep.test.ts +0 -21
- package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -23
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -22
- package/src/__tests__/guardian-dispatch.test.ts +0 -21
- package/src/__tests__/guardian-grant-minting.test.ts +0 -22
- package/src/__tests__/guardian-outbound-http.test.ts +0 -22
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -23
- package/src/__tests__/guardian-routing-invariants.test.ts +0 -22
- package/src/__tests__/guardian-routing-state.test.ts +0 -22
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -24
- package/src/__tests__/headless-browser-interactions.test.ts +0 -4
- package/src/__tests__/headless-browser-navigate.test.ts +0 -4
- package/src/__tests__/headless-browser-read-tools.test.ts +0 -4
- package/src/__tests__/headless-browser-snapshot.test.ts +0 -4
- package/src/__tests__/heartbeat-service.test.ts +99 -26
- package/src/__tests__/hooks-blocking.test.ts +3 -3
- package/src/__tests__/hooks-config.test.ts +7 -7
- package/src/__tests__/hooks-discovery.test.ts +3 -3
- package/src/__tests__/hooks-integration.test.ts +5 -5
- package/src/__tests__/hooks-manager.test.ts +3 -3
- package/src/__tests__/hooks-runner.test.ts +5 -23
- package/src/__tests__/hooks-settings.test.ts +3 -3
- package/src/__tests__/hooks-templates.test.ts +3 -3
- package/src/__tests__/http-conversation-lineage.test.ts +0 -27
- package/src/__tests__/identity-intro-cache.test.ts +0 -4
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -22
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -16
- package/src/__tests__/intent-routing.test.ts +2 -55
- package/src/__tests__/invite-redemption-service.test.ts +0 -21
- package/src/__tests__/invite-routes-http.test.ts +0 -21
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +0 -17
- package/src/__tests__/journal-context.test.ts +8 -75
- package/src/__tests__/list-messages-attachments.test.ts +0 -22
- package/src/__tests__/llm-context-route-provider.test.ts +0 -21
- package/src/__tests__/llm-request-log-turn-query.test.ts +46 -28
- package/src/__tests__/llm-usage-store.test.ts +0 -21
- package/src/__tests__/log-export-workspace.test.ts +1 -1
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
- package/src/__tests__/managed-store.test.ts +1 -1
- package/src/__tests__/mcp-cli.test.ts +7 -10
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -21
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +0 -11
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -21
- package/src/__tests__/memory-recall-log-store.test.ts +0 -27
- package/src/__tests__/memory-recall-quality.test.ts +0 -21
- package/src/__tests__/memory-regressions.experimental.test.ts +31 -30
- package/src/__tests__/memory-regressions.test.ts +282 -70
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -21
- package/src/__tests__/memory-upsert-concurrency.test.ts +0 -21
- package/src/__tests__/messaging-send-tool.test.ts +201 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +18 -13
- package/src/__tests__/migration-export-http.test.ts +7 -1
- package/src/__tests__/migration-import-commit-http.test.ts +16 -14
- package/src/__tests__/migration-import-preflight-http.test.ts +27 -44
- package/src/__tests__/migration-validate-http.test.ts +1 -28
- package/src/__tests__/native-web-search.test.ts +25 -22
- package/src/__tests__/non-member-access-request.test.ts +0 -22
- package/src/__tests__/notification-guardian-path.test.ts +0 -21
- package/src/__tests__/notification-schedule-dedup.test.ts +1 -25
- package/src/__tests__/oauth-apps-routes.test.ts +103 -2
- package/src/__tests__/oauth-cli.test.ts +52 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +0 -16
- package/src/__tests__/oauth-provider-serializer.test.ts +232 -0
- package/src/__tests__/oauth-providers-routes.test.ts +257 -0
- package/src/__tests__/oauth-store.test.ts +0 -21
- package/src/__tests__/onboarding-template-contract.test.ts +2 -2
- package/src/__tests__/openai-provider.test.ts +261 -0
- package/src/__tests__/pairing-concurrent.test.ts +6 -6
- package/src/__tests__/pairing-routes.test.ts +7 -1
- package/src/__tests__/path-policy.test.ts +1 -1
- package/src/__tests__/platform.test.ts +64 -88
- package/src/__tests__/playbook-execution.test.ts +0 -21
- package/src/__tests__/playbook-tools.test.ts +0 -21
- package/src/__tests__/pricing.test.ts +100 -0
- package/src/__tests__/relay-server.test.ts +1 -25
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -24
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -24
- package/src/__tests__/runtime-events-sse.test.ts +0 -24
- package/src/__tests__/sandbox-diagnostics.test.ts +2 -1
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
- package/src/__tests__/schedule-store.test.ts +0 -21
- package/src/__tests__/schedule-tools.test.ts +0 -21
- package/src/__tests__/scheduler-recurrence.test.ts +0 -21
- package/src/__tests__/scoped-approval-grants.test.ts +0 -21
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -21
- package/src/__tests__/secret-allowlist.test.ts +1 -1
- package/src/__tests__/secret-ingress-channel.test.ts +0 -5
- package/src/__tests__/secret-ingress-cli.test.ts +0 -6
- package/src/__tests__/secret-ingress-http.test.ts +0 -5
- package/src/__tests__/secret-ingress.test.ts +0 -5
- package/src/__tests__/send-endpoint-busy.test.ts +0 -24
- package/src/__tests__/sequence-store.test.ts +0 -21
- package/src/__tests__/server-history-render.test.ts +0 -24
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -4
- package/src/__tests__/skill-load-inline-command.test.ts +9 -0
- package/src/__tests__/skill-load-inline-includes.test.ts +9 -0
- package/src/__tests__/skill-load-tool.test.ts +11 -0
- package/src/__tests__/skills-uninstall.test.ts +10 -8
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-channel-config.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +0 -22
- package/src/__tests__/starter-bundle.test.ts +4 -1
- package/src/__tests__/suggestion-routes.test.ts +2 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/test-preload.ts +31 -0
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +0 -20
- package/src/__tests__/tool-input-summary.test.ts +124 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -1
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +1 -1
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/turn-boundary-resolution.test.ts +1 -1
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/update-bulletin.test.ts +1 -1
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +1 -1
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
- package/src/__tests__/voice-session-bridge.test.ts +1 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -4
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-down-functions.test.ts +15 -3
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +40 -4
- package/src/agent/loop.ts +6 -9
- package/src/approvals/guardian-decision-primitive.ts +46 -18
- package/src/approvals/guardian-request-resolvers.ts +19 -2
- package/src/calls/active-call-lease.ts +2 -2
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/commands/doctor.ts +9 -9
- package/src/cli/commands/memory.ts +142 -0
- package/src/cli/commands/oauth/__tests__/connect.test.ts +13 -11
- package/src/cli/commands/oauth/__tests__/ping.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +13 -12
- package/src/cli/commands/oauth/index.ts +1 -1
- package/src/cli/commands/oauth/providers.ts +47 -62
- package/src/cli/commands/platform/__tests__/connect.test.ts +72 -46
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +54 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +36 -0
- package/src/cli/commands/platform/connect.ts +17 -7
- package/src/cli/commands/platform/disconnect.ts +28 -3
- package/src/cli/commands/platform/index.ts +3 -3
- package/src/cli.ts +1 -299
- package/src/config/assistant-feature-flags.ts +23 -15
- package/src/config/bundled-skills/app-builder/TOOLS.json +16 -0
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +4 -0
- package/src/config/bundled-skills/app-builder/tools/app-delete.ts +5 -1
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +9 -1
- package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +5 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +8 -0
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +10 -1
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +16 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +1 -0
- package/src/config/bundled-skills/messaging/SKILL.md +7 -7
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +37 -0
- package/src/config/bundled-skills/slack/SKILL.md +18 -0
- package/src/config/env-registry.ts +15 -11
- package/src/config/env.ts +1 -11
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/heartbeat.ts +6 -1
- package/src/config/schemas/inference.ts +14 -3
- package/src/config/schemas/memory-processing.ts +16 -8
- package/src/config/schemas/memory-retrieval.ts +3 -3
- package/src/config/skills.ts +1 -1
- package/src/context/window-manager.ts +174 -51
- package/src/credential-execution/executable-discovery.ts +2 -2
- package/src/daemon/approved-devices-store.ts +2 -2
- package/src/daemon/assistant-attachments.ts +2 -0
- package/src/daemon/config-watcher.ts +4 -50
- package/src/daemon/conversation-agent-loop-handlers.ts +9 -1
- package/src/daemon/conversation-agent-loop.ts +12 -0
- package/src/daemon/conversation-error.ts +3 -5
- package/src/daemon/conversation-history.ts +7 -3
- package/src/daemon/conversation-lifecycle.ts +16 -0
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-notifiers.ts +67 -30
- package/src/daemon/conversation-process.ts +161 -2
- package/src/daemon/conversation-queue-manager.ts +2 -0
- package/src/daemon/conversation-runtime-assembly.ts +33 -11
- package/src/daemon/conversation-slash.ts +14 -3
- package/src/daemon/conversation-tool-setup.ts +2 -0
- package/src/daemon/conversation-usage.ts +32 -4
- package/src/daemon/conversation.ts +33 -1
- package/src/daemon/daemon-control.ts +32 -16
- package/src/daemon/date-context.ts +47 -45
- package/src/daemon/dictation-profile-store.ts +2 -2
- package/src/daemon/handlers/conversations.ts +19 -0
- package/src/daemon/handlers/shared.ts +14 -21
- package/src/daemon/lifecycle.ts +5 -7
- package/src/daemon/message-types/conversations.ts +2 -0
- package/src/daemon/message-types/guardian-actions.ts +3 -17
- package/src/daemon/message-types/integrations.ts +11 -1
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/pairing-store.ts +2 -79
- package/src/daemon/server.ts +154 -8
- package/src/daemon/watch-handler.ts +65 -21
- package/src/email/guardrails.ts +3 -3
- package/src/heartbeat/heartbeat-service.ts +14 -7
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/config.ts +2 -2
- package/src/hooks/discovery.ts +2 -2
- package/src/hooks/manager.ts +2 -2
- package/src/hooks/runner.ts +5 -2
- package/src/hooks/templates.ts +2 -2
- package/src/memory/admin.ts +181 -2
- package/src/memory/app-git-service.ts +61 -4
- package/src/memory/attachments-store.ts +2 -0
- package/src/memory/canonical-guardian-store.ts +16 -0
- package/src/memory/db-init.ts +8 -0
- package/src/memory/embedding-local.ts +5 -2
- package/src/memory/indexer.ts +44 -26
- package/src/memory/items-extractor.ts +34 -82
- package/src/memory/job-handlers/batch-extraction.ts +741 -0
- package/src/memory/job-handlers/journal-carry-forward.test.ts +383 -0
- package/src/memory/job-handlers/journal-carry-forward.ts +255 -0
- package/src/memory/jobs-store.ts +28 -0
- package/src/memory/jobs-worker.ts +56 -9
- package/src/memory/lifecycle-events-store.ts +4 -2
- package/src/memory/llm-request-log-store.ts +40 -2
- package/src/memory/llm-usage-store.ts +4 -3
- package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +71 -0
- package/src/memory/migrations/200-usage-llm-call-count.ts +20 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/query-expansion.ts +83 -0
- package/src/memory/retriever.test.ts +119 -0
- package/src/memory/retriever.ts +513 -105
- package/src/memory/schema/guardian.ts +4 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/search/formatting.test.ts +140 -0
- package/src/memory/search/formatting.ts +143 -198
- package/src/memory/search/mmr.ts +136 -0
- package/src/memory/search/staleness.ts +0 -15
- package/src/memory/search/tier-classifier.ts +10 -21
- package/src/memory/search/types.ts +17 -0
- package/src/messaging/providers/slack/adapter.ts +51 -5
- package/src/notifications/broadcaster.ts +13 -0
- package/src/notifications/copy-composer.ts +8 -0
- package/src/oauth/connect-orchestrator.ts +1 -1
- package/src/oauth/connection-resolver.ts +2 -2
- package/src/oauth/provider-serializer.ts +116 -0
- package/src/permissions/trust-store.ts +24 -7
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +5 -0
- package/src/prompts/journal-context.ts +50 -35
- package/src/prompts/persona-resolver.ts +1 -1
- package/src/prompts/system-prompt.ts +27 -28
- package/src/prompts/templates/BOOTSTRAP.md +14 -1
- package/src/prompts/templates/HEARTBEAT.md +10 -0
- package/src/prompts/templates/NOW.md +19 -25
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/update-bulletin.ts +1 -1
- package/src/providers/anthropic/client.ts +89 -18
- package/src/providers/model-catalog.ts +22 -2
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/client.ts +40 -1
- package/src/providers/retry.ts +23 -4
- package/src/providers/types.ts +2 -0
- package/src/runtime/assistant-scope.ts +1 -1
- package/src/runtime/auth/__tests__/credential-service.test.ts +1 -0
- package/src/runtime/auth/route-policy.ts +1 -0
- package/src/runtime/auth/token-service.ts +51 -29
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -1
- package/src/runtime/guardian-decision-types.ts +16 -10
- package/src/runtime/http-server.ts +3 -14
- package/src/runtime/http-types.ts +1 -0
- package/src/runtime/migrations/vbundle-builder.ts +7 -4
- package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -4
- package/src/runtime/migrations/vbundle-importer.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +40 -8
- package/src/runtime/routes/conversation-routes.ts +125 -3
- package/src/runtime/routes/guardian-action-routes.ts +9 -3
- package/src/runtime/routes/identity-routes.ts +25 -4
- package/src/runtime/routes/llm-context-normalization.ts +1 -0
- package/src/runtime/routes/log-export-routes.ts +34 -12
- package/src/runtime/routes/migration-routes.ts +6 -10
- package/src/runtime/routes/oauth-apps.ts +2 -9
- package/src/runtime/routes/oauth-providers.ts +60 -0
- package/src/runtime/routes/pairing-routes.ts +0 -8
- package/src/runtime/routes/settings-routes.ts +0 -1
- package/src/runtime/routes/telemetry-routes.ts +16 -4
- package/src/security/encrypted-store.ts +2 -2
- package/src/security/secret-allowlist.ts +3 -3
- package/src/signals/emit-event.ts +42 -0
- package/src/signals/user-message.ts +37 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +83 -19
- package/src/telemetry/usage-telemetry-reporter.ts +23 -17
- package/src/tools/browser/runtime-check.ts +2 -2
- package/src/tools/credentials/vault.ts +2 -249
- package/src/tools/memory/definitions.ts +1 -1
- package/src/tools/memory/handlers.test.ts +50 -8
- package/src/tools/memory/handlers.ts +3 -1
- package/src/tools/side-effects.ts +1 -6
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +11 -14
- package/src/tools/tool-approval-handler.ts +20 -1
- package/src/tools/tool-input-summary.ts +66 -0
- package/src/tools/types.ts +4 -0
- package/src/usage/types.ts +4 -0
- package/src/util/device-id.ts +10 -10
- package/src/util/platform.ts +71 -33
- package/src/util/pricing.ts +19 -6
- package/src/util/strip-comment-lines.ts +28 -0
- package/src/workspace/git-service.ts +8 -18
- package/src/workspace/migrations/003-seed-device-id.ts +6 -4
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +7 -1
- package/src/workspace/migrations/017-seed-persona-dirs.ts +2 -4
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +84 -0
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +94 -0
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +86 -0
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +126 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +3 -6
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/signals/confirm.ts +0 -82
- package/src/signals/trust-rule.ts +0 -174
|
@@ -32,6 +32,7 @@ let renderedHistoryContent: {
|
|
|
32
32
|
toolCallsBeforeText: boolean;
|
|
33
33
|
contentOrder: string[];
|
|
34
34
|
surfaces: unknown[];
|
|
35
|
+
thinkingSegments: string[];
|
|
35
36
|
} = {
|
|
36
37
|
text: "",
|
|
37
38
|
textSegments: [],
|
|
@@ -39,6 +40,7 @@ let renderedHistoryContent: {
|
|
|
39
40
|
toolCallsBeforeText: false,
|
|
40
41
|
contentOrder: [],
|
|
41
42
|
surfaces: [],
|
|
43
|
+
thinkingSegments: [],
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
let deliveryFailAtIndex = -1;
|
|
@@ -111,6 +113,7 @@ describe("channel-reply-delivery", () => {
|
|
|
111
113
|
toolCallsBeforeText: false,
|
|
112
114
|
contentOrder: [],
|
|
113
115
|
surfaces: [],
|
|
116
|
+
thinkingSegments: [],
|
|
114
117
|
};
|
|
115
118
|
});
|
|
116
119
|
|
|
@@ -197,6 +200,7 @@ describe("channel-reply-delivery", () => {
|
|
|
197
200
|
toolCallsBeforeText: false,
|
|
198
201
|
contentOrder: ["text:0", "tool:0", "text:1"],
|
|
199
202
|
surfaces: [],
|
|
203
|
+
thinkingSegments: [],
|
|
200
204
|
};
|
|
201
205
|
|
|
202
206
|
await deliverReplyViaCallback(
|
|
@@ -432,6 +436,7 @@ describe("channel-reply-delivery", () => {
|
|
|
432
436
|
toolCallsBeforeText: false,
|
|
433
437
|
contentOrder: ["text:0", "tool:0", "text:1", "tool:1", "text:2"],
|
|
434
438
|
surfaces: [],
|
|
439
|
+
thinkingSegments: [],
|
|
435
440
|
};
|
|
436
441
|
|
|
437
442
|
const delivered: number[] = [];
|
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
1
|
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
5
2
|
|
|
6
3
|
import { eq } from "drizzle-orm";
|
|
7
4
|
|
|
8
|
-
const testDir = mkdtempSync(join(tmpdir(), "channel-retry-sweep-test-"));
|
|
9
|
-
|
|
10
|
-
mock.module("../util/platform.js", () => ({
|
|
11
|
-
getDataDir: () => testDir,
|
|
12
|
-
isMacOS: () => process.platform === "darwin",
|
|
13
|
-
isLinux: () => process.platform === "linux",
|
|
14
|
-
isWindows: () => process.platform === "win32",
|
|
15
|
-
getPidPath: () => join(testDir, "test.pid"),
|
|
16
|
-
getDbPath: () => join(testDir, "test.db"),
|
|
17
|
-
getLogPath: () => join(testDir, "test.log"),
|
|
18
|
-
ensureDataDir: () => {},
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
5
|
mock.module("../util/logger.js", () => ({
|
|
22
6
|
getLogger: () =>
|
|
23
7
|
new Proxy({} as Record<string, unknown>, {
|
|
@@ -34,11 +18,6 @@ initializeDb();
|
|
|
34
18
|
|
|
35
19
|
afterAll(() => {
|
|
36
20
|
resetDb();
|
|
37
|
-
try {
|
|
38
|
-
rmSync(testDir, { recursive: true });
|
|
39
|
-
} catch {
|
|
40
|
-
// Best effort cleanup
|
|
41
|
-
}
|
|
42
21
|
});
|
|
43
22
|
|
|
44
23
|
function resetTables(): void {
|
|
@@ -21,21 +21,11 @@ import {
|
|
|
21
21
|
test,
|
|
22
22
|
} from "bun:test";
|
|
23
23
|
|
|
24
|
-
// Use
|
|
25
|
-
const checkerTestDir =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
getDataDir: () => join(checkerTestDir, "data"),
|
|
30
|
-
getWorkspaceSkillsDir: () => join(checkerTestDir, "skills"),
|
|
31
|
-
isMacOS: () => process.platform === "darwin",
|
|
32
|
-
isLinux: () => process.platform === "linux",
|
|
33
|
-
isWindows: () => process.platform === "win32",
|
|
34
|
-
getPidPath: () => join(checkerTestDir, "test.pid"),
|
|
35
|
-
getDbPath: () => join(checkerTestDir, "test.db"),
|
|
36
|
-
getLogPath: () => join(checkerTestDir, "test.log"),
|
|
37
|
-
ensureDataDir: () => {},
|
|
38
|
-
}));
|
|
24
|
+
// Use the preload-provided workspace directory so trust-store doesn't touch ~/.vellum
|
|
25
|
+
const checkerTestDir = process.env.VELLUM_WORKSPACE_DIR!;
|
|
26
|
+
|
|
27
|
+
// Point the file-based trust backend at the test temp dir.
|
|
28
|
+
process.env.GATEWAY_SECURITY_DIR = join(checkerTestDir, "protected");
|
|
39
29
|
|
|
40
30
|
// Capture logger.warn() calls so tests can assert on deprecation warnings.
|
|
41
31
|
const loggerWarnCalls: string[] = [];
|
|
@@ -175,14 +165,6 @@ describe("Permission Checker", () => {
|
|
|
175
165
|
} catch {
|
|
176
166
|
/* may not exist */
|
|
177
167
|
}
|
|
178
|
-
try {
|
|
179
|
-
rmSync(join(checkerTestDir, "workspace", "skills"), {
|
|
180
|
-
recursive: true,
|
|
181
|
-
force: true,
|
|
182
|
-
});
|
|
183
|
-
} catch {
|
|
184
|
-
/* may not exist */
|
|
185
|
-
}
|
|
186
168
|
});
|
|
187
169
|
|
|
188
170
|
// ── classifyRisk ────────────────────────────────────────────────
|
|
@@ -1484,7 +1466,7 @@ describe("Permission Checker", () => {
|
|
|
1484
1466
|
|
|
1485
1467
|
describe("default workspace prompt file allow rules", () => {
|
|
1486
1468
|
test("file_edit of workspace IDENTITY.md is auto-allowed", async () => {
|
|
1487
|
-
const identityPath = join(checkerTestDir, "
|
|
1469
|
+
const identityPath = join(checkerTestDir, "IDENTITY.md");
|
|
1488
1470
|
const result = await check("file_edit", { path: identityPath }, "/tmp");
|
|
1489
1471
|
expect(result.decision).toBe("allow");
|
|
1490
1472
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1492,7 +1474,7 @@ describe("Permission Checker", () => {
|
|
|
1492
1474
|
});
|
|
1493
1475
|
|
|
1494
1476
|
test("file_read of workspace USER.md is auto-allowed", async () => {
|
|
1495
|
-
const userPath = join(checkerTestDir, "
|
|
1477
|
+
const userPath = join(checkerTestDir, "USER.md");
|
|
1496
1478
|
const result = await check("file_read", { path: userPath }, "/tmp");
|
|
1497
1479
|
expect(result.decision).toBe("allow");
|
|
1498
1480
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1500,7 +1482,7 @@ describe("Permission Checker", () => {
|
|
|
1500
1482
|
});
|
|
1501
1483
|
|
|
1502
1484
|
test("file_write of workspace SOUL.md is auto-allowed", async () => {
|
|
1503
|
-
const soulPath = join(checkerTestDir, "
|
|
1485
|
+
const soulPath = join(checkerTestDir, "SOUL.md");
|
|
1504
1486
|
const result = await check("file_write", { path: soulPath }, "/tmp");
|
|
1505
1487
|
expect(result.decision).toBe("allow");
|
|
1506
1488
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1508,7 +1490,7 @@ describe("Permission Checker", () => {
|
|
|
1508
1490
|
});
|
|
1509
1491
|
|
|
1510
1492
|
test("file_write of workspace BOOTSTRAP.md is auto-allowed", async () => {
|
|
1511
|
-
const bootstrapPath = join(checkerTestDir, "
|
|
1493
|
+
const bootstrapPath = join(checkerTestDir, "BOOTSTRAP.md");
|
|
1512
1494
|
const result = await check("file_write", { path: bootstrapPath }, "/tmp");
|
|
1513
1495
|
expect(result.decision).toBe("allow");
|
|
1514
1496
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1516,7 +1498,7 @@ describe("Permission Checker", () => {
|
|
|
1516
1498
|
});
|
|
1517
1499
|
|
|
1518
1500
|
test("file_read of workspace UPDATES.md is auto-allowed", async () => {
|
|
1519
|
-
const updatesPath = join(checkerTestDir, "
|
|
1501
|
+
const updatesPath = join(checkerTestDir, "UPDATES.md");
|
|
1520
1502
|
const result = await check("file_read", { path: updatesPath }, "/tmp");
|
|
1521
1503
|
expect(result.decision).toBe("allow");
|
|
1522
1504
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1524,7 +1506,7 @@ describe("Permission Checker", () => {
|
|
|
1524
1506
|
});
|
|
1525
1507
|
|
|
1526
1508
|
test("file_write of workspace UPDATES.md is auto-allowed", async () => {
|
|
1527
|
-
const updatesPath = join(checkerTestDir, "
|
|
1509
|
+
const updatesPath = join(checkerTestDir, "UPDATES.md");
|
|
1528
1510
|
const result = await check("file_write", { path: updatesPath }, "/tmp");
|
|
1529
1511
|
expect(result.decision).toBe("allow");
|
|
1530
1512
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1532,7 +1514,7 @@ describe("Permission Checker", () => {
|
|
|
1532
1514
|
});
|
|
1533
1515
|
|
|
1534
1516
|
test("file_edit of workspace UPDATES.md is auto-allowed", async () => {
|
|
1535
|
-
const updatesPath = join(checkerTestDir, "
|
|
1517
|
+
const updatesPath = join(checkerTestDir, "UPDATES.md");
|
|
1536
1518
|
const result = await check("file_edit", { path: updatesPath }, "/tmp");
|
|
1537
1519
|
expect(result.decision).toBe("allow");
|
|
1538
1520
|
expect(result.matchedRule).toBeDefined();
|
|
@@ -1540,7 +1522,7 @@ describe("Permission Checker", () => {
|
|
|
1540
1522
|
});
|
|
1541
1523
|
|
|
1542
1524
|
test("file_write of non-workspace file is auto-allowed (Low risk)", async () => {
|
|
1543
|
-
const otherPath = join(checkerTestDir, "
|
|
1525
|
+
const otherPath = join(checkerTestDir, "OTHER.md");
|
|
1544
1526
|
// Use a workingDir that doesn't contain the path so it's not workspace-scoped
|
|
1545
1527
|
const result = await check("file_write", { path: otherPath }, "/home");
|
|
1546
1528
|
// Low risk → auto-allowed even outside workspace
|
|
@@ -2067,7 +2049,7 @@ describe("Permission Checker", () => {
|
|
|
2067
2049
|
expect(risk).toBe(RiskLevel.Low);
|
|
2068
2050
|
});
|
|
2069
2051
|
|
|
2070
|
-
test("file_write to skill directory prompts
|
|
2052
|
+
test("file_write to skill directory prompts via default ask rule", async () => {
|
|
2071
2053
|
ensureSkillsDir();
|
|
2072
2054
|
const skillPath = join(
|
|
2073
2055
|
checkerTestDir,
|
|
@@ -2077,7 +2059,10 @@ describe("Permission Checker", () => {
|
|
|
2077
2059
|
);
|
|
2078
2060
|
const result = await check("file_write", { path: skillPath }, "/tmp");
|
|
2079
2061
|
expect(result.decision).toBe("prompt");
|
|
2080
|
-
expect(result.
|
|
2062
|
+
expect(result.matchedRule).toBeDefined();
|
|
2063
|
+
expect(result.matchedRule!.id).toBe(
|
|
2064
|
+
"default:ask-file_write-managed-skills",
|
|
2065
|
+
);
|
|
2081
2066
|
});
|
|
2082
2067
|
|
|
2083
2068
|
test("file_write to skill directory is NOT allowed by a generic file_write allow rule (High risk)", async () => {
|
|
@@ -2092,7 +2077,6 @@ describe("Permission Checker", () => {
|
|
|
2092
2077
|
const result = await check("file_write", { path: skillPath }, "/tmp");
|
|
2093
2078
|
// High risk requires explicit allowHighRisk — a plain allow rule is insufficient.
|
|
2094
2079
|
expect(result.decision).toBe("prompt");
|
|
2095
|
-
expect(result.reason).toContain("High risk");
|
|
2096
2080
|
});
|
|
2097
2081
|
|
|
2098
2082
|
test("file_write to skill directory is allowed with allowHighRisk: true rule", async () => {
|
|
@@ -2592,10 +2576,8 @@ describe("Permission Checker", () => {
|
|
|
2592
2576
|
"executor.ts",
|
|
2593
2577
|
);
|
|
2594
2578
|
const result = await check("file_write", { path: skillPath }, "/tmp");
|
|
2579
|
+
// The important invariant is that it prompts (default ask rule or strict mode).
|
|
2595
2580
|
expect(result.decision).toBe("prompt");
|
|
2596
|
-
// In strict mode the "no matching rule" check fires before the
|
|
2597
|
-
// high-risk fallback — the important invariant is that it prompts.
|
|
2598
|
-
expect(result.reason).toContain("requires approval");
|
|
2599
2581
|
});
|
|
2600
2582
|
|
|
2601
2583
|
test("strict mode: file_edit of skill source prompts (no implicit allow)", async () => {
|
|
@@ -2609,7 +2591,6 @@ describe("Permission Checker", () => {
|
|
|
2609
2591
|
);
|
|
2610
2592
|
const result = await check("file_edit", { path: skillPath }, "/tmp");
|
|
2611
2593
|
expect(result.decision).toBe("prompt");
|
|
2612
|
-
expect(result.reason).toContain("requires approval");
|
|
2613
2594
|
});
|
|
2614
2595
|
|
|
2615
2596
|
test("strict mode: file_write to non-skill path prompts as Strict mode", async () => {
|
|
@@ -2621,7 +2602,7 @@ describe("Permission Checker", () => {
|
|
|
2621
2602
|
expect(result.reason).toContain("Strict mode");
|
|
2622
2603
|
});
|
|
2623
2604
|
|
|
2624
|
-
test("workspace mode: file_write to skill source still prompts
|
|
2605
|
+
test("workspace mode: file_write to skill source still prompts", async () => {
|
|
2625
2606
|
testConfig.permissions.mode = "workspace";
|
|
2626
2607
|
ensureSkillsDir();
|
|
2627
2608
|
const skillPath = join(
|
|
@@ -2632,7 +2613,6 @@ describe("Permission Checker", () => {
|
|
|
2632
2613
|
);
|
|
2633
2614
|
const result = await check("file_write", { path: skillPath }, "/tmp");
|
|
2634
2615
|
expect(result.decision).toBe("prompt");
|
|
2635
|
-
expect(result.reason).toContain("High risk");
|
|
2636
2616
|
});
|
|
2637
2617
|
|
|
2638
2618
|
test("strict mode: host_file_write to skill source prompts (high risk overrides host ask)", async () => {
|
|
@@ -2792,35 +2772,20 @@ describe("Permission Checker", () => {
|
|
|
2792
2772
|
// Regression tests: user-created allow rules (priority 100) must override
|
|
2793
2773
|
// the default ask rules for skill-source mutations (priority 50).
|
|
2794
2774
|
//
|
|
2795
|
-
// Paths use
|
|
2796
|
-
//
|
|
2797
|
-
//
|
|
2798
|
-
// the
|
|
2799
|
-
//
|
|
2800
|
-
// extraDirs is set to the parent "workspace" directory (not "workspace/skills")
|
|
2801
|
-
// so that isSkillSourcePath classifies the paths as High risk without creating
|
|
2802
|
-
// a duplicate extra-0 ask rule for the exact same path as the managed rule.
|
|
2803
|
-
// The third test explicitly asserts the matched rule ID is the managed-skill
|
|
2804
|
-
// rule to guard against regressions in default rule generation.
|
|
2775
|
+
// Paths use the real workspace skills directory (getWorkspaceSkillsDir())
|
|
2776
|
+
// so that getDefaultRuleTemplates builds the managed-skill ask rule for the
|
|
2777
|
+
// exact same path. The third test explicitly asserts the matched rule ID is
|
|
2778
|
+
// the managed-skill rule to guard against regressions in default rule
|
|
2779
|
+
// generation.
|
|
2805
2780
|
|
|
2806
2781
|
describe("user override of skill mutation default ask rules", () => {
|
|
2807
2782
|
// Must match the path getDefaultRuleTemplates computes for managedSkillsDir
|
|
2808
|
-
const wsSkillsDir = join(checkerTestDir, "
|
|
2809
|
-
// Use parent directory for extraDirs — broad enough for isSkillSourcePath
|
|
2810
|
-
// to recognize skill paths, but distinct from the managed-skill rule path.
|
|
2811
|
-
const wsDir = join(checkerTestDir, "workspace");
|
|
2783
|
+
const wsSkillsDir = join(checkerTestDir, "skills");
|
|
2812
2784
|
|
|
2813
2785
|
function ensureSkillsDir(): void {
|
|
2814
2786
|
mkdirSync(wsSkillsDir, { recursive: true });
|
|
2815
2787
|
}
|
|
2816
2788
|
|
|
2817
|
-
beforeEach(() => {
|
|
2818
|
-
// Register the workspace parent dir so isSkillSourcePath detects skill
|
|
2819
|
-
// paths under workspace/skills/ without duplicating the managed-skill
|
|
2820
|
-
// default ask rule (the mock for getWorkspaceSkillsDir points elsewhere).
|
|
2821
|
-
testConfig.skills.load.extraDirs = [wsDir];
|
|
2822
|
-
});
|
|
2823
|
-
|
|
2824
2789
|
test("user allowHighRisk rule at priority 100 overrides default ask for skill source writes", async () => {
|
|
2825
2790
|
ensureSkillsDir();
|
|
2826
2791
|
const skillPath = join(wsSkillsDir, "my-skill", "executor.ts");
|
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
existsSync,
|
|
3
|
-
mkdirSync,
|
|
4
|
-
mkdtempSync,
|
|
5
|
-
rmSync,
|
|
6
|
-
writeFileSync,
|
|
7
|
-
} from "node:fs";
|
|
8
|
-
import { tmpdir } from "node:os";
|
|
1
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
9
2
|
import { join } from "node:path";
|
|
10
|
-
import {
|
|
3
|
+
import { describe, expect, test } from "bun:test";
|
|
11
4
|
import { mock } from "bun:test";
|
|
12
5
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
mock.module("../util/platform.js", () => ({
|
|
16
|
-
getRootDir: () => TEST_DIR,
|
|
17
|
-
getWorkspaceSkillsDir: () => join(TEST_DIR, "skills"),
|
|
18
|
-
}));
|
|
6
|
+
const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
19
7
|
|
|
20
8
|
mock.module("../util/logger.js", () => ({
|
|
21
9
|
getLogger: () =>
|
|
@@ -31,15 +19,6 @@ import {
|
|
|
31
19
|
verifyAndRecordSkillHash,
|
|
32
20
|
} from "../skills/clawhub.js";
|
|
33
21
|
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
TEST_DIR = mkdtempSync(join(tmpdir(), "clawhub-test-"));
|
|
36
|
-
mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
afterEach(() => {
|
|
40
|
-
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
41
|
-
});
|
|
42
|
-
|
|
43
22
|
// ---------------------------------------------------------------------------
|
|
44
23
|
// Slug validation (exercised through public API)
|
|
45
24
|
// ---------------------------------------------------------------------------
|
|
@@ -125,6 +104,7 @@ describe("integrity manifest", () => {
|
|
|
125
104
|
}
|
|
126
105
|
|
|
127
106
|
test("malformed integrity JSON is handled gracefully", () => {
|
|
107
|
+
mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
|
|
128
108
|
const integrityPath = join(TEST_DIR, "skills", ".integrity.json");
|
|
129
109
|
writeFileSync(integrityPath, "{not valid json!!!", "utf-8");
|
|
130
110
|
createSkillFiles("valid-slug");
|
|
@@ -139,7 +119,11 @@ describe("integrity manifest", () => {
|
|
|
139
119
|
});
|
|
140
120
|
|
|
141
121
|
test("missing integrity manifest is created on first install", () => {
|
|
142
|
-
const
|
|
122
|
+
const skillsDir = join(TEST_DIR, "skills");
|
|
123
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
124
|
+
const integrityPath = join(skillsDir, ".integrity.json");
|
|
125
|
+
// Remove any manifest left by earlier tests so we test the fresh-creation path
|
|
126
|
+
rmSync(integrityPath, { force: true });
|
|
143
127
|
expect(existsSync(integrityPath)).toBe(false);
|
|
144
128
|
createSkillFiles("new-skill");
|
|
145
129
|
|
|
@@ -5,26 +5,8 @@
|
|
|
5
5
|
// sensitive subcommands are intentionally elevated to Medium or High.
|
|
6
6
|
// See #18982 / #18998 for the regression that motivated this guard.
|
|
7
7
|
|
|
8
|
-
import { mkdtempSync } from "node:fs";
|
|
9
|
-
import { tmpdir } from "node:os";
|
|
10
|
-
import { join } from "node:path";
|
|
11
8
|
import { describe, expect, mock, test } from "bun:test";
|
|
12
9
|
|
|
13
|
-
const guardTestDir = mkdtempSync(join(tmpdir(), "cli-risk-guard-test-"));
|
|
14
|
-
|
|
15
|
-
mock.module("../util/platform.js", () => ({
|
|
16
|
-
getRootDir: () => guardTestDir,
|
|
17
|
-
getDataDir: () => join(guardTestDir, "data"),
|
|
18
|
-
getWorkspaceSkillsDir: () => join(guardTestDir, "skills"),
|
|
19
|
-
isMacOS: () => process.platform === "darwin",
|
|
20
|
-
isLinux: () => process.platform === "linux",
|
|
21
|
-
isWindows: () => process.platform === "win32",
|
|
22
|
-
getPidPath: () => join(guardTestDir, "test.pid"),
|
|
23
|
-
getDbPath: () => join(guardTestDir, "test.db"),
|
|
24
|
-
getLogPath: () => join(guardTestDir, "test.log"),
|
|
25
|
-
ensureDataDir: () => {},
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
10
|
mock.module("../util/logger.js", () => ({
|
|
29
11
|
getLogger: () =>
|
|
30
12
|
new Proxy({} as Record<string, unknown>, {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
1
|
import {
|
|
3
2
|
existsSync,
|
|
4
3
|
mkdirSync,
|
|
@@ -6,7 +5,6 @@ import {
|
|
|
6
5
|
rmSync,
|
|
7
6
|
writeFileSync,
|
|
8
7
|
} from "node:fs";
|
|
9
|
-
import { tmpdir } from "node:os";
|
|
10
8
|
import { join } from "node:path";
|
|
11
9
|
import {
|
|
12
10
|
afterAll,
|
|
@@ -22,21 +20,16 @@ import {
|
|
|
22
20
|
// Mocks — declared before imports that depend on platform/logger
|
|
23
21
|
// ---------------------------------------------------------------------------
|
|
24
22
|
|
|
25
|
-
const
|
|
26
|
-
tmpdir(),
|
|
27
|
-
`vellum-backfill-test-${randomBytes(4).toString("hex")}`,
|
|
28
|
-
);
|
|
29
|
-
const WORKSPACE_DIR = join(TEST_DIR, "workspace");
|
|
23
|
+
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
30
24
|
const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
|
|
31
25
|
|
|
32
26
|
function ensureTestDir(): void {
|
|
33
27
|
const dirs = [
|
|
34
|
-
TEST_DIR,
|
|
35
28
|
WORKSPACE_DIR,
|
|
36
|
-
join(
|
|
37
|
-
join(
|
|
38
|
-
join(
|
|
39
|
-
join(
|
|
29
|
+
join(WORKSPACE_DIR, "data"),
|
|
30
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
31
|
+
join(WORKSPACE_DIR, "data", "memory", "knowledge"),
|
|
32
|
+
join(WORKSPACE_DIR, "data", "logs"),
|
|
40
33
|
];
|
|
41
34
|
for (const dir of dirs) {
|
|
42
35
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
@@ -64,18 +57,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
64
57
|
getLogger: () => makeLoggerStub(),
|
|
65
58
|
}));
|
|
66
59
|
|
|
67
|
-
mock.module("../util/platform.js", () => ({
|
|
68
|
-
getRootDir: () => TEST_DIR,
|
|
69
|
-
getWorkspaceDir: () => WORKSPACE_DIR,
|
|
70
|
-
getWorkspaceConfigPath: () => CONFIG_PATH,
|
|
71
|
-
getDataDir: () => join(TEST_DIR, "data"),
|
|
72
|
-
getLogPath: () => join(TEST_DIR, "logs", "vellum.log"),
|
|
73
|
-
ensureDataDir: () => ensureTestDir(),
|
|
74
|
-
isMacOS: () => false,
|
|
75
|
-
isLinux: () => false,
|
|
76
|
-
isWindows: () => false,
|
|
77
|
-
}));
|
|
78
|
-
|
|
79
60
|
// Restore all mocked modules after this file's tests complete to prevent
|
|
80
61
|
// cross-test contamination when running grouped with other test files.
|
|
81
62
|
afterAll(() => {
|
|
@@ -171,9 +152,9 @@ describe("config loader backfill", () => {
|
|
|
171
152
|
ensureTestDir();
|
|
172
153
|
const resetPaths = [
|
|
173
154
|
CONFIG_PATH,
|
|
174
|
-
join(
|
|
175
|
-
join(
|
|
176
|
-
join(
|
|
155
|
+
join(WORKSPACE_DIR, "keys.enc"),
|
|
156
|
+
join(WORKSPACE_DIR, "data"),
|
|
157
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
177
158
|
];
|
|
178
159
|
for (const path of resetPaths) {
|
|
179
160
|
if (existsSync(path)) {
|
|
@@ -181,7 +162,7 @@ describe("config loader backfill", () => {
|
|
|
181
162
|
}
|
|
182
163
|
}
|
|
183
164
|
ensureTestDir();
|
|
184
|
-
_setStorePath(join(
|
|
165
|
+
_setStorePath(join(WORKSPACE_DIR, "keys.enc"));
|
|
185
166
|
invalidateConfigCache();
|
|
186
167
|
});
|
|
187
168
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
1
|
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
2
|
import { join } from "node:path";
|
|
5
3
|
import { describe, expect, mock, test } from "bun:test";
|
|
6
4
|
|
|
@@ -8,21 +6,15 @@ import { describe, expect, mock, test } from "bun:test";
|
|
|
8
6
|
// Mocks — declared before imports that depend on platform/logger
|
|
9
7
|
// ---------------------------------------------------------------------------
|
|
10
8
|
|
|
11
|
-
const
|
|
12
|
-
tmpdir(),
|
|
13
|
-
`vellum-schema-cmd-test-${randomBytes(4).toString("hex")}`,
|
|
14
|
-
);
|
|
15
|
-
const WORKSPACE_DIR = join(TEST_DIR, "workspace");
|
|
16
|
-
const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
|
|
9
|
+
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
17
10
|
|
|
18
11
|
function ensureTestDir(): void {
|
|
19
12
|
const dirs = [
|
|
20
|
-
TEST_DIR,
|
|
21
13
|
WORKSPACE_DIR,
|
|
22
|
-
join(
|
|
23
|
-
join(
|
|
24
|
-
join(
|
|
25
|
-
join(
|
|
14
|
+
join(WORKSPACE_DIR, "data"),
|
|
15
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
16
|
+
join(WORKSPACE_DIR, "data", "memory", "knowledge"),
|
|
17
|
+
join(WORKSPACE_DIR, "data", "logs"),
|
|
26
18
|
];
|
|
27
19
|
for (const dir of dirs) {
|
|
28
20
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
@@ -53,18 +45,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
53
45
|
getCliLogger: () => makeLoggerStub(),
|
|
54
46
|
}));
|
|
55
47
|
|
|
56
|
-
mock.module("../util/platform.js", () => ({
|
|
57
|
-
getRootDir: () => TEST_DIR,
|
|
58
|
-
getWorkspaceDir: () => WORKSPACE_DIR,
|
|
59
|
-
getWorkspaceConfigPath: () => CONFIG_PATH,
|
|
60
|
-
getDataDir: () => join(TEST_DIR, "data"),
|
|
61
|
-
getLogPath: () => join(TEST_DIR, "logs", "vellum.log"),
|
|
62
|
-
ensureDataDir: () => ensureTestDir(),
|
|
63
|
-
isMacOS: () => false,
|
|
64
|
-
isLinux: () => false,
|
|
65
|
-
isWindows: () => false,
|
|
66
|
-
}));
|
|
67
|
-
|
|
68
48
|
mock.module("../config/loader.js", () => ({
|
|
69
49
|
getConfig: () => ({
|
|
70
50
|
services: {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
1
|
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
2
|
import { join } from "node:path";
|
|
5
3
|
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
6
4
|
|
|
@@ -8,21 +6,16 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
8
6
|
// Mocks — declared before imports that depend on platform/logger
|
|
9
7
|
// ---------------------------------------------------------------------------
|
|
10
8
|
|
|
11
|
-
const
|
|
12
|
-
tmpdir(),
|
|
13
|
-
`vellum-schema-test-${randomBytes(4).toString("hex")}`,
|
|
14
|
-
);
|
|
15
|
-
const WORKSPACE_DIR = join(TEST_DIR, "workspace");
|
|
9
|
+
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
16
10
|
const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
|
|
17
11
|
|
|
18
12
|
function ensureTestDir(): void {
|
|
19
13
|
const dirs = [
|
|
20
|
-
TEST_DIR,
|
|
21
14
|
WORKSPACE_DIR,
|
|
22
|
-
join(
|
|
23
|
-
join(
|
|
24
|
-
join(
|
|
25
|
-
join(
|
|
15
|
+
join(WORKSPACE_DIR, "data"),
|
|
16
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
17
|
+
join(WORKSPACE_DIR, "data", "memory", "knowledge"),
|
|
18
|
+
join(WORKSPACE_DIR, "data", "logs"),
|
|
26
19
|
];
|
|
27
20
|
for (const dir of dirs) {
|
|
28
21
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
@@ -50,18 +43,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
50
43
|
getLogger: () => makeLoggerStub(),
|
|
51
44
|
}));
|
|
52
45
|
|
|
53
|
-
mock.module("../util/platform.js", () => ({
|
|
54
|
-
getRootDir: () => TEST_DIR,
|
|
55
|
-
getWorkspaceDir: () => WORKSPACE_DIR,
|
|
56
|
-
getWorkspaceConfigPath: () => CONFIG_PATH,
|
|
57
|
-
getDataDir: () => join(TEST_DIR, "data"),
|
|
58
|
-
getLogPath: () => join(TEST_DIR, "logs", "vellum.log"),
|
|
59
|
-
ensureDataDir: () => ensureTestDir(),
|
|
60
|
-
isMacOS: () => false,
|
|
61
|
-
isLinux: () => false,
|
|
62
|
-
isWindows: () => false,
|
|
63
|
-
}));
|
|
64
|
-
|
|
65
46
|
import {
|
|
66
47
|
buildElevenLabsVoiceSpec,
|
|
67
48
|
resolveVoiceQualityProfile,
|
|
@@ -102,8 +83,8 @@ describe("AssistantConfigSchema", () => {
|
|
|
102
83
|
expect(result.services["web-search"].mode).toBe("your-own");
|
|
103
84
|
expect(result.maxTokens).toBe(16000);
|
|
104
85
|
expect(result.thinking).toEqual({
|
|
105
|
-
enabled:
|
|
106
|
-
streamThinking:
|
|
86
|
+
enabled: true,
|
|
87
|
+
streamThinking: true,
|
|
107
88
|
});
|
|
108
89
|
expect(result.contextWindow).toEqual({
|
|
109
90
|
enabled: true,
|
|
@@ -175,8 +156,8 @@ describe("AssistantConfigSchema", () => {
|
|
|
175
156
|
const result = AssistantConfigSchema.parse({});
|
|
176
157
|
expect(result.memory.retrieval.dynamicBudget).toEqual({
|
|
177
158
|
enabled: true,
|
|
178
|
-
minInjectTokens:
|
|
179
|
-
maxInjectTokens:
|
|
159
|
+
minInjectTokens: 2400,
|
|
160
|
+
maxInjectTokens: 16000,
|
|
180
161
|
targetHeadroomTokens: 10000,
|
|
181
162
|
});
|
|
182
163
|
});
|
|
@@ -975,13 +956,13 @@ describe("buildElevenLabsVoiceSpec", () => {
|
|
|
975
956
|
|
|
976
957
|
describe("loadConfig with schema validation", () => {
|
|
977
958
|
beforeEach(() => {
|
|
978
|
-
// Keep
|
|
959
|
+
// Keep WORKSPACE_DIR and logs in place to avoid racing async logger stream init.
|
|
979
960
|
ensureTestDir();
|
|
980
961
|
const resetPaths = [
|
|
981
962
|
CONFIG_PATH,
|
|
982
|
-
join(
|
|
983
|
-
join(
|
|
984
|
-
join(
|
|
963
|
+
join(WORKSPACE_DIR, "keys.enc"),
|
|
964
|
+
join(WORKSPACE_DIR, "data"),
|
|
965
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
985
966
|
];
|
|
986
967
|
for (const path of resetPaths) {
|
|
987
968
|
if (existsSync(path)) {
|
|
@@ -989,7 +970,7 @@ describe("loadConfig with schema validation", () => {
|
|
|
989
970
|
}
|
|
990
971
|
}
|
|
991
972
|
ensureTestDir();
|
|
992
|
-
_setStorePath(join(
|
|
973
|
+
_setStorePath(join(WORKSPACE_DIR, "keys.enc"));
|
|
993
974
|
invalidateConfigCache();
|
|
994
975
|
});
|
|
995
976
|
|
|
@@ -998,7 +979,7 @@ describe("loadConfig with schema validation", () => {
|
|
|
998
979
|
invalidateConfigCache();
|
|
999
980
|
});
|
|
1000
981
|
|
|
1001
|
-
// Intentionally do not remove
|
|
982
|
+
// Intentionally do not remove WORKSPACE_DIR in afterAll.
|
|
1002
983
|
// A late async logger flush may still target logs under this path and can
|
|
1003
984
|
// intermittently trigger unhandled ENOENT in CI if the directory is removed.
|
|
1004
985
|
test("loads valid config", () => {
|
|
@@ -1021,8 +1002,8 @@ describe("loadConfig with schema validation", () => {
|
|
|
1021
1002
|
expect(config.services.inference.model).toBe("claude-opus-4-6");
|
|
1022
1003
|
expect(config.maxTokens).toBe(16000);
|
|
1023
1004
|
expect(config.thinking).toEqual({
|
|
1024
|
-
enabled:
|
|
1025
|
-
streamThinking:
|
|
1005
|
+
enabled: true,
|
|
1006
|
+
streamThinking: true,
|
|
1026
1007
|
});
|
|
1027
1008
|
expect(config.contextWindow).toEqual({
|
|
1028
1009
|
enabled: true,
|
|
@@ -1209,9 +1190,9 @@ describe("Call entrypoint gating", () => {
|
|
|
1209
1190
|
ensureTestDir();
|
|
1210
1191
|
const resetPaths = [
|
|
1211
1192
|
CONFIG_PATH,
|
|
1212
|
-
join(
|
|
1213
|
-
join(
|
|
1214
|
-
join(
|
|
1193
|
+
join(WORKSPACE_DIR, "keys.enc"),
|
|
1194
|
+
join(WORKSPACE_DIR, "data"),
|
|
1195
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
1215
1196
|
];
|
|
1216
1197
|
for (const path of resetPaths) {
|
|
1217
1198
|
if (existsSync(path)) {
|
|
@@ -1219,7 +1200,7 @@ describe("Call entrypoint gating", () => {
|
|
|
1219
1200
|
}
|
|
1220
1201
|
}
|
|
1221
1202
|
ensureTestDir();
|
|
1222
|
-
_setStorePath(join(
|
|
1203
|
+
_setStorePath(join(WORKSPACE_DIR, "keys.enc"));
|
|
1223
1204
|
invalidateConfigCache();
|
|
1224
1205
|
});
|
|
1225
1206
|
|