@vellumai/assistant 0.4.56 → 0.4.57
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/ARCHITECTURE.md +10 -10
- package/Dockerfile +3 -0
- package/README.md +11 -11
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/memory.md +3 -4
- package/docs/credential-execution-service.md +13 -20
- package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +7 -7
- package/src/__tests__/anthropic-provider.test.ts +172 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
- package/src/__tests__/approval-cascade.test.ts +2 -2
- package/src/__tests__/approval-routes-http.test.ts +3 -4
- package/src/__tests__/asset-materialize-tool.test.ts +5 -5
- package/src/__tests__/asset-search-tool.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +5 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
- package/src/__tests__/attachments-store.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +5 -3
- package/src/__tests__/browser-skill-endstate.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +2 -2
- package/src/__tests__/callback-handoff-copy.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +31 -32
- package/src/__tests__/chrome-cdp.test.ts +47 -18
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +9 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop.test.ts +11 -4
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +33 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
- package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +23 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +185 -173
- package/src/__tests__/conversation-seed-composer.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +4 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
- package/src/__tests__/conversation-starter-routes.test.ts +291 -0
- package/src/__tests__/conversation-wipe.test.ts +438 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
- package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
- package/src/__tests__/credential-security-e2e.test.ts +20 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +227 -0
- package/src/__tests__/credentials-cli.test.ts +3 -0
- package/src/__tests__/date-context.test.ts +59 -377
- package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/encrypted-store.test.ts +237 -15
- package/src/__tests__/ephemeral-permissions.test.ts +4 -5
- package/src/__tests__/event-bus.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +4 -4
- package/src/__tests__/gemini-provider.test.ts +6 -9
- package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/host-shell-tool.test.ts +6 -6
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/intent-routing.test.ts +51 -99
- package/src/__tests__/invite-routes-http.test.ts +5 -0
- package/src/__tests__/list-messages-attachments.test.ts +1 -1
- package/src/__tests__/managed-proxy-context.test.ts +2 -5
- package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
- package/src/__tests__/media-generate-image.test.ts +32 -15
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
- package/src/__tests__/memory-recall-quality.test.ts +4 -3
- package/src/__tests__/memory-regressions.test.ts +86 -90
- package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
- package/src/__tests__/migration-export-http.test.ts +26 -27
- package/src/__tests__/migration-import-commit-http.test.ts +165 -37
- package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
- package/src/__tests__/migration-validate-http.test.ts +16 -16
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
- package/src/__tests__/notification-broadcaster.test.ts +1 -1
- package/src/__tests__/notification-decision-fallback.test.ts +2 -2
- package/src/__tests__/notification-decision-identity.test.ts +8 -9
- package/src/__tests__/notification-decision-strategy.test.ts +1 -1
- package/src/__tests__/notification-deep-link.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
- package/src/__tests__/onboarding-template-contract.test.ts +23 -59
- package/src/__tests__/provider-error-scenarios.test.ts +154 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
- package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
- package/src/__tests__/provider-registry-ollama.test.ts +5 -2
- package/src/__tests__/qdrant-manager.test.ts +7 -7
- package/src/__tests__/ratelimit.test.ts +0 -74
- package/src/__tests__/recording-handler.test.ts +0 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +46 -2
- package/src/__tests__/schema-transforms.test.ts +114 -54
- package/src/__tests__/secret-onetime-send.test.ts +20 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
- package/src/__tests__/secret-scanner-executor.test.ts +1 -2
- package/src/__tests__/send-endpoint-busy.test.ts +63 -4
- package/src/__tests__/send-notification-tool.test.ts +2 -2
- package/src/__tests__/shell-credential-ref.test.ts +0 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
- package/src/__tests__/skill-memory.test.ts +547 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
- package/src/__tests__/slack-channel-config.test.ts +109 -94
- package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
- package/src/__tests__/swarm-recursion.test.ts +2 -2
- package/src/__tests__/swarm-tool.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +19 -66
- package/src/__tests__/telegram-config.test.ts +121 -0
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trace-emitter.test.ts +8 -1
- package/src/__tests__/trust-store.test.ts +7 -8
- package/src/__tests__/twilio-routes.test.ts +1 -18
- package/src/__tests__/user-reference.test.ts +82 -2
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +3 -3
- package/src/avatar/ascii-renderer.ts +2 -2
- package/src/avatar/png-renderer.ts +2 -2
- package/src/avatar/resvg-lazy.ts +21 -0
- package/src/calls/guardian-dispatch.ts +1 -1
- package/src/calls/relay-access-wait.ts +2 -2
- package/src/calls/twilio-rest.ts +0 -248
- package/src/cli/AGENTS.md +5 -8
- package/src/cli/__tests__/notifications.test.ts +5 -5
- package/src/cli/commands/avatar.ts +64 -2
- package/src/cli/commands/conversations.ts +131 -1
- package/src/cli/commands/credentials.ts +2 -0
- package/src/cli/commands/notifications.ts +3 -3
- package/src/cli.ts +10 -0
- package/src/config/bundled-skills/acp/SKILL.md +5 -5
- package/src/config/bundled-skills/acp/TOOLS.json +6 -6
- package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
- package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
- package/src/config/bundled-skills/browser/SKILL.md +15 -15
- package/src/config/bundled-skills/browser/TOOLS.json +14 -14
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
- package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
- package/src/config/bundled-skills/contacts/SKILL.md +3 -3
- package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
- package/src/config/bundled-skills/document/SKILL.md +4 -4
- package/src/config/bundled-skills/document/TOOLS.json +2 -2
- package/src/config/bundled-skills/followups/TOOLS.json +3 -3
- package/src/config/bundled-skills/gmail/SKILL.md +32 -32
- package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
- package/src/config/bundled-skills/google-calendar/types.ts +1 -1
- package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
- package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
- package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
- package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +29 -25
- package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +3 -3
- package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
- package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
- package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
- package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
- package/src/config/bundled-skills/schedule/SKILL.md +26 -26
- package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
- package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
- package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
- package/src/config/bundled-skills/sequences/SKILL.md +2 -2
- package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
- package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
- package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
- package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
- package/src/config/bundled-skills/slack/SKILL.md +2 -2
- package/src/config/bundled-skills/slack/TOOLS.json +8 -8
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
- package/src/config/bundled-skills/tasks/SKILL.md +1 -1
- package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
- package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
- package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
- package/src/config/bundled-skills/watcher/SKILL.md +4 -4
- package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
- package/src/config/feature-flag-registry.json +33 -17
- package/src/config/schemas/sandbox.ts +1 -1
- package/src/config/schemas/services.ts +13 -3
- package/src/config/schemas/timeouts.ts +0 -10
- package/src/contacts/contact-store.ts +63 -0
- package/src/contacts/contacts-write.ts +1 -1
- package/src/daemon/assistant-attachments.ts +2 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
- package/src/daemon/conversation-agent-loop.ts +7 -30
- package/src/daemon/conversation-error.ts +24 -0
- package/src/daemon/conversation-memory.ts +8 -7
- package/src/daemon/conversation-runtime-assembly.ts +139 -274
- package/src/daemon/conversation-slash.ts +7 -26
- package/src/daemon/conversation-surfaces.ts +14 -0
- package/src/daemon/conversation-tool-setup.ts +9 -8
- package/src/daemon/conversation.ts +2 -0
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +10 -83
- package/src/daemon/handlers/config-channels.ts +12 -2
- package/src/daemon/handlers/config-slack-channel.ts +7 -1
- package/src/daemon/handlers/config-telegram.ts +6 -1
- package/src/daemon/handlers/conversations.ts +2 -2
- package/src/daemon/handlers/skills.ts +4 -0
- package/src/daemon/lifecycle.ts +28 -4
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +1 -5
- package/src/daemon/shutdown-handlers.ts +9 -3
- package/src/daemon/tool-side-effects.ts +40 -0
- package/src/daemon/trace-emitter.ts +25 -2
- package/src/events/domain-events.ts +1 -1
- package/src/events/tool-permission-telemetry-listener.ts +46 -0
- package/src/inbound/platform-callback-registration.ts +0 -18
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +15 -8
- package/src/media/gemini-image-service.ts +125 -21
- package/src/memory/attachments-store.ts +3 -3
- package/src/memory/channel-verification-sessions.ts +6 -6
- package/src/memory/conversation-crud.ts +196 -1
- package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
- package/src/memory/conversation-title-service.ts +2 -3
- package/src/memory/db-init.ts +25 -1
- package/src/memory/invite-store.ts +4 -4
- package/src/memory/items-extractor.ts +4 -4
- package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/jobs-worker.ts +7 -5
- package/src/memory/lifecycle-events-store.ts +63 -0
- package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
- package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
- package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
- package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
- package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
- package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +223 -96
- package/src/memory/retriever.ts +115 -138
- package/src/memory/schema/calls.ts +1 -1
- package/src/memory/schema/contacts.ts +1 -1
- package/src/memory/schema/infrastructure.ts +29 -0
- package/src/memory/schema/memory-core.ts +7 -17
- package/src/memory/schema/notifications.ts +1 -1
- package/src/memory/search/formatting.ts +23 -6
- package/src/memory/search/lexical.ts +2 -0
- package/src/memory/search/semantic.ts +2 -0
- package/src/memory/search/staleness.ts +1 -0
- package/src/memory/search/types.ts +4 -0
- package/src/memory/task-memory-cleanup.ts +96 -6
- package/src/memory/trace-event-store.ts +148 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/emit-signal.ts +4 -4
- package/src/notifications/events-store.ts +4 -4
- package/src/notifications/signal.ts +1 -1
- package/src/oauth/manual-token-connection.ts +49 -25
- package/src/permissions/checker.ts +6 -5
- package/src/permissions/defaults.ts +4 -4
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
- package/src/prompts/cache-boundary.ts +8 -0
- package/src/prompts/system-prompt.ts +105 -634
- package/src/prompts/templates/BOOTSTRAP.md +166 -33
- package/src/prompts/templates/IDENTITY.md +8 -23
- package/src/prompts/templates/SOUL.md +20 -41
- package/src/prompts/templates/USER.md +3 -19
- package/src/prompts/user-reference.ts +14 -16
- package/src/providers/anthropic/client.ts +46 -2
- package/src/providers/gemini/client.ts +6 -9
- package/src/providers/managed-proxy/constants.ts +1 -7
- package/src/providers/managed-proxy/context.ts +0 -1
- package/src/providers/model-intents.ts +5 -5
- package/src/providers/openai/client.ts +10 -1
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/ratelimit.ts +0 -35
- package/src/providers/registry.ts +3 -5
- package/src/providers/retry.ts +18 -1
- package/src/runtime/access-request-helper.ts +1 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/channel-verification-service.ts +1 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/guardian-vellum-migration.ts +63 -1
- package/src/runtime/http-server.ts +8 -4
- package/src/runtime/migrations/vbundle-builder.ts +212 -32
- package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
- package/src/runtime/migrations/vbundle-importer.ts +66 -1
- package/src/runtime/migrations/vbundle-validator.ts +17 -3
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
- package/src/runtime/routes/attachment-routes.ts +2 -2
- package/src/runtime/routes/btw-routes.ts +9 -0
- package/src/runtime/routes/channel-verification-routes.ts +19 -2
- package/src/runtime/routes/conversation-management-routes.ts +55 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +49 -5
- package/src/runtime/routes/conversation-starter-routes.ts +207 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +25 -13
- package/src/runtime/routes/secret-routes.ts +18 -0
- package/src/runtime/routes/settings-routes.ts +8 -8
- package/src/runtime/routes/telemetry-routes.ts +53 -0
- package/src/runtime/routes/trace-event-routes.ts +62 -0
- package/src/runtime/tool-grant-request-helper.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +47 -31
- package/src/security/encrypted-store.ts +263 -78
- package/src/skills/catalog-install.ts +10 -0
- package/src/skills/managed-store.ts +2 -0
- package/src/skills/skill-memory.ts +220 -0
- package/src/subagent/manager.ts +1 -4
- package/src/telemetry/types.ts +10 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/telemetry/usage-telemetry-reporter.ts +51 -4
- package/src/tools/AGENTS.md +11 -11
- package/src/tools/acp/spawn.ts +1 -1
- package/src/tools/apps/executors.ts +8 -8
- package/src/tools/apps/registry.ts +1 -1
- package/src/tools/assets/materialize.ts +6 -6
- package/src/tools/assets/search.ts +10 -10
- package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
- package/src/tools/browser/auth-detector.ts +6 -6
- package/src/tools/browser/browser-execution.ts +13 -13
- package/src/tools/browser/browser-manager.ts +3 -3
- package/src/tools/browser/chrome-cdp.ts +5 -5
- package/src/tools/browser/jit-auth.ts +2 -2
- package/src/tools/browser/network-recorder.test.ts +2 -2
- package/src/tools/browser/network-recorder.ts +3 -3
- package/src/tools/browser/runtime-check.ts +3 -3
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/computer-use/definitions.ts +18 -18
- package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
- package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
- package/src/tools/credentials/broker-types.ts +5 -5
- package/src/tools/credentials/broker.ts +15 -15
- package/src/tools/credentials/metadata-store.ts +2 -2
- package/src/tools/credentials/resolve.ts +1 -1
- package/src/tools/credentials/selection.ts +1 -1
- package/src/tools/credentials/tool-policy.ts +1 -1
- package/src/tools/credentials/vault.ts +115 -25
- package/src/tools/execution-target.ts +2 -2
- package/src/tools/executor.ts +7 -7
- package/src/tools/filesystem/edit.ts +2 -2
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +1 -1
- package/src/tools/host-filesystem/edit.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -1
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +9 -8
- package/src/tools/mcp/mcp-tool-factory.ts +7 -6
- package/src/tools/memory/definitions.ts +6 -5
- package/src/tools/memory/handlers.test.ts +1 -1
- package/src/tools/network/__tests__/web-search.test.ts +3 -3
- package/src/tools/network/domain-normalize.ts +2 -2
- package/src/tools/network/script-proxy/session-manager.ts +10 -10
- package/src/tools/network/web-fetch.ts +1 -1
- package/src/tools/network/web-search.ts +3 -3
- package/src/tools/permission-checker.ts +8 -8
- package/src/tools/registry.ts +7 -7
- package/src/tools/schedule/list.ts +2 -2
- package/src/tools/schema-transforms.ts +31 -21
- package/src/tools/secret-detection-handler.ts +1 -1
- package/src/tools/sensitive-output-placeholders.ts +1 -1
- package/src/tools/shared/filesystem/edit-engine.ts +1 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
- package/src/tools/shared/filesystem/image-read.ts +25 -5
- package/src/tools/shared/filesystem/path-policy.ts +2 -2
- package/src/tools/shared/shell-output.ts +1 -1
- package/src/tools/side-effects.ts +1 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +3 -3
- package/src/tools/skills/sandbox-runner.ts +3 -3
- package/src/tools/subagent/read.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -2
- package/src/tools/swarm/delegate.ts +3 -3
- package/src/tools/system/request-permission.ts +5 -4
- package/src/tools/terminal/backends/native.ts +4 -4
- package/src/tools/terminal/parser.ts +6 -6
- package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
- package/src/tools/terminal/shell.ts +16 -16
- package/src/tools/tool-approval-handler.ts +21 -12
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +3 -3
- package/src/tools/ui-surface/definitions.ts +9 -37
- package/src/tools/watcher/list.ts +1 -1
- package/src/util/logger.ts +7 -2
- package/src/util/retry.ts +29 -1
- package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
- package/src/cli/reference.ts +0 -38
- package/src/memory/job-handlers/capability-cards.ts +0 -420
- package/src/runtime/routes/thread-starter-routes.ts +0 -294
|
@@ -34,13 +34,14 @@ function toArrayBuffer(data: Uint8Array): ArrayBuffer {
|
|
|
34
34
|
const testDir = realpathSync(
|
|
35
35
|
mkdtempSync(join(tmpdir(), "migration-import-preflight-http-test-")),
|
|
36
36
|
);
|
|
37
|
-
const testDbDir = join(testDir, "db");
|
|
37
|
+
const testDbDir = join(testDir, "data", "db");
|
|
38
38
|
const testDbPath = join(testDbDir, "assistant.db");
|
|
39
39
|
const testConfigPath = join(testDir, "config.json");
|
|
40
40
|
|
|
41
41
|
mock.module("../util/platform.js", () => ({
|
|
42
42
|
getRootDir: () => testDir,
|
|
43
|
-
getDataDir: () => testDir,
|
|
43
|
+
getDataDir: () => join(testDir, "data"),
|
|
44
|
+
getWorkspaceDir: () => testDir,
|
|
44
45
|
getWorkspaceConfigPath: () => testConfigPath,
|
|
45
46
|
isMacOS: () => process.platform === "darwin",
|
|
46
47
|
isLinux: () => process.platform === "linux",
|
|
@@ -64,9 +65,8 @@ mock.module("../config/loader.js", () => ({
|
|
|
64
65
|
model: "test",
|
|
65
66
|
provider: "test",
|
|
66
67
|
memory: { enabled: false },
|
|
67
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
68
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
68
69
|
secretDetection: { enabled: false },
|
|
69
|
-
sandbox: { enabled: false },
|
|
70
70
|
}),
|
|
71
71
|
}));
|
|
72
72
|
|
|
@@ -525,8 +525,8 @@ describe("handleMigrationImportPreflight — validation failures", () => {
|
|
|
525
525
|
describe("analyzeImport", () => {
|
|
526
526
|
test("detects create when file does not exist on disk", () => {
|
|
527
527
|
const resolver = new DefaultPathResolver(
|
|
528
|
-
|
|
529
|
-
join(testDir, "nonexistent-
|
|
528
|
+
undefined,
|
|
529
|
+
join(testDir, "nonexistent-workspace"),
|
|
530
530
|
);
|
|
531
531
|
|
|
532
532
|
const report = analyzeImport({
|
|
@@ -553,7 +553,7 @@ describe("analyzeImport", () => {
|
|
|
553
553
|
});
|
|
554
554
|
|
|
555
555
|
test("detects unchanged when file on disk matches bundle", () => {
|
|
556
|
-
const resolver = new DefaultPathResolver(
|
|
556
|
+
const resolver = new DefaultPathResolver(undefined, testDir);
|
|
557
557
|
|
|
558
558
|
const report = analyzeImport({
|
|
559
559
|
manifest: {
|
|
@@ -577,7 +577,7 @@ describe("analyzeImport", () => {
|
|
|
577
577
|
});
|
|
578
578
|
|
|
579
579
|
test("detects overwrite when file on disk differs from bundle", () => {
|
|
580
|
-
const resolver = new DefaultPathResolver(
|
|
580
|
+
const resolver = new DefaultPathResolver(undefined, testDir);
|
|
581
581
|
|
|
582
582
|
const report = analyzeImport({
|
|
583
583
|
manifest: {
|
|
@@ -602,7 +602,7 @@ describe("analyzeImport", () => {
|
|
|
602
602
|
});
|
|
603
603
|
|
|
604
604
|
test("flags unknown archive paths as conflicts with skip action", () => {
|
|
605
|
-
const resolver = new DefaultPathResolver(
|
|
605
|
+
const resolver = new DefaultPathResolver(undefined, testDir);
|
|
606
606
|
|
|
607
607
|
const report = analyzeImport({
|
|
608
608
|
manifest: {
|
|
@@ -640,7 +640,7 @@ describe("analyzeImport", () => {
|
|
|
640
640
|
});
|
|
641
641
|
|
|
642
642
|
test("includes manifest in report", () => {
|
|
643
|
-
const resolver = new DefaultPathResolver(
|
|
643
|
+
const resolver = new DefaultPathResolver(undefined, testDir);
|
|
644
644
|
const manifest = {
|
|
645
645
|
schema_version: "1.0",
|
|
646
646
|
created_at: "2024-01-01T00:00:00.000Z",
|
|
@@ -668,29 +668,90 @@ describe("analyzeImport", () => {
|
|
|
668
668
|
// ---------------------------------------------------------------------------
|
|
669
669
|
|
|
670
670
|
describe("DefaultPathResolver", () => {
|
|
671
|
-
test("resolves data/db/assistant.db to
|
|
671
|
+
test("resolves data/db/assistant.db to workspace db path (backward compat)", () => {
|
|
672
672
|
const resolver = new DefaultPathResolver(
|
|
673
|
-
|
|
674
|
-
"/
|
|
673
|
+
undefined,
|
|
674
|
+
"/home/user/.vellum/workspace",
|
|
675
|
+
);
|
|
676
|
+
expect(resolver.resolve("data/db/assistant.db")).toBe(
|
|
677
|
+
"/home/user/.vellum/workspace/data/db/assistant.db",
|
|
675
678
|
);
|
|
676
|
-
expect(resolver.resolve("data/db/assistant.db")).toBe("/some/db.db");
|
|
677
679
|
});
|
|
678
680
|
|
|
679
|
-
test("resolves config/settings.json to
|
|
681
|
+
test("resolves config/settings.json to workspace config path (backward compat)", () => {
|
|
680
682
|
const resolver = new DefaultPathResolver(
|
|
681
|
-
|
|
682
|
-
"/
|
|
683
|
+
undefined,
|
|
684
|
+
"/home/user/.vellum/workspace",
|
|
685
|
+
);
|
|
686
|
+
expect(resolver.resolve("config/settings.json")).toBe(
|
|
687
|
+
"/home/user/.vellum/workspace/config.json",
|
|
683
688
|
);
|
|
684
|
-
expect(resolver.resolve("config/settings.json")).toBe("/some/config.json");
|
|
685
689
|
});
|
|
686
690
|
|
|
687
691
|
test("returns null for unknown paths", () => {
|
|
688
692
|
const resolver = new DefaultPathResolver(
|
|
689
|
-
|
|
690
|
-
"/
|
|
693
|
+
undefined,
|
|
694
|
+
"/home/user/.vellum/workspace",
|
|
691
695
|
);
|
|
692
696
|
expect(resolver.resolve("unknown/path.txt")).toBeNull();
|
|
693
697
|
});
|
|
698
|
+
|
|
699
|
+
test("resolves valid skills path via backward compat", () => {
|
|
700
|
+
const resolver = new DefaultPathResolver(
|
|
701
|
+
undefined,
|
|
702
|
+
"/home/user/.vellum/workspace",
|
|
703
|
+
);
|
|
704
|
+
expect(resolver.resolve("skills/my-skill/SKILL.md")).toBe(
|
|
705
|
+
"/home/user/.vellum/workspace/skills/my-skill/SKILL.md",
|
|
706
|
+
);
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
test("resolves workspace/ prefix paths", () => {
|
|
710
|
+
const resolver = new DefaultPathResolver(
|
|
711
|
+
undefined,
|
|
712
|
+
"/home/user/.vellum/workspace",
|
|
713
|
+
);
|
|
714
|
+
expect(resolver.resolve("workspace/data/db/assistant.db")).toBe(
|
|
715
|
+
"/home/user/.vellum/workspace/data/db/assistant.db",
|
|
716
|
+
);
|
|
717
|
+
expect(resolver.resolve("workspace/config.json")).toBe(
|
|
718
|
+
"/home/user/.vellum/workspace/config.json",
|
|
719
|
+
);
|
|
720
|
+
expect(resolver.resolve("workspace/skills/my-skill/SKILL.md")).toBe(
|
|
721
|
+
"/home/user/.vellum/workspace/skills/my-skill/SKILL.md",
|
|
722
|
+
);
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
test("returns null for workspace/ path traversal attempt", () => {
|
|
726
|
+
const resolver = new DefaultPathResolver(
|
|
727
|
+
undefined,
|
|
728
|
+
"/home/user/.vellum/workspace",
|
|
729
|
+
);
|
|
730
|
+
expect(resolver.resolve("workspace/../../etc/passwd")).toBeNull();
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
test("returns null for skills path traversal attempt (../../etc/passwd)", () => {
|
|
734
|
+
const resolver = new DefaultPathResolver(
|
|
735
|
+
undefined,
|
|
736
|
+
"/home/user/.vellum/workspace",
|
|
737
|
+
);
|
|
738
|
+
expect(resolver.resolve("skills/../../etc/passwd")).toBeNull();
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
test("returns null for skills path traversal attempt (../../../.ssh/authorized_keys)", () => {
|
|
742
|
+
const resolver = new DefaultPathResolver(
|
|
743
|
+
undefined,
|
|
744
|
+
"/home/user/.vellum/workspace",
|
|
745
|
+
);
|
|
746
|
+
expect(
|
|
747
|
+
resolver.resolve("skills/../../../.ssh/authorized_keys"),
|
|
748
|
+
).toBeNull();
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
test("returns null for skills paths when workspaceDir is not provided", () => {
|
|
752
|
+
const resolver = new DefaultPathResolver();
|
|
753
|
+
expect(resolver.resolve("skills/my-skill/SKILL.md")).toBeNull();
|
|
754
|
+
});
|
|
694
755
|
});
|
|
695
756
|
|
|
696
757
|
// ---------------------------------------------------------------------------
|
|
@@ -53,9 +53,8 @@ mock.module("../config/loader.js", () => ({
|
|
|
53
53
|
model: "test",
|
|
54
54
|
provider: "test",
|
|
55
55
|
memory: { enabled: false },
|
|
56
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
56
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
57
57
|
secretDetection: { enabled: false },
|
|
58
|
-
sandbox: { enabled: false },
|
|
59
58
|
}),
|
|
60
59
|
}));
|
|
61
60
|
|
|
@@ -307,26 +306,27 @@ describe("validateVBundle", () => {
|
|
|
307
306
|
expect(manifestError).toBeDefined();
|
|
308
307
|
});
|
|
309
308
|
|
|
310
|
-
test("
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
);
|
|
309
|
+
test("bundle with only manifest (no data files) is structurally valid", () => {
|
|
310
|
+
// After the workspace walk refactor, only manifest.json is required.
|
|
311
|
+
// But the manifest checksum must match for full validity.
|
|
312
|
+
const manifestWithoutChecksum = {
|
|
313
|
+
schema_version: "1.0",
|
|
314
|
+
created_at: new Date().toISOString(),
|
|
315
|
+
files: [],
|
|
316
|
+
};
|
|
317
|
+
const manifestSha256 = sha256Hex(canonicalizeJson(manifestWithoutChecksum));
|
|
318
|
+
const manifest = {
|
|
319
|
+
...manifestWithoutChecksum,
|
|
320
|
+
manifest_sha256: manifestSha256,
|
|
321
|
+
};
|
|
322
|
+
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
319
323
|
const tar = createTarArchive([
|
|
320
324
|
{ name: "manifest.json", data: manifestData },
|
|
321
325
|
]);
|
|
322
326
|
const vbundle = gzipSync(tar);
|
|
323
327
|
const result = validateVBundle(vbundle);
|
|
324
328
|
|
|
325
|
-
expect(result.is_valid).toBe(
|
|
326
|
-
const dbError = result.errors.find(
|
|
327
|
-
(e) => e.code === "MISSING_ENTRY" && e.path === "data/db/assistant.db",
|
|
328
|
-
);
|
|
329
|
-
expect(dbError).toBeDefined();
|
|
329
|
+
expect(result.is_valid).toBe(true);
|
|
330
330
|
});
|
|
331
331
|
|
|
332
332
|
test("invalid manifest JSON returns INVALID_MANIFEST_JSON error", () => {
|
|
@@ -62,7 +62,7 @@ describe("model intents", () => {
|
|
|
62
62
|
"claude-opus-4-6",
|
|
63
63
|
);
|
|
64
64
|
expect(resolveModelIntent("anthropic", "vision-optimized")).toBe(
|
|
65
|
-
"claude-
|
|
65
|
+
"claude-opus-4-6",
|
|
66
66
|
);
|
|
67
67
|
expect(resolveModelIntent("openai", "latency-optimized")).toBe(
|
|
68
68
|
"gpt-4o-mini",
|
|
@@ -5,7 +5,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
5
5
|
/**
|
|
6
6
|
* Guard test: domain-specific routing sections must NOT appear in the system
|
|
7
7
|
* prompt source file. Routing cues now live in skill frontmatter
|
|
8
|
-
* (`activation-hints` / `avoid-when`) and are projected into
|
|
8
|
+
* (`activation-hints` / `avoid-when`) and are projected into the skills catalog.
|
|
9
9
|
*
|
|
10
10
|
* If this test fails, you are re-introducing hardcoded routing into the system
|
|
11
11
|
* prompt. Instead, add `activation-hints` to the skill's SKILL.md frontmatter.
|
|
@@ -115,7 +115,7 @@ function makeSignal(
|
|
|
115
115
|
signalId: "sig-broadcast-001",
|
|
116
116
|
createdAt: Date.now(),
|
|
117
117
|
sourceChannel: "scheduler",
|
|
118
|
-
|
|
118
|
+
sourceContextId: "sess-001",
|
|
119
119
|
sourceEventName: "test.event",
|
|
120
120
|
contextPayload: {},
|
|
121
121
|
attentionHints: {
|
|
@@ -65,7 +65,7 @@ function makeSignal(
|
|
|
65
65
|
signalId: "sig-fallback-guardian-1",
|
|
66
66
|
createdAt: Date.now(),
|
|
67
67
|
sourceChannel: "phone",
|
|
68
|
-
|
|
68
|
+
sourceContextId: "call-session-1",
|
|
69
69
|
sourceEventName: "guardian.question",
|
|
70
70
|
contextPayload: {
|
|
71
71
|
questionText: "What is the gate code?",
|
|
@@ -308,7 +308,7 @@ describe("access-request instruction enforcement", () => {
|
|
|
308
308
|
signalId: "sig-access-req-1",
|
|
309
309
|
createdAt: Date.now(),
|
|
310
310
|
sourceChannel: "telegram",
|
|
311
|
-
|
|
311
|
+
sourceContextId: "tg-session-1",
|
|
312
312
|
sourceEventName: "ingress.access_request",
|
|
313
313
|
contextPayload: {
|
|
314
314
|
senderIdentifier: "Alice",
|
|
@@ -45,7 +45,9 @@ mock.module("../prompts/system-prompt.js", () => ({
|
|
|
45
45
|
|
|
46
46
|
// ── Provider mock with system prompt capture ──────────────────────────
|
|
47
47
|
|
|
48
|
-
let configuredProvider: {
|
|
48
|
+
let configuredProvider: {
|
|
49
|
+
sendMessage: (...args: unknown[]) => Promise<unknown>;
|
|
50
|
+
} | null = null;
|
|
49
51
|
let extractedToolUse: unknown = null;
|
|
50
52
|
let capturedSystemPrompt: string | undefined;
|
|
51
53
|
|
|
@@ -81,7 +83,7 @@ function makeSignal(
|
|
|
81
83
|
signalId: "sig-identity-test-1",
|
|
82
84
|
createdAt: Date.now(),
|
|
83
85
|
sourceChannel: "phone",
|
|
84
|
-
|
|
86
|
+
sourceContextId: "call-session-1",
|
|
85
87
|
sourceEventName: "guardian.question",
|
|
86
88
|
contextPayload: {
|
|
87
89
|
questionText: "What is the gate code?",
|
|
@@ -141,9 +143,7 @@ describe("identity context in notification decision engine", () => {
|
|
|
141
143
|
|
|
142
144
|
expect(capturedSystemPrompt).toBeDefined();
|
|
143
145
|
expect(capturedSystemPrompt).toContain("<assistant-identity>");
|
|
144
|
-
expect(capturedSystemPrompt).toContain(
|
|
145
|
-
"I am Jarvis, a helpful assistant",
|
|
146
|
-
);
|
|
146
|
+
expect(capturedSystemPrompt).toContain("I am Jarvis, a helpful assistant");
|
|
147
147
|
expect(capturedSystemPrompt).toContain("</assistant-identity>");
|
|
148
148
|
});
|
|
149
149
|
|
|
@@ -192,10 +192,9 @@ describe("identity context in notification decision engine", () => {
|
|
|
192
192
|
configuredProvider = null;
|
|
193
193
|
|
|
194
194
|
const signal = makeSignal();
|
|
195
|
-
const decision = await evaluateSignal(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
);
|
|
195
|
+
const decision = await evaluateSignal(signal, [
|
|
196
|
+
"vellum",
|
|
197
|
+
] as NotificationChannel[]);
|
|
199
198
|
|
|
200
199
|
// Fallback should produce valid copy regardless of identity context
|
|
201
200
|
expect(decision.fallbackUsed).toBe(true);
|
|
@@ -239,7 +239,6 @@ describe("ASK_GUARDIAN canonical notification path", () => {
|
|
|
239
239
|
|
|
240
240
|
const signalParams = emitCalls[0] as Record<string, unknown>;
|
|
241
241
|
expect(typeof signalParams.onConversationCreated).toBe("function");
|
|
242
|
-
expect(signalParams.skipVellumThread).toBeUndefined();
|
|
243
242
|
});
|
|
244
243
|
|
|
245
244
|
test("creates guardian action deliveries from notification pipeline delivery results", async () => {
|
|
@@ -72,7 +72,7 @@ function makeSignal(
|
|
|
72
72
|
signalId: `sig-${crypto.randomUUID()}`,
|
|
73
73
|
createdAt: Date.now(),
|
|
74
74
|
sourceChannel: "scheduler",
|
|
75
|
-
|
|
75
|
+
sourceContextId: "schedule-123",
|
|
76
76
|
sourceEventName: "schedule.complete",
|
|
77
77
|
contextPayload: { scheduleId: "schedule-123", name: "Drink water" },
|
|
78
78
|
attentionHints: {
|
|
@@ -118,7 +118,7 @@ describe("recurring schedule notification dedup", () => {
|
|
|
118
118
|
id: firstSignal.signalId,
|
|
119
119
|
sourceEventName: "schedule.complete",
|
|
120
120
|
sourceChannel: "scheduler",
|
|
121
|
-
|
|
121
|
+
sourceContextId: "schedule-123",
|
|
122
122
|
attentionHints: firstSignal.attentionHints,
|
|
123
123
|
payload: firstSignal.contextPayload,
|
|
124
124
|
// No dedupeKey — this is the bug scenario
|
|
@@ -132,7 +132,7 @@ describe("recurring schedule notification dedup", () => {
|
|
|
132
132
|
id: secondSignal.signalId,
|
|
133
133
|
sourceEventName: "schedule.complete",
|
|
134
134
|
sourceChannel: "scheduler",
|
|
135
|
-
|
|
135
|
+
sourceContextId: "schedule-123",
|
|
136
136
|
attentionHints: secondSignal.attentionHints,
|
|
137
137
|
payload: secondSignal.contextPayload,
|
|
138
138
|
});
|
|
@@ -160,7 +160,7 @@ describe("recurring schedule notification dedup", () => {
|
|
|
160
160
|
id: firstSignal.signalId,
|
|
161
161
|
sourceEventName: "schedule.complete",
|
|
162
162
|
sourceChannel: "scheduler",
|
|
163
|
-
|
|
163
|
+
sourceContextId: "schedule-123",
|
|
164
164
|
attentionHints: firstSignal.attentionHints,
|
|
165
165
|
payload: firstSignal.contextPayload,
|
|
166
166
|
dedupeKey: `schedule:complete:schedule-123:${Date.now() - 60_000}`,
|
|
@@ -173,7 +173,7 @@ describe("recurring schedule notification dedup", () => {
|
|
|
173
173
|
id: secondSignal.signalId,
|
|
174
174
|
sourceEventName: "schedule.complete",
|
|
175
175
|
sourceChannel: "scheduler",
|
|
176
|
-
|
|
176
|
+
sourceContextId: "schedule-123",
|
|
177
177
|
attentionHints: secondSignal.attentionHints,
|
|
178
178
|
payload: secondSignal.contextPayload,
|
|
179
179
|
dedupeKey: `schedule:complete:schedule-123:${Date.now()}`,
|
|
@@ -204,7 +204,7 @@ describe("recurring schedule notification dedup", () => {
|
|
|
204
204
|
id: firstSignal.signalId,
|
|
205
205
|
sourceEventName: "schedule.notify",
|
|
206
206
|
sourceChannel: "scheduler",
|
|
207
|
-
|
|
207
|
+
sourceContextId: "schedule-123",
|
|
208
208
|
attentionHints: firstSignal.attentionHints,
|
|
209
209
|
payload: firstSignal.contextPayload,
|
|
210
210
|
dedupeKey: `schedule:notify:schedule-123:${Date.now() - 60_000}`,
|
|
@@ -219,7 +219,7 @@ describe("recurring schedule notification dedup", () => {
|
|
|
219
219
|
id: secondSignal.signalId,
|
|
220
220
|
sourceEventName: "schedule.notify",
|
|
221
221
|
sourceChannel: "scheduler",
|
|
222
|
-
|
|
222
|
+
sourceContextId: "schedule-123",
|
|
223
223
|
attentionHints: secondSignal.attentionHints,
|
|
224
224
|
payload: secondSignal.contextPayload,
|
|
225
225
|
dedupeKey: `schedule:notify:schedule-123:${Date.now()}`,
|
|
@@ -83,9 +83,7 @@ async function createTestApp(providerKey = "github", clientId = "client-1") {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
beforeEach(() => {
|
|
86
|
-
|
|
87
|
-
initializeDb();
|
|
88
|
-
// Explicitly clear all OAuth tables to prevent cross-test state pollution.
|
|
86
|
+
// Clear OAuth tables between tests instead of full DB reset + migration.
|
|
89
87
|
// Delete in FK-dependency order: connections → apps → providers.
|
|
90
88
|
resetTestTables("oauth_connections", "oauth_apps", "oauth_providers");
|
|
91
89
|
mockDeleteSecureKeyAsync.mockClear();
|
|
@@ -484,17 +484,22 @@ describe("OAuth2 gateway transport", () => {
|
|
|
484
484
|
};
|
|
485
485
|
|
|
486
486
|
let capturedAuthUrl = "";
|
|
487
|
+
let urlReady!: () => void;
|
|
488
|
+
const urlReadyPromise = new Promise<void>((r) => {
|
|
489
|
+
urlReady = r;
|
|
490
|
+
});
|
|
487
491
|
const flowPromise = startOAuth2Flow(
|
|
488
492
|
BASE_OAUTH_CONFIG,
|
|
489
493
|
{
|
|
490
494
|
openUrl: (url) => {
|
|
491
495
|
capturedAuthUrl = url;
|
|
496
|
+
urlReady();
|
|
492
497
|
},
|
|
493
498
|
},
|
|
494
499
|
{ callbackTransport: "loopback" },
|
|
495
500
|
);
|
|
496
501
|
|
|
497
|
-
await
|
|
502
|
+
await urlReadyPromise;
|
|
498
503
|
|
|
499
504
|
const authUrl = new URL(capturedAuthUrl);
|
|
500
505
|
const redirectUri = authUrl.searchParams.get("redirect_uri")!;
|
|
@@ -9,14 +9,19 @@ const user = readFileSync(join(templatesDir, "USER.md"), "utf-8");
|
|
|
9
9
|
|
|
10
10
|
describe("onboarding template contracts", () => {
|
|
11
11
|
describe("BOOTSTRAP.md", () => {
|
|
12
|
-
test("
|
|
12
|
+
test("preserves comment line format instruction", () => {
|
|
13
|
+
expect(bootstrap).toMatch(/^_ Lines starting with _/);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("contains identity discovery prompts", () => {
|
|
13
17
|
const lower = bootstrap.toLowerCase();
|
|
14
|
-
expect(lower).toContain("
|
|
18
|
+
expect(lower).toContain("your name");
|
|
19
|
+
expect(lower).toContain("personality");
|
|
20
|
+
expect(lower).toContain("avatar");
|
|
15
21
|
});
|
|
16
22
|
|
|
17
23
|
test("infers personality organically instead of asking directly", () => {
|
|
18
24
|
const lower = bootstrap.toLowerCase();
|
|
19
|
-
// Personality step must instruct organic discovery via conversation
|
|
20
25
|
expect(lower).toContain("personality");
|
|
21
26
|
expect(lower).toContain("emerge");
|
|
22
27
|
expect(lower).toContain("vibe");
|
|
@@ -28,28 +33,17 @@ describe("onboarding template contracts", () => {
|
|
|
28
33
|
expect(lower).toContain("change it later");
|
|
29
34
|
});
|
|
30
35
|
|
|
31
|
-
test("
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
expect(
|
|
35
|
-
|
|
36
|
-
expect(
|
|
37
|
-
// The conversation sequence must include identity/naming
|
|
38
|
-
expect(lower).toContain("who am i");
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("asks user name AFTER assistant identity is established", () => {
|
|
42
|
-
// Step 1 is the assistant's name, step 4 is asking the user's name
|
|
43
|
-
const assistantNameIdx = bootstrap.indexOf("Your name:");
|
|
44
|
-
const userNameIdx = bootstrap.indexOf("who am I talking to?");
|
|
45
|
-
expect(assistantNameIdx).toBeGreaterThan(-1);
|
|
46
|
-
expect(userNameIdx).toBeGreaterThan(-1);
|
|
47
|
-
expect(assistantNameIdx).toBeLessThan(userNameIdx);
|
|
36
|
+
test("asks about user after assistant identity", () => {
|
|
37
|
+
const nameIdx = bootstrap.indexOf("Your name");
|
|
38
|
+
const theirNameIdx = bootstrap.indexOf("Their name");
|
|
39
|
+
expect(nameIdx).toBeGreaterThan(-1);
|
|
40
|
+
expect(theirNameIdx).toBeGreaterThan(-1);
|
|
41
|
+
expect(nameIdx).toBeLessThan(theirNameIdx);
|
|
48
42
|
});
|
|
49
43
|
|
|
50
44
|
test("gathers user context: work role, hobbies, daily tools", () => {
|
|
51
45
|
const lower = bootstrap.toLowerCase();
|
|
52
|
-
expect(lower).toContain("work");
|
|
46
|
+
expect(lower).toContain("work role");
|
|
53
47
|
expect(lower).toContain("hobbies");
|
|
54
48
|
expect(lower).toContain("tools");
|
|
55
49
|
});
|
|
@@ -57,51 +51,32 @@ describe("onboarding template contracts", () => {
|
|
|
57
51
|
test("shows exactly 2 suggestions via ui_show card with relay_prompt actions", () => {
|
|
58
52
|
expect(bootstrap).toContain("ui_show");
|
|
59
53
|
expect(bootstrap).toContain("exactly 2");
|
|
60
|
-
// Must use card surface with relay_prompt action buttons
|
|
61
|
-
expect(bootstrap).toContain('surface_type: "card"');
|
|
62
54
|
expect(bootstrap).toContain("relay_prompt");
|
|
63
55
|
});
|
|
64
56
|
|
|
65
|
-
test("contains
|
|
57
|
+
test("contains wrapping-up criteria with required conditions", () => {
|
|
66
58
|
const lower = bootstrap.toLowerCase();
|
|
67
|
-
expect(lower).toContain("
|
|
68
|
-
expect(lower).toContain("
|
|
69
|
-
// Assistant name is hard-required
|
|
70
|
-
expect(lower).toContain("you have a name");
|
|
71
|
-
expect(lower).toContain("hard-required");
|
|
59
|
+
expect(lower).toContain("wrapping up");
|
|
60
|
+
expect(lower).toContain("done with onboarding");
|
|
72
61
|
expect(lower).toContain("vibe");
|
|
73
|
-
|
|
74
|
-
expect(lower).toContain("resolved");
|
|
75
|
-
expect(lower).toContain("work role");
|
|
76
|
-
expect(lower).toContain("2 suggestions from step 6");
|
|
62
|
+
expect(lower).toContain("two suggestions");
|
|
77
63
|
});
|
|
78
64
|
|
|
79
65
|
test("contains refusal policy", () => {
|
|
80
66
|
const lower = bootstrap.toLowerCase();
|
|
81
|
-
// Assistant name is hard-required, user details are best-effort
|
|
82
67
|
expect(lower).toContain("hard-required");
|
|
83
68
|
expect(lower).toContain("best-effort");
|
|
84
|
-
// Refusal is a valid resolution
|
|
85
69
|
expect(lower).toContain("declined");
|
|
86
|
-
expect(lower).toContain("
|
|
70
|
+
expect(lower).toContain("not interrogation");
|
|
87
71
|
});
|
|
88
72
|
|
|
89
73
|
test("defines resolved as provided, inferred, or declined", () => {
|
|
90
74
|
const lower = bootstrap.toLowerCase();
|
|
91
|
-
// The template must define what "resolved" means
|
|
92
75
|
expect(lower).toContain("resolved");
|
|
93
76
|
expect(lower).toContain("inferred");
|
|
94
77
|
expect(lower).toContain("declined");
|
|
95
78
|
});
|
|
96
79
|
|
|
97
|
-
// em-dash and technical jargon instructions are now hardcoded in the system
|
|
98
|
-
// prompt builder (buildSystemPrompt) rather than in the BOOTSTRAP.md template.
|
|
99
|
-
|
|
100
|
-
test("preserves comment line format instruction", () => {
|
|
101
|
-
// The template must start with the comment format explanation
|
|
102
|
-
expect(bootstrap).toMatch(/^_ Lines starting with _/);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
80
|
test("instructs saving to IDENTITY.md, USER.md, and SOUL.md via file_edit", () => {
|
|
106
81
|
expect(bootstrap).toContain("IDENTITY.md");
|
|
107
82
|
expect(bootstrap).toContain("USER.md");
|
|
@@ -118,18 +93,13 @@ describe("onboarding template contracts", () => {
|
|
|
118
93
|
expect(identity).toContain("**Emoji:**");
|
|
119
94
|
});
|
|
120
95
|
|
|
121
|
-
test("contains
|
|
122
|
-
|
|
123
|
-
expect(lower).toContain("change their emoji");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("contains the style tendency field", () => {
|
|
127
|
-
expect(identity).toContain("**Style tendency:**");
|
|
96
|
+
test("contains parsed field format guidance", () => {
|
|
97
|
+
expect(identity).toContain("parsed by the app");
|
|
128
98
|
});
|
|
129
99
|
});
|
|
130
100
|
|
|
131
101
|
describe("USER.md", () => {
|
|
132
|
-
test("contains
|
|
102
|
+
test("contains profile fields", () => {
|
|
133
103
|
expect(user).toContain("Preferred name/reference:");
|
|
134
104
|
expect(user).toContain("Goals:");
|
|
135
105
|
expect(user).toContain("Locale:");
|
|
@@ -137,11 +107,5 @@ describe("onboarding template contracts", () => {
|
|
|
137
107
|
expect(user).toContain("Hobbies/fun:");
|
|
138
108
|
expect(user).toContain("Daily tools:");
|
|
139
109
|
});
|
|
140
|
-
|
|
141
|
-
test("documents resolved-field status conventions", () => {
|
|
142
|
-
const lower = user.toLowerCase();
|
|
143
|
-
expect(lower).toContain("declined_by_user");
|
|
144
|
-
expect(lower).toContain("resolved");
|
|
145
|
-
});
|
|
146
110
|
});
|
|
147
111
|
});
|