@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
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caching layer for the LLM-generated identity intro text.
|
|
3
|
+
*
|
|
4
|
+
* The intro (a short identity tagline) is generated via the
|
|
5
|
+
* /v1/btw endpoint and displayed on the Identity panel. To avoid redundant LLM
|
|
6
|
+
* calls, we cache the result for 4 hours with content-hash-based invalidation:
|
|
7
|
+
* when USER.md, IDENTITY.md, or SOUL.md change, the cache is busted.
|
|
8
|
+
*
|
|
9
|
+
* Storage uses the existing `memory_checkpoints` table (simple key-value store).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createHash } from "node:crypto";
|
|
13
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
getMemoryCheckpoint,
|
|
17
|
+
setMemoryCheckpoint,
|
|
18
|
+
} from "../../memory/checkpoints.js";
|
|
19
|
+
import { getWorkspacePromptPath } from "../../util/platform.js";
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Constants
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
const CACHE_TTL_MS = 4 * 60 * 60 * 1000; // 4 hours
|
|
26
|
+
|
|
27
|
+
const CHECKPOINT_KEY_TEXT = "identity:intro:text";
|
|
28
|
+
const CHECKPOINT_KEY_HASH = "identity:intro:content_hash";
|
|
29
|
+
const CHECKPOINT_KEY_TIMESTAMP = "identity:intro:cached_at";
|
|
30
|
+
|
|
31
|
+
/** Workspace files whose content influences the identity intro. */
|
|
32
|
+
const IDENTITY_FILES = ["USER.md", "IDENTITY.md", "SOUL.md"] as const;
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Helpers
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/** Read a workspace prompt file, returning empty string if missing. */
|
|
39
|
+
function readWorkspaceFile(name: string): string {
|
|
40
|
+
try {
|
|
41
|
+
const path = getWorkspacePromptPath(name);
|
|
42
|
+
if (!existsSync(path)) return "";
|
|
43
|
+
return readFileSync(path, "utf-8");
|
|
44
|
+
} catch {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Compute a SHA-256 hex hash of the concatenated identity file contents. */
|
|
50
|
+
export function computeIdentityContentHash(): string {
|
|
51
|
+
const combined = IDENTITY_FILES.map(readWorkspaceFile).join("\n---\n");
|
|
52
|
+
return createHash("sha256").update(combined).digest("hex");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Public API
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
export interface CachedIntro {
|
|
60
|
+
text: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Retrieve the cached identity intro if it exists, is within the TTL window,
|
|
65
|
+
* and the identity files have not changed since it was generated.
|
|
66
|
+
*
|
|
67
|
+
* Returns `null` when the cache is missing, expired, or invalidated.
|
|
68
|
+
*/
|
|
69
|
+
export function getCachedIntro(): CachedIntro | null {
|
|
70
|
+
try {
|
|
71
|
+
const text = getMemoryCheckpoint(CHECKPOINT_KEY_TEXT);
|
|
72
|
+
const hash = getMemoryCheckpoint(CHECKPOINT_KEY_HASH);
|
|
73
|
+
const timestampStr = getMemoryCheckpoint(CHECKPOINT_KEY_TIMESTAMP);
|
|
74
|
+
|
|
75
|
+
if (!text || !hash || !timestampStr) return null;
|
|
76
|
+
|
|
77
|
+
// TTL check
|
|
78
|
+
const cachedAt = Number(timestampStr);
|
|
79
|
+
if (isNaN(cachedAt) || Date.now() - cachedAt > CACHE_TTL_MS) return null;
|
|
80
|
+
|
|
81
|
+
// Content-hash check — bust cache when identity files change
|
|
82
|
+
const currentHash = computeIdentityContentHash();
|
|
83
|
+
if (currentHash !== hash) return null;
|
|
84
|
+
|
|
85
|
+
return { text };
|
|
86
|
+
} catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Store the generated identity intro text in the cache along with
|
|
93
|
+
* the current content hash and timestamp.
|
|
94
|
+
*/
|
|
95
|
+
export function setCachedIntro(text: string): void {
|
|
96
|
+
try {
|
|
97
|
+
const hash = computeIdentityContentHash();
|
|
98
|
+
const now = String(Date.now());
|
|
99
|
+
setMemoryCheckpoint(CHECKPOINT_KEY_TEXT, text);
|
|
100
|
+
setMemoryCheckpoint(CHECKPOINT_KEY_HASH, hash);
|
|
101
|
+
setMemoryCheckpoint(CHECKPOINT_KEY_TIMESTAMP, now);
|
|
102
|
+
} catch {
|
|
103
|
+
// Cache write failure is non-fatal — next request will regenerate.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -11,6 +11,7 @@ import { getBaseDataDir } from "../../config/env-registry.js";
|
|
|
11
11
|
import { getWorkspacePromptPath, readLockfile } from "../../util/platform.js";
|
|
12
12
|
import { httpError } from "../http-errors.js";
|
|
13
13
|
import type { RouteDefinition } from "../http-router.js";
|
|
14
|
+
import { getCachedIntro } from "./identity-intro-cache.js";
|
|
14
15
|
|
|
15
16
|
interface DiskSpaceInfo {
|
|
16
17
|
path: string;
|
|
@@ -233,6 +234,51 @@ export function handleGetIdentity(): Response {
|
|
|
233
234
|
});
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Identity intro cache
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Parse the `## Identity Intro` section from SOUL.md.
|
|
243
|
+
* Returns the first non-empty line under that heading, or null.
|
|
244
|
+
*/
|
|
245
|
+
function readSoulIdentityIntro(): string | null {
|
|
246
|
+
try {
|
|
247
|
+
const soulPath = getWorkspacePromptPath("SOUL.md");
|
|
248
|
+
if (!existsSync(soulPath)) return null;
|
|
249
|
+
const content = readFileSync(soulPath, "utf-8");
|
|
250
|
+
|
|
251
|
+
let inSection = false;
|
|
252
|
+
for (const line of content.split("\n")) {
|
|
253
|
+
const trimmed = line.trim();
|
|
254
|
+
if (/^#+\s/.test(trimmed)) {
|
|
255
|
+
inSection = trimmed.toLowerCase().includes("identity intro");
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (inSection && trimmed.length > 0) {
|
|
259
|
+
return trimmed;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} catch {
|
|
263
|
+
// Fall through to cache/fallback
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function handleGetIdentityIntro(): Response {
|
|
269
|
+
// Prefer SOUL.md persisted intro over LLM-generated cache
|
|
270
|
+
const soulIntro = readSoulIdentityIntro();
|
|
271
|
+
if (soulIntro) {
|
|
272
|
+
return Response.json({ text: soulIntro });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const cached = getCachedIntro();
|
|
276
|
+
if (!cached) {
|
|
277
|
+
return httpError("NOT_FOUND", "No cached identity intro available", 404);
|
|
278
|
+
}
|
|
279
|
+
return Response.json({ text: cached.text });
|
|
280
|
+
}
|
|
281
|
+
|
|
236
282
|
// ---------------------------------------------------------------------------
|
|
237
283
|
// Route definitions
|
|
238
284
|
// ---------------------------------------------------------------------------
|
|
@@ -249,5 +295,10 @@ export function identityRouteDefinitions(): RouteDefinition[] {
|
|
|
249
295
|
method: "GET",
|
|
250
296
|
handler: () => handleGetIdentity(),
|
|
251
297
|
},
|
|
298
|
+
{
|
|
299
|
+
endpoint: "identity/intro",
|
|
300
|
+
method: "GET",
|
|
301
|
+
handler: () => handleGetIdentityIntro(),
|
|
302
|
+
},
|
|
252
303
|
];
|
|
253
304
|
}
|
|
@@ -134,7 +134,7 @@ export function handleEscalationIntercept(
|
|
|
134
134
|
void emitNotificationSignal({
|
|
135
135
|
sourceEventName: "ingress.escalation",
|
|
136
136
|
sourceChannel: sourceChannel as NotificationSourceChannel,
|
|
137
|
-
|
|
137
|
+
sourceContextId: conversationId,
|
|
138
138
|
attentionHints: {
|
|
139
139
|
requiresAction: true,
|
|
140
140
|
urgency: "high",
|
|
@@ -231,7 +231,7 @@ export async function handleVerificationIntercept(
|
|
|
231
231
|
void emitNotificationSignal({
|
|
232
232
|
sourceEventName: "ingress.trusted_contact.activated",
|
|
233
233
|
sourceChannel: sourceChannel as NotificationSourceChannel,
|
|
234
|
-
|
|
234
|
+
sourceContextId: conversationId,
|
|
235
235
|
attentionHints: {
|
|
236
236
|
requiresAction: false,
|
|
237
237
|
urgency: "low",
|
|
@@ -11,12 +11,19 @@
|
|
|
11
11
|
* results with is_valid flag and detailed error descriptions.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import { join } from "node:path";
|
|
14
15
|
import { Database } from "bun:sqlite";
|
|
15
16
|
|
|
16
17
|
import { invalidateConfigCache } from "../../config/loader.js";
|
|
17
18
|
import { resetDb } from "../../memory/db-connection.js";
|
|
19
|
+
import { clearCache as clearTrustCache } from "../../permissions/trust-store.js";
|
|
18
20
|
import { getLogger } from "../../util/logger.js";
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
getDbPath,
|
|
23
|
+
getHooksDir,
|
|
24
|
+
getRootDir,
|
|
25
|
+
getWorkspaceDir,
|
|
26
|
+
} from "../../util/platform.js";
|
|
20
27
|
import { httpError } from "../http-errors.js";
|
|
21
28
|
import type { RouteDefinition } from "../http-router.js";
|
|
22
29
|
import { buildExportVBundle } from "../migrations/vbundle-builder.js";
|
|
@@ -135,13 +142,14 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
|
|
|
135
142
|
|
|
136
143
|
try {
|
|
137
144
|
const { archive, manifest } = buildExportVBundle({
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
trustPath: join(getRootDir(), "protected", "trust.json"),
|
|
146
|
+
hooksDir: getHooksDir(),
|
|
147
|
+
workspaceDir: getWorkspaceDir(),
|
|
140
148
|
source: "runtime-export",
|
|
141
149
|
description,
|
|
142
150
|
checkpoint: () => {
|
|
151
|
+
const dbPath = getDbPath();
|
|
143
152
|
try {
|
|
144
|
-
const dbPath = getDbPath();
|
|
145
153
|
const db = new Database(dbPath);
|
|
146
154
|
try {
|
|
147
155
|
db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
@@ -149,10 +157,10 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
|
|
|
149
157
|
db.close();
|
|
150
158
|
}
|
|
151
159
|
} catch (err) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
);
|
|
160
|
+
// Best-effort: if the DB can't be checkpointed (e.g. not a valid
|
|
161
|
+
// SQLite file, missing WAL, etc.) we still proceed with the export
|
|
162
|
+
// using whatever is on disk.
|
|
163
|
+
log.warn({ err }, "WAL checkpoint failed — exporting without checkpoint");
|
|
156
164
|
}
|
|
157
165
|
},
|
|
158
166
|
});
|
|
@@ -289,8 +297,9 @@ export async function handleMigrationImportPreflight(
|
|
|
289
297
|
|
|
290
298
|
// Step 2: Analyze what would change on import
|
|
291
299
|
const pathResolver = new DefaultPathResolver(
|
|
292
|
-
|
|
293
|
-
|
|
300
|
+
join(getRootDir(), "protected"),
|
|
301
|
+
getWorkspaceDir(),
|
|
302
|
+
getHooksDir(),
|
|
294
303
|
);
|
|
295
304
|
|
|
296
305
|
const report = analyzeImport({
|
|
@@ -371,8 +380,9 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
371
380
|
}
|
|
372
381
|
|
|
373
382
|
const pathResolver = new DefaultPathResolver(
|
|
374
|
-
|
|
375
|
-
|
|
383
|
+
join(getRootDir(), "protected"),
|
|
384
|
+
getWorkspaceDir(),
|
|
385
|
+
getHooksDir(),
|
|
376
386
|
);
|
|
377
387
|
|
|
378
388
|
// Close the live SQLite connection before overwriting assistant.db on disk.
|
|
@@ -384,6 +394,7 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
384
394
|
pathResolver,
|
|
385
395
|
preValidatedManifest: validation.manifest,
|
|
386
396
|
preValidatedEntries: validation.entries,
|
|
397
|
+
workspaceDir: getWorkspaceDir(),
|
|
387
398
|
});
|
|
388
399
|
|
|
389
400
|
if (!result.ok) {
|
|
@@ -420,8 +431,9 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
420
431
|
);
|
|
421
432
|
}
|
|
422
433
|
|
|
423
|
-
// Invalidate in-process
|
|
434
|
+
// Invalidate in-process caches so imported settings.json and trust.json take effect
|
|
424
435
|
invalidateConfigCache();
|
|
436
|
+
clearTrustCache();
|
|
425
437
|
|
|
426
438
|
return Response.json(result.report);
|
|
427
439
|
} catch (err) {
|
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
} from "../../config/loader.js";
|
|
12
12
|
import type { CesClient } from "../../credential-execution/client.js";
|
|
13
13
|
import { setSentryOrganizationId } from "../../instrument.js";
|
|
14
|
+
import { syncManualTokenConnection } from "../../oauth/manual-token-connection.js";
|
|
15
|
+
import { validateAnthropicApiKey } from "../../providers/anthropic/client.js";
|
|
14
16
|
import { initializeProviders } from "../../providers/registry.js";
|
|
15
17
|
import { credentialKey } from "../../security/credential-key.js";
|
|
16
18
|
import {
|
|
@@ -129,6 +131,21 @@ export async function handleAddSecret(
|
|
|
129
131
|
400,
|
|
130
132
|
);
|
|
131
133
|
}
|
|
134
|
+
// Validate Anthropic API keys before storing
|
|
135
|
+
if (name === "anthropic") {
|
|
136
|
+
const validation = await validateAnthropicApiKey(value);
|
|
137
|
+
if (!validation.valid) {
|
|
138
|
+
log.warn(
|
|
139
|
+
{ provider: name, reason: validation.reason },
|
|
140
|
+
"API key validation failed",
|
|
141
|
+
);
|
|
142
|
+
return Response.json(
|
|
143
|
+
{ success: false, error: validation.reason },
|
|
144
|
+
{ status: 422 },
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
132
149
|
const stored = await setSecureKeyAsync(name, value);
|
|
133
150
|
if (!stored) {
|
|
134
151
|
return httpError(
|
|
@@ -201,6 +218,7 @@ export async function handleAddSecret(
|
|
|
201
218
|
);
|
|
202
219
|
}
|
|
203
220
|
upsertCredentialMetadata(service, field, {});
|
|
221
|
+
await syncManualTokenConnection(service);
|
|
204
222
|
if (service === "vellum" && field === "platform_base_url") {
|
|
205
223
|
setPlatformBaseUrl(effectiveValue);
|
|
206
224
|
}
|
|
@@ -43,8 +43,8 @@ import {
|
|
|
43
43
|
} from "../../tools/execution-target.js";
|
|
44
44
|
import { getAllTools, getTool } from "../../tools/registry.js";
|
|
45
45
|
import {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
ACTIVITY_SKIP_SET,
|
|
47
|
+
injectActivityField,
|
|
48
48
|
} from "../../tools/schema-transforms.js";
|
|
49
49
|
import { isSideEffectTool } from "../../tools/side-effects.js";
|
|
50
50
|
import { generateAndSaveAvatar } from "../../tools/system/avatar-generator.js";
|
|
@@ -400,17 +400,17 @@ function handleToolNamesList(): Response {
|
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
// Apply
|
|
404
|
-
const transformedDefs =
|
|
403
|
+
// Apply activity injection so settings/debug schemas match runtime behavior.
|
|
404
|
+
const transformedDefs = injectActivityField(rawDefs, ACTIVITY_SKIP_SET);
|
|
405
405
|
for (const def of transformedDefs) {
|
|
406
406
|
schemas[def.name] = def.input_schema as SchemaShape;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
// Skill manifest schemas are served raw (untransformed). Unlike runtime tool
|
|
410
|
-
// schemas which have `
|
|
411
|
-
// reflect the original TOOLS.json content. This is intentional:
|
|
412
|
-
// invoked through skill_execute (which has its own
|
|
413
|
-
// individual schemas are never sent to the LLM directly.
|
|
410
|
+
// schemas which have `activity` injected via injectActivityField(), skill
|
|
411
|
+
// manifests reflect the original TOOLS.json content. This is intentional:
|
|
412
|
+
// skill tools are invoked through skill_execute (which has its own activity
|
|
413
|
+
// field), so their individual schemas are never sent to the LLM directly.
|
|
414
414
|
try {
|
|
415
415
|
const catalog = loadSkillCatalog();
|
|
416
416
|
for (const skill of catalog) {
|
|
@@ -522,7 +522,7 @@ async function handleToolPermissionSimulate(body: {
|
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
return Response.json({
|
|
525
|
-
|
|
525
|
+
success: true,
|
|
526
526
|
decision: result.decision,
|
|
527
527
|
riskLevel,
|
|
528
528
|
reason: result.reason,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handlers for telemetry lifecycle events.
|
|
3
|
+
*
|
|
4
|
+
* POST /v1/telemetry/lifecycle — record a lifecycle event (app_open, hatch).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { recordLifecycleEvent } from "../../memory/lifecycle-events-store.js";
|
|
8
|
+
import { getLogger } from "../../util/logger.js";
|
|
9
|
+
import { httpError } from "../http-errors.js";
|
|
10
|
+
import type { RouteDefinition } from "../http-router.js";
|
|
11
|
+
|
|
12
|
+
const log = getLogger("telemetry-routes");
|
|
13
|
+
|
|
14
|
+
const VALID_EVENT_NAMES = new Set(["app_open", "hatch"]);
|
|
15
|
+
|
|
16
|
+
export async function handleRecordLifecycleEvent(
|
|
17
|
+
req: Request,
|
|
18
|
+
): Promise<Response> {
|
|
19
|
+
let body: { event_name?: string };
|
|
20
|
+
try {
|
|
21
|
+
body = (await req.json()) as { event_name?: string };
|
|
22
|
+
} catch {
|
|
23
|
+
return httpError("BAD_REQUEST", "Invalid JSON body", 400);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const eventName = body.event_name;
|
|
27
|
+
if (!eventName || !VALID_EVENT_NAMES.has(eventName)) {
|
|
28
|
+
return httpError(
|
|
29
|
+
"BAD_REQUEST",
|
|
30
|
+
`event_name must be one of: ${[...VALID_EVENT_NAMES].join(", ")}`,
|
|
31
|
+
400,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const event = recordLifecycleEvent(eventName);
|
|
36
|
+
log.info({ eventName, eventId: event.id }, "Recorded lifecycle event");
|
|
37
|
+
|
|
38
|
+
return Response.json({ id: event.id, event_name: event.eventName });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Route definitions
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
export function telemetryRouteDefinitions(): RouteDefinition[] {
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
endpoint: "telemetry/lifecycle",
|
|
49
|
+
method: "POST",
|
|
50
|
+
handler: async ({ req }) => handleRecordLifecycleEvent(req),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP route handlers for trace event retrieval.
|
|
3
|
+
*
|
|
4
|
+
* GET /v1/trace-events — Returns persisted trace events for a conversation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getTraceEvents } from "../../memory/trace-event-store.js";
|
|
8
|
+
import { httpError } from "../http-errors.js";
|
|
9
|
+
import type { RouteDefinition } from "../http-router.js";
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Route definitions
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export function traceEventRouteDefinitions(): RouteDefinition[] {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
endpoint: "trace-events",
|
|
19
|
+
method: "GET",
|
|
20
|
+
handler: ({ url }) => {
|
|
21
|
+
const conversationId = url.searchParams.get("conversationId");
|
|
22
|
+
if (!conversationId) {
|
|
23
|
+
return httpError(
|
|
24
|
+
"BAD_REQUEST",
|
|
25
|
+
"conversationId query parameter is required",
|
|
26
|
+
400,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const limitParam = url.searchParams.get("limit");
|
|
31
|
+
const afterSequenceParam = url.searchParams.get("afterSequence");
|
|
32
|
+
|
|
33
|
+
const limit = limitParam ? parseInt(limitParam, 10) : undefined;
|
|
34
|
+
if (limitParam && (isNaN(limit!) || limit! <= 0)) {
|
|
35
|
+
return httpError(
|
|
36
|
+
"BAD_REQUEST",
|
|
37
|
+
"limit must be a positive integer",
|
|
38
|
+
400,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const afterSequence = afterSequenceParam
|
|
43
|
+
? parseInt(afterSequenceParam, 10)
|
|
44
|
+
: undefined;
|
|
45
|
+
if (afterSequenceParam && (isNaN(afterSequence!) || afterSequence! < 0)) {
|
|
46
|
+
return httpError(
|
|
47
|
+
"BAD_REQUEST",
|
|
48
|
+
"afterSequence must be a non-negative integer",
|
|
49
|
+
400,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const events = getTraceEvents(conversationId, {
|
|
54
|
+
limit,
|
|
55
|
+
afterSequence,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return Response.json({ events });
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
@@ -146,7 +146,7 @@ export function createOrReuseToolGrantRequest(
|
|
|
146
146
|
const signalPromise = emitNotificationSignal({
|
|
147
147
|
sourceEventName: "guardian.question",
|
|
148
148
|
sourceChannel: sourceChannel as NotificationSourceChannel,
|
|
149
|
-
|
|
149
|
+
sourceContextId: conversationId,
|
|
150
150
|
attentionHints: {
|
|
151
151
|
requiresAction: true,
|
|
152
152
|
urgency: "high",
|
|
@@ -116,6 +116,12 @@ export interface OutboundActionResult {
|
|
|
116
116
|
pendingBootstrap?: boolean;
|
|
117
117
|
/** Echoed back so consumers know which conversation to target for pointers. */
|
|
118
118
|
originConversationId?: string;
|
|
119
|
+
/** Internal: Slack DM delivery payload for the caller to dispatch.
|
|
120
|
+
* The shared startOutbound/resendOutbound functions no longer fire the
|
|
121
|
+
* delivery themselves because CLI subprocesses are sandboxed and cannot
|
|
122
|
+
* reach the gateway. The daemon HTTP route handler calls
|
|
123
|
+
* deliverVerificationSlack() after receiving this payload. */
|
|
124
|
+
_pendingSlackDm?: { userId: string; text: string; assistantId: string };
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
// ---------------------------------------------------------------------------
|
|
@@ -486,42 +492,52 @@ function startOutboundVoice(
|
|
|
486
492
|
|
|
487
493
|
/**
|
|
488
494
|
* Deliver a verification Slack DM via the gateway's /deliver/slack endpoint.
|
|
489
|
-
*
|
|
495
|
+
* Returns a promise that resolves when the delivery attempt completes.
|
|
490
496
|
*/
|
|
491
|
-
export function
|
|
497
|
+
export async function deliverVerificationSlackAsync(
|
|
492
498
|
userId: string,
|
|
493
499
|
text: string,
|
|
494
500
|
assistantId: string,
|
|
495
|
-
): void {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const body = await resp.text().catch(() => "<unreadable>");
|
|
511
|
-
log.error(
|
|
512
|
-
{ userId, assistantId, status: resp.status, body },
|
|
513
|
-
"Gateway /deliver/slack failed for verification",
|
|
514
|
-
);
|
|
515
|
-
} else {
|
|
516
|
-
log.info({ userId, assistantId }, "Verification Slack DM delivered");
|
|
517
|
-
}
|
|
518
|
-
} catch (err) {
|
|
501
|
+
): Promise<void> {
|
|
502
|
+
try {
|
|
503
|
+
const gatewayUrl = getGatewayInternalBaseUrl();
|
|
504
|
+
const bearerToken = mintDaemonDeliveryToken();
|
|
505
|
+
const url = `${gatewayUrl}/deliver/slack`;
|
|
506
|
+
const resp = await fetch(url, {
|
|
507
|
+
method: "POST",
|
|
508
|
+
headers: {
|
|
509
|
+
"Content-Type": "application/json",
|
|
510
|
+
Authorization: `Bearer ${bearerToken}`,
|
|
511
|
+
},
|
|
512
|
+
body: JSON.stringify({ chatId: userId, text, assistantId }),
|
|
513
|
+
});
|
|
514
|
+
if (!resp.ok) {
|
|
515
|
+
const body = await resp.text().catch(() => "<unreadable>");
|
|
519
516
|
log.error(
|
|
520
|
-
{
|
|
521
|
-
"
|
|
517
|
+
{ userId, assistantId, status: resp.status, body },
|
|
518
|
+
"Gateway /deliver/slack failed for verification",
|
|
522
519
|
);
|
|
520
|
+
} else {
|
|
521
|
+
log.info({ userId, assistantId }, "Verification Slack DM delivered");
|
|
523
522
|
}
|
|
524
|
-
}
|
|
523
|
+
} catch (err) {
|
|
524
|
+
log.error(
|
|
525
|
+
{ err, userId, assistantId },
|
|
526
|
+
"Failed to deliver verification Slack DM",
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Deliver a verification Slack DM via the gateway's /deliver/slack endpoint.
|
|
533
|
+
* Fire-and-forget wrapper for use in the daemon process (HTTP route handlers).
|
|
534
|
+
*/
|
|
535
|
+
export function deliverVerificationSlack(
|
|
536
|
+
userId: string,
|
|
537
|
+
text: string,
|
|
538
|
+
assistantId: string,
|
|
539
|
+
): void {
|
|
540
|
+
deliverVerificationSlackAsync(userId, text, assistantId);
|
|
525
541
|
}
|
|
526
542
|
|
|
527
543
|
function startOutboundSlack(
|
|
@@ -588,7 +604,6 @@ function startOutboundSlack(
|
|
|
588
604
|
const sendCount = 1;
|
|
589
605
|
|
|
590
606
|
updateSessionDelivery(sessionResult.sessionId, now, sendCount, nextResendAt);
|
|
591
|
-
deliverVerificationSlack(destination, slackBody, assistantId);
|
|
592
607
|
|
|
593
608
|
return {
|
|
594
609
|
success: true,
|
|
@@ -599,6 +614,7 @@ function startOutboundSlack(
|
|
|
599
614
|
sendCount,
|
|
600
615
|
channel,
|
|
601
616
|
originConversationId,
|
|
617
|
+
_pendingSlackDm: { userId: destination, text: slackBody, assistantId },
|
|
602
618
|
};
|
|
603
619
|
}
|
|
604
620
|
|
|
@@ -788,7 +804,6 @@ export function resendOutbound(
|
|
|
788
804
|
newSendCount,
|
|
789
805
|
nextResendAt,
|
|
790
806
|
);
|
|
791
|
-
deliverVerificationSlack(destination, slackBody, assistantId);
|
|
792
807
|
|
|
793
808
|
return {
|
|
794
809
|
success: true,
|
|
@@ -798,6 +813,7 @@ export function resendOutbound(
|
|
|
798
813
|
sendCount: newSendCount,
|
|
799
814
|
channel,
|
|
800
815
|
originConversationId,
|
|
816
|
+
_pendingSlackDm: { userId: destination, text: slackBody, assistantId },
|
|
801
817
|
};
|
|
802
818
|
}
|
|
803
819
|
|