@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
|
@@ -30,6 +30,7 @@ import { createToolAuditListener } from "../events/tool-audit-listener.js";
|
|
|
30
30
|
import { createToolDomainEventPublisher } from "../events/tool-domain-event-publisher.js";
|
|
31
31
|
import { registerToolMetricsLoggingListener } from "../events/tool-metrics-listener.js";
|
|
32
32
|
import { registerToolNotificationListener } from "../events/tool-notification-listener.js";
|
|
33
|
+
import { registerToolPermissionTelemetryListener } from "../events/tool-permission-telemetry-listener.js";
|
|
33
34
|
import {
|
|
34
35
|
registerToolProfilingListener,
|
|
35
36
|
ToolProfiler,
|
|
@@ -294,6 +295,7 @@ export class Conversation {
|
|
|
294
295
|
);
|
|
295
296
|
registerToolTraceListener(this.eventBus, this.traceEmitter);
|
|
296
297
|
registerToolProfilingListener(this.eventBus, this.profiler);
|
|
298
|
+
registerToolPermissionTelemetryListener(this.eventBus);
|
|
297
299
|
const auditToolLifecycleEvent = createToolAuditListener();
|
|
298
300
|
const publishToolDomainEvent = createToolDomainEventPublisher(
|
|
299
301
|
this.eventBus,
|
|
@@ -133,7 +133,7 @@ function isVellumDaemonProcess(pid: number): boolean {
|
|
|
133
133
|
* Wildcard addresses (0.0.0.0, ::) bind all interfaces but aren't
|
|
134
134
|
* connectable on all platforms — substitute loopback. IPv6 literals
|
|
135
135
|
* need brackets in URLs. */
|
|
136
|
-
function healthCheckHost(host: string): string {
|
|
136
|
+
export function healthCheckHost(host: string): string {
|
|
137
137
|
if (host === "0.0.0.0") return "127.0.0.1";
|
|
138
138
|
if (host === "::") return "[::1]";
|
|
139
139
|
if (host.includes(":")) return `[${host}]`;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Temporal context formatter for
|
|
2
|
+
* Temporal context formatter for date/time grounding.
|
|
3
3
|
*
|
|
4
4
|
* Produces a compact, deterministic payload describing the current date,
|
|
5
|
-
*
|
|
6
|
-
* future dates. Intended for runtime injection into the model context.
|
|
5
|
+
* time, and timezone. Intended for runtime injection into the model context.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
export interface TemporalContextOptions {
|
|
@@ -17,13 +16,8 @@ export interface TemporalContextOptions {
|
|
|
17
16
|
configuredUserTimeZone?: string | null;
|
|
18
17
|
/** IANA timezone inferred from user profile/memory (if available). */
|
|
19
18
|
userTimeZone?: string | null;
|
|
20
|
-
/** Number of future days to list (default 14, hard-capped at 14). */
|
|
21
|
-
horizonDays?: number;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
const MAX_OUTPUT_CHARS = 1500;
|
|
25
|
-
const MAX_HORIZON_ENTRIES = 14;
|
|
26
|
-
|
|
27
21
|
const WEEKDAY_NAMES = [
|
|
28
22
|
"Sunday",
|
|
29
23
|
"Monday",
|
|
@@ -316,35 +310,8 @@ function formatLocalIsoWithOffset(date: Date, timeZone: string): string {
|
|
|
316
310
|
return `${year}-${month}-${day}T${hour}:${minute}:${second}${offset}`;
|
|
317
311
|
}
|
|
318
312
|
|
|
319
|
-
/**
|
|
320
|
-
* Advance a date by `days` calendar days in the given timezone.
|
|
321
|
-
*
|
|
322
|
-
* Computes the local date, adds days to the day component, then anchors
|
|
323
|
-
* the result at noon local time to avoid DST-transition edge cases.
|
|
324
|
-
*/
|
|
325
|
-
function addDays(date: Date, days: number, timeZone: string): Date {
|
|
326
|
-
const parts = localDateParts(date, timeZone);
|
|
327
|
-
// Use Date.UTC for calendar overflow (e.g. Jan 32 → Feb 1).
|
|
328
|
-
const ref = new Date(Date.UTC(parts.year, parts.month - 1, parts.day + days));
|
|
329
|
-
const tY = ref.getUTCFullYear();
|
|
330
|
-
const tM = ref.getUTCMonth() + 1;
|
|
331
|
-
const tD = ref.getUTCDate();
|
|
332
|
-
// Noon UTC covers UTC-12 through ~UTC+11. For far-east timezones
|
|
333
|
-
// (UTC+12/+13/+14) noon UTC is already the next local day, so fall
|
|
334
|
-
// back to midnight UTC which resolves correctly there.
|
|
335
|
-
const noonUTC = new Date(Date.UTC(tY, tM - 1, tD, 12, 0, 0));
|
|
336
|
-
const r = localDateParts(noonUTC, timeZone);
|
|
337
|
-
if (r.year === tY && r.month === tM && r.day === tD) {
|
|
338
|
-
return noonUTC;
|
|
339
|
-
}
|
|
340
|
-
return new Date(Date.UTC(tY, tM - 1, tD, 0, 0, 0));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
313
|
/**
|
|
344
314
|
* Build a compact temporal context string for model injection.
|
|
345
|
-
*
|
|
346
|
-
* Output is hard-capped at {@link MAX_OUTPUT_CHARS} characters and
|
|
347
|
-
* {@link MAX_HORIZON_ENTRIES} horizon entries.
|
|
348
315
|
*/
|
|
349
316
|
export function buildTemporalContext(
|
|
350
317
|
options: TemporalContextOptions = {},
|
|
@@ -376,67 +343,27 @@ export function buildTemporalContext(
|
|
|
376
343
|
: resolvedUserTimeZone
|
|
377
344
|
? "user_profile_memory"
|
|
378
345
|
: "assistant_host_fallback";
|
|
379
|
-
const horizonDays = Math.min(
|
|
380
|
-
options.horizonDays ?? MAX_HORIZON_ENTRIES,
|
|
381
|
-
MAX_HORIZON_ENTRIES,
|
|
382
|
-
);
|
|
383
|
-
|
|
384
346
|
const todayParts = localDateParts(now, timeZone);
|
|
385
347
|
const todayStr = formatLocalDate(now, timeZone);
|
|
386
348
|
const todayWeekday = WEEKDAY_NAMES[todayParts.weekday];
|
|
387
349
|
|
|
388
|
-
// ── Next weekend (Saturday-Sunday) ──
|
|
389
|
-
const daysUntilSaturday = (6 - todayParts.weekday + 7) % 7 || 7;
|
|
390
|
-
const nextSaturday = addDays(now, daysUntilSaturday, timeZone);
|
|
391
|
-
const nextSunday = addDays(now, daysUntilSaturday + 1, timeZone);
|
|
392
|
-
|
|
393
|
-
// ── Next work week (Monday-Friday) ──
|
|
394
|
-
const daysUntilMonday = (1 - todayParts.weekday + 7) % 7 || 7;
|
|
395
|
-
const nextMonday = addDays(now, daysUntilMonday, timeZone);
|
|
396
|
-
const nextFriday = addDays(now, daysUntilMonday + 4, timeZone);
|
|
397
|
-
|
|
398
|
-
// ── Horizon list ──
|
|
399
|
-
const horizonLines: string[] = [];
|
|
400
|
-
for (let i = 1; i <= horizonDays; i++) {
|
|
401
|
-
const futureDate = addDays(now, i, timeZone);
|
|
402
|
-
const futureParts = localDateParts(futureDate, timeZone);
|
|
403
|
-
const label = WEEKDAY_NAMES[futureParts.weekday];
|
|
404
|
-
horizonLines.push(` ${formatLocalDate(futureDate, timeZone)} ${label}`);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
350
|
const lines = [
|
|
408
351
|
`<temporal_context>`,
|
|
409
352
|
`Today: ${todayStr} (${todayWeekday})`,
|
|
410
353
|
`Timezone: ${timeZone}`,
|
|
411
354
|
`Current local time: ${formatLocalIsoWithOffset(now, timeZone)}`,
|
|
412
355
|
`Current UTC time: ${now.toISOString()}`,
|
|
413
|
-
`Clock source: assistant host machine`,
|
|
414
|
-
`Assistant host timezone: ${resolvedHostTimeZone}`,
|
|
415
|
-
`User timezone: ${userTimeZone ?? "unknown"}`,
|
|
416
356
|
`Timezone source: ${timeZoneSource}`,
|
|
417
|
-
``,
|
|
418
|
-
`Week definitions: work week = Monday–Friday, weekend = Saturday–Sunday`,
|
|
419
|
-
``,
|
|
420
|
-
`Next weekend: ${formatLocalDate(
|
|
421
|
-
nextSaturday,
|
|
422
|
-
timeZone,
|
|
423
|
-
)} – ${formatLocalDate(nextSunday, timeZone)}`,
|
|
424
|
-
`Next work week: ${formatLocalDate(
|
|
425
|
-
nextMonday,
|
|
426
|
-
timeZone,
|
|
427
|
-
)} – ${formatLocalDate(nextFriday, timeZone)}`,
|
|
428
|
-
``,
|
|
429
|
-
`Upcoming dates:`,
|
|
430
|
-
...horizonLines,
|
|
431
|
-
`</temporal_context>`,
|
|
432
357
|
];
|
|
433
358
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
// Hard cap: truncate if somehow over budget (shouldn't happen with 14 entries).
|
|
437
|
-
if (output.length > MAX_OUTPUT_CHARS) {
|
|
438
|
-
output = output.slice(0, MAX_OUTPUT_CHARS - 25) + "\n</temporal_context>";
|
|
359
|
+
if (userTimeZone && userTimeZone !== timeZone) {
|
|
360
|
+
lines.push(`User timezone: ${userTimeZone}`);
|
|
439
361
|
}
|
|
362
|
+
if (resolvedHostTimeZone !== timeZone) {
|
|
363
|
+
lines.push(`Assistant host timezone: ${resolvedHostTimeZone}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
lines.push(`</temporal_context>`);
|
|
440
367
|
|
|
441
|
-
return
|
|
368
|
+
return lines.join("\n");
|
|
442
369
|
}
|
|
@@ -551,9 +551,14 @@ export async function handleChannelVerificationSession(
|
|
|
551
551
|
rebind: msg.rebind,
|
|
552
552
|
originConversationId: msg.originConversationId,
|
|
553
553
|
});
|
|
554
|
+
if (result._pendingSlackDm) {
|
|
555
|
+
const { userId, text, assistantId: aid } = result._pendingSlackDm;
|
|
556
|
+
deliverVerificationSlack(userId, text, aid);
|
|
557
|
+
}
|
|
558
|
+
const { _pendingSlackDm: _, ...publicResult } = result;
|
|
554
559
|
ctx.send({
|
|
555
560
|
type: "channel_verification_session_response",
|
|
556
|
-
...
|
|
561
|
+
...publicResult,
|
|
557
562
|
});
|
|
558
563
|
} else {
|
|
559
564
|
const result = createInboundChallenge(
|
|
@@ -591,9 +596,14 @@ export async function handleChannelVerificationSession(
|
|
|
591
596
|
channel,
|
|
592
597
|
originConversationId: msg.originConversationId,
|
|
593
598
|
});
|
|
599
|
+
if (result._pendingSlackDm) {
|
|
600
|
+
const { userId, text, assistantId: aid } = result._pendingSlackDm;
|
|
601
|
+
deliverVerificationSlack(userId, text, aid);
|
|
602
|
+
}
|
|
603
|
+
const { _pendingSlackDm: _, ...publicResult } = result;
|
|
594
604
|
ctx.send({
|
|
595
605
|
type: "channel_verification_session_response",
|
|
596
|
-
...
|
|
606
|
+
...publicResult,
|
|
597
607
|
});
|
|
598
608
|
} else {
|
|
599
609
|
ctx.send({
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
ensureManualTokenConnection,
|
|
10
10
|
removeManualTokenConnection,
|
|
11
|
+
syncManualTokenConnection,
|
|
11
12
|
} from "../../oauth/manual-token-connection.js";
|
|
12
13
|
import { getConnectionByProvider } from "../../oauth/oauth-store.js";
|
|
13
14
|
import { credentialKey } from "../../security/credential-key.js";
|
|
@@ -40,6 +41,12 @@ export interface SlackChannelConfigResult {
|
|
|
40
41
|
// -- Business logic --
|
|
41
42
|
|
|
42
43
|
export async function getSlackChannelConfig(): Promise<SlackChannelConfigResult> {
|
|
44
|
+
const { teamId, teamName, botUserId, botUsername } = getConfig().slack;
|
|
45
|
+
const accountInfo = teamName
|
|
46
|
+
? `${teamName}${botUsername ? ` (@${botUsername})` : ""}`
|
|
47
|
+
: undefined;
|
|
48
|
+
await syncManualTokenConnection("slack_channel", accountInfo);
|
|
49
|
+
|
|
43
50
|
const hasBotToken = !!(await getSecureKeyAsync(
|
|
44
51
|
credentialKey("slack_channel", "bot_token"),
|
|
45
52
|
));
|
|
@@ -49,7 +56,6 @@ export async function getSlackChannelConfig(): Promise<SlackChannelConfigResult>
|
|
|
49
56
|
const conn = getConnectionByProvider("slack_channel");
|
|
50
57
|
const connected =
|
|
51
58
|
!!(conn && conn.status === "active") && hasBotToken && hasAppToken;
|
|
52
|
-
const { teamId, teamName, botUserId, botUsername } = getConfig().slack;
|
|
53
59
|
return {
|
|
54
60
|
success: true,
|
|
55
61
|
hasBotToken,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
ensureManualTokenConnection,
|
|
13
13
|
removeManualTokenConnection,
|
|
14
|
+
syncManualTokenConnection,
|
|
14
15
|
} from "../../oauth/manual-token-connection.js";
|
|
15
16
|
import { getConnectionByProvider } from "../../oauth/oauth-store.js";
|
|
16
17
|
import { credentialKey } from "../../security/credential-key.js";
|
|
@@ -69,6 +70,11 @@ export type TelegramConfigResult = Omit<TelegramConfigResponse, "type">;
|
|
|
69
70
|
// -- Extracted business logic functions --
|
|
70
71
|
|
|
71
72
|
export async function getTelegramConfig(): Promise<TelegramConfigResult> {
|
|
73
|
+
const botUsername = getTelegramBotUsername();
|
|
74
|
+
await syncManualTokenConnection(
|
|
75
|
+
"telegram",
|
|
76
|
+
botUsername ? `@${botUsername}` : undefined,
|
|
77
|
+
);
|
|
72
78
|
const hasBotToken = !!(await getSecureKeyAsync(
|
|
73
79
|
credentialKey("telegram", "bot_token"),
|
|
74
80
|
));
|
|
@@ -78,7 +84,6 @@ export async function getTelegramConfig(): Promise<TelegramConfigResult> {
|
|
|
78
84
|
const conn = getConnectionByProvider("telegram");
|
|
79
85
|
const connected = !!(conn && conn.status === "active");
|
|
80
86
|
const botId = getTelegramBotId();
|
|
81
|
-
const botUsername = getTelegramBotUsername();
|
|
82
87
|
return {
|
|
83
88
|
success: true,
|
|
84
89
|
hasBotToken,
|
|
@@ -581,14 +581,14 @@ export function deleteQueuedMessage(
|
|
|
581
581
|
) => { removeQueuedMessage(requestId: string): boolean } | undefined,
|
|
582
582
|
):
|
|
583
583
|
| { removed: true }
|
|
584
|
-
| { removed: false; reason: "
|
|
584
|
+
| { removed: false; reason: "conversation_not_found" | "message_not_found" } {
|
|
585
585
|
const conversation = findConversation(conversationId);
|
|
586
586
|
if (!conversation) {
|
|
587
587
|
log.warn(
|
|
588
588
|
{ conversationId, requestId },
|
|
589
589
|
"No conversation found for delete_queued_message",
|
|
590
590
|
);
|
|
591
|
-
return { removed: false, reason: "
|
|
591
|
+
return { removed: false, reason: "conversation_not_found" };
|
|
592
592
|
}
|
|
593
593
|
const removed = conversation.removeQueuedMessage(requestId);
|
|
594
594
|
if (removed) {
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
removeSkillsIndexEntry,
|
|
39
39
|
validateManagedSkillId,
|
|
40
40
|
} from "../../skills/managed-store.js";
|
|
41
|
+
import { deleteSkillCapabilityMemory } from "../../skills/skill-memory.js";
|
|
41
42
|
import { getWorkspaceSkillsDir } from "../../util/platform.js";
|
|
42
43
|
import {
|
|
43
44
|
CONFIG_RELOAD_DEBOUNCE_MS,
|
|
@@ -603,6 +604,9 @@ export async function uninstallSkill(
|
|
|
603
604
|
} catch {
|
|
604
605
|
/* best effort */
|
|
605
606
|
}
|
|
607
|
+
// Best-effort cleanup of capability memory for uninstalled skill
|
|
608
|
+
// (managed path handles this internally via deleteManagedSkill)
|
|
609
|
+
deleteSkillCapabilityMemory(skillId);
|
|
606
610
|
}
|
|
607
611
|
|
|
608
612
|
// Clean config entry
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -42,6 +42,7 @@ import { startMemoryJobsWorker } from "../memory/jobs-worker.js";
|
|
|
42
42
|
import { initQdrantClient } from "../memory/qdrant-client.js";
|
|
43
43
|
import { QdrantManager } from "../memory/qdrant-manager.js";
|
|
44
44
|
import { rotateToolInvocations } from "../memory/tool-usage-store.js";
|
|
45
|
+
import { deleteOldTraceEvents } from "../memory/trace-event-store.js";
|
|
45
46
|
import {
|
|
46
47
|
emitNotificationSignal,
|
|
47
48
|
registerBroadcastFn,
|
|
@@ -61,6 +62,7 @@ import {
|
|
|
61
62
|
import { ensureVellumGuardianBinding } from "../runtime/guardian-vellum-migration.js";
|
|
62
63
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
63
64
|
import { startScheduler } from "../schedule/scheduler.js";
|
|
65
|
+
import { seedCatalogSkillMemories } from "../skills/skill-memory.js";
|
|
64
66
|
import { UsageTelemetryReporter } from "../telemetry/usage-telemetry-reporter.js";
|
|
65
67
|
import { getLogger, initLogger } from "../util/logger.js";
|
|
66
68
|
import {
|
|
@@ -373,6 +375,12 @@ export async function runDaemon(): Promise<void> {
|
|
|
373
375
|
log.info("Daemon startup: starting memory worker");
|
|
374
376
|
const memoryWorker = startMemoryJobsWorker();
|
|
375
377
|
|
|
378
|
+
// Seed capability memories for first-party catalog skills so the memory
|
|
379
|
+
// pipeline can surface relevant skills via semantic search.
|
|
380
|
+
void seedCatalogSkillMemories().catch((err) =>
|
|
381
|
+
log.warn({ err }, "Catalog skill memory seeding failed — continuing"),
|
|
382
|
+
);
|
|
383
|
+
|
|
376
384
|
registerWatcherProviders();
|
|
377
385
|
registerMessagingProviders();
|
|
378
386
|
|
|
@@ -400,7 +408,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
400
408
|
await emitNotificationSignal({
|
|
401
409
|
sourceEventName: "schedule.notify",
|
|
402
410
|
sourceChannel: "scheduler",
|
|
403
|
-
|
|
411
|
+
sourceContextId: schedule.id,
|
|
404
412
|
attentionHints: {
|
|
405
413
|
requiresAction: true,
|
|
406
414
|
urgency: "high",
|
|
@@ -422,7 +430,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
422
430
|
void emitNotificationSignal({
|
|
423
431
|
sourceEventName: "schedule.complete",
|
|
424
432
|
sourceChannel: "scheduler",
|
|
425
|
-
|
|
433
|
+
sourceContextId: schedule.id,
|
|
426
434
|
attentionHints: {
|
|
427
435
|
requiresAction: false,
|
|
428
436
|
urgency: "medium",
|
|
@@ -440,7 +448,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
440
448
|
void emitNotificationSignal({
|
|
441
449
|
sourceEventName: "watcher.notification",
|
|
442
450
|
sourceChannel: "watcher",
|
|
443
|
-
|
|
451
|
+
sourceContextId: `watcher-${Date.now()}`,
|
|
444
452
|
attentionHints: {
|
|
445
453
|
requiresAction: false,
|
|
446
454
|
urgency: "low",
|
|
@@ -458,7 +466,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
458
466
|
void emitNotificationSignal({
|
|
459
467
|
sourceEventName: "watcher.escalation",
|
|
460
468
|
sourceChannel: "watcher",
|
|
461
|
-
|
|
469
|
+
sourceContextId: `watcher-escalation-${Date.now()}`,
|
|
462
470
|
attentionHints: {
|
|
463
471
|
requiresAction: true,
|
|
464
472
|
urgency: "high",
|
|
@@ -824,6 +832,22 @@ export async function runDaemon(): Promise<void> {
|
|
|
824
832
|
}
|
|
825
833
|
}
|
|
826
834
|
|
|
835
|
+
// Prune trace events older than 7 days to keep the database lean.
|
|
836
|
+
// Deferred so synchronous cleanup doesn't block the startup path.
|
|
837
|
+
setTimeout(() => {
|
|
838
|
+
try {
|
|
839
|
+
const deletedTraceEvents = deleteOldTraceEvents(7);
|
|
840
|
+
if (deletedTraceEvents > 0) {
|
|
841
|
+
log.debug(
|
|
842
|
+
{ deletedTraceEvents },
|
|
843
|
+
`Pruned ${deletedTraceEvents} trace event(s) older than 7 days`,
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
} catch (err) {
|
|
847
|
+
log.warn({ err }, "Trace event cleanup failed");
|
|
848
|
+
}
|
|
849
|
+
}, 0);
|
|
850
|
+
|
|
827
851
|
const workspaceHeartbeat = new WorkspaceHeartbeatService();
|
|
828
852
|
workspaceHeartbeat.start();
|
|
829
853
|
|
|
@@ -49,7 +49,7 @@ export async function initializeProvidersAndTools(
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// Rehydrate the platform assistant ID from the credential store so
|
|
52
|
-
//
|
|
52
|
+
// shouldUsePlatformCallbacks() works after assistant restarts.
|
|
53
53
|
try {
|
|
54
54
|
const key = credentialKey("vellum", "platform_assistant_id");
|
|
55
55
|
const persisted = await getSecureKeyAsync(key);
|
package/src/daemon/server.ts
CHANGED
|
@@ -758,10 +758,7 @@ export class DaemonServer {
|
|
|
758
758
|
config.providerOrder,
|
|
759
759
|
);
|
|
760
760
|
const { rateLimit } = config;
|
|
761
|
-
if (
|
|
762
|
-
rateLimit.maxRequestsPerMinute > 0 ||
|
|
763
|
-
rateLimit.maxTokensPerSession > 0
|
|
764
|
-
) {
|
|
761
|
+
if (rateLimit.maxRequestsPerMinute > 0) {
|
|
765
762
|
provider = new RateLimitProvider(
|
|
766
763
|
provider,
|
|
767
764
|
rateLimit,
|
|
@@ -915,7 +912,6 @@ export class DaemonServer {
|
|
|
915
912
|
resolveChannelCapabilities(
|
|
916
913
|
sourceChannel,
|
|
917
914
|
sourceInterface,
|
|
918
|
-
null,
|
|
919
915
|
options?.transport?.chatType,
|
|
920
916
|
),
|
|
921
917
|
);
|
|
@@ -30,6 +30,7 @@ export interface ShutdownDeps {
|
|
|
30
30
|
|
|
31
31
|
export function installShutdownHandlers(deps: ShutdownDeps): void {
|
|
32
32
|
let shuttingDown = false;
|
|
33
|
+
let exitCode = 0;
|
|
33
34
|
|
|
34
35
|
const shutdown = async () => {
|
|
35
36
|
if (shuttingDown) return;
|
|
@@ -134,19 +135,24 @@ export function installShutdownHandlers(deps: ShutdownDeps): void {
|
|
|
134
135
|
await Sentry.flush(2000);
|
|
135
136
|
clearTimeout(forceTimer);
|
|
136
137
|
deps.cleanupPidFile();
|
|
137
|
-
process.exit(
|
|
138
|
+
process.exit(exitCode);
|
|
138
139
|
};
|
|
139
140
|
|
|
140
141
|
process.on("SIGTERM", shutdown);
|
|
141
142
|
process.on("SIGINT", shutdown);
|
|
143
|
+
process.on("SIGHUP", shutdown);
|
|
142
144
|
|
|
143
145
|
process.on("unhandledRejection", (reason) => {
|
|
144
|
-
log.error({ err: reason }, "Unhandled promise rejection");
|
|
146
|
+
log.error({ err: reason }, "Unhandled promise rejection — initiating shutdown");
|
|
145
147
|
Sentry.captureException(reason);
|
|
148
|
+
exitCode = 1;
|
|
149
|
+
void shutdown();
|
|
146
150
|
});
|
|
147
151
|
|
|
148
152
|
process.on("uncaughtException", (err) => {
|
|
149
|
-
log.error({ err }, "Uncaught exception");
|
|
153
|
+
log.error({ err }, "Uncaught exception — initiating shutdown");
|
|
150
154
|
Sentry.captureException(err);
|
|
155
|
+
exitCode = 1;
|
|
156
|
+
void shutdown();
|
|
151
157
|
});
|
|
152
158
|
}
|
|
@@ -12,6 +12,7 @@ import { join } from "node:path";
|
|
|
12
12
|
import { compileApp } from "../bundler/app-compiler.js";
|
|
13
13
|
import { generateAppIcon } from "../media/app-icon-generator.js";
|
|
14
14
|
import { getApp, getAppsDir, isMultifileApp } from "../memory/app-store.js";
|
|
15
|
+
import { deliverVerificationSlack } from "../runtime/verification-outbound-actions.js";
|
|
15
16
|
import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
|
|
16
17
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
17
18
|
import { getLogger } from "../util/logger.js";
|
|
@@ -226,6 +227,45 @@ registerHook(
|
|
|
226
227
|
},
|
|
227
228
|
);
|
|
228
229
|
|
|
230
|
+
// Dispatch pending Slack DM delivery when a CLI verification command
|
|
231
|
+
// completes. The CLI subprocess is sandboxed and cannot reach the
|
|
232
|
+
// gateway, so it includes a `_pendingSlackDm` field in its JSON output.
|
|
233
|
+
// This hook runs in the unsandboxed daemon process and delivers the DM.
|
|
234
|
+
registerHook("bash", (_name, input, result) => {
|
|
235
|
+
const command = (input.command ?? "") as string;
|
|
236
|
+
if (!command.includes("channel-verification-sessions")) return;
|
|
237
|
+
if (!result.content.includes("_pendingSlackDm")) return;
|
|
238
|
+
|
|
239
|
+
type PendingDm = { userId: string; text: string; assistantId: string };
|
|
240
|
+
type Parsed = { _pendingSlackDm?: PendingDm };
|
|
241
|
+
|
|
242
|
+
const dispatch = (parsed: Parsed) => {
|
|
243
|
+
if (parsed._pendingSlackDm) {
|
|
244
|
+
const { userId, text, assistantId } = parsed._pendingSlackDm;
|
|
245
|
+
deliverVerificationSlack(userId, text, assistantId);
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
return false;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Try full content first (handles pretty-printed single-object JSON)
|
|
252
|
+
try {
|
|
253
|
+
if (dispatch(JSON.parse(result.content.trim()) as Parsed)) return;
|
|
254
|
+
} catch {
|
|
255
|
+
// Not a single JSON object — fall back to line-by-line for
|
|
256
|
+
// multi-object output (e.g. cancel + create chained with &&).
|
|
257
|
+
}
|
|
258
|
+
for (const line of result.content.split("\n")) {
|
|
259
|
+
const trimmed = line.trim();
|
|
260
|
+
if (!trimmed.startsWith("{")) continue;
|
|
261
|
+
try {
|
|
262
|
+
if (dispatch(JSON.parse(trimmed) as Parsed)) return;
|
|
263
|
+
} catch {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
229
269
|
// ── Runner ───────────────────────────────────────────────────────────
|
|
230
270
|
|
|
231
271
|
/**
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
getMaxSequence,
|
|
5
|
+
persistTraceEvent,
|
|
6
|
+
} from "../memory/trace-event-store.js";
|
|
7
|
+
import { getLogger } from "../util/logger.js";
|
|
3
8
|
import type { ServerMessage, TraceEventKind } from "./message-protocol.js";
|
|
9
|
+
import type { TraceEvent } from "./message-types/messages.js";
|
|
4
10
|
|
|
5
11
|
export type TraceEventStatus = "info" | "success" | "warning" | "error";
|
|
6
12
|
|
|
13
|
+
const log = getLogger("trace-emitter");
|
|
14
|
+
|
|
7
15
|
const SUMMARY_MAX_LENGTH = 200;
|
|
8
16
|
const ATTRIBUTE_VALUE_MAX_LENGTH = 500;
|
|
9
17
|
|
|
@@ -19,12 +27,21 @@ export interface TraceEmitOptions {
|
|
|
19
27
|
* even if timestamps collide.
|
|
20
28
|
*/
|
|
21
29
|
export class TraceEmitter {
|
|
22
|
-
private sequence
|
|
30
|
+
private sequence: number;
|
|
23
31
|
|
|
24
32
|
constructor(
|
|
25
33
|
private readonly conversationId: string,
|
|
26
34
|
private sendToClient: (msg: ServerMessage) => void,
|
|
27
|
-
) {
|
|
35
|
+
) {
|
|
36
|
+
// Seed from the highest persisted sequence so that new events always
|
|
37
|
+
// have strictly higher sequence numbers, even across daemon restarts.
|
|
38
|
+
try {
|
|
39
|
+
const maxPersisted = getMaxSequence(conversationId);
|
|
40
|
+
this.sequence = maxPersisted + 1;
|
|
41
|
+
} catch {
|
|
42
|
+
this.sequence = 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
|
|
29
46
|
updateSender(sendToClient: (msg: ServerMessage) => void): void {
|
|
30
47
|
this.sendToClient = sendToClient;
|
|
@@ -50,7 +67,14 @@ export class TraceEmitter {
|
|
|
50
67
|
attributes,
|
|
51
68
|
};
|
|
52
69
|
|
|
70
|
+
// Send to client first so synchronous DB writes don't block SSE delivery.
|
|
53
71
|
this.sendToClient(event);
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
persistTraceEvent(event as TraceEvent);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
log.warn({ err, eventId }, "Failed to persist trace event");
|
|
77
|
+
}
|
|
54
78
|
}
|
|
55
79
|
}
|
|
56
80
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { recordLifecycleEvent } from "../memory/lifecycle-events-store.js";
|
|
2
|
+
import { getLogger } from "../util/logger.js";
|
|
3
|
+
import type { EventBus, Subscription } from "./bus.js";
|
|
4
|
+
import type { AssistantDomainEvents } from "./domain-events.js";
|
|
5
|
+
|
|
6
|
+
const log = getLogger("tool-permission-telemetry");
|
|
7
|
+
|
|
8
|
+
export function registerToolPermissionTelemetryListener(
|
|
9
|
+
eventBus: EventBus<AssistantDomainEvents>,
|
|
10
|
+
): Subscription {
|
|
11
|
+
// Track which tool calls were actually prompted so we only record
|
|
12
|
+
// decided telemetry for real user interactions, not auto-allowed tools.
|
|
13
|
+
// Uses a composite key (requestId:toolName) because requestId is per-message,
|
|
14
|
+
// not per-tool-call — parallel tool_use blocks share the same requestId.
|
|
15
|
+
const promptedToolCalls = new Set<string>();
|
|
16
|
+
|
|
17
|
+
return eventBus.onAny((event) => {
|
|
18
|
+
try {
|
|
19
|
+
switch (event.type) {
|
|
20
|
+
case "tool.permission.requested": {
|
|
21
|
+
const { requestId, toolName } = event.payload;
|
|
22
|
+
if (requestId) {
|
|
23
|
+
promptedToolCalls.add(`${requestId}:${toolName}`);
|
|
24
|
+
}
|
|
25
|
+
recordLifecycleEvent(`permission_prompt:${toolName}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
case "tool.permission.decided": {
|
|
29
|
+
const { requestId, toolName, decision } = event.payload;
|
|
30
|
+
const key = requestId ? `${requestId}:${toolName}` : undefined;
|
|
31
|
+
if (key && promptedToolCalls.has(key)) {
|
|
32
|
+
promptedToolCalls.delete(key);
|
|
33
|
+
recordLifecycleEvent(
|
|
34
|
+
`permission_decided:${toolName}:${decision}`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
default:
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
} catch (err) {
|
|
43
|
+
log.warn({ err }, "Failed to record permission telemetry event");
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -24,28 +24,10 @@ import {
|
|
|
24
24
|
getPlatformInternalApiKey,
|
|
25
25
|
} from "../config/env.js";
|
|
26
26
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
27
|
-
import { isManagedProxyEnabledSync } from "../providers/managed-proxy/context.js";
|
|
28
27
|
import { getLogger } from "../util/logger.js";
|
|
29
28
|
|
|
30
29
|
const log = getLogger("platform-callback-registration");
|
|
31
30
|
|
|
32
|
-
/**
|
|
33
|
-
* Whether this is a platform-managed deployment with usable managed credentials.
|
|
34
|
-
*
|
|
35
|
-
* True when PLATFORM_BASE_URL and PLATFORM_ASSISTANT_ID are both set **and**
|
|
36
|
-
* the managed proxy prerequisites (including the assistant API key) were
|
|
37
|
-
* satisfied the last time `resolveManagedProxyContext()` ran. This prevents
|
|
38
|
-
* the system prompt from claiming managed credentials are available during
|
|
39
|
-
* partial/failed platform bootstrap where the API key is missing.
|
|
40
|
-
*/
|
|
41
|
-
export function isPlatformManaged(): boolean {
|
|
42
|
-
return (
|
|
43
|
-
!!getPlatformBaseUrl() &&
|
|
44
|
-
!!getPlatformAssistantId() &&
|
|
45
|
-
isManagedProxyEnabledSync()
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
31
|
/**
|
|
50
32
|
* Whether the daemon should register callback routes with the platform.
|
|
51
33
|
* True when IS_CONTAINERIZED, PLATFORM_BASE_URL, and PLATFORM_ASSISTANT_ID
|