@vellumai/assistant 0.4.56 → 0.4.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +10 -10
- package/Dockerfile +3 -0
- package/README.md +11 -11
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/memory.md +3 -4
- package/docs/credential-execution-service.md +13 -20
- package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +7 -7
- package/src/__tests__/anthropic-provider.test.ts +172 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
- package/src/__tests__/approval-cascade.test.ts +2 -2
- package/src/__tests__/approval-routes-http.test.ts +3 -4
- package/src/__tests__/asset-materialize-tool.test.ts +5 -5
- package/src/__tests__/asset-search-tool.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +5 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
- package/src/__tests__/attachments-store.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +5 -3
- package/src/__tests__/browser-skill-endstate.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +2 -2
- package/src/__tests__/callback-handoff-copy.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +31 -32
- package/src/__tests__/chrome-cdp.test.ts +47 -18
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +9 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop.test.ts +11 -4
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +33 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
- package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +23 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +185 -173
- package/src/__tests__/conversation-seed-composer.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +4 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
- package/src/__tests__/conversation-starter-routes.test.ts +291 -0
- package/src/__tests__/conversation-wipe.test.ts +438 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
- package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
- package/src/__tests__/credential-security-e2e.test.ts +20 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +227 -0
- package/src/__tests__/credentials-cli.test.ts +3 -0
- package/src/__tests__/date-context.test.ts +59 -377
- package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/encrypted-store.test.ts +237 -15
- package/src/__tests__/ephemeral-permissions.test.ts +4 -5
- package/src/__tests__/event-bus.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +4 -4
- package/src/__tests__/gemini-provider.test.ts +6 -9
- package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/host-shell-tool.test.ts +6 -6
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/intent-routing.test.ts +51 -99
- package/src/__tests__/invite-routes-http.test.ts +5 -0
- package/src/__tests__/list-messages-attachments.test.ts +1 -1
- package/src/__tests__/managed-proxy-context.test.ts +2 -5
- package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
- package/src/__tests__/media-generate-image.test.ts +32 -15
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
- package/src/__tests__/memory-recall-quality.test.ts +4 -3
- package/src/__tests__/memory-regressions.test.ts +86 -90
- package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
- package/src/__tests__/migration-export-http.test.ts +26 -27
- package/src/__tests__/migration-import-commit-http.test.ts +165 -37
- package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
- package/src/__tests__/migration-validate-http.test.ts +16 -16
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
- package/src/__tests__/notification-broadcaster.test.ts +1 -1
- package/src/__tests__/notification-decision-fallback.test.ts +2 -2
- package/src/__tests__/notification-decision-identity.test.ts +8 -9
- package/src/__tests__/notification-decision-strategy.test.ts +1 -1
- package/src/__tests__/notification-deep-link.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
- package/src/__tests__/onboarding-template-contract.test.ts +23 -59
- package/src/__tests__/provider-error-scenarios.test.ts +154 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
- package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
- package/src/__tests__/provider-registry-ollama.test.ts +5 -2
- package/src/__tests__/qdrant-manager.test.ts +7 -7
- package/src/__tests__/ratelimit.test.ts +0 -74
- package/src/__tests__/recording-handler.test.ts +0 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +46 -2
- package/src/__tests__/schema-transforms.test.ts +114 -54
- package/src/__tests__/secret-onetime-send.test.ts +20 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
- package/src/__tests__/secret-scanner-executor.test.ts +1 -2
- package/src/__tests__/send-endpoint-busy.test.ts +63 -4
- package/src/__tests__/send-notification-tool.test.ts +2 -2
- package/src/__tests__/shell-credential-ref.test.ts +0 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
- package/src/__tests__/skill-memory.test.ts +547 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
- package/src/__tests__/slack-channel-config.test.ts +109 -94
- package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
- package/src/__tests__/swarm-recursion.test.ts +2 -2
- package/src/__tests__/swarm-tool.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +19 -66
- package/src/__tests__/telegram-config.test.ts +121 -0
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trace-emitter.test.ts +8 -1
- package/src/__tests__/trust-store.test.ts +7 -8
- package/src/__tests__/twilio-routes.test.ts +1 -18
- package/src/__tests__/user-reference.test.ts +82 -2
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +3 -3
- package/src/avatar/ascii-renderer.ts +2 -2
- package/src/avatar/png-renderer.ts +2 -2
- package/src/avatar/resvg-lazy.ts +21 -0
- package/src/calls/guardian-dispatch.ts +1 -1
- package/src/calls/relay-access-wait.ts +2 -2
- package/src/calls/twilio-rest.ts +0 -248
- package/src/cli/AGENTS.md +5 -8
- package/src/cli/__tests__/notifications.test.ts +5 -5
- package/src/cli/commands/avatar.ts +64 -2
- package/src/cli/commands/conversations.ts +131 -1
- package/src/cli/commands/credentials.ts +2 -0
- package/src/cli/commands/notifications.ts +3 -3
- package/src/cli.ts +10 -0
- package/src/config/bundled-skills/acp/SKILL.md +5 -5
- package/src/config/bundled-skills/acp/TOOLS.json +6 -6
- package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
- package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
- package/src/config/bundled-skills/browser/SKILL.md +15 -15
- package/src/config/bundled-skills/browser/TOOLS.json +14 -14
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
- package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
- package/src/config/bundled-skills/contacts/SKILL.md +3 -3
- package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
- package/src/config/bundled-skills/document/SKILL.md +4 -4
- package/src/config/bundled-skills/document/TOOLS.json +2 -2
- package/src/config/bundled-skills/followups/TOOLS.json +3 -3
- package/src/config/bundled-skills/gmail/SKILL.md +32 -32
- package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
- package/src/config/bundled-skills/google-calendar/types.ts +1 -1
- package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
- package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
- package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
- package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +29 -25
- package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +3 -3
- package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
- package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
- package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
- package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
- package/src/config/bundled-skills/schedule/SKILL.md +26 -26
- package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
- package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
- package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
- package/src/config/bundled-skills/sequences/SKILL.md +2 -2
- package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
- package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
- package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
- package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
- package/src/config/bundled-skills/slack/SKILL.md +2 -2
- package/src/config/bundled-skills/slack/TOOLS.json +8 -8
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
- package/src/config/bundled-skills/tasks/SKILL.md +1 -1
- package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
- package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
- package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
- package/src/config/bundled-skills/watcher/SKILL.md +4 -4
- package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
- package/src/config/feature-flag-registry.json +33 -17
- package/src/config/schemas/sandbox.ts +1 -1
- package/src/config/schemas/services.ts +13 -3
- package/src/config/schemas/timeouts.ts +0 -10
- package/src/contacts/contact-store.ts +63 -0
- package/src/contacts/contacts-write.ts +1 -1
- package/src/daemon/assistant-attachments.ts +2 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
- package/src/daemon/conversation-agent-loop.ts +7 -30
- package/src/daemon/conversation-error.ts +24 -0
- package/src/daemon/conversation-memory.ts +8 -7
- package/src/daemon/conversation-runtime-assembly.ts +139 -274
- package/src/daemon/conversation-slash.ts +7 -26
- package/src/daemon/conversation-surfaces.ts +14 -0
- package/src/daemon/conversation-tool-setup.ts +9 -8
- package/src/daemon/conversation.ts +2 -0
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +10 -83
- package/src/daemon/handlers/config-channels.ts +12 -2
- package/src/daemon/handlers/config-slack-channel.ts +7 -1
- package/src/daemon/handlers/config-telegram.ts +6 -1
- package/src/daemon/handlers/conversations.ts +2 -2
- package/src/daemon/handlers/skills.ts +4 -0
- package/src/daemon/lifecycle.ts +28 -4
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +1 -5
- package/src/daemon/shutdown-handlers.ts +9 -3
- package/src/daemon/tool-side-effects.ts +40 -0
- package/src/daemon/trace-emitter.ts +25 -2
- package/src/events/domain-events.ts +1 -1
- package/src/events/tool-permission-telemetry-listener.ts +46 -0
- package/src/inbound/platform-callback-registration.ts +0 -18
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +15 -8
- package/src/media/gemini-image-service.ts +125 -21
- package/src/memory/attachments-store.ts +3 -3
- package/src/memory/channel-verification-sessions.ts +6 -6
- package/src/memory/conversation-crud.ts +196 -1
- package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
- package/src/memory/conversation-title-service.ts +2 -3
- package/src/memory/db-init.ts +25 -1
- package/src/memory/invite-store.ts +4 -4
- package/src/memory/items-extractor.ts +4 -4
- package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/jobs-worker.ts +7 -5
- package/src/memory/lifecycle-events-store.ts +63 -0
- package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
- package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
- package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
- package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
- package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
- package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +223 -96
- package/src/memory/retriever.ts +115 -138
- package/src/memory/schema/calls.ts +1 -1
- package/src/memory/schema/contacts.ts +1 -1
- package/src/memory/schema/infrastructure.ts +29 -0
- package/src/memory/schema/memory-core.ts +7 -17
- package/src/memory/schema/notifications.ts +1 -1
- package/src/memory/search/formatting.ts +23 -6
- package/src/memory/search/lexical.ts +2 -0
- package/src/memory/search/semantic.ts +2 -0
- package/src/memory/search/staleness.ts +1 -0
- package/src/memory/search/types.ts +4 -0
- package/src/memory/task-memory-cleanup.ts +96 -6
- package/src/memory/trace-event-store.ts +148 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/emit-signal.ts +4 -4
- package/src/notifications/events-store.ts +4 -4
- package/src/notifications/signal.ts +1 -1
- package/src/oauth/manual-token-connection.ts +49 -25
- package/src/permissions/checker.ts +6 -5
- package/src/permissions/defaults.ts +4 -4
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
- package/src/prompts/cache-boundary.ts +8 -0
- package/src/prompts/system-prompt.ts +105 -634
- package/src/prompts/templates/BOOTSTRAP.md +166 -33
- package/src/prompts/templates/IDENTITY.md +8 -23
- package/src/prompts/templates/SOUL.md +20 -41
- package/src/prompts/templates/USER.md +3 -19
- package/src/prompts/user-reference.ts +14 -16
- package/src/providers/anthropic/client.ts +46 -2
- package/src/providers/gemini/client.ts +6 -9
- package/src/providers/managed-proxy/constants.ts +1 -7
- package/src/providers/managed-proxy/context.ts +0 -1
- package/src/providers/model-intents.ts +5 -5
- package/src/providers/openai/client.ts +10 -1
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/ratelimit.ts +0 -35
- package/src/providers/registry.ts +3 -5
- package/src/providers/retry.ts +18 -1
- package/src/runtime/access-request-helper.ts +1 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/channel-verification-service.ts +1 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/guardian-vellum-migration.ts +63 -1
- package/src/runtime/http-server.ts +8 -4
- package/src/runtime/migrations/vbundle-builder.ts +212 -32
- package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
- package/src/runtime/migrations/vbundle-importer.ts +66 -1
- package/src/runtime/migrations/vbundle-validator.ts +17 -3
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
- package/src/runtime/routes/attachment-routes.ts +2 -2
- package/src/runtime/routes/btw-routes.ts +9 -0
- package/src/runtime/routes/channel-verification-routes.ts +19 -2
- package/src/runtime/routes/conversation-management-routes.ts +55 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +49 -5
- package/src/runtime/routes/conversation-starter-routes.ts +207 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +25 -13
- package/src/runtime/routes/secret-routes.ts +18 -0
- package/src/runtime/routes/settings-routes.ts +8 -8
- package/src/runtime/routes/telemetry-routes.ts +53 -0
- package/src/runtime/routes/trace-event-routes.ts +62 -0
- package/src/runtime/tool-grant-request-helper.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +47 -31
- package/src/security/encrypted-store.ts +263 -78
- package/src/skills/catalog-install.ts +10 -0
- package/src/skills/managed-store.ts +2 -0
- package/src/skills/skill-memory.ts +220 -0
- package/src/subagent/manager.ts +1 -4
- package/src/telemetry/types.ts +10 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/telemetry/usage-telemetry-reporter.ts +51 -4
- package/src/tools/AGENTS.md +11 -11
- package/src/tools/acp/spawn.ts +1 -1
- package/src/tools/apps/executors.ts +8 -8
- package/src/tools/apps/registry.ts +1 -1
- package/src/tools/assets/materialize.ts +6 -6
- package/src/tools/assets/search.ts +10 -10
- package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
- package/src/tools/browser/auth-detector.ts +6 -6
- package/src/tools/browser/browser-execution.ts +13 -13
- package/src/tools/browser/browser-manager.ts +3 -3
- package/src/tools/browser/chrome-cdp.ts +5 -5
- package/src/tools/browser/jit-auth.ts +2 -2
- package/src/tools/browser/network-recorder.test.ts +2 -2
- package/src/tools/browser/network-recorder.ts +3 -3
- package/src/tools/browser/runtime-check.ts +3 -3
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/computer-use/definitions.ts +18 -18
- package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
- package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
- package/src/tools/credentials/broker-types.ts +5 -5
- package/src/tools/credentials/broker.ts +15 -15
- package/src/tools/credentials/metadata-store.ts +2 -2
- package/src/tools/credentials/resolve.ts +1 -1
- package/src/tools/credentials/selection.ts +1 -1
- package/src/tools/credentials/tool-policy.ts +1 -1
- package/src/tools/credentials/vault.ts +115 -25
- package/src/tools/execution-target.ts +2 -2
- package/src/tools/executor.ts +7 -7
- package/src/tools/filesystem/edit.ts +2 -2
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +1 -1
- package/src/tools/host-filesystem/edit.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -1
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +9 -8
- package/src/tools/mcp/mcp-tool-factory.ts +7 -6
- package/src/tools/memory/definitions.ts +6 -5
- package/src/tools/memory/handlers.test.ts +1 -1
- package/src/tools/network/__tests__/web-search.test.ts +3 -3
- package/src/tools/network/domain-normalize.ts +2 -2
- package/src/tools/network/script-proxy/session-manager.ts +10 -10
- package/src/tools/network/web-fetch.ts +1 -1
- package/src/tools/network/web-search.ts +3 -3
- package/src/tools/permission-checker.ts +8 -8
- package/src/tools/registry.ts +7 -7
- package/src/tools/schedule/list.ts +2 -2
- package/src/tools/schema-transforms.ts +31 -21
- package/src/tools/secret-detection-handler.ts +1 -1
- package/src/tools/sensitive-output-placeholders.ts +1 -1
- package/src/tools/shared/filesystem/edit-engine.ts +1 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
- package/src/tools/shared/filesystem/image-read.ts +25 -5
- package/src/tools/shared/filesystem/path-policy.ts +2 -2
- package/src/tools/shared/shell-output.ts +1 -1
- package/src/tools/side-effects.ts +1 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +3 -3
- package/src/tools/skills/sandbox-runner.ts +3 -3
- package/src/tools/subagent/read.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -2
- package/src/tools/swarm/delegate.ts +3 -3
- package/src/tools/system/request-permission.ts +5 -4
- package/src/tools/terminal/backends/native.ts +4 -4
- package/src/tools/terminal/parser.ts +6 -6
- package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
- package/src/tools/terminal/shell.ts +16 -16
- package/src/tools/tool-approval-handler.ts +21 -12
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +3 -3
- package/src/tools/ui-surface/definitions.ts +9 -37
- package/src/tools/watcher/list.ts +1 -1
- package/src/util/logger.ts +7 -2
- package/src/util/retry.ts +29 -1
- package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
- package/src/cli/reference.ts +0 -38
- package/src/memory/job-handlers/capability-cards.ts +0 -420
- package/src/runtime/routes/thread-starter-routes.ts +0 -294
|
@@ -42,9 +42,13 @@ export function isConversationFailed(conversationId: string): boolean {
|
|
|
42
42
|
export function invalidateAssistantInferredItemsForConversation(
|
|
43
43
|
conversationId: string,
|
|
44
44
|
): number {
|
|
45
|
-
// Cancel pending
|
|
45
|
+
// Cancel pending extraction jobs for this conversation's messages
|
|
46
46
|
// so the worker never processes them. Jobs already running will be
|
|
47
47
|
// caught by the isConversationFailed check in the extraction handler.
|
|
48
|
+
// NOTE: Only extract_items jobs are cancelled here — not embed_item or
|
|
49
|
+
// other job types. Multi-sourced items may still be valid (corroborated
|
|
50
|
+
// by other conversations), and their embedding jobs must not be killed.
|
|
51
|
+
// The broader cancelPendingJobsForConversation is used by the wipe path.
|
|
48
52
|
cancelPendingExtractionJobsForConversation(conversationId);
|
|
49
53
|
|
|
50
54
|
const affected = rawRun(
|
|
@@ -94,9 +98,95 @@ export function invalidateAssistantInferredItemsForConversation(
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
/**
|
|
97
|
-
* Cancel pending
|
|
98
|
-
*
|
|
99
|
-
*
|
|
101
|
+
* Cancel all pending/running memory jobs referencing the given conversation.
|
|
102
|
+
* Covers every job type: `extract_items`, `embed_attachment` (keyed by messageId),
|
|
103
|
+
* `embed_segment` (keyed by segmentId via memory_segments),
|
|
104
|
+
* `build_conversation_summary` (keyed by conversationId),
|
|
105
|
+
* and `embed_item` (keyed by itemId sourced from the conversation's messages).
|
|
106
|
+
*/
|
|
107
|
+
export function cancelPendingJobsForConversation(
|
|
108
|
+
conversationId: string,
|
|
109
|
+
reason: string = "conversation_wiped",
|
|
110
|
+
): number {
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
let total = 0;
|
|
113
|
+
|
|
114
|
+
// Jobs keyed by messageId: extract_items, embed_attachment
|
|
115
|
+
total += rawRun(
|
|
116
|
+
`UPDATE memory_jobs
|
|
117
|
+
SET status = 'failed',
|
|
118
|
+
last_error = ?,
|
|
119
|
+
updated_at = ?
|
|
120
|
+
WHERE status IN ('pending', 'running')
|
|
121
|
+
AND json_extract(payload, '$.messageId') IN (
|
|
122
|
+
SELECT id FROM messages WHERE conversation_id = ?
|
|
123
|
+
)`,
|
|
124
|
+
reason,
|
|
125
|
+
now,
|
|
126
|
+
conversationId,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Jobs keyed by conversationId: build_conversation_summary
|
|
130
|
+
total += rawRun(
|
|
131
|
+
`UPDATE memory_jobs
|
|
132
|
+
SET status = 'failed',
|
|
133
|
+
last_error = ?,
|
|
134
|
+
updated_at = ?
|
|
135
|
+
WHERE status IN ('pending', 'running')
|
|
136
|
+
AND json_extract(payload, '$.conversationId') = ?`,
|
|
137
|
+
reason,
|
|
138
|
+
now,
|
|
139
|
+
conversationId,
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// Jobs keyed by segmentId: embed_segment (segments belong to the conversation)
|
|
143
|
+
total += rawRun(
|
|
144
|
+
`UPDATE memory_jobs
|
|
145
|
+
SET status = 'failed',
|
|
146
|
+
last_error = ?,
|
|
147
|
+
updated_at = ?
|
|
148
|
+
WHERE status IN ('pending', 'running')
|
|
149
|
+
AND json_extract(payload, '$.segmentId') IN (
|
|
150
|
+
SELECT id FROM memory_segments WHERE conversation_id = ?
|
|
151
|
+
)`,
|
|
152
|
+
reason,
|
|
153
|
+
now,
|
|
154
|
+
conversationId,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Jobs keyed by itemId: embed_item (items sourced from this conversation)
|
|
158
|
+
total += rawRun(
|
|
159
|
+
`UPDATE memory_jobs
|
|
160
|
+
SET status = 'failed',
|
|
161
|
+
last_error = ?,
|
|
162
|
+
updated_at = ?
|
|
163
|
+
WHERE status IN ('pending', 'running')
|
|
164
|
+
AND json_extract(payload, '$.itemId') IN (
|
|
165
|
+
SELECT mis.memory_item_id
|
|
166
|
+
FROM memory_item_sources mis
|
|
167
|
+
JOIN messages m ON m.id = mis.message_id
|
|
168
|
+
WHERE m.conversation_id = ?
|
|
169
|
+
)`,
|
|
170
|
+
reason,
|
|
171
|
+
now,
|
|
172
|
+
conversationId,
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (total > 0) {
|
|
176
|
+
log.info(
|
|
177
|
+
{ conversationId, cancelled: total },
|
|
178
|
+
"Cancelled pending memory jobs for conversation",
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return total;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Cancel only pending/running `extract_items` jobs for messages in the
|
|
187
|
+
* given conversation. Used by the task-failure path where we want to
|
|
188
|
+
* stop new extractions but must NOT cancel `embed_item` jobs — those
|
|
189
|
+
* items may be multi-sourced and still valid.
|
|
100
190
|
*/
|
|
101
191
|
function cancelPendingExtractionJobsForConversation(
|
|
102
192
|
conversationId: string,
|
|
@@ -107,8 +197,8 @@ function cancelPendingExtractionJobsForConversation(
|
|
|
107
197
|
SET status = 'failed',
|
|
108
198
|
last_error = 'conversation_failed',
|
|
109
199
|
updated_at = ?
|
|
110
|
-
WHERE
|
|
111
|
-
AND
|
|
200
|
+
WHERE status IN ('pending', 'running')
|
|
201
|
+
AND type = 'extract_items'
|
|
112
202
|
AND json_extract(payload, '$.messageId') IN (
|
|
113
203
|
SELECT id FROM messages WHERE conversation_id = ?
|
|
114
204
|
)`,
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { and, asc, eq, gt, lt, sql } from "drizzle-orm";
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
TraceEvent,
|
|
5
|
+
TraceEventKind,
|
|
6
|
+
} from "../daemon/message-types/messages.js";
|
|
7
|
+
import { getDb, rawChanges } from "./db.js";
|
|
8
|
+
import { traceEvents } from "./schema.js";
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Types
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export interface TraceEventRow {
|
|
15
|
+
eventId: string;
|
|
16
|
+
conversationId: string;
|
|
17
|
+
requestId?: string;
|
|
18
|
+
timestampMs: number;
|
|
19
|
+
sequence: number;
|
|
20
|
+
kind: TraceEventKind;
|
|
21
|
+
status?: "info" | "success" | "warning" | "error";
|
|
22
|
+
summary: string;
|
|
23
|
+
attributes?: Record<string, string | number | boolean | null>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Write
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
/** Insert a single trace event row. Duplicate eventIds are silently ignored. */
|
|
31
|
+
export function persistTraceEvent(event: TraceEvent): void {
|
|
32
|
+
const db = getDb();
|
|
33
|
+
db.insert(traceEvents)
|
|
34
|
+
.values({
|
|
35
|
+
eventId: event.eventId,
|
|
36
|
+
conversationId: event.conversationId,
|
|
37
|
+
requestId: event.requestId ?? null,
|
|
38
|
+
timestampMs: event.timestampMs,
|
|
39
|
+
sequence: event.sequence,
|
|
40
|
+
kind: event.kind,
|
|
41
|
+
status: event.status ?? null,
|
|
42
|
+
summary: event.summary,
|
|
43
|
+
attributesJson: event.attributes
|
|
44
|
+
? JSON.stringify(event.attributes)
|
|
45
|
+
: null,
|
|
46
|
+
createdAt: Date.now(),
|
|
47
|
+
})
|
|
48
|
+
.onConflictDoNothing()
|
|
49
|
+
.run();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Read
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
/** Parse a raw DB row into a TraceEventRow with deserialized attributes. */
|
|
57
|
+
function rowToTraceEventRow(row: {
|
|
58
|
+
eventId: string;
|
|
59
|
+
conversationId: string;
|
|
60
|
+
requestId: string | null;
|
|
61
|
+
timestampMs: number;
|
|
62
|
+
sequence: number;
|
|
63
|
+
kind: string;
|
|
64
|
+
status: string | null;
|
|
65
|
+
summary: string;
|
|
66
|
+
attributesJson: string | null;
|
|
67
|
+
}): TraceEventRow {
|
|
68
|
+
return {
|
|
69
|
+
eventId: row.eventId,
|
|
70
|
+
conversationId: row.conversationId,
|
|
71
|
+
requestId: row.requestId ?? undefined,
|
|
72
|
+
timestampMs: row.timestampMs,
|
|
73
|
+
sequence: row.sequence,
|
|
74
|
+
kind: row.kind as TraceEventKind,
|
|
75
|
+
status: (row.status as TraceEventRow["status"]) ?? undefined,
|
|
76
|
+
summary: row.summary,
|
|
77
|
+
attributes: row.attributesJson
|
|
78
|
+
? (JSON.parse(row.attributesJson) as Record<
|
|
79
|
+
string,
|
|
80
|
+
string | number | boolean | null
|
|
81
|
+
>)
|
|
82
|
+
: undefined,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Query trace events for a conversation, ordered by sequence ASC, timestamp_ms ASC.
|
|
88
|
+
* Default limit of 5000 (matching the client's retention cap).
|
|
89
|
+
* Supports `afterSequence` for incremental fetching.
|
|
90
|
+
*/
|
|
91
|
+
export function getTraceEvents(
|
|
92
|
+
conversationId: string,
|
|
93
|
+
opts?: { limit?: number; afterSequence?: number },
|
|
94
|
+
): TraceEventRow[] {
|
|
95
|
+
const db = getDb();
|
|
96
|
+
const limit = opts?.limit ?? 5000;
|
|
97
|
+
|
|
98
|
+
const where =
|
|
99
|
+
opts?.afterSequence != null
|
|
100
|
+
? and(
|
|
101
|
+
eq(traceEvents.conversationId, conversationId),
|
|
102
|
+
gt(traceEvents.sequence, opts.afterSequence),
|
|
103
|
+
)
|
|
104
|
+
: eq(traceEvents.conversationId, conversationId);
|
|
105
|
+
|
|
106
|
+
const rows = db
|
|
107
|
+
.select()
|
|
108
|
+
.from(traceEvents)
|
|
109
|
+
.where(where)
|
|
110
|
+
.orderBy(asc(traceEvents.sequence), asc(traceEvents.timestampMs))
|
|
111
|
+
.limit(limit)
|
|
112
|
+
.all();
|
|
113
|
+
|
|
114
|
+
return rows.map(rowToTraceEventRow);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Cleanup
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Delete trace events older than `maxAgeDays` based on `created_at`.
|
|
123
|
+
* Returns the count of deleted rows.
|
|
124
|
+
*/
|
|
125
|
+
export function deleteOldTraceEvents(maxAgeDays: number): number {
|
|
126
|
+
const db = getDb();
|
|
127
|
+
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;
|
|
128
|
+
db.delete(traceEvents).where(lt(traceEvents.createdAt, cutoff)).run();
|
|
129
|
+
return rawChanges();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Sequence
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Return the highest sequence number persisted for a conversation,
|
|
138
|
+
* or -1 if no events exist yet.
|
|
139
|
+
*/
|
|
140
|
+
export function getMaxSequence(conversationId: string): number {
|
|
141
|
+
const db = getDb();
|
|
142
|
+
const row = db
|
|
143
|
+
.select({ maxSeq: sql<number>`MAX(${traceEvents.sequence})` })
|
|
144
|
+
.from(traceEvents)
|
|
145
|
+
.where(eq(traceEvents.conversationId, conversationId))
|
|
146
|
+
.get();
|
|
147
|
+
return row?.maxSeq ?? -1;
|
|
148
|
+
}
|
|
@@ -441,7 +441,7 @@ import { emitNotificationSignal } from "../notifications/emit-signal.js";
|
|
|
441
441
|
await emitNotificationSignal({
|
|
442
442
|
sourceEventName: "your_event_name",
|
|
443
443
|
sourceChannel: "scheduler", // where the event originated
|
|
444
|
-
|
|
444
|
+
sourceContextId: conversationId,
|
|
445
445
|
attentionHints: {
|
|
446
446
|
requiresAction: true,
|
|
447
447
|
urgency: "high",
|
|
@@ -319,7 +319,7 @@ function buildFallbackDecision(
|
|
|
319
319
|
selectedChannels: [],
|
|
320
320
|
reasoningSummary: "Fallback: suppressed (vellum channel not available)",
|
|
321
321
|
renderedCopy: {},
|
|
322
|
-
dedupeKey: `fallback:${signal.sourceEventName}:${signal.
|
|
322
|
+
dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceContextId}:${signal.createdAt}`,
|
|
323
323
|
confidence: 0.3,
|
|
324
324
|
fallbackUsed: true,
|
|
325
325
|
};
|
|
@@ -334,7 +334,7 @@ function buildFallbackDecision(
|
|
|
334
334
|
? "Fallback: high urgency + requires action — all channels"
|
|
335
335
|
: "Fallback: vellum-only (local, always delivered)",
|
|
336
336
|
renderedCopy: copy,
|
|
337
|
-
dedupeKey: `fallback:${signal.sourceEventName}:${signal.
|
|
337
|
+
dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceContextId}:${signal.createdAt}`,
|
|
338
338
|
confidence: 0.3,
|
|
339
339
|
fallbackUsed: true,
|
|
340
340
|
};
|
|
@@ -148,8 +148,8 @@ export interface EmitSignalParams<TEventName extends string = string> {
|
|
|
148
148
|
sourceEventName: TEventName;
|
|
149
149
|
/** Source channel that produced the event — must be a registered channel. */
|
|
150
150
|
sourceChannel: NotificationSourceChannel;
|
|
151
|
-
/**
|
|
152
|
-
|
|
151
|
+
/** Opaque identifier for the source context (conversation ID, schedule ID, call session ID, etc.). */
|
|
152
|
+
sourceContextId: string;
|
|
153
153
|
/** Attention hints for the decision engine. */
|
|
154
154
|
attentionHints: AttentionHints;
|
|
155
155
|
/** Arbitrary context payload passed to the decision engine. */
|
|
@@ -202,7 +202,7 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
202
202
|
signalId,
|
|
203
203
|
createdAt: Date.now(),
|
|
204
204
|
sourceChannel: params.sourceChannel,
|
|
205
|
-
|
|
205
|
+
sourceContextId: params.sourceContextId,
|
|
206
206
|
sourceEventName: params.sourceEventName,
|
|
207
207
|
contextPayload: (params.contextPayload ??
|
|
208
208
|
{}) as NotificationContextPayload<TEventName>,
|
|
@@ -218,7 +218,7 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
218
218
|
id: signalId,
|
|
219
219
|
sourceEventName: params.sourceEventName,
|
|
220
220
|
sourceChannel: params.sourceChannel,
|
|
221
|
-
|
|
221
|
+
sourceContextId: params.sourceContextId,
|
|
222
222
|
attentionHints: params.attentionHints,
|
|
223
223
|
payload: params.contextPayload ?? {},
|
|
224
224
|
dedupeKey: params.dedupeKey,
|
|
@@ -16,7 +16,7 @@ export interface NotificationEventRow {
|
|
|
16
16
|
id: string;
|
|
17
17
|
sourceEventName: string;
|
|
18
18
|
sourceChannel: string;
|
|
19
|
-
|
|
19
|
+
sourceContextId: string;
|
|
20
20
|
attentionHintsJson: string;
|
|
21
21
|
payloadJson: string;
|
|
22
22
|
dedupeKey: string | null;
|
|
@@ -31,7 +31,7 @@ function rowToEvent(
|
|
|
31
31
|
id: row.id,
|
|
32
32
|
sourceEventName: row.sourceEventName,
|
|
33
33
|
sourceChannel: row.sourceChannel,
|
|
34
|
-
|
|
34
|
+
sourceContextId: row.sourceContextId,
|
|
35
35
|
attentionHintsJson: row.attentionHintsJson,
|
|
36
36
|
payloadJson: row.payloadJson,
|
|
37
37
|
dedupeKey: row.dedupeKey,
|
|
@@ -44,7 +44,7 @@ export interface CreateEventParams {
|
|
|
44
44
|
id: string;
|
|
45
45
|
sourceEventName: string;
|
|
46
46
|
sourceChannel: string;
|
|
47
|
-
|
|
47
|
+
sourceContextId: string;
|
|
48
48
|
attentionHints: AttentionHints;
|
|
49
49
|
payload: Record<string, unknown>;
|
|
50
50
|
dedupeKey?: string;
|
|
@@ -76,7 +76,7 @@ export function createEvent(
|
|
|
76
76
|
id: params.id,
|
|
77
77
|
sourceEventName: params.sourceEventName,
|
|
78
78
|
sourceChannel: params.sourceChannel,
|
|
79
|
-
|
|
79
|
+
sourceContextId: params.sourceContextId,
|
|
80
80
|
attentionHintsJson: JSON.stringify(params.attentionHints),
|
|
81
81
|
payloadJson: JSON.stringify(params.payload),
|
|
82
82
|
dedupeKey: normalizedDedupeKey,
|
|
@@ -131,7 +131,7 @@ export interface NotificationSignal<TEventName extends string = string> {
|
|
|
131
131
|
signalId: string;
|
|
132
132
|
createdAt: number; // epoch ms
|
|
133
133
|
sourceChannel: NotificationSourceChannel; // see NOTIFICATION_SOURCE_CHANNELS registry
|
|
134
|
-
|
|
134
|
+
sourceContextId: string;
|
|
135
135
|
sourceEventName: TEventName; // free-form: 'reminder_fired', 'schedule_complete', 'guardian_question', etc.
|
|
136
136
|
contextPayload: NotificationContextPayload<TEventName>;
|
|
137
137
|
attentionHints: AttentionHints;
|
|
@@ -65,6 +65,53 @@ export function removeManualTokenConnection(providerKey: string): void {
|
|
|
65
65
|
deleteConnection(conn.id);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Reconcile the synthetic oauth_connection row for a manual-token provider
|
|
70
|
+
* with whatever credentials are currently present in secure storage.
|
|
71
|
+
*
|
|
72
|
+
* This lets generic credential entry paths (chat setup, CLI, secure prompt)
|
|
73
|
+
* keep connection status in sync without duplicating per-provider rules.
|
|
74
|
+
*/
|
|
75
|
+
export async function syncManualTokenConnection(
|
|
76
|
+
providerKey: string,
|
|
77
|
+
accountInfo?: string,
|
|
78
|
+
): Promise<void> {
|
|
79
|
+
switch (providerKey) {
|
|
80
|
+
case "telegram": {
|
|
81
|
+
const hasBotToken = !!(await getSecureKeyAsync(
|
|
82
|
+
credentialKey("telegram", "bot_token"),
|
|
83
|
+
));
|
|
84
|
+
const hasWebhookSecret = !!(await getSecureKeyAsync(
|
|
85
|
+
credentialKey("telegram", "webhook_secret"),
|
|
86
|
+
));
|
|
87
|
+
if (hasBotToken && hasWebhookSecret) {
|
|
88
|
+
await ensureManualTokenConnection(providerKey, accountInfo);
|
|
89
|
+
} else {
|
|
90
|
+
removeManualTokenConnection(providerKey);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
case "slack_channel": {
|
|
96
|
+
const hasBotToken = !!(await getSecureKeyAsync(
|
|
97
|
+
credentialKey("slack_channel", "bot_token"),
|
|
98
|
+
));
|
|
99
|
+
const hasAppToken = !!(await getSecureKeyAsync(
|
|
100
|
+
credentialKey("slack_channel", "app_token"),
|
|
101
|
+
));
|
|
102
|
+
if (hasBotToken && hasAppToken) {
|
|
103
|
+
await ensureManualTokenConnection(providerKey, accountInfo);
|
|
104
|
+
} else {
|
|
105
|
+
removeManualTokenConnection(providerKey);
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
default:
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
68
115
|
/**
|
|
69
116
|
* Backfill oauth_connection rows for manual-token providers that already
|
|
70
117
|
* have valid keychain credentials but are missing connection records.
|
|
@@ -78,29 +125,6 @@ export function removeManualTokenConnection(providerKey: string): void {
|
|
|
78
125
|
* connection row.
|
|
79
126
|
*/
|
|
80
127
|
export async function backfillManualTokenConnections(): Promise<void> {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const hasBotToken = !!(await getSecureKeyAsync(
|
|
84
|
-
credentialKey("telegram", "bot_token"),
|
|
85
|
-
));
|
|
86
|
-
const hasWebhookSecret = !!(await getSecureKeyAsync(
|
|
87
|
-
credentialKey("telegram", "webhook_secret"),
|
|
88
|
-
));
|
|
89
|
-
if (hasBotToken && hasWebhookSecret) {
|
|
90
|
-
await ensureManualTokenConnection("telegram");
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Slack channel: requires both bot_token and app_token
|
|
95
|
-
if (!getConnectionByProvider("slack_channel")) {
|
|
96
|
-
const hasBotToken = !!(await getSecureKeyAsync(
|
|
97
|
-
credentialKey("slack_channel", "bot_token"),
|
|
98
|
-
));
|
|
99
|
-
const hasAppToken = !!(await getSecureKeyAsync(
|
|
100
|
-
credentialKey("slack_channel", "app_token"),
|
|
101
|
-
));
|
|
102
|
-
if (hasBotToken && hasAppToken) {
|
|
103
|
-
await ensureManualTokenConnection("slack_channel");
|
|
104
|
-
}
|
|
105
|
-
}
|
|
128
|
+
await syncManualTokenConnection("telegram");
|
|
129
|
+
await syncManualTokenConnection("slack_channel");
|
|
106
130
|
}
|
|
@@ -48,10 +48,10 @@ function riskCacheKey(
|
|
|
48
48
|
workingDir?: string,
|
|
49
49
|
manifestOverride?: ManifestOverride,
|
|
50
50
|
): string {
|
|
51
|
-
// Strip `reason` before computing the cache key —
|
|
52
|
-
// per invocation even for identical tool
|
|
53
|
-
// cache misses.
|
|
54
|
-
const { reason: _reason, ...cacheableInput } = input;
|
|
51
|
+
// Strip `reason` and `activity` before computing the cache key — they are
|
|
52
|
+
// cosmetic status text that varies per invocation even for identical tool
|
|
53
|
+
// operations, causing unnecessary cache misses.
|
|
54
|
+
const { reason: _reason, activity: _activity, ...cacheableInput } = input;
|
|
55
55
|
const inputJson = JSON.stringify(cacheableInput);
|
|
56
56
|
const hash = createHash("sha256")
|
|
57
57
|
.update(inputJson)
|
|
@@ -143,6 +143,7 @@ const LOW_RISK_PROGRAMS = new Set([
|
|
|
143
143
|
"tree",
|
|
144
144
|
"du",
|
|
145
145
|
"df",
|
|
146
|
+
"assistant",
|
|
146
147
|
]);
|
|
147
148
|
|
|
148
149
|
// High-risk shell programs / patterns
|
|
@@ -544,7 +545,7 @@ async function classifyRiskUncached(
|
|
|
544
545
|
) {
|
|
545
546
|
return RiskLevel.High;
|
|
546
547
|
}
|
|
547
|
-
return RiskLevel.
|
|
548
|
+
return RiskLevel.Low;
|
|
548
549
|
}
|
|
549
550
|
if (toolName === "web_search") return RiskLevel.Low;
|
|
550
551
|
if (toolName === "web_fetch") {
|
|
@@ -259,10 +259,10 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
259
259
|
}),
|
|
260
260
|
);
|
|
261
261
|
|
|
262
|
-
//
|
|
263
|
-
// surfaces
|
|
264
|
-
//
|
|
265
|
-
const UI_SURFACE_TOOLS = ["ui_update", "ui_dismiss"] as const;
|
|
262
|
+
// All three UI surface tools are passive, user-visible operations. ui_show
|
|
263
|
+
// creates surfaces (cards, forms, tables) but user input is voluntary and
|
|
264
|
+
// user-controlled — safe to auto-approve like ui_update and ui_dismiss.
|
|
265
|
+
const UI_SURFACE_TOOLS = ["ui_show", "ui_update", "ui_dismiss"] as const;
|
|
266
266
|
const uiSurfaceRules: DefaultRuleTemplate[] = UI_SURFACE_TOOLS.map(
|
|
267
267
|
(tool) => ({
|
|
268
268
|
id: `default:allow-${tool}-global`,
|
|
@@ -1,113 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for buildCliReferenceSection — verifies the CLI reference section
|
|
3
|
-
* included in the system prompt has the expected structure
|
|
4
|
-
* and caching behaviour.
|
|
3
|
+
* included in the system prompt has the expected structure.
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
|
-
import {
|
|
6
|
+
import { describe, expect, test } from "bun:test";
|
|
8
7
|
|
|
9
|
-
import {
|
|
10
|
-
_resetCliHelpCache,
|
|
11
|
-
buildCliReferenceSection,
|
|
12
|
-
} from "../system-prompt.js";
|
|
8
|
+
import { buildCliReferenceSection } from "../system-prompt.js";
|
|
13
9
|
|
|
14
10
|
describe("buildCliReferenceSection", () => {
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
_resetCliHelpCache();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
11
|
test("includes the Assistant CLI heading", () => {
|
|
20
12
|
const result = buildCliReferenceSection();
|
|
21
13
|
expect(result).toContain("## Assistant CLI");
|
|
22
14
|
});
|
|
23
15
|
|
|
24
|
-
test("includes CLI help text with command listings", () => {
|
|
25
|
-
const result = buildCliReferenceSection();
|
|
26
|
-
// The reference is a side-effect-free snapshot of the top-level CLI help.
|
|
27
|
-
expect(result).toContain("Usage:");
|
|
28
|
-
expect(result).toContain("Commands:");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
16
|
test("mentions bash as the way to invoke the CLI", () => {
|
|
32
17
|
const result = buildCliReferenceSection();
|
|
33
18
|
expect(result).toContain("use the `bash` tool");
|
|
34
19
|
});
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
// CES tool guidance — new credential workflow
|
|
38
|
-
// -----------------------------------------------------------------------
|
|
39
|
-
|
|
40
|
-
test("teaches handle discovery via assistant credentials list", () => {
|
|
41
|
-
const result = buildCliReferenceSection();
|
|
42
|
-
expect(result).toContain("assistant credentials list");
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("teaches handle discovery via assistant oauth connections list", () => {
|
|
21
|
+
test("tells the model to run assistant --help for discovery", () => {
|
|
46
22
|
const result = buildCliReferenceSection();
|
|
47
|
-
expect(result).toContain("assistant
|
|
23
|
+
expect(result).toContain("assistant --help");
|
|
48
24
|
});
|
|
49
25
|
|
|
50
|
-
test("
|
|
26
|
+
test("does not embed the full CLI help output", () => {
|
|
51
27
|
const result = buildCliReferenceSection();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
test("teaches run_authenticated_command CES tool", () => {
|
|
56
|
-
const result = buildCliReferenceSection();
|
|
57
|
-
expect(result).toContain("run_authenticated_command");
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("teaches manage_secure_command_tool CES tool", () => {
|
|
61
|
-
const result = buildCliReferenceSection();
|
|
62
|
-
expect(result).toContain("manage_secure_command_tool");
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test("warns against revealing raw secrets", () => {
|
|
66
|
-
const result = buildCliReferenceSection();
|
|
67
|
-
expect(result).toContain("Never reveal raw secrets");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("warns that host_bash is outside CES secrecy boundary", () => {
|
|
71
|
-
const result = buildCliReferenceSection();
|
|
72
|
-
expect(result).toContain("outside the CES secrecy boundary");
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// -----------------------------------------------------------------------
|
|
76
|
-
// Deprecated patterns must NOT appear
|
|
77
|
-
// -----------------------------------------------------------------------
|
|
78
|
-
|
|
79
|
-
test("does not teach token-reveal via oauth connections token", () => {
|
|
80
|
-
const result = buildCliReferenceSection();
|
|
81
|
-
// The old pattern was: assistant oauth connections token <provider-key>
|
|
82
|
-
// for fetching raw tokens. This must not appear in the guidance.
|
|
83
|
-
expect(result).not.toContain(
|
|
84
|
-
"assistant oauth connections token <provider-key>",
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test("does not recommend using credential_store for direct API calls", () => {
|
|
89
|
-
const result = buildCliReferenceSection();
|
|
90
|
-
// The old pattern was: "Direct API calls via host_bash — Use curl/httpie
|
|
91
|
-
// with API tokens from credential_store". This is replaced by CES tools.
|
|
92
|
-
expect(result).not.toContain("API tokens from credential_store");
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// -----------------------------------------------------------------------
|
|
96
|
-
// Caching
|
|
97
|
-
// -----------------------------------------------------------------------
|
|
98
|
-
|
|
99
|
-
test("result is cached — calling twice returns the same string", () => {
|
|
100
|
-
const first = buildCliReferenceSection();
|
|
101
|
-
const second = buildCliReferenceSection();
|
|
102
|
-
expect(first).toBe(second);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test("cache is reset by _resetCliHelpCache", () => {
|
|
106
|
-
const first = buildCliReferenceSection();
|
|
107
|
-
_resetCliHelpCache();
|
|
108
|
-
const second = buildCliReferenceSection();
|
|
109
|
-
// Content should be identical even after reset (same CLI program),
|
|
110
|
-
// but they should be independently computed strings.
|
|
111
|
-
expect(first).toEqual(second);
|
|
28
|
+
// The full help text used to be embedded; now the model should
|
|
29
|
+
// discover commands by running the CLI itself.
|
|
30
|
+
expect(result).not.toContain("Commands:\n");
|
|
112
31
|
});
|
|
113
32
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SYSTEM_PROMPT_CACHE_BOUNDARY marker is a lightweight constant kept in its
|
|
3
|
+
* own file so that providers (openai, gemini) can import it without pulling in
|
|
4
|
+
* the full system-prompt module and its heavy transitive dependencies, which
|
|
5
|
+
* would otherwise create a circular import cycle.
|
|
6
|
+
*/
|
|
7
|
+
export const SYSTEM_PROMPT_CACHE_BOUNDARY =
|
|
8
|
+
"\n<!-- SYSTEM_PROMPT_CACHE_BOUNDARY -->\n";
|