@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
|
@@ -193,11 +193,11 @@ describe("validateDrafts", () => {
|
|
|
193
193
|
expect(result.warnings).toHaveLength(0);
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
-
test("accepts a
|
|
196
|
+
test("accepts a 75 MB attachment (under 100 MB limit)", () => {
|
|
197
197
|
const drafts = [
|
|
198
198
|
makeDraft({
|
|
199
199
|
filename: "video.mov",
|
|
200
|
-
sizeBytes:
|
|
200
|
+
sizeBytes: 75 * 1024 * 1024,
|
|
201
201
|
}),
|
|
202
202
|
];
|
|
203
203
|
const result = validateDrafts(drafts);
|
|
@@ -205,18 +205,18 @@ describe("validateDrafts", () => {
|
|
|
205
205
|
expect(result.warnings).toHaveLength(0);
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
test("rejects a
|
|
208
|
+
test("rejects a 101 MB attachment with warning mentioning 100.0 MB limit", () => {
|
|
209
209
|
const drafts = [
|
|
210
210
|
makeDraft({
|
|
211
211
|
filename: "huge.mov",
|
|
212
|
-
sizeBytes:
|
|
212
|
+
sizeBytes: 101 * 1024 * 1024,
|
|
213
213
|
}),
|
|
214
214
|
];
|
|
215
215
|
const result = validateDrafts(drafts);
|
|
216
216
|
expect(result.accepted).toHaveLength(0);
|
|
217
217
|
expect(result.warnings).toHaveLength(1);
|
|
218
218
|
expect(result.warnings[0]).toContain("huge.mov");
|
|
219
|
-
expect(result.warnings[0]).toContain("
|
|
219
|
+
expect(result.warnings[0]).toContain("100.0 MB");
|
|
220
220
|
expect(result.warnings[0]).toContain("limit");
|
|
221
221
|
});
|
|
222
222
|
});
|
|
@@ -41,7 +41,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
41
41
|
model: "test",
|
|
42
42
|
provider: "test",
|
|
43
43
|
memory: { enabled: false },
|
|
44
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
44
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
45
45
|
secretDetection: { enabled: false },
|
|
46
46
|
}),
|
|
47
47
|
}));
|
|
@@ -29,7 +29,6 @@ const TEST_DIR = join(
|
|
|
29
29
|
);
|
|
30
30
|
|
|
31
31
|
let currentConfig: Record<string, unknown> = {
|
|
32
|
-
sandbox: { enabled: false, backend: "native" },
|
|
33
32
|
services: {
|
|
34
33
|
inference: {
|
|
35
34
|
mode: "your-own",
|
|
@@ -39,9 +38,9 @@ let currentConfig: Record<string, unknown> = {
|
|
|
39
38
|
"image-generation": {
|
|
40
39
|
mode: "your-own",
|
|
41
40
|
provider: "gemini",
|
|
42
|
-
model: "gemini-
|
|
41
|
+
model: "gemini-3.1-flash-image-preview",
|
|
43
42
|
},
|
|
44
|
-
"web-search": { mode: "your-own", provider: "
|
|
43
|
+
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
45
44
|
},
|
|
46
45
|
};
|
|
47
46
|
|
|
@@ -132,7 +131,6 @@ const { skillFlagKey } = await import("../config/skill-state.js");
|
|
|
132
131
|
beforeEach(() => {
|
|
133
132
|
mkdirSync(TEST_DIR, { recursive: true });
|
|
134
133
|
currentConfig = {
|
|
135
|
-
sandbox: { enabled: false, backend: "native" },
|
|
136
134
|
services: {
|
|
137
135
|
inference: {
|
|
138
136
|
mode: "your-own",
|
|
@@ -142,9 +140,9 @@ beforeEach(() => {
|
|
|
142
140
|
"image-generation": {
|
|
143
141
|
mode: "your-own",
|
|
144
142
|
provider: "gemini",
|
|
145
|
-
model: "gemini-
|
|
143
|
+
model: "gemini-3.1-flash-image-preview",
|
|
146
144
|
},
|
|
147
|
-
"web-search": { mode: "your-own", provider: "
|
|
145
|
+
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
148
146
|
},
|
|
149
147
|
};
|
|
150
148
|
});
|
|
@@ -186,7 +184,7 @@ function createSkillOnDisk(
|
|
|
186
184
|
// ---------------------------------------------------------------------------
|
|
187
185
|
|
|
188
186
|
describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
189
|
-
test("flag OFF skill does not appear in
|
|
187
|
+
test("flag OFF skill does not appear in skills catalog", () => {
|
|
190
188
|
createSkillOnDisk(
|
|
191
189
|
DECLARED_SKILL_ID,
|
|
192
190
|
"Contacts",
|
|
@@ -201,7 +199,6 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
201
199
|
);
|
|
202
200
|
|
|
203
201
|
currentConfig = {
|
|
204
|
-
sandbox: { enabled: false, backend: "native" },
|
|
205
202
|
assistantFeatureFlagValues: {
|
|
206
203
|
[DECLARED_FLAG_KEY]: false,
|
|
207
204
|
"feature_flags.browser.enabled": true,
|
|
@@ -215,17 +212,20 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
215
212
|
"image-generation": {
|
|
216
213
|
mode: "your-own",
|
|
217
214
|
provider: "gemini",
|
|
218
|
-
model: "gemini-
|
|
215
|
+
model: "gemini-3.1-flash-image-preview",
|
|
216
|
+
},
|
|
217
|
+
"web-search": {
|
|
218
|
+
mode: "your-own",
|
|
219
|
+
provider: "inference-provider-native",
|
|
219
220
|
},
|
|
220
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
221
221
|
},
|
|
222
222
|
};
|
|
223
223
|
|
|
224
224
|
const result = buildSystemPrompt();
|
|
225
225
|
|
|
226
226
|
// browser is explicitly enabled, declared flagged skill is explicitly off
|
|
227
|
-
expect(result).toContain(
|
|
228
|
-
expect(result).not.toContain(
|
|
227
|
+
expect(result).toContain("**browser**");
|
|
228
|
+
expect(result).not.toContain(`**${DECLARED_SKILL_ID}**`);
|
|
229
229
|
});
|
|
230
230
|
|
|
231
231
|
test("declared skills hidden when no flag overrides set (registry defaults to false)", () => {
|
|
@@ -243,7 +243,6 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
243
243
|
);
|
|
244
244
|
|
|
245
245
|
currentConfig = {
|
|
246
|
-
sandbox: { enabled: false, backend: "native" },
|
|
247
246
|
services: {
|
|
248
247
|
inference: {
|
|
249
248
|
mode: "your-own",
|
|
@@ -253,17 +252,20 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
253
252
|
"image-generation": {
|
|
254
253
|
mode: "your-own",
|
|
255
254
|
provider: "gemini",
|
|
256
|
-
model: "gemini-
|
|
255
|
+
model: "gemini-3.1-flash-image-preview",
|
|
256
|
+
},
|
|
257
|
+
"web-search": {
|
|
258
|
+
mode: "your-own",
|
|
259
|
+
provider: "inference-provider-native",
|
|
257
260
|
},
|
|
258
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
259
261
|
},
|
|
260
262
|
};
|
|
261
263
|
|
|
262
264
|
const result = buildSystemPrompt();
|
|
263
265
|
|
|
264
266
|
// Both skills declare feature flags with registry defaultEnabled: false
|
|
265
|
-
expect(result).not.toContain(
|
|
266
|
-
expect(result).not.toContain(
|
|
267
|
+
expect(result).not.toContain(`**${DECLARED_SKILL_ID}**`);
|
|
268
|
+
expect(result).not.toContain("**email-channel**");
|
|
267
269
|
});
|
|
268
270
|
|
|
269
271
|
test("flagged-off skills hidden when all flags are OFF", () => {
|
|
@@ -281,7 +283,6 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
281
283
|
);
|
|
282
284
|
|
|
283
285
|
currentConfig = {
|
|
284
|
-
sandbox: { enabled: false, backend: "native" },
|
|
285
286
|
assistantFeatureFlagValues: {
|
|
286
287
|
[DECLARED_FLAG_KEY]: false,
|
|
287
288
|
"feature_flags.email-channel.enabled": false,
|
|
@@ -295,16 +296,19 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
295
296
|
"image-generation": {
|
|
296
297
|
mode: "your-own",
|
|
297
298
|
provider: "gemini",
|
|
298
|
-
model: "gemini-
|
|
299
|
+
model: "gemini-3.1-flash-image-preview",
|
|
300
|
+
},
|
|
301
|
+
"web-search": {
|
|
302
|
+
mode: "your-own",
|
|
303
|
+
provider: "inference-provider-native",
|
|
299
304
|
},
|
|
300
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
301
305
|
},
|
|
302
306
|
};
|
|
303
307
|
|
|
304
308
|
const result = buildSystemPrompt();
|
|
305
309
|
|
|
306
|
-
expect(result).not.toContain(
|
|
307
|
-
expect(result).not.toContain(
|
|
310
|
+
expect(result).not.toContain(`**${DECLARED_SKILL_ID}**`);
|
|
311
|
+
expect(result).not.toContain("**email-channel**");
|
|
308
312
|
});
|
|
309
313
|
|
|
310
314
|
test("assistantFeatureFlagValues overrides control visibility", () => {
|
|
@@ -316,7 +320,6 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
316
320
|
);
|
|
317
321
|
|
|
318
322
|
currentConfig = {
|
|
319
|
-
sandbox: { enabled: false, backend: "native" },
|
|
320
323
|
assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: true },
|
|
321
324
|
services: {
|
|
322
325
|
inference: {
|
|
@@ -327,15 +330,18 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
327
330
|
"image-generation": {
|
|
328
331
|
mode: "your-own",
|
|
329
332
|
provider: "gemini",
|
|
330
|
-
model: "gemini-
|
|
333
|
+
model: "gemini-3.1-flash-image-preview",
|
|
334
|
+
},
|
|
335
|
+
"web-search": {
|
|
336
|
+
mode: "your-own",
|
|
337
|
+
provider: "inference-provider-native",
|
|
331
338
|
},
|
|
332
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
333
339
|
},
|
|
334
340
|
};
|
|
335
341
|
|
|
336
342
|
const result = buildSystemPrompt();
|
|
337
343
|
|
|
338
|
-
expect(result).toContain(
|
|
344
|
+
expect(result).toContain(`**${DECLARED_SKILL_ID}**`);
|
|
339
345
|
});
|
|
340
346
|
|
|
341
347
|
test("persisted overrides for undeclared flags are respected", () => {
|
|
@@ -347,7 +353,6 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
347
353
|
);
|
|
348
354
|
|
|
349
355
|
currentConfig = {
|
|
350
|
-
sandbox: { enabled: false, backend: "native" },
|
|
351
356
|
assistantFeatureFlagValues: { "feature_flags.browser.enabled": false },
|
|
352
357
|
services: {
|
|
353
358
|
inference: {
|
|
@@ -358,9 +363,12 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
358
363
|
"image-generation": {
|
|
359
364
|
mode: "your-own",
|
|
360
365
|
provider: "gemini",
|
|
361
|
-
model: "gemini-
|
|
366
|
+
model: "gemini-3.1-flash-image-preview",
|
|
367
|
+
},
|
|
368
|
+
"web-search": {
|
|
369
|
+
mode: "your-own",
|
|
370
|
+
provider: "inference-provider-native",
|
|
362
371
|
},
|
|
363
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
364
372
|
},
|
|
365
373
|
};
|
|
366
374
|
|
|
@@ -368,7 +376,7 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
368
376
|
|
|
369
377
|
// browser declares featureFlag: "browser" and the user
|
|
370
378
|
// explicitly disabled it — that override must be honored.
|
|
371
|
-
expect(result).not.toContain(
|
|
379
|
+
expect(result).not.toContain("**browser**");
|
|
372
380
|
});
|
|
373
381
|
|
|
374
382
|
test("declared flags with no persisted override use registry default", () => {
|
|
@@ -380,7 +388,6 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
380
388
|
);
|
|
381
389
|
|
|
382
390
|
currentConfig = {
|
|
383
|
-
sandbox: { enabled: false, backend: "native" },
|
|
384
391
|
services: {
|
|
385
392
|
inference: {
|
|
386
393
|
mode: "your-own",
|
|
@@ -390,23 +397,25 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
390
397
|
"image-generation": {
|
|
391
398
|
mode: "your-own",
|
|
392
399
|
provider: "gemini",
|
|
393
|
-
model: "gemini-
|
|
400
|
+
model: "gemini-3.1-flash-image-preview",
|
|
401
|
+
},
|
|
402
|
+
"web-search": {
|
|
403
|
+
mode: "your-own",
|
|
404
|
+
provider: "inference-provider-native",
|
|
394
405
|
},
|
|
395
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
396
406
|
},
|
|
397
407
|
};
|
|
398
408
|
|
|
399
409
|
const result = buildSystemPrompt();
|
|
400
410
|
|
|
401
411
|
// browser is declared in the registry with defaultEnabled: true
|
|
402
|
-
expect(result).toContain(
|
|
412
|
+
expect(result).toContain("**browser**");
|
|
403
413
|
});
|
|
404
414
|
|
|
405
415
|
test("skill without featureFlag is never flag-gated", () => {
|
|
406
416
|
createSkillOnDisk("my-skill", "My Skill", "A skill without feature flag");
|
|
407
417
|
|
|
408
418
|
currentConfig = {
|
|
409
|
-
sandbox: { enabled: false, backend: "native" },
|
|
410
419
|
services: {
|
|
411
420
|
inference: {
|
|
412
421
|
mode: "your-own",
|
|
@@ -416,16 +425,19 @@ describe("buildSystemPrompt assistant feature flag filtering", () => {
|
|
|
416
425
|
"image-generation": {
|
|
417
426
|
mode: "your-own",
|
|
418
427
|
provider: "gemini",
|
|
419
|
-
model: "gemini-
|
|
428
|
+
model: "gemini-3.1-flash-image-preview",
|
|
429
|
+
},
|
|
430
|
+
"web-search": {
|
|
431
|
+
mode: "your-own",
|
|
432
|
+
provider: "inference-provider-native",
|
|
420
433
|
},
|
|
421
|
-
"web-search": { mode: "your-own", provider: "anthropic-native" },
|
|
422
434
|
},
|
|
423
435
|
};
|
|
424
436
|
|
|
425
437
|
const result = buildSystemPrompt();
|
|
426
438
|
|
|
427
439
|
// Skills without featureFlag declared are never gated — always pass through
|
|
428
|
-
expect(result).toContain(
|
|
440
|
+
expect(result).toContain("**my-skill**");
|
|
429
441
|
});
|
|
430
442
|
});
|
|
431
443
|
|
|
@@ -31,7 +31,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
31
31
|
model: "test",
|
|
32
32
|
provider: "test",
|
|
33
33
|
memory: { enabled: false },
|
|
34
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
34
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
35
35
|
}),
|
|
36
36
|
}));
|
|
37
37
|
|
|
@@ -167,7 +167,7 @@ describe("uploadAttachment", () => {
|
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
test("accepts payload exactly at MAX_UPLOAD_BYTES", () => {
|
|
170
|
-
// MAX_UPLOAD_BYTES (
|
|
170
|
+
// MAX_UPLOAD_BYTES (100 MB) is divisible by 3, so (MAX/3)*4 base64 chars
|
|
171
171
|
// decodes to exactly MAX bytes with no padding.
|
|
172
172
|
const exactLength = (MAX_UPLOAD_BYTES / 3) * 4;
|
|
173
173
|
const exactData = "A".repeat(exactLength);
|
|
@@ -27,7 +27,7 @@ const geminiGenerateContentFn = mock(async () => geminiGenerateContentResult);
|
|
|
27
27
|
|
|
28
28
|
mock.module("../config/loader.js", () => ({
|
|
29
29
|
getConfig: () => ({
|
|
30
|
-
imageGenModel: "gemini-
|
|
30
|
+
imageGenModel: "gemini-3.1-flash-image-preview",
|
|
31
31
|
services: {
|
|
32
32
|
inference: {
|
|
33
33
|
mode: "your-own",
|
|
@@ -37,9 +37,9 @@ mock.module("../config/loader.js", () => ({
|
|
|
37
37
|
"image-generation": {
|
|
38
38
|
mode: "your-own",
|
|
39
39
|
provider: "gemini",
|
|
40
|
-
model: "gemini-
|
|
40
|
+
model: "gemini-3.1-flash-image-preview",
|
|
41
41
|
},
|
|
42
|
-
"web-search": { mode: "your-own", provider: "
|
|
42
|
+
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
43
43
|
},
|
|
44
44
|
}),
|
|
45
45
|
}));
|
|
@@ -47,6 +47,8 @@ mock.module("../config/loader.js", () => ({
|
|
|
47
47
|
mock.module("../security/secure-keys.js", () => ({
|
|
48
48
|
getSecureKeyAsync: async (name: string) =>
|
|
49
49
|
name === "gemini" ? mockGeminiKey : null,
|
|
50
|
+
getProviderKeyAsync: async (provider: string) =>
|
|
51
|
+
provider === "gemini" ? mockGeminiKey : undefined,
|
|
50
52
|
}));
|
|
51
53
|
|
|
52
54
|
mock.module("../util/platform.js", () => ({
|
|
@@ -8,7 +8,6 @@ import { afterAll, beforeAll, describe, expect, mock, test } from "bun:test";
|
|
|
8
8
|
|
|
9
9
|
mock.module("../config/loader.js", () => ({
|
|
10
10
|
getConfig: () => ({
|
|
11
|
-
sandbox: { enabled: false, backend: "native" },
|
|
12
11
|
assistantFeatureFlagValues: {
|
|
13
12
|
"feature_flags.browser.enabled": true,
|
|
14
13
|
},
|
|
@@ -54,7 +54,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
54
54
|
model: "test",
|
|
55
55
|
provider: "test",
|
|
56
56
|
memory: { enabled: false },
|
|
57
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
57
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
58
58
|
secretDetection: { enabled: false },
|
|
59
59
|
calls: mockCallsConfig,
|
|
60
60
|
}),
|
|
@@ -62,7 +62,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
62
62
|
model: "test",
|
|
63
63
|
provider: "test",
|
|
64
64
|
memory: { enabled: false },
|
|
65
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
65
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
66
66
|
secretDetection: { enabled: false },
|
|
67
67
|
calls: mockCallsConfig,
|
|
68
68
|
ingress: {
|
|
@@ -17,7 +17,7 @@ function buildSignal(
|
|
|
17
17
|
signalId: "test-signal-1",
|
|
18
18
|
createdAt: Date.now(),
|
|
19
19
|
sourceChannel: "phone",
|
|
20
|
-
|
|
20
|
+
sourceContextId: "test-session-1",
|
|
21
21
|
sourceEventName: "ingress.access_request.callback_handoff",
|
|
22
22
|
contextPayload: {
|
|
23
23
|
requestId: "req-123",
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test: POST /v1/conversations/:id/cancel must resolve the
|
|
3
|
+
* conversation key to the internal conversation ID before calling
|
|
4
|
+
* cancelGeneration(). Without resolveConversationId(), the cancel
|
|
5
|
+
* endpoint receives the client's local conversation key (which differs
|
|
6
|
+
* from the daemon's internal ID), fails to find the conversation, and
|
|
7
|
+
* silently ignores the cancel — leaving the stream running.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdtempSync, realpathSync, rmSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { afterAll, describe, expect, mock, test } from "bun:test";
|
|
13
|
+
|
|
14
|
+
mock.module("../config/env.js", () => ({ isHttpAuthDisabled: () => true }));
|
|
15
|
+
|
|
16
|
+
const testDir = realpathSync(
|
|
17
|
+
mkdtempSync(join(tmpdir(), "cancel-resolve-key-test-")),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
mock.module("../util/platform.js", () => ({
|
|
21
|
+
getRootDir: () => testDir,
|
|
22
|
+
getDataDir: () => testDir,
|
|
23
|
+
isMacOS: () => process.platform === "darwin",
|
|
24
|
+
isLinux: () => process.platform === "linux",
|
|
25
|
+
isWindows: () => process.platform === "win32",
|
|
26
|
+
getPidPath: () => join(testDir, "test.pid"),
|
|
27
|
+
getDbPath: () => join(testDir, "test.db"),
|
|
28
|
+
getLogPath: () => join(testDir, "test.log"),
|
|
29
|
+
ensureDataDir: () => {},
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
mock.module("../util/logger.js", () => ({
|
|
33
|
+
getLogger: () =>
|
|
34
|
+
new Proxy({} as Record<string, unknown>, {
|
|
35
|
+
get: () => () => {},
|
|
36
|
+
}),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
mock.module("../config/loader.js", () => ({
|
|
40
|
+
getConfig: () => ({
|
|
41
|
+
ui: {},
|
|
42
|
+
model: "test",
|
|
43
|
+
provider: "test",
|
|
44
|
+
memory: { enabled: false },
|
|
45
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
46
|
+
secretDetection: { enabled: false },
|
|
47
|
+
contextWindow: { maxInputTokens: 200000 },
|
|
48
|
+
services: {
|
|
49
|
+
inference: {
|
|
50
|
+
mode: "your-own",
|
|
51
|
+
provider: "anthropic",
|
|
52
|
+
model: "claude-opus-4-6",
|
|
53
|
+
},
|
|
54
|
+
"image-generation": {
|
|
55
|
+
mode: "your-own",
|
|
56
|
+
provider: "gemini",
|
|
57
|
+
model: "gemini-3.1-flash-image-preview",
|
|
58
|
+
},
|
|
59
|
+
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
import { getOrCreateConversation } from "../memory/conversation-key-store.js";
|
|
65
|
+
import { initializeDb, resetDb } from "../memory/db.js";
|
|
66
|
+
import { conversationManagementRouteDefinitions } from "../runtime/routes/conversation-management-routes.js";
|
|
67
|
+
|
|
68
|
+
initializeDb();
|
|
69
|
+
|
|
70
|
+
afterAll(() => {
|
|
71
|
+
resetDb();
|
|
72
|
+
try {
|
|
73
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
74
|
+
} catch {
|
|
75
|
+
/* best effort */
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe("POST /v1/conversations/:id/cancel", () => {
|
|
80
|
+
test("resolves conversation key to internal ID before cancelling", () => {
|
|
81
|
+
// Create a conversation via key — this assigns an internal ID that
|
|
82
|
+
// differs from the key.
|
|
83
|
+
const conversationKey = "client-local-uuid-abc123";
|
|
84
|
+
const mapping = getOrCreateConversation(conversationKey);
|
|
85
|
+
const internalId = mapping.conversationId;
|
|
86
|
+
|
|
87
|
+
// Sanity: key and internal ID should differ.
|
|
88
|
+
expect(internalId).not.toBe(conversationKey);
|
|
89
|
+
|
|
90
|
+
// Track which ID cancelGeneration receives.
|
|
91
|
+
let cancelledId: string | undefined;
|
|
92
|
+
const routes = conversationManagementRouteDefinitions({
|
|
93
|
+
switchConversation: async () => null,
|
|
94
|
+
renameConversation: () => false,
|
|
95
|
+
clearAllConversations: () => 0,
|
|
96
|
+
cancelGeneration: (id) => {
|
|
97
|
+
cancelledId = id;
|
|
98
|
+
return true;
|
|
99
|
+
},
|
|
100
|
+
destroyConversation: () => {},
|
|
101
|
+
undoLastMessage: async () => null,
|
|
102
|
+
regenerateResponse: async () => null,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const cancelRoute = routes.find(
|
|
106
|
+
(r) => r.endpoint === "conversations/:id/cancel",
|
|
107
|
+
)!;
|
|
108
|
+
|
|
109
|
+
// Simulate the HTTP handler with the conversation KEY (what the
|
|
110
|
+
// macOS client sends — it uses the key, not the internal ID).
|
|
111
|
+
cancelRoute.handler({
|
|
112
|
+
params: { id: conversationKey },
|
|
113
|
+
req: new Request("http://localhost/v1/conversations/x/cancel", {
|
|
114
|
+
method: "POST",
|
|
115
|
+
}),
|
|
116
|
+
url: new URL("http://localhost/v1/conversations/x/cancel"),
|
|
117
|
+
server: undefined as never,
|
|
118
|
+
authContext: undefined as never,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// cancelGeneration must receive the INTERNAL ID, not the raw key.
|
|
122
|
+
expect(cancelledId).toBe(internalId);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("falls back to raw ID when key is not in the mapping", () => {
|
|
126
|
+
let cancelledId: string | undefined;
|
|
127
|
+
const routes = conversationManagementRouteDefinitions({
|
|
128
|
+
switchConversation: async () => null,
|
|
129
|
+
renameConversation: () => false,
|
|
130
|
+
clearAllConversations: () => 0,
|
|
131
|
+
cancelGeneration: (id) => {
|
|
132
|
+
cancelledId = id;
|
|
133
|
+
return true;
|
|
134
|
+
},
|
|
135
|
+
destroyConversation: () => {},
|
|
136
|
+
undoLastMessage: async () => null,
|
|
137
|
+
regenerateResponse: async () => null,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const cancelRoute = routes.find(
|
|
141
|
+
(r) => r.endpoint === "conversations/:id/cancel",
|
|
142
|
+
)!;
|
|
143
|
+
|
|
144
|
+
// Use an ID that isn't a known key — should pass through as-is.
|
|
145
|
+
const directId = "direct-conversation-id";
|
|
146
|
+
cancelRoute.handler({
|
|
147
|
+
params: { id: directId },
|
|
148
|
+
req: new Request("http://localhost/v1/conversations/x/cancel", {
|
|
149
|
+
method: "POST",
|
|
150
|
+
}),
|
|
151
|
+
url: new URL("http://localhost/v1/conversations/x/cancel"),
|
|
152
|
+
server: undefined as never,
|
|
153
|
+
authContext: undefined as never,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
expect(cancelledId).toBe(directId);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
@@ -19,7 +19,6 @@ let mockPrimaryInboxAddress: string | undefined;
|
|
|
19
19
|
mock.module("../calls/twilio-rest.js", () => ({
|
|
20
20
|
hasTwilioCredentials: () => mockHasTwilioCredentials,
|
|
21
21
|
getPhoneNumberSid: async () => null,
|
|
22
|
-
getTollFreeVerificationStatus: async () => null,
|
|
23
22
|
}));
|
|
24
23
|
|
|
25
24
|
mock.module("../config/env.js", () => ({}));
|
|
@@ -13,7 +13,6 @@ let mockGatewayHealth = {
|
|
|
13
13
|
|
|
14
14
|
mock.module("../calls/twilio-rest.js", () => ({
|
|
15
15
|
getPhoneNumberSid: async () => null,
|
|
16
|
-
getTollFreeVerificationStatus: async () => null,
|
|
17
16
|
getTwilioCredentials: () => ({
|
|
18
17
|
accountSid: "AC_test",
|
|
19
18
|
authToken: "test-auth-token",
|