@vellumai/assistant 0.4.56 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +204 -185
- 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 +249 -15
- package/src/__tests__/ephemeral-permissions.test.ts +4 -5
- package/src/__tests__/event-bus.test.ts +3 -3
- package/src/__tests__/file-read-tool.test.ts +40 -0
- 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-file-read-tool.test.ts +87 -0
- package/src/__tests__/host-shell-tool.test.ts +6 -6
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/identity-intro-cache.test.ts +209 -0
- 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 +2 -2
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
- package/src/__tests__/non-member-access-request.test.ts +3 -3
- 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 +549 -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 +141 -275
- 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 +26 -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 +5 -1
- 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 +45 -4
- package/src/notifications/emit-signal.ts +5 -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 +172 -33
- package/src/prompts/templates/IDENTITY.md +8 -24
- 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 +51 -19
- 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 +16 -2
- 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 +61 -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 +93 -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/identity-intro-cache.ts +105 -0
- package/src/runtime/routes/identity-routes.ts +51 -0
- 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 +9 -9
- 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 +262 -78
- package/src/skills/catalog-install.ts +10 -0
- package/src/skills/managed-store.ts +2 -0
- package/src/skills/skill-memory.ts +222 -0
- package/src/subagent/manager.ts +1 -4
- package/src/telemetry/types.ts +10 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +7 -2
- package/src/telemetry/usage-telemetry-reporter.ts +53 -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 +15 -4
- package/src/tools/filesystem/write.ts +1 -1
- package/src/tools/host-filesystem/edit.ts +2 -1
- package/src/tools/host-filesystem/read.ts +18 -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/pricing.ts +4 -0
- 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
|
@@ -10,18 +10,9 @@ import {
|
|
|
10
10
|
/** Wednesday 2026-02-18 12:00 UTC */
|
|
11
11
|
const WED_FEB_18 = Date.UTC(2026, 1, 18, 12, 0, 0);
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
const SAT_FEB_21 = Date.UTC(2026, 1, 21, 12, 0, 0);
|
|
15
|
-
|
|
16
|
-
/** Sunday 2026-02-22 12:00 UTC */
|
|
17
|
-
const SUN_FEB_22 = Date.UTC(2026, 1, 22, 12, 0, 0);
|
|
18
|
-
|
|
19
|
-
/** Tuesday 2026-12-29 12:00 UTC — year boundary */
|
|
13
|
+
/** Tuesday 2026-12-29 12:00 UTC - year boundary */
|
|
20
14
|
const TUE_DEC_29 = Date.UTC(2026, 11, 29, 12, 0, 0);
|
|
21
15
|
|
|
22
|
-
/** Friday 2026-02-27 12:00 UTC */
|
|
23
|
-
const FRI_FEB_27 = Date.UTC(2026, 1, 27, 12, 0, 0);
|
|
24
|
-
|
|
25
16
|
// ---------------------------------------------------------------------------
|
|
26
17
|
// Basic structure
|
|
27
18
|
// ---------------------------------------------------------------------------
|
|
@@ -56,9 +47,17 @@ describe("buildTemporalContext", () => {
|
|
|
56
47
|
expect(result).toContain("Current UTC time: 2026-02-18T12:00:00.000Z");
|
|
57
48
|
});
|
|
58
49
|
|
|
59
|
-
test("
|
|
50
|
+
test("includes timezone source", () => {
|
|
51
|
+
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
52
|
+
expect(result).toContain("Timezone source:");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("does not include week definitions, next weekend, next work week, or horizon dates", () => {
|
|
60
56
|
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
61
|
-
expect(result).toContain("
|
|
57
|
+
expect(result).not.toContain("Week definitions");
|
|
58
|
+
expect(result).not.toContain("Next weekend");
|
|
59
|
+
expect(result).not.toContain("Next work week");
|
|
60
|
+
expect(result).not.toContain("Upcoming dates");
|
|
62
61
|
});
|
|
63
62
|
|
|
64
63
|
test("uses user timezone when provided and records source metadata", () => {
|
|
@@ -69,11 +68,48 @@ describe("buildTemporalContext", () => {
|
|
|
69
68
|
});
|
|
70
69
|
expect(result).toContain("Timezone: America/New_York");
|
|
71
70
|
expect(result).toContain("Current local time: 2026-02-18T07:00:00-05:00");
|
|
72
|
-
expect(result).toContain("Assistant host timezone: UTC");
|
|
73
|
-
expect(result).toContain("User timezone: America/New_York");
|
|
74
71
|
expect(result).toContain("Timezone source: user_profile_memory");
|
|
75
72
|
});
|
|
76
73
|
|
|
74
|
+
test("shows user timezone only when different from primary timezone", () => {
|
|
75
|
+
// When user timezone equals the primary timezone, omit it
|
|
76
|
+
const sameResult = buildTemporalContext({
|
|
77
|
+
nowMs: WED_FEB_18,
|
|
78
|
+
hostTimeZone: "UTC",
|
|
79
|
+
configuredUserTimeZone: "UTC",
|
|
80
|
+
});
|
|
81
|
+
expect(sameResult).not.toContain("User timezone:");
|
|
82
|
+
|
|
83
|
+
// When user timezone differs from host, it becomes the primary timezone
|
|
84
|
+
// and the host timezone is shown as a secondary annotation
|
|
85
|
+
const diffResult = buildTemporalContext({
|
|
86
|
+
nowMs: WED_FEB_18,
|
|
87
|
+
hostTimeZone: "UTC",
|
|
88
|
+
userTimeZone: "America/New_York",
|
|
89
|
+
});
|
|
90
|
+
expect(diffResult).toContain("Timezone: America/New_York");
|
|
91
|
+
expect(diffResult).toContain("Assistant host timezone: UTC");
|
|
92
|
+
expect(diffResult).not.toContain("User timezone:");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("shows assistant host timezone only when different from primary timezone", () => {
|
|
96
|
+
// When host timezone equals the primary timezone, omit it
|
|
97
|
+
const sameResult = buildTemporalContext({
|
|
98
|
+
nowMs: WED_FEB_18,
|
|
99
|
+
hostTimeZone: "UTC",
|
|
100
|
+
timeZone: "UTC",
|
|
101
|
+
});
|
|
102
|
+
expect(sameResult).not.toContain("Assistant host timezone:");
|
|
103
|
+
|
|
104
|
+
// When different, include it
|
|
105
|
+
const diffResult = buildTemporalContext({
|
|
106
|
+
nowMs: WED_FEB_18,
|
|
107
|
+
hostTimeZone: "UTC",
|
|
108
|
+
userTimeZone: "America/New_York",
|
|
109
|
+
});
|
|
110
|
+
expect(diffResult).toContain("Assistant host timezone: UTC");
|
|
111
|
+
});
|
|
112
|
+
|
|
77
113
|
test("uses configured user timezone when profile timezone is unavailable", () => {
|
|
78
114
|
const result = buildTemporalContext({
|
|
79
115
|
nowMs: WED_FEB_18,
|
|
@@ -83,7 +119,6 @@ describe("buildTemporalContext", () => {
|
|
|
83
119
|
});
|
|
84
120
|
expect(result).toContain("Timezone: America/Chicago");
|
|
85
121
|
expect(result).toContain("Current local time: 2026-02-18T06:00:00-06:00");
|
|
86
|
-
expect(result).toContain("User timezone: America/Chicago");
|
|
87
122
|
expect(result).toContain("Timezone source: user_settings");
|
|
88
123
|
});
|
|
89
124
|
|
|
@@ -96,7 +131,6 @@ describe("buildTemporalContext", () => {
|
|
|
96
131
|
});
|
|
97
132
|
expect(result).toContain("Timezone: America/Los_Angeles");
|
|
98
133
|
expect(result).toContain("Current local time: 2026-02-18T04:00:00-08:00");
|
|
99
|
-
expect(result).toContain("User timezone: America/Los_Angeles");
|
|
100
134
|
expect(result).toContain("Timezone source: user_settings");
|
|
101
135
|
});
|
|
102
136
|
|
|
@@ -107,7 +141,6 @@ describe("buildTemporalContext", () => {
|
|
|
107
141
|
userTimeZone: null,
|
|
108
142
|
});
|
|
109
143
|
expect(result).toContain("Timezone: UTC");
|
|
110
|
-
expect(result).toContain("User timezone: unknown");
|
|
111
144
|
expect(result).toContain("Timezone source: assistant_host_fallback");
|
|
112
145
|
});
|
|
113
146
|
|
|
@@ -119,7 +152,6 @@ describe("buildTemporalContext", () => {
|
|
|
119
152
|
});
|
|
120
153
|
expect(result).toContain("Timezone: Etc/GMT-2");
|
|
121
154
|
expect(result).toContain("Current local time: 2026-02-18T14:00:00+02:00");
|
|
122
|
-
expect(result).toContain("User timezone: Etc/GMT-2");
|
|
123
155
|
expect(result).toContain("Timezone source: user_profile_memory");
|
|
124
156
|
});
|
|
125
157
|
|
|
@@ -131,16 +163,9 @@ describe("buildTemporalContext", () => {
|
|
|
131
163
|
});
|
|
132
164
|
expect(result).toContain("Timezone: +05:30");
|
|
133
165
|
expect(result).toContain("Current local time: 2026-02-18T17:30:00+05:30");
|
|
134
|
-
expect(result).toContain("User timezone: +05:30");
|
|
135
166
|
expect(result).toContain("Timezone source: user_profile_memory");
|
|
136
167
|
});
|
|
137
168
|
|
|
138
|
-
test("includes week definitions", () => {
|
|
139
|
-
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
140
|
-
expect(result).toContain("work week = Monday–Friday");
|
|
141
|
-
expect(result).toContain("weekend = Saturday–Sunday");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
169
|
test("formats midnight hours as 00 (never 24) in local ISO output", () => {
|
|
145
170
|
const justAfterMidnight = Date.UTC(2026, 1, 19, 0, 5, 0);
|
|
146
171
|
const result = buildTemporalContext({
|
|
@@ -150,151 +175,16 @@ describe("buildTemporalContext", () => {
|
|
|
150
175
|
expect(result).toContain("Current local time: 2026-02-19T00:05:00+00:00");
|
|
151
176
|
expect(result).not.toContain("T24:05:00");
|
|
152
177
|
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
|
-
// Weekday baseline — today is Wednesday
|
|
157
|
-
// ---------------------------------------------------------------------------
|
|
158
178
|
|
|
159
|
-
|
|
160
|
-
test("next weekend is the upcoming Saturday-Sunday", () => {
|
|
179
|
+
test("Today line includes full YYYY-MM-DD format with year", () => {
|
|
161
180
|
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
162
|
-
|
|
163
|
-
expect(result).toContain("
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("next work week is the following Monday-Friday", () => {
|
|
167
|
-
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
168
|
-
// Wednesday Feb 18 → next Monday is Feb 23, Friday is Feb 27
|
|
169
|
-
expect(result).toContain("Next work week: 2026-02-23 – 2026-02-27");
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// ---------------------------------------------------------------------------
|
|
174
|
-
// Weekend baseline — today is Saturday
|
|
175
|
-
// ---------------------------------------------------------------------------
|
|
176
|
-
|
|
177
|
-
describe("weekend baseline (Saturday)", () => {
|
|
178
|
-
test("next weekend is the *following* Saturday-Sunday, not today", () => {
|
|
179
|
-
const result = buildTemporalContext({ nowMs: SAT_FEB_21, timeZone: "UTC" });
|
|
180
|
-
// Saturday Feb 21 → next Saturday is Feb 28, Sunday is Mar 1
|
|
181
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
test("next work week is the upcoming Monday-Friday", () => {
|
|
185
|
-
const result = buildTemporalContext({ nowMs: SAT_FEB_21, timeZone: "UTC" });
|
|
186
|
-
// Saturday Feb 21 → next Monday is Feb 23, Friday is Feb 27
|
|
187
|
-
expect(result).toContain("Next work week: 2026-02-23 – 2026-02-27");
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// ---------------------------------------------------------------------------
|
|
192
|
-
// Weekend baseline — today is Sunday
|
|
193
|
-
// ---------------------------------------------------------------------------
|
|
194
|
-
|
|
195
|
-
describe("weekend baseline (Sunday)", () => {
|
|
196
|
-
test("next weekend is the following Saturday-Sunday", () => {
|
|
197
|
-
const result = buildTemporalContext({ nowMs: SUN_FEB_22, timeZone: "UTC" });
|
|
198
|
-
// Sunday Feb 22 → next Saturday is Feb 28, Sunday is Mar 1
|
|
199
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test("next work week is the upcoming Monday-Friday", () => {
|
|
203
|
-
const result = buildTemporalContext({ nowMs: SUN_FEB_22, timeZone: "UTC" });
|
|
204
|
-
// Sunday Feb 22 → next Monday is Feb 23, Friday is Feb 27
|
|
205
|
-
expect(result).toContain("Next work week: 2026-02-23 – 2026-02-27");
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
// ---------------------------------------------------------------------------
|
|
210
|
-
// Friday baseline
|
|
211
|
-
// ---------------------------------------------------------------------------
|
|
212
|
-
|
|
213
|
-
describe("Friday baseline", () => {
|
|
214
|
-
test("next weekend is tomorrow (Saturday) and Sunday", () => {
|
|
215
|
-
const result = buildTemporalContext({ nowMs: FRI_FEB_27, timeZone: "UTC" });
|
|
216
|
-
// Friday Feb 27 → next Saturday is Feb 28, Sunday is Mar 1
|
|
217
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test("next work week is the following Monday-Friday", () => {
|
|
221
|
-
const result = buildTemporalContext({ nowMs: FRI_FEB_27, timeZone: "UTC" });
|
|
222
|
-
// Friday Feb 27 → next Monday is Mar 2, Friday is Mar 6
|
|
223
|
-
expect(result).toContain("Next work week: 2026-03-02 – 2026-03-06");
|
|
181
|
+
expect(result).toMatch(/Today: \d{4}-\d{2}-\d{2} \(\w+\)/);
|
|
182
|
+
expect(result).toContain("2026-02-18");
|
|
224
183
|
});
|
|
225
|
-
});
|
|
226
184
|
|
|
227
|
-
// ---------------------------------------------------------------------------
|
|
228
|
-
// Month / year boundary
|
|
229
|
-
// ---------------------------------------------------------------------------
|
|
230
|
-
|
|
231
|
-
describe("month/year boundary", () => {
|
|
232
185
|
test("handles year boundary correctly", () => {
|
|
233
186
|
const result = buildTemporalContext({ nowMs: TUE_DEC_29, timeZone: "UTC" });
|
|
234
187
|
expect(result).toContain("Today: 2026-12-29 (Tuesday)");
|
|
235
|
-
// Tuesday Dec 29 → next Saturday is Jan 2 2027
|
|
236
|
-
expect(result).toContain("Next weekend: 2027-01-02 – 2027-01-03");
|
|
237
|
-
// Next Monday is Jan 4 2027 (skips current work week)
|
|
238
|
-
// Wait — Dec 29 is Tuesday, so next Monday = Jan 4? Let me think:
|
|
239
|
-
// Dec 29 Tue → Mon is (1-2+7)%7 = 6 days → Jan 4 Mon
|
|
240
|
-
expect(result).toContain("Next work week: 2027-01-04 – 2027-01-08");
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
test("horizon entries cross year boundary", () => {
|
|
244
|
-
const result = buildTemporalContext({
|
|
245
|
-
nowMs: TUE_DEC_29,
|
|
246
|
-
timeZone: "UTC",
|
|
247
|
-
horizonDays: 5,
|
|
248
|
-
});
|
|
249
|
-
expect(result).toContain("2026-12-30 Wednesday");
|
|
250
|
-
expect(result).toContain("2026-12-31 Thursday");
|
|
251
|
-
expect(result).toContain("2027-01-01 Friday");
|
|
252
|
-
expect(result).toContain("2027-01-02 Saturday");
|
|
253
|
-
expect(result).toContain("2027-01-03 Sunday");
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// ---------------------------------------------------------------------------
|
|
258
|
-
// Output size caps
|
|
259
|
-
// ---------------------------------------------------------------------------
|
|
260
|
-
|
|
261
|
-
describe("output size caps", () => {
|
|
262
|
-
test("output is at most 1500 characters", () => {
|
|
263
|
-
const result = buildTemporalContext({
|
|
264
|
-
nowMs: WED_FEB_18,
|
|
265
|
-
timeZone: "UTC",
|
|
266
|
-
horizonDays: 14,
|
|
267
|
-
});
|
|
268
|
-
expect(result.length).toBeLessThanOrEqual(1500);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
test("horizon entries are capped at 14 even if more requested", () => {
|
|
272
|
-
const result = buildTemporalContext({
|
|
273
|
-
nowMs: WED_FEB_18,
|
|
274
|
-
timeZone: "UTC",
|
|
275
|
-
horizonDays: 30,
|
|
276
|
-
});
|
|
277
|
-
const horizonMatches = result.match(/^\s+\d{4}-\d{2}-\d{2} \w+$/gm);
|
|
278
|
-
expect(horizonMatches).not.toBeNull();
|
|
279
|
-
expect(horizonMatches!.length).toBeLessThanOrEqual(14);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
test("default horizon is 14 days", () => {
|
|
283
|
-
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
284
|
-
const horizonMatches = result.match(/^\s+\d{4}-\d{2}-\d{2} \w+$/gm);
|
|
285
|
-
expect(horizonMatches).not.toBeNull();
|
|
286
|
-
expect(horizonMatches!.length).toBe(14);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
test("respects smaller horizonDays", () => {
|
|
290
|
-
const result = buildTemporalContext({
|
|
291
|
-
nowMs: WED_FEB_18,
|
|
292
|
-
timeZone: "UTC",
|
|
293
|
-
horizonDays: 3,
|
|
294
|
-
});
|
|
295
|
-
const horizonMatches = result.match(/^\s+\d{4}-\d{2}-\d{2} \w+$/gm);
|
|
296
|
-
expect(horizonMatches).not.toBeNull();
|
|
297
|
-
expect(horizonMatches!.length).toBe(3);
|
|
298
188
|
});
|
|
299
189
|
});
|
|
300
190
|
|
|
@@ -304,7 +194,6 @@ describe("output size caps", () => {
|
|
|
304
194
|
|
|
305
195
|
describe("DST-safe timezone behavior", () => {
|
|
306
196
|
test("date labels are correct in US Eastern timezone", () => {
|
|
307
|
-
// Feb 18 12:00 UTC = Feb 18 07:00 EST (same calendar date)
|
|
308
197
|
const result = buildTemporalContext({
|
|
309
198
|
nowMs: WED_FEB_18,
|
|
310
199
|
timeZone: "America/New_York",
|
|
@@ -314,7 +203,6 @@ describe("DST-safe timezone behavior", () => {
|
|
|
314
203
|
});
|
|
315
204
|
|
|
316
205
|
test("date labels are correct in timezone ahead of UTC", () => {
|
|
317
|
-
// Use a timestamp near midnight UTC so the local date differs
|
|
318
206
|
// Feb 18 23:00 UTC = Feb 19 08:00 JST
|
|
319
207
|
const nearMidnight = Date.UTC(2026, 1, 18, 23, 0, 0);
|
|
320
208
|
const result = buildTemporalContext({
|
|
@@ -324,57 +212,6 @@ describe("DST-safe timezone behavior", () => {
|
|
|
324
212
|
expect(result).toContain("Today: 2026-02-19 (Thursday)");
|
|
325
213
|
});
|
|
326
214
|
|
|
327
|
-
test("addDays is correct across DST spring-forward boundary", () => {
|
|
328
|
-
// 2026-03-08 is spring-forward day in America/New_York (clocks jump 2:00→3:00 AM).
|
|
329
|
-
// Use a timestamp at local 23:30 on Friday March 6 (04:30 UTC March 7).
|
|
330
|
-
const preDST = Date.UTC(2026, 2, 7, 4, 30, 0); // local: Fri Mar 6 23:30 EST
|
|
331
|
-
const result = buildTemporalContext({
|
|
332
|
-
nowMs: preDST,
|
|
333
|
-
timeZone: "America/New_York",
|
|
334
|
-
horizonDays: 5,
|
|
335
|
-
});
|
|
336
|
-
// Today should be Friday March 6
|
|
337
|
-
expect(result).toContain("Today: 2026-03-06 (Friday)");
|
|
338
|
-
// Horizon should have 5 consecutive days with no duplicates/skips
|
|
339
|
-
expect(result).toContain("2026-03-07 Saturday");
|
|
340
|
-
expect(result).toContain("2026-03-08 Sunday");
|
|
341
|
-
expect(result).toContain("2026-03-09 Monday");
|
|
342
|
-
expect(result).toContain("2026-03-10 Tuesday");
|
|
343
|
-
expect(result).toContain("2026-03-11 Wednesday");
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
test("addDays is correct across DST fall-back boundary", () => {
|
|
347
|
-
// 2026-11-01 is fall-back day in America/New_York (clocks jump 2:00→1:00 AM).
|
|
348
|
-
// Use a timestamp at local 00:30 on Sunday Nov 1 (04:30 UTC Nov 1).
|
|
349
|
-
const preFallback = Date.UTC(2026, 10, 1, 4, 30, 0); // local: Sun Nov 1 00:30 EDT
|
|
350
|
-
const result = buildTemporalContext({
|
|
351
|
-
nowMs: preFallback,
|
|
352
|
-
timeZone: "America/New_York",
|
|
353
|
-
horizonDays: 3,
|
|
354
|
-
});
|
|
355
|
-
// Today should be Sunday Nov 1
|
|
356
|
-
expect(result).toContain("Today: 2026-11-01 (Sunday)");
|
|
357
|
-
// Horizon should have 3 consecutive days
|
|
358
|
-
expect(result).toContain("2026-11-02 Monday");
|
|
359
|
-
expect(result).toContain("2026-11-03 Tuesday");
|
|
360
|
-
expect(result).toContain("2026-11-04 Wednesday");
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
test("dates are correct in far-east UTC+13 timezone (Pacific/Auckland NZDT)", () => {
|
|
364
|
-
// Feb 18 12:00 UTC = Feb 19 01:00 NZDT (UTC+13 during daylight saving)
|
|
365
|
-
const result = buildTemporalContext({
|
|
366
|
-
nowMs: WED_FEB_18,
|
|
367
|
-
timeZone: "Pacific/Auckland",
|
|
368
|
-
horizonDays: 3,
|
|
369
|
-
});
|
|
370
|
-
// In Auckland, Feb 18 12:00 UTC is already Feb 19 (Thursday)
|
|
371
|
-
expect(result).toContain("Today: 2026-02-19 (Thursday)");
|
|
372
|
-
// Horizon should show consecutive days without +1 shift
|
|
373
|
-
expect(result).toContain("2026-02-20 Friday");
|
|
374
|
-
expect(result).toContain("2026-02-21 Saturday");
|
|
375
|
-
expect(result).toContain("2026-02-22 Sunday");
|
|
376
|
-
});
|
|
377
|
-
|
|
378
215
|
test("local offset tracks daylight saving changes", () => {
|
|
379
216
|
// Jul 1 12:00 UTC = Jul 1 08:00 EDT
|
|
380
217
|
const summer = Date.UTC(2026, 6, 1, 12, 0, 0);
|
|
@@ -386,160 +223,6 @@ describe("DST-safe timezone behavior", () => {
|
|
|
386
223
|
});
|
|
387
224
|
});
|
|
388
225
|
|
|
389
|
-
// ---------------------------------------------------------------------------
|
|
390
|
-
// Trip-planning regression: "next weekend" resolution
|
|
391
|
-
// ---------------------------------------------------------------------------
|
|
392
|
-
|
|
393
|
-
describe("trip-planning: next weekend resolution", () => {
|
|
394
|
-
test('Wednesday → "next weekend" anchors resolve to upcoming Sat-Sun', () => {
|
|
395
|
-
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
396
|
-
// A user asking "plan a trip for next weekend" on Wednesday Feb 18
|
|
397
|
-
// expects Sat Feb 21 – Sun Feb 22.
|
|
398
|
-
expect(result).toContain("Next weekend: 2026-02-21 – 2026-02-22");
|
|
399
|
-
// Both dates must appear in the horizon so the model can reference them.
|
|
400
|
-
expect(result).toContain("2026-02-21 Saturday");
|
|
401
|
-
expect(result).toContain("2026-02-22 Sunday");
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
test('Saturday → "next weekend" skips current weekend', () => {
|
|
405
|
-
const result = buildTemporalContext({ nowMs: SAT_FEB_21, timeZone: "UTC" });
|
|
406
|
-
// Already on Saturday → "next weekend" means the *following* weekend.
|
|
407
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
test('Sunday → "next weekend" skips current weekend', () => {
|
|
411
|
-
const result = buildTemporalContext({ nowMs: SUN_FEB_22, timeZone: "UTC" });
|
|
412
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
test('Friday → "next weekend" is tomorrow', () => {
|
|
416
|
-
const result = buildTemporalContext({ nowMs: FRI_FEB_27, timeZone: "UTC" });
|
|
417
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
// ---------------------------------------------------------------------------
|
|
422
|
-
// Trip-planning regression: "next work week" resolution
|
|
423
|
-
// ---------------------------------------------------------------------------
|
|
424
|
-
|
|
425
|
-
describe("trip-planning: next work week resolution", () => {
|
|
426
|
-
test('Wednesday → "next work week" skips remainder of current week', () => {
|
|
427
|
-
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
428
|
-
expect(result).toContain("Next work week: 2026-02-23 – 2026-02-27");
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
test('Monday → "next work week" is the following Monday-Friday', () => {
|
|
432
|
-
/** Monday 2026-02-23 12:00 UTC */
|
|
433
|
-
const MON_FEB_23 = Date.UTC(2026, 1, 23, 12, 0, 0);
|
|
434
|
-
const result = buildTemporalContext({ nowMs: MON_FEB_23, timeZone: "UTC" });
|
|
435
|
-
expect(result).toContain("Next work week: 2026-03-02 – 2026-03-06");
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
test('Saturday → "next work week" is the upcoming Monday-Friday', () => {
|
|
439
|
-
const result = buildTemporalContext({ nowMs: SAT_FEB_21, timeZone: "UTC" });
|
|
440
|
-
expect(result).toContain("Next work week: 2026-02-23 – 2026-02-27");
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
// ---------------------------------------------------------------------------
|
|
445
|
-
// Trip-planning regression: month-without-year disambiguation
|
|
446
|
-
// ---------------------------------------------------------------------------
|
|
447
|
-
|
|
448
|
-
describe("trip-planning: month-without-year disambiguation via temporal anchors", () => {
|
|
449
|
-
test("Today line includes full YYYY-MM-DD format with year for month disambiguation", () => {
|
|
450
|
-
const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
|
|
451
|
-
// The Today line must include the full year so the model can resolve bare
|
|
452
|
-
// month names (e.g. "May" → May 2026 because today is Feb 2026).
|
|
453
|
-
// Regex ensures YYYY-MM-DD format is present (regression if year is dropped).
|
|
454
|
-
expect(result).toMatch(/Today: \d{4}-\d{2}-\d{2} \(\w+\)/);
|
|
455
|
-
expect(result).toContain("2026-02-18");
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
test("future-month anchors: horizon dates are all in the future relative to today", () => {
|
|
459
|
-
const result = buildTemporalContext({
|
|
460
|
-
nowMs: WED_FEB_18,
|
|
461
|
-
timeZone: "UTC",
|
|
462
|
-
horizonDays: 14,
|
|
463
|
-
});
|
|
464
|
-
// Extract all horizon dates (indented YYYY-MM-DD lines)
|
|
465
|
-
const horizonDates = result.match(/^\s+(\d{4}-\d{2}-\d{2}) \w+$/gm);
|
|
466
|
-
expect(horizonDates).not.toBeNull();
|
|
467
|
-
// All horizon dates must be after today (2026-02-18)
|
|
468
|
-
for (const line of horizonDates!) {
|
|
469
|
-
const dateStr = line.trim().split(" ")[0];
|
|
470
|
-
expect(dateStr > "2026-02-18").toBe(true);
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
test("year-end context: horizon spans into next year for Dec disambiguation", () => {
|
|
475
|
-
const result = buildTemporalContext({
|
|
476
|
-
nowMs: TUE_DEC_29,
|
|
477
|
-
timeZone: "UTC",
|
|
478
|
-
horizonDays: 14,
|
|
479
|
-
});
|
|
480
|
-
// Today is Dec 29 2026 — horizon must include 2027 dates so the model can
|
|
481
|
-
// distinguish "January" (Jan 2027) from past January (Jan 2026).
|
|
482
|
-
expect(result).toContain("Today: 2026-12-29");
|
|
483
|
-
expect(result).toMatch(/2027-01-\d{2} \w+/); // At least one January 2027 date
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
test("timezone is always present for correct local-month resolution", () => {
|
|
487
|
-
const result = buildTemporalContext({
|
|
488
|
-
nowMs: WED_FEB_18,
|
|
489
|
-
timeZone: "America/New_York",
|
|
490
|
-
});
|
|
491
|
-
// Timezone must be present so the model resolves months in the user's
|
|
492
|
-
// local calendar, not UTC.
|
|
493
|
-
expect(result).toMatch(/Timezone: .+/);
|
|
494
|
-
expect(result).toContain("America/New_York");
|
|
495
|
-
});
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
// ---------------------------------------------------------------------------
|
|
499
|
-
// Trip-planning regression: cross-month weekend resolution
|
|
500
|
-
// ---------------------------------------------------------------------------
|
|
501
|
-
|
|
502
|
-
describe("trip-planning: cross-month weekend resolution", () => {
|
|
503
|
-
test("weekend that spans a month boundary (Feb → Mar)", () => {
|
|
504
|
-
const result = buildTemporalContext({ nowMs: FRI_FEB_27, timeZone: "UTC" });
|
|
505
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
test("year-boundary weekend (Dec 2026 → Jan 2027)", () => {
|
|
509
|
-
const result = buildTemporalContext({ nowMs: TUE_DEC_29, timeZone: "UTC" });
|
|
510
|
-
expect(result).toContain("Next weekend: 2027-01-02 – 2027-01-03");
|
|
511
|
-
});
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
// ---------------------------------------------------------------------------
|
|
515
|
-
// Trip-planning regression: timezone-shifted weekend anchors
|
|
516
|
-
// ---------------------------------------------------------------------------
|
|
517
|
-
|
|
518
|
-
describe("trip-planning: timezone-shifted weekend anchors", () => {
|
|
519
|
-
test("late Friday UTC is already Saturday in Auckland → skips to next weekend", () => {
|
|
520
|
-
// Friday Feb 27 23:00 UTC = Saturday Feb 28 12:00 NZDT
|
|
521
|
-
const lateFriUTC = Date.UTC(2026, 1, 27, 23, 0, 0);
|
|
522
|
-
const result = buildTemporalContext({
|
|
523
|
-
nowMs: lateFriUTC,
|
|
524
|
-
timeZone: "Pacific/Auckland",
|
|
525
|
-
});
|
|
526
|
-
expect(result).toContain("Today: 2026-02-28 (Saturday)");
|
|
527
|
-
// "Next weekend" skips current weekend → Mar 7-8.
|
|
528
|
-
expect(result).toContain("Next weekend: 2026-03-07 – 2026-03-08");
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
test("early Saturday UTC is still Friday in US Pacific → next weekend is tomorrow", () => {
|
|
532
|
-
// Saturday Feb 28 02:00 UTC = Friday Feb 27 18:00 PST
|
|
533
|
-
const earlySatUTC = Date.UTC(2026, 1, 28, 2, 0, 0);
|
|
534
|
-
const result = buildTemporalContext({
|
|
535
|
-
nowMs: earlySatUTC,
|
|
536
|
-
timeZone: "America/Los_Angeles",
|
|
537
|
-
});
|
|
538
|
-
expect(result).toContain("Today: 2026-02-27 (Friday)");
|
|
539
|
-
expect(result).toContain("Next weekend: 2026-02-28 – 2026-03-01");
|
|
540
|
-
});
|
|
541
|
-
});
|
|
542
|
-
|
|
543
226
|
// ---------------------------------------------------------------------------
|
|
544
227
|
// extractUserTimeZoneFromRecall
|
|
545
228
|
// ---------------------------------------------------------------------------
|
|
@@ -551,7 +234,7 @@ describe("extractUserTimeZoneFromRecall", () => {
|
|
|
551
234
|
});
|
|
552
235
|
|
|
553
236
|
test("extracts IANA timezone from user_identity section", () => {
|
|
554
|
-
const text = `<memory_context>
|
|
237
|
+
const text = `<memory_context __injected>
|
|
555
238
|
|
|
556
239
|
<user_identity>
|
|
557
240
|
User's timezone is America/New_York
|
|
@@ -563,7 +246,7 @@ User works as a software engineer
|
|
|
563
246
|
});
|
|
564
247
|
|
|
565
248
|
test("extracts timezone from 'timezone: ...' line in identity", () => {
|
|
566
|
-
const text = `<memory_context>
|
|
249
|
+
const text = `<memory_context __injected>
|
|
567
250
|
|
|
568
251
|
<user_identity>
|
|
569
252
|
- name: Alice
|
|
@@ -576,7 +259,7 @@ User works as a software engineer
|
|
|
576
259
|
});
|
|
577
260
|
|
|
578
261
|
test("extracts UTC offset timezone", () => {
|
|
579
|
-
const text = `<memory_context>
|
|
262
|
+
const text = `<memory_context __injected>
|
|
580
263
|
|
|
581
264
|
<user_identity>
|
|
582
265
|
User's time zone is UTC+5:30
|
|
@@ -585,12 +268,11 @@ User's time zone is UTC+5:30
|
|
|
585
268
|
</memory_context>`;
|
|
586
269
|
const result = extractUserTimeZoneFromRecall(text);
|
|
587
270
|
expect(result).not.toBeNull();
|
|
588
|
-
// UTC+5:30 should canonicalize to +05:30
|
|
589
271
|
expect(result).toBe("+05:30");
|
|
590
272
|
});
|
|
591
273
|
|
|
592
274
|
test("falls back to scanning full text when no identity section", () => {
|
|
593
|
-
const text = `<memory_context>
|
|
275
|
+
const text = `<memory_context __injected>
|
|
594
276
|
|
|
595
277
|
<relevant_context>
|
|
596
278
|
<episode source="Mar 5">
|
|
@@ -603,7 +285,7 @@ User mentioned their timezone is Asia/Tokyo
|
|
|
603
285
|
});
|
|
604
286
|
|
|
605
287
|
test("returns null when no timezone info present", () => {
|
|
606
|
-
const text = `<memory_context>
|
|
288
|
+
const text = `<memory_context __injected>
|
|
607
289
|
|
|
608
290
|
<user_identity>
|
|
609
291
|
User's name is Bob
|
|
@@ -615,7 +297,7 @@ User works at Acme Corp
|
|
|
615
297
|
});
|
|
616
298
|
|
|
617
299
|
test("prefers identity section over other sections", () => {
|
|
618
|
-
const text = `<memory_context>
|
|
300
|
+
const text = `<memory_context __injected>
|
|
619
301
|
|
|
620
302
|
<user_identity>
|
|
621
303
|
User's timezone is America/Chicago
|