@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2
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/bun.lock +0 -20
- package/docs/workspace-tools.md +33 -42
- package/eslint-rules/cli-no-daemon-internals.js +0 -6
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
- package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
- package/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
- package/openapi.yaml +0 -155
- package/package.json +1 -4
- package/scripts/test.sh +15 -36
- package/src/__tests__/actor-token-service.test.ts +14 -36
- package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
- package/src/__tests__/annotate-risk-options.test.ts +0 -2
- package/src/__tests__/approval-cascade.test.ts +0 -2
- package/src/__tests__/assistant-attachments.test.ts +0 -42
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -2
- package/src/__tests__/build-persisted-content.test.ts +0 -2
- package/src/__tests__/call-controller.test.ts +0 -19
- package/src/__tests__/channel-guardian.test.ts +58 -94
- package/src/__tests__/channel-reply-delivery.test.ts +0 -2
- package/src/__tests__/compaction-events.test.ts +0 -2
- package/src/__tests__/compaction.benchmark.test.ts +0 -2
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
- package/src/__tests__/config-loader-backfill.test.ts +10 -123
- package/src/__tests__/config-schema.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
- package/src/__tests__/contacts-relay-reads.test.ts +15 -13
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +0 -134
- package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
- package/src/__tests__/conversation-history-web-search.test.ts +0 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -2
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
- package/src/__tests__/conversation-process-callsite.test.ts +0 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
- package/src/__tests__/conversation-queue.test.ts +0 -91
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
- package/src/__tests__/conversation-slash-queue.test.ts +0 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
- package/src/__tests__/conversation-speed-override.test.ts +0 -2
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
- package/src/__tests__/conversation-title-service.test.ts +0 -2
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-migration-rollback.test.ts +171 -205
- package/src/__tests__/db-test-helpers.ts +4 -5
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
- package/src/__tests__/disk-pressure-guard.test.ts +0 -41
- package/src/__tests__/dm-persistence.test.ts +0 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
- package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
- package/src/__tests__/exploration-drift-hook.test.ts +2 -3
- package/src/__tests__/filing-service.test.ts +0 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
- package/src/__tests__/guardian-dispatch.test.ts +1 -95
- package/src/__tests__/guardian-outbound-http.test.ts +0 -13
- package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
- package/src/__tests__/heartbeat-service.test.ts +0 -2
- package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
- package/src/__tests__/host-app-control-routes.test.ts +30 -24
- package/src/__tests__/host-bash-routes.test.ts +41 -31
- package/src/__tests__/host-browser-routes.test.ts +32 -26
- package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
- package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
- package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
- package/src/__tests__/http-user-message-parity.test.ts +8 -290
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/invite-redemption-service.test.ts +0 -198
- package/src/__tests__/llm-context-normalization.test.ts +0 -105
- package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
- package/src/__tests__/llm-usage-store.test.ts +0 -25
- package/src/__tests__/mcp-health-check.test.ts +1 -2
- package/src/__tests__/media-stream-server-integration.test.ts +0 -127
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
- package/src/__tests__/messaging-send-tool.test.ts +0 -2
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +5 -146
- package/src/__tests__/native-web-search.test.ts +0 -2
- package/src/__tests__/non-member-access-request.test.ts +17 -189
- package/src/__tests__/notification-broadcaster.test.ts +0 -4
- package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
- package/src/__tests__/notification-deep-link.test.ts +0 -6
- package/src/__tests__/notification-guardian-path.test.ts +0 -19
- package/src/__tests__/openai-provider.test.ts +12 -22
- package/src/__tests__/openai-responses-provider.test.ts +2 -12
- package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
- package/src/__tests__/plugin-bootstrap.test.ts +73 -3
- package/src/__tests__/plugin-route-contribution.test.ts +17 -4
- package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
- package/src/__tests__/plugin-types.test.ts +2 -0
- package/src/__tests__/process-message-background-slack.test.ts +0 -2
- package/src/__tests__/process-message-display-content.test.ts +0 -2
- package/src/__tests__/provider-error-scenarios.test.ts +4 -5
- package/src/__tests__/provider-usage-tracking.test.ts +0 -39
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
- package/src/__tests__/registry.test.ts +1 -4
- package/src/__tests__/relay-server.test.ts +25 -694
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -14
- package/src/__tests__/send-endpoint-busy.test.ts +8 -30
- package/src/__tests__/skills.test.ts +0 -44
- package/src/__tests__/slack-inbound-verification.test.ts +2 -47
- package/src/__tests__/stt-hints.test.ts +13 -44
- package/src/__tests__/subagent-detail.test.ts +0 -27
- package/src/__tests__/subagent-disposal.test.ts +0 -65
- package/src/__tests__/subagent-notify-parent.test.ts +0 -2
- package/src/__tests__/subagent-role-registry.test.ts +2 -7
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
- package/src/__tests__/subagent-tools.test.ts +0 -2
- package/src/__tests__/suggestion-routes.test.ts +0 -2
- package/src/__tests__/title-generate-hook.test.ts +0 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
- package/src/__tests__/tool-executor.test.ts +11 -16
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
- package/src/__tests__/tool-start-timestamp.test.ts +0 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
- package/src/__tests__/twilio-routes.test.ts +0 -96
- package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +0 -33
- package/src/__tests__/web-search-backend-failure.test.ts +0 -2
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
- package/src/__tests__/workspace-tool-loader.test.ts +2 -195
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +0 -56
- package/src/api/index.ts +1 -19
- package/src/api/responses/llm-request-log-entry.ts +0 -29
- package/src/api/responses/subagent-detail.ts +0 -17
- package/src/api/surfaces.ts +3 -39
- package/src/approvals/guardian-request-resolvers.ts +11 -1
- package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +8 -10
- package/src/calls/inbound-trust-reader.ts +1 -17
- package/src/calls/media-stream-server.ts +0 -21
- package/src/calls/relay-server.ts +50 -167
- package/src/calls/relay-setup-router.ts +7 -37
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +12 -9
- package/src/calls/twilio-routes.ts +4 -14
- package/src/channels/types.ts +20 -10
- package/src/cli/commands/__tests__/cache.test.ts +1 -8
- package/src/cli/commands/cache.ts +181 -194
- package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
- package/src/cli/commands/db/status.ts +1 -37
- package/src/cli/commands/mcp.ts +218 -252
- package/src/cli/commands/memory/index.ts +0 -2
- package/src/cli/commands/plugins.ts +3 -75
- package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
- package/src/cli/lib/list-installed-plugins.ts +1 -179
- package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
- package/src/config/bundled-skills/subagent/SKILL.md +1 -1
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/feature-flag-registry.json +13 -5
- package/src/config/loader.ts +5 -38
- package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
- package/src/config/schemas/memory-lifecycle.ts +0 -12
- package/src/config/schemas/memory-v3.ts +0 -7
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/timeouts.ts +0 -8
- package/src/config/seed-inference-profiles.ts +11 -21
- package/src/config/skills.ts +5 -27
- package/src/config/sync-gated-profiles.ts +13 -12
- package/src/contacts/contacts-write.ts +0 -3
- package/src/daemon/assistant-attachments.ts +4 -27
- package/src/daemon/conversation-agent-loop.ts +0 -28
- package/src/daemon/conversation-process.ts +16 -35
- package/src/daemon/conversation-surfaces.ts +38 -111
- package/src/daemon/conversation-tool-setup.ts +16 -50
- package/src/daemon/conversation.ts +1 -13
- package/src/daemon/disk-pressure-guard.ts +2 -12
- package/src/daemon/event-loop-watchdog.ts +1 -28
- package/src/daemon/external-plugins-bootstrap.ts +34 -4
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
- package/src/daemon/handlers/config-a2a.ts +14 -6
- package/src/daemon/handlers/config-channels.ts +22 -78
- package/src/daemon/handlers/conversations.ts +0 -77
- package/src/daemon/lifecycle.ts +0 -4
- package/src/daemon/mcp-reload-service.ts +0 -10
- package/src/daemon/memory-v2-startup.test.ts +0 -72
- package/src/daemon/memory-v2-startup.ts +19 -87
- package/src/daemon/message-types/conversations.ts +0 -2
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +4 -0
- package/src/daemon/shutdown-handlers.ts +0 -20
- package/src/daemon/tool-setup-types.ts +0 -9
- package/src/daemon/workspace-tools-watcher.ts +328 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/client.ts +1 -15
- package/src/mcp/mcp-auth-orchestrator.ts +1 -6
- package/src/mcp/mcp-oauth-provider.ts +8 -19
- package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
- package/src/memory/conversation-crud.ts +0 -38
- package/src/memory/db-connection.ts +3 -22
- package/src/memory/db-init.ts +502 -36
- package/src/memory/db-singleton.ts +4 -6
- package/src/memory/jobs-worker.ts +0 -58
- package/src/memory/llm-request-log-store.ts +1 -26
- package/src/memory/llm-usage-store.ts +20 -48
- package/src/memory/memory-retrospective-job.ts +8 -9
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/registry.ts +573 -0
- package/src/memory/migrations/run-migrations.ts +6 -90
- package/src/memory/migrations/validate-migration-state.ts +66 -101
- package/src/memory/schema/conversations.ts +0 -9
- package/src/memory/schema/infrastructure.ts +0 -20
- package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
- package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
- package/src/memory/v2/cli-command-store.ts +38 -75
- package/src/memory/v2/prompts/consolidation.ts +82 -13
- package/src/memory/v2/prompts/router.ts +93 -21
- package/src/memory/v2/skill-store.ts +31 -68
- package/src/notifications/__tests__/broadcaster.test.ts +8 -16
- package/src/notifications/__tests__/decision-engine.test.ts +9 -78
- package/src/notifications/broadcaster.ts +1 -8
- package/src/notifications/decision-engine.ts +7 -15
- package/src/notifications/destination-resolver.ts +24 -68
- package/src/notifications/emit-signal.ts +14 -39
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +4 -7
- package/src/plugin-api/index.ts +6 -6
- package/src/plugin-api/types.ts +5 -3
- package/src/plugin-api/vision-support.test.ts +4 -28
- package/src/plugin-api/vision-support.ts +31 -66
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
- package/src/plugins/defaults/advisor/consult.ts +6 -110
- package/src/plugins/defaults/advisor/steering.ts +2 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
- package/src/plugins/mtime-cache.ts +291 -76
- package/src/plugins/pipeline.ts +13 -111
- package/src/plugins/types.ts +2 -0
- package/src/providers/anthropic/client.ts +0 -5
- package/src/providers/call-site-routing.ts +0 -4
- package/src/providers/model-catalog.ts +0 -16
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/chat-completions-provider.ts +83 -37
- package/src/providers/openai/responses-provider.ts +46 -50
- package/src/providers/openrouter/client.ts +0 -5
- package/src/providers/provider-send-message.ts +0 -4
- package/src/providers/ratelimit.ts +0 -4
- package/src/providers/retry.ts +0 -4
- package/src/providers/types.ts +0 -9
- package/src/providers/usage-tracking.ts +0 -4
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
- package/src/runtime/access-request-helper.ts +39 -19
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +2 -9
- package/src/runtime/auth/require-bound-guardian.ts +11 -21
- package/src/runtime/channel-verification-service.ts +31 -56
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +7 -66
- package/src/runtime/invite-redemption-service.ts +187 -198
- package/src/runtime/local-actor-identity.ts +11 -76
- package/src/runtime/pending-interactions.ts +1 -11
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +32 -8
- package/src/runtime/routes/conversation-cli-routes.ts +5 -4
- package/src/runtime/routes/conversation-list-routes.ts +7 -4
- package/src/runtime/routes/conversation-query-routes.ts +0 -72
- package/src/runtime/routes/conversation-routes.ts +85 -84
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -3
- package/src/runtime/routes/guardian-action-routes.ts +5 -4
- package/src/runtime/routes/host-app-control-routes.ts +4 -5
- package/src/runtime/routes/host-bash-routes.ts +4 -5
- package/src/runtime/routes/host-browser-routes.ts +11 -9
- package/src/runtime/routes/host-cu-routes.ts +4 -5
- package/src/runtime/routes/host-file-routes.ts +4 -5
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +2 -3
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
- package/src/runtime/routes/index.ts +0 -2
- package/src/runtime/routes/llm-context-normalization.ts +0 -83
- package/src/runtime/routes/mcp-auth-routes.ts +19 -171
- package/src/runtime/routes/migration-rollback-routes.ts +3 -4
- package/src/runtime/routes/migration-routes.ts +1 -4
- package/src/runtime/routes/subagents-routes.ts +0 -5
- package/src/runtime/routes/surface-action-routes.ts +56 -42
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
- package/src/runtime/services/conversation-serializer.ts +9 -7
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +9 -85
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +0 -16
- package/src/subagent/manager.ts +0 -9
- package/src/subagent/types.ts +3 -3
- package/src/telemetry/types.ts +1 -34
- package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
- package/src/telemetry/usage-telemetry-reporter.ts +3 -87
- package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
- package/src/tools/ask-question/ask-question-tool.ts +0 -13
- package/src/tools/executor.ts +4 -4
- package/src/tools/registry.ts +0 -18
- package/src/tools/shared/filesystem/path-policy.ts +5 -12
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +2 -9
- package/src/tools/tool-manifest.ts +0 -3
- package/src/tools/types.ts +2 -17
- package/src/tools/workspace-tools/loader.ts +244 -348
- package/src/util/errors.ts +1 -26
- package/src/util/platform.ts +0 -5
- package/src/workflows/library.test.ts +0 -140
- package/src/workflows/library.ts +28 -82
- package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
- package/src/workspace/migrations/registry.ts +0 -2
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
- package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
- package/src/__tests__/code-search-tool.test.ts +0 -585
- package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
- package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
- package/src/__tests__/plugin-pipeline.test.ts +0 -96
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
- package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
- package/src/agent/loop-exclusive-tool.test.ts +0 -150
- package/src/api/constants/sse-replay.ts +0 -41
- package/src/api/events/conversation-notice.ts +0 -26
- package/src/approvals/guardian-channel-delivery.ts +0 -30
- package/src/approvals/guardian-expiry-notifier.ts +0 -148
- package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
- package/src/cli/commands/memory/worker.ts +0 -175
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
- package/src/config/prune-seeded-callsite-defaults.ts +0 -110
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
- package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
- package/src/contacts/guardian-delivery-reader.ts +0 -223
- package/src/contacts/member-write-relay.ts +0 -189
- package/src/daemon/conversation-notices.ts +0 -60
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
- package/src/hooks/hook-loader.ts +0 -341
- package/src/mcp/mcp-header-store.ts +0 -134
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
- package/src/memory/__tests__/prompt-override.test.ts +0 -192
- package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
- package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
- package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
- package/src/memory/prompt-override.ts +0 -129
- package/src/memory/steps.ts +0 -573
- package/src/memory/watchdog-events-store.ts +0 -87
- package/src/memory/worker-control.ts +0 -118
- package/src/memory/worker-process.ts +0 -72
- package/src/notifications/__tests__/connected-channels.test.ts +0 -114
- package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
- package/src/onboarding/checkin-event.test.ts +0 -222
- package/src/onboarding/checkin-event.ts +0 -321
- package/src/onboarding/schedule-checkin.ts +0 -190
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
- package/src/plugins/defaults/advisor/context-pack.ts +0 -288
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
- package/src/plugins/surface-import.ts +0 -121
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
- package/src/providers/openai/api-error-normalization.ts +0 -270
- package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
- package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
- package/src/runtime/anchored-guardian.test.ts +0 -156
- package/src/runtime/anchored-guardian.ts +0 -135
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
- package/src/runtime/local-principal-trust.ts +0 -52
- package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
- package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
- package/src/tools/filesystem/search.ts +0 -543
- package/src/util/telemetry-db-path.ts +0 -24
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
|
@@ -3,10 +3,7 @@ import { v4 as uuid } from "uuid";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
5
|
import { SurfaceActionSchema } from "../api/events/ui-surface-show.js";
|
|
6
|
-
import {
|
|
7
|
-
CardSurfaceDataSchema,
|
|
8
|
-
FileUploadSurfaceDataSchema,
|
|
9
|
-
} from "../api/surfaces.js";
|
|
6
|
+
import { CardSurfaceDataSchema } from "../api/surfaces.js";
|
|
10
7
|
import { isActivationSession } from "../memory/activation-session-store.js";
|
|
11
8
|
import {
|
|
12
9
|
addAppConversationId,
|
|
@@ -59,7 +56,6 @@ import type {
|
|
|
59
56
|
ConfirmationSurfaceData,
|
|
60
57
|
CopyBlockSurfaceData,
|
|
61
58
|
DynamicPageSurfaceData,
|
|
62
|
-
FileUploadSurfaceData,
|
|
63
59
|
FormSurfaceData,
|
|
64
60
|
ListSurfaceData,
|
|
65
61
|
OAuthConnectSurfaceData,
|
|
@@ -587,20 +583,12 @@ function normalizeCardShowData(
|
|
|
587
583
|
(typeof input[k] === "string" &&
|
|
588
584
|
(input[k] as string).trim().length > 0),
|
|
589
585
|
);
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
used_aliases: usedAliases,
|
|
597
|
-
candidate_count: candidates.length,
|
|
598
|
-
});
|
|
599
|
-
Sentry.captureMessage("card_normalization:alias_recovery:body");
|
|
600
|
-
});
|
|
601
|
-
} catch {
|
|
602
|
-
// Never let telemetry break card rendering.
|
|
603
|
-
}
|
|
586
|
+
Sentry.addBreadcrumb({
|
|
587
|
+
category: "card-normalization",
|
|
588
|
+
message: `alias recovery: ${usedAliases.join(", ")} → body`,
|
|
589
|
+
level: "info",
|
|
590
|
+
data: { usedAliases, candidateCount: candidates.length },
|
|
591
|
+
});
|
|
604
592
|
}
|
|
605
593
|
}
|
|
606
594
|
for (const key of bodyAliasKeys) {
|
|
@@ -617,16 +605,11 @@ function normalizeCardShowData(
|
|
|
617
605
|
]);
|
|
618
606
|
if (aliased !== undefined) {
|
|
619
607
|
normalized.title = aliased;
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
Sentry.captureMessage("card_normalization:alias_recovery:title");
|
|
626
|
-
});
|
|
627
|
-
} catch {
|
|
628
|
-
// Never let telemetry break card rendering.
|
|
629
|
-
}
|
|
608
|
+
Sentry.addBreadcrumb({
|
|
609
|
+
category: "card-normalization",
|
|
610
|
+
message: `alias recovery: title`,
|
|
611
|
+
level: "info",
|
|
612
|
+
});
|
|
630
613
|
}
|
|
631
614
|
}
|
|
632
615
|
for (const key of titleAliasKeys) {
|
|
@@ -651,16 +634,11 @@ function normalizeCardShowData(
|
|
|
651
634
|
]);
|
|
652
635
|
if (aliased !== undefined) {
|
|
653
636
|
normalized.subtitle = aliased;
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
Sentry.captureMessage("card_normalization:alias_recovery:subtitle");
|
|
660
|
-
});
|
|
661
|
-
} catch {
|
|
662
|
-
// Never let telemetry break card rendering.
|
|
663
|
-
}
|
|
637
|
+
Sentry.addBreadcrumb({
|
|
638
|
+
category: "card-normalization",
|
|
639
|
+
message: `alias recovery: subtitle`,
|
|
640
|
+
level: "info",
|
|
641
|
+
});
|
|
664
642
|
}
|
|
665
643
|
}
|
|
666
644
|
for (const key of subtitleAliasKeys) {
|
|
@@ -710,21 +688,12 @@ function normalizeCardShowData(
|
|
|
710
688
|
{ droppedKeys },
|
|
711
689
|
"ui_show card data carried keys the card contract does not model; their content will not render",
|
|
712
690
|
);
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
});
|
|
720
|
-
// Key names are model-controlled, so they ride in `extra`, which
|
|
721
|
-
// beforeSend redacts (it does not scrub `contexts`) — see instrument.ts.
|
|
722
|
-
scope.setExtra("dropped_keys", droppedKeys);
|
|
723
|
-
Sentry.captureMessage("card_normalization:dropped_keys");
|
|
724
|
-
});
|
|
725
|
-
} catch {
|
|
726
|
-
// Never let telemetry break card rendering.
|
|
727
|
-
}
|
|
691
|
+
Sentry.addBreadcrumb({
|
|
692
|
+
category: "card-normalization",
|
|
693
|
+
message: `dropped keys: ${droppedKeys.join(", ")}`,
|
|
694
|
+
level: "warning",
|
|
695
|
+
data: { droppedKeys },
|
|
696
|
+
});
|
|
728
697
|
}
|
|
729
698
|
const parsed = CardSurfaceDataSchema.safeParse(normalized);
|
|
730
699
|
if (parsed.success) {
|
|
@@ -860,24 +829,6 @@ function normalizeOAuthConnectShowData(
|
|
|
860
829
|
};
|
|
861
830
|
}
|
|
862
831
|
|
|
863
|
-
function normalizeFileUploadShowData(
|
|
864
|
-
rawData: Record<string, unknown>,
|
|
865
|
-
): FileUploadSurfaceData {
|
|
866
|
-
// Parse against the canonical schema so the surface carries the shape the
|
|
867
|
-
// renderer expects. The schema is tolerant (every field optional and coerced)
|
|
868
|
-
// and recovers the common malformed `acceptedTypes` shapes — a comma-joined or
|
|
869
|
-
// bare string — into the `string[]` the renderer requires.
|
|
870
|
-
const parsed = FileUploadSurfaceDataSchema.safeParse(rawData);
|
|
871
|
-
if (parsed.success) {
|
|
872
|
-
return parsed.data;
|
|
873
|
-
}
|
|
874
|
-
log.warn(
|
|
875
|
-
{ issues: parsed.error.issues },
|
|
876
|
-
"ui_show file_upload data failed FileUploadSurfaceDataSchema; rendering an empty file_upload surface",
|
|
877
|
-
);
|
|
878
|
-
return {};
|
|
879
|
-
}
|
|
880
|
-
|
|
881
832
|
function buildChoiceActions(data: ChoiceSurfaceData): Array<{
|
|
882
833
|
id: string;
|
|
883
834
|
label: string;
|
|
@@ -2944,9 +2895,7 @@ export async function surfaceProxyResolver(
|
|
|
2944
2895
|
? normalizeOAuthConnectShowData(rawData)
|
|
2945
2896
|
: surfaceType === "dynamic_page"
|
|
2946
2897
|
? normalizeDynamicPageShowData(input, rawData)
|
|
2947
|
-
:
|
|
2948
|
-
? normalizeFileUploadShowData(rawData)
|
|
2949
|
-
: (rawData as SurfaceData);
|
|
2898
|
+
: (rawData as SurfaceData);
|
|
2950
2899
|
// Parse actions through the schema instead of typecasting raw model output.
|
|
2951
2900
|
// The model may place actions inside `data` instead of the top-level
|
|
2952
2901
|
// `actions` param — recover them so they aren't silently dropped.
|
|
@@ -2963,27 +2912,18 @@ export async function surfaceProxyResolver(
|
|
|
2963
2912
|
if (result.success) {
|
|
2964
2913
|
valid.push(result.data);
|
|
2965
2914
|
} else {
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
// raw object keys are model-controlled, so they ride in `extra`,
|
|
2974
|
-
// which beforeSend redacts (it does not scrub `contexts`) — see
|
|
2975
|
-
// instrument.ts.
|
|
2976
|
-
scope.setExtra(
|
|
2977
|
-
"raw_keys",
|
|
2915
|
+
Sentry.addBreadcrumb({
|
|
2916
|
+
category: "card-normalization",
|
|
2917
|
+
message: "action parse failure (individual)",
|
|
2918
|
+
level: "warning",
|
|
2919
|
+
data: {
|
|
2920
|
+
issuePaths: result.error.issues.map((i) => i.path.join(".")),
|
|
2921
|
+
keys:
|
|
2978
2922
|
typeof raw === "object" && raw !== null
|
|
2979
2923
|
? Object.keys(raw)
|
|
2980
2924
|
: [typeof raw],
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
});
|
|
2984
|
-
} catch {
|
|
2985
|
-
// Never let telemetry break card rendering.
|
|
2986
|
-
}
|
|
2925
|
+
},
|
|
2926
|
+
});
|
|
2987
2927
|
}
|
|
2988
2928
|
}
|
|
2989
2929
|
inputActions = valid.length > 0 ? valid : undefined;
|
|
@@ -3021,24 +2961,11 @@ export async function surfaceProxyResolver(
|
|
|
3021
2961
|
!hasTemplate &&
|
|
3022
2962
|
!hasActions
|
|
3023
2963
|
) {
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
surface_type: surfaceType,
|
|
3030
|
-
has_title: hasTitle,
|
|
3031
|
-
has_body: hasBody,
|
|
3032
|
-
has_subtitle: hasSubtitle,
|
|
3033
|
-
has_metadata: hasMetadata,
|
|
3034
|
-
has_template: hasTemplate,
|
|
3035
|
-
has_actions: hasActions,
|
|
3036
|
-
});
|
|
3037
|
-
Sentry.captureMessage("card_normalization:empty_card_rejected");
|
|
3038
|
-
});
|
|
3039
|
-
} catch {
|
|
3040
|
-
// Never let telemetry break card rendering.
|
|
3041
|
-
}
|
|
2964
|
+
Sentry.addBreadcrumb({
|
|
2965
|
+
category: "card-normalization",
|
|
2966
|
+
message: "empty card rejected",
|
|
2967
|
+
level: "warning",
|
|
2968
|
+
});
|
|
3042
2969
|
return {
|
|
3043
2970
|
content:
|
|
3044
2971
|
"Error: ui_show card requires content — provide `data.body`, a `template` (e.g. task_progress with steps), `data.metadata`, `data.subtitle`, a `title`, or `actions`. The surface was not displayed because it carried no renderable content. Resend ui_show with populated card content.",
|
|
@@ -22,12 +22,7 @@ import type { Message, ToolDefinition } from "../providers/types.js";
|
|
|
22
22
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
23
23
|
import { registerConversationSender } from "../tools/browser/browser-screencast.js";
|
|
24
24
|
import type { ToolExecutor } from "../tools/executor.js";
|
|
25
|
-
import {
|
|
26
|
-
getMcpToolDefinitions,
|
|
27
|
-
getTool,
|
|
28
|
-
getWorkspaceToolDefinitions,
|
|
29
|
-
getWorkspaceToolNames,
|
|
30
|
-
} from "../tools/registry.js";
|
|
25
|
+
import { getMcpToolDefinitions, getTool } from "../tools/registry.js";
|
|
31
26
|
import {
|
|
32
27
|
ACTIVITY_SKIP_SET,
|
|
33
28
|
injectActivityField,
|
|
@@ -46,7 +41,6 @@ import {
|
|
|
46
41
|
type ToolExecutionResult,
|
|
47
42
|
type ToolLifecycleEventHandler,
|
|
48
43
|
} from "../tools/types.js";
|
|
49
|
-
import { loadWorkspaceTools } from "../tools/workspace-tools/loader.js";
|
|
50
44
|
import {
|
|
51
45
|
resolveUsageAttribution,
|
|
52
46
|
type UsageAttributionSnapshot,
|
|
@@ -244,10 +238,7 @@ export function createToolExecutor(
|
|
|
244
238
|
});
|
|
245
239
|
}
|
|
246
240
|
},
|
|
247
|
-
isInteractive:
|
|
248
|
-
ctx.currentTurnIsNonInteractive !== undefined
|
|
249
|
-
? !ctx.currentTurnIsNonInteractive
|
|
250
|
-
: !ctx.hasNoClient && !ctx.headlessLock,
|
|
241
|
+
isInteractive: !ctx.hasNoClient && !ctx.headlessLock,
|
|
251
242
|
proxyToolResolver: (
|
|
252
243
|
toolName: string,
|
|
253
244
|
proxyInput: Record<string, unknown>,
|
|
@@ -515,7 +506,6 @@ const PLATFORM_TOOL_NAMES = new Set(["request_system_permission"]);
|
|
|
515
506
|
*/
|
|
516
507
|
export const SUBAGENT_ONLY_TOOL_NAMES = new Set<string>([
|
|
517
508
|
"file_list",
|
|
518
|
-
"code_search",
|
|
519
509
|
"notify_parent",
|
|
520
510
|
]);
|
|
521
511
|
|
|
@@ -660,13 +650,11 @@ export function isToolActiveForContext(
|
|
|
660
650
|
* allowedToolNames so newly-activated skill tools aren't blocked by
|
|
661
651
|
* the executor's stale gate.
|
|
662
652
|
*
|
|
663
|
-
* Core (non-MCP
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
* requiring conversation disposal or app restart
|
|
668
|
-
* reload`, workspace tools via edits under `<workspaceDir>/tools/` that the
|
|
669
|
-
* per-turn reconcile (kicked below) folds into the registry.
|
|
653
|
+
* Core (non-MCP) tool definitions are captured at conversation creation and
|
|
654
|
+
* reused on each turn. MCP tool definitions are re-read from the global
|
|
655
|
+
* registry on each turn so that tools registered after conversation creation
|
|
656
|
+
* (e.g. via `vellum mcp reload`) are automatically picked up without
|
|
657
|
+
* requiring conversation disposal or app restart.
|
|
670
658
|
*/
|
|
671
659
|
export function createResolveToolsCallback(
|
|
672
660
|
toolDefs: ToolDefinition[],
|
|
@@ -674,21 +662,16 @@ export function createResolveToolsCallback(
|
|
|
674
662
|
): ((history: Message[]) => ToolDefinition[]) | undefined {
|
|
675
663
|
if (toolDefs.length === 0) return undefined;
|
|
676
664
|
|
|
677
|
-
// Separate the initial tool defs into core (stable) and
|
|
678
|
-
//
|
|
679
|
-
// re-read MCP + workspace tools from the registry each turn.
|
|
665
|
+
// Separate the initial tool defs into core (stable) and MCP (dynamic).
|
|
666
|
+
// We keep core tools from the snapshot and re-read MCP tools each turn.
|
|
680
667
|
const initialMcpDefs = getMcpToolDefinitions();
|
|
681
668
|
const initialMcpNames = new Set(initialMcpDefs.map((d) => d.name));
|
|
682
|
-
const
|
|
683
|
-
const coreToolDefs = toolDefs.filter(
|
|
684
|
-
(d) => !initialMcpNames.has(d.name) && !initialWorkspaceNames.has(d.name),
|
|
685
|
-
);
|
|
669
|
+
const coreToolDefs = toolDefs.filter((d) => !initialMcpNames.has(d.name));
|
|
686
670
|
log.debug(
|
|
687
671
|
{
|
|
688
672
|
coreCount: coreToolDefs.length,
|
|
689
673
|
mcpCount: initialMcpDefs.length,
|
|
690
674
|
mcpTools: initialMcpDefs.map((d) => d.name),
|
|
691
|
-
workspaceCount: initialWorkspaceNames.size,
|
|
692
675
|
},
|
|
693
676
|
"Conversation tool resolver initialized",
|
|
694
677
|
);
|
|
@@ -702,13 +685,6 @@ export function createResolveToolsCallback(
|
|
|
702
685
|
return [];
|
|
703
686
|
}
|
|
704
687
|
|
|
705
|
-
// Reconcile workspace tool overrides under `<workspaceDir>/tools/` into
|
|
706
|
-
// the registry, then re-read them below — the on-read replacement for a
|
|
707
|
-
// filesystem watcher. Fire-and-forget: the reconcile is idempotent,
|
|
708
|
-
// mtime-cached (a no-op costs one readdir + a stat per file) and
|
|
709
|
-
// serialized, so the registry settles for a subsequent turn to read.
|
|
710
|
-
void loadWorkspaceTools();
|
|
711
|
-
|
|
712
688
|
// Filter core tools based on current conversation context so that tools
|
|
713
689
|
// irrelevant to this turn (e.g. UI tools when no client is connected)
|
|
714
690
|
// are omitted from the definitions sent to the provider.
|
|
@@ -729,34 +705,24 @@ export function createResolveToolsCallback(
|
|
|
729
705
|
? filteredCoreDefs.filter((d) => wireAllowlist.has(d.name))
|
|
730
706
|
: filteredCoreDefs;
|
|
731
707
|
|
|
732
|
-
// Re-read MCP
|
|
733
|
-
//
|
|
734
|
-
// mcp reload` and workspace-tool edits reconciled from disk, without
|
|
735
|
-
// recreating the conversation.
|
|
708
|
+
// Re-read MCP tool definitions from the registry each turn so conversations
|
|
709
|
+
// automatically pick up tools added/removed by `vellum mcp reload`.
|
|
736
710
|
const currentMcpDefs = getMcpToolDefinitions();
|
|
737
|
-
const currentWorkspaceDefs = getWorkspaceToolDefinitions();
|
|
738
711
|
log.debug(
|
|
739
712
|
{
|
|
740
713
|
coreCount: scopedCoreDefs.length,
|
|
741
714
|
mcpCount: currentMcpDefs.length,
|
|
742
715
|
mcpTools: currentMcpDefs.map((d) => d.name),
|
|
743
|
-
workspaceCount: currentWorkspaceDefs.length,
|
|
744
|
-
workspaceTools: currentWorkspaceDefs.map((d) => d.name),
|
|
745
716
|
},
|
|
746
|
-
"MCP
|
|
717
|
+
"MCP tools resolved for turn",
|
|
747
718
|
);
|
|
748
719
|
const scopedMcpDefs = wireAllowlist
|
|
749
720
|
? currentMcpDefs.filter((d) => wireAllowlist.has(d.name))
|
|
750
721
|
: currentMcpDefs;
|
|
751
|
-
const scopedWorkspaceDefs = wireAllowlist
|
|
752
|
-
? currentWorkspaceDefs.filter((d) => wireAllowlist.has(d.name))
|
|
753
|
-
: currentWorkspaceDefs;
|
|
754
722
|
const excluded = new Set(getConfig().tools.exclude);
|
|
755
|
-
const allBaseDefs = [
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
...scopedMcpDefs,
|
|
759
|
-
].filter((d) => !excluded.has(d.name));
|
|
723
|
+
const allBaseDefs = [...scopedCoreDefs, ...scopedMcpDefs].filter(
|
|
724
|
+
(d) => !excluded.has(d.name),
|
|
725
|
+
);
|
|
760
726
|
|
|
761
727
|
const effectivePreactivated = [
|
|
762
728
|
...DEFAULT_PREACTIVATED_SKILL_IDS,
|
|
@@ -50,7 +50,6 @@ import {
|
|
|
50
50
|
getMessages,
|
|
51
51
|
resolveOverrideProfile,
|
|
52
52
|
setConversationHistoryStrippedAt,
|
|
53
|
-
setConversationProcessingStartedAt,
|
|
54
53
|
} from "../memory/conversation-crud.js";
|
|
55
54
|
import { getResolvedConversationDirPath } from "../memory/conversation-directories.js";
|
|
56
55
|
import { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
|
|
@@ -92,7 +91,7 @@ import {
|
|
|
92
91
|
isActivationMomentParam,
|
|
93
92
|
} from "../telemetry/activation-funnel.js";
|
|
94
93
|
import { ToolExecutor } from "../tools/executor.js";
|
|
95
|
-
import { getAllToolDefinitions
|
|
94
|
+
import { getAllToolDefinitions } from "../tools/registry.js";
|
|
96
95
|
import type { ToolLifecycleEvent } from "../tools/types.js";
|
|
97
96
|
import type { OnboardingContext } from "../types/onboarding-context.js";
|
|
98
97
|
import type { AbortReason } from "../util/abort-reasons.js";
|
|
@@ -377,7 +376,6 @@ export class Conversation {
|
|
|
377
376
|
*/
|
|
378
377
|
wakePersonaOverride?: SystemPromptPersonaOverride;
|
|
379
378
|
/** @internal */ currentTurnOverrideProfile?: string;
|
|
380
|
-
/** @internal */ currentTurnIsNonInteractive?: boolean;
|
|
381
379
|
/** @internal */ authContext?: AuthContext;
|
|
382
380
|
/** @internal */ currentTurnAuthContext?: AuthContext;
|
|
383
381
|
/** @internal */ currentTurnSourceActorPrincipalId?: string;
|
|
@@ -703,9 +701,6 @@ export class Conversation {
|
|
|
703
701
|
tools: toolDefs.length > 0 ? toolDefs : undefined,
|
|
704
702
|
toolExecutor: toolDefs.length > 0 ? toolExecutor : undefined,
|
|
705
703
|
resolveTools,
|
|
706
|
-
// A tool the registry marks exclusive (e.g. `advisor`) runs alone in its
|
|
707
|
-
// turn; the loop defers any sibling calls until the next turn.
|
|
708
|
-
isExclusiveTool: (name) => getTool(name)?.exclusive === true,
|
|
709
704
|
resolveConversationDir: () => {
|
|
710
705
|
const conv = getConversation(this.conversationId);
|
|
711
706
|
if (!conv) return null;
|
|
@@ -1340,13 +1335,6 @@ export class Conversation {
|
|
|
1340
1335
|
setProcessing(value: boolean): void {
|
|
1341
1336
|
const wasProcessing = this._processing;
|
|
1342
1337
|
this._processing = value;
|
|
1343
|
-
// Persist the cross-process source of truth so out-of-process callers
|
|
1344
|
-
// (retrospective CLI, future detached workers) can detect mid-turn state
|
|
1345
|
-
// by reading the conversations row directly.
|
|
1346
|
-
setConversationProcessingStartedAt(
|
|
1347
|
-
this.conversationId,
|
|
1348
|
-
value ? Date.now() : null,
|
|
1349
|
-
);
|
|
1350
1338
|
if (wasProcessing && !value) {
|
|
1351
1339
|
void publishSyncInvalidation([
|
|
1352
1340
|
conversationMetadataSyncTag(this.conversationId),
|
|
@@ -24,12 +24,6 @@ export const DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT = 90;
|
|
|
24
24
|
// clears the warning state, which discards the banner's (state-scoped) dismissal
|
|
25
25
|
// so it re-appears the moment usage ticks back up.
|
|
26
26
|
export const DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT = 77;
|
|
27
|
-
// Absolute free-space floor (MiB). Regardless of usage percentage, never enter
|
|
28
|
-
// the warning or critical state while at least this much space remains free. A
|
|
29
|
-
// high usage percentage on a large disk can still leave many gigabytes
|
|
30
|
-
// available, where locking is pointless. Small volumes (where a high percentage
|
|
31
|
-
// genuinely means near-full) drop below the floor and remain protected.
|
|
32
|
-
export const DISK_PRESSURE_MIN_FREE_FLOOR_MB = 2048;
|
|
33
27
|
export const DISK_PRESSURE_CHECK_INTERVAL_MS = 60_000;
|
|
34
28
|
export const DISK_PRESSURE_OVERRIDE_CONFIRMATION = "I understand the risks";
|
|
35
29
|
export const DISK_PRESSURE_BLOCKED_CAPABILITIES = [
|
|
@@ -225,10 +219,7 @@ export function evaluateDiskPressureNow(): DiskPressureStatus {
|
|
|
225
219
|
const criticalThreshold = state.status.locked
|
|
226
220
|
? DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT
|
|
227
221
|
: DISK_PRESSURE_THRESHOLD_PERCENT;
|
|
228
|
-
|
|
229
|
-
// space remains free, report "ok" no matter how full the volume is by percent.
|
|
230
|
-
const hasAmpleFreeSpace = usageInfo.freeMb >= DISK_PRESSURE_MIN_FREE_FLOOR_MB;
|
|
231
|
-
const isCritical = !hasAmpleFreeSpace && usagePercent >= criticalThreshold;
|
|
222
|
+
const isCritical = usagePercent >= criticalThreshold;
|
|
232
223
|
// Mirror the critical deadband for the warning band: once in an active
|
|
233
224
|
// pressure state (warning or critical), hold warning until usage clears the
|
|
234
225
|
// lower warning-clear threshold. Treating "critical" as active here matters
|
|
@@ -244,8 +235,7 @@ export function evaluateDiskPressureNow(): DiskPressureStatus {
|
|
|
244
235
|
const warningThreshold = inActivePressureState
|
|
245
236
|
? DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT
|
|
246
237
|
: DISK_PRESSURE_WARNING_THRESHOLD_PERCENT;
|
|
247
|
-
const isWarning =
|
|
248
|
-
!hasAmpleFreeSpace && !isCritical && usagePercent >= warningThreshold;
|
|
238
|
+
const isWarning = !isCritical && usagePercent >= warningThreshold;
|
|
249
239
|
const lastCheckedAt = new Date().toISOString();
|
|
250
240
|
|
|
251
241
|
if (!isCritical && !isWarning) {
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
|
|
34
34
|
import * as Sentry from "@sentry/node";
|
|
35
35
|
|
|
36
|
-
import { recordWatchdogEvent } from "../memory/watchdog-events-store.js";
|
|
37
36
|
import { getLogger } from "../util/logger.js";
|
|
38
37
|
|
|
39
38
|
const log = getLogger("event-loop-watchdog");
|
|
@@ -75,37 +74,11 @@ export function evaluateTick(
|
|
|
75
74
|
return { blockedMs, exceeded: blockedMs >= thresholdMs };
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
/**
|
|
79
|
-
* Check name emitted for event-loop block events. The platform's
|
|
80
|
-
* `watchdog__event_loop_blocking_daily` admin query filters `check_name` to
|
|
81
|
-
* this exact string, so it is the primary group-by dimension downstream —
|
|
82
|
-
* keep it stable.
|
|
83
|
-
*/
|
|
84
|
-
export const EVENT_LOOP_BLOCKED_CHECK_NAME = "event_loop_blocked";
|
|
85
|
-
|
|
86
77
|
function reportBlock(blockedMs: number, thresholdMs: number): void {
|
|
87
78
|
log.warn(
|
|
88
79
|
{ blockedMs, thresholdMs, tickIntervalMs: TICK_INTERVAL_MS },
|
|
89
80
|
"event loop blocked",
|
|
90
81
|
);
|
|
91
|
-
// Persist a `watchdog` telemetry event so the platform can surface
|
|
92
|
-
// event-loop blocking in the infrastructure admin chart. `recordWatchdogEvent`
|
|
93
|
-
// no-ops when usage-data collection is disabled (the event is dropped to
|
|
94
|
-
// honor the opt-out), so the watchdog runs unconditionally without leaking
|
|
95
|
-
// health data for opted-out owners. Never let a telemetry failure escape
|
|
96
|
-
// the timer callback — wrap it alongside the Sentry capture below.
|
|
97
|
-
try {
|
|
98
|
-
recordWatchdogEvent({
|
|
99
|
-
checkName: EVENT_LOOP_BLOCKED_CHECK_NAME,
|
|
100
|
-
value: blockedMs,
|
|
101
|
-
detail: {
|
|
102
|
-
threshold_ms: thresholdMs,
|
|
103
|
-
tick_interval_ms: TICK_INTERVAL_MS,
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
} catch {
|
|
107
|
-
// Never let a telemetry failure escape the timer callback.
|
|
108
|
-
}
|
|
109
82
|
try {
|
|
110
83
|
Sentry.withScope((scope) => {
|
|
111
84
|
scope.setLevel("warning");
|
|
@@ -115,7 +88,7 @@ function reportBlock(blockedMs: number, thresholdMs: number): void {
|
|
|
115
88
|
threshold_ms: thresholdMs,
|
|
116
89
|
tick_interval_ms: TICK_INTERVAL_MS,
|
|
117
90
|
});
|
|
118
|
-
Sentry.captureMessage(
|
|
91
|
+
Sentry.captureMessage("event_loop_blocked");
|
|
119
92
|
});
|
|
120
93
|
} catch {
|
|
121
94
|
// Never let a telemetry failure escape the timer callback.
|
|
@@ -19,20 +19,24 @@
|
|
|
19
19
|
* dropped from the registry via {@link unregisterPlugin} so none of its
|
|
20
20
|
* hooks participate in the turn lifecycle. This is the primary mechanism for
|
|
21
21
|
* shipping experimental plugins behind a feature flag.
|
|
22
|
-
* 4.
|
|
22
|
+
* 4. Resolves the plugin's `manifest.requiresCredential` entries via the
|
|
23
|
+
* credential store helper ({@link getSecureKeyAsync}). In Docker mode
|
|
24
|
+
* that helper goes through the CES HTTP API transparently; in local mode
|
|
25
|
+
* it hits the encrypted file store / CES RPC backend.
|
|
26
|
+
* 5. Validates the config block under `plugins.<name>` against
|
|
23
27
|
* `manifest.config` if the manifest supplies a parser-like validator
|
|
24
28
|
* (Zod schemas with `.parse()` are supported; anything else is passed
|
|
25
29
|
* through untouched).
|
|
26
|
-
*
|
|
30
|
+
* 6. Creates `<workspaceDir>/plugins-data/<plugin>/` on demand for per-plugin
|
|
27
31
|
* writable state and exposes it via {@link PluginInitContext.pluginStorageDir}.
|
|
28
|
-
*
|
|
32
|
+
* 7. For each surviving plugin, registers its contributed tools and routes
|
|
29
33
|
* into their global registries via {@link registerPluginTools} and
|
|
30
34
|
* {@link registerSkillRoute}. Contributions land BEFORE `init()` so
|
|
31
35
|
* the plugin's hook can observe a registry where its own model-visible
|
|
32
36
|
* surface is already wired — useful for plugins that want to attach
|
|
33
37
|
* metadata, warm caches, or otherwise interact with their own
|
|
34
38
|
* contributions during initialization.
|
|
35
|
-
*
|
|
39
|
+
* 8. Awaits `plugin.init(ctx)` sequentially. An init failure is contained to
|
|
36
40
|
* the offending plugin: its already-registered tools and routes are rolled
|
|
37
41
|
* back, it is dropped from the registry, the failure is logged, and
|
|
38
42
|
* bootstrap continues with the remaining plugins. A single plugin's failure
|
|
@@ -72,6 +76,7 @@ import {
|
|
|
72
76
|
type SkillRouteHandle,
|
|
73
77
|
unregisterSkillRoute,
|
|
74
78
|
} from "../runtime/skill-route-registry.js";
|
|
79
|
+
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
75
80
|
import {
|
|
76
81
|
registerPluginTools,
|
|
77
82
|
unregisterPluginTools,
|
|
@@ -83,6 +88,25 @@ import { registerShutdownHook } from "./shutdown-registry.js";
|
|
|
83
88
|
|
|
84
89
|
const log = getLogger("plugins-bootstrap");
|
|
85
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Resolve one credential value. Returns the raw secret string or throws a
|
|
93
|
+
* {@link PluginExecutionError} tagged with the plugin name so the caller can
|
|
94
|
+
* fail startup with clear attribution.
|
|
95
|
+
*/
|
|
96
|
+
async function resolveCredentialOrThrow(
|
|
97
|
+
pluginName: string,
|
|
98
|
+
credentialKey: string,
|
|
99
|
+
): Promise<string> {
|
|
100
|
+
const value = await getSecureKeyAsync(credentialKey);
|
|
101
|
+
if (value === undefined || value === "") {
|
|
102
|
+
throw new PluginExecutionError(
|
|
103
|
+
`plugin ${pluginName} requires credential "${credentialKey}" but the credential store returned no value`,
|
|
104
|
+
pluginName,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
|
|
86
110
|
/**
|
|
87
111
|
* Validate a plugin config block. If the manifest supplies a parser-like
|
|
88
112
|
* validator (Zod schemas expose `.parse()`), use it. Otherwise pass the
|
|
@@ -322,6 +346,11 @@ async function initializePlugin(
|
|
|
322
346
|
let initCompleted = false;
|
|
323
347
|
|
|
324
348
|
try {
|
|
349
|
+
const credentials: Record<string, string> = {};
|
|
350
|
+
for (const key of plugin.manifest.requiresCredential ?? []) {
|
|
351
|
+
credentials[key] = await resolveCredentialOrThrow(name, key);
|
|
352
|
+
}
|
|
353
|
+
|
|
325
354
|
const config = validatePluginConfig(
|
|
326
355
|
name,
|
|
327
356
|
plugin.manifest.config,
|
|
@@ -330,6 +359,7 @@ async function initializePlugin(
|
|
|
330
359
|
|
|
331
360
|
const initContext = {
|
|
332
361
|
config,
|
|
362
|
+
credentials,
|
|
333
363
|
logger: log.child({ plugin: name }),
|
|
334
364
|
pluginStorageDir: ensurePluginStorageDir(name),
|
|
335
365
|
assistantVersion: APP_VERSION,
|
|
@@ -129,29 +129,4 @@ describe("redeemA2AInvite", () => {
|
|
|
129
129
|
const result = redeemA2AInvite({ sender: SENDER });
|
|
130
130
|
expect(result.success).toBe(true);
|
|
131
131
|
});
|
|
132
|
-
|
|
133
|
-
test("activeConnections counts a2a channel existence, not status", () => {
|
|
134
|
-
const result = redeemA2AInvite({ sender: SENDER });
|
|
135
|
-
expect(result.success).toBe(true);
|
|
136
|
-
|
|
137
|
-
expect(getA2AConfig().activeConnections).toBe(1);
|
|
138
|
-
|
|
139
|
-
// Readiness is existence-based: a non-active stored status still counts.
|
|
140
|
-
const sqlite = getSqlite();
|
|
141
|
-
sqlite.run("UPDATE contact_channels SET status = 'unverified'");
|
|
142
|
-
invalidateConfigCache();
|
|
143
|
-
expect(getA2AConfig().activeConnections).toBe(1);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test("already-connected guard fires regardless of stored channel status", () => {
|
|
147
|
-
const first = redeemA2AInvite({ sender: SENDER });
|
|
148
|
-
expect(first.success).toBe(true);
|
|
149
|
-
|
|
150
|
-
const sqlite = getSqlite();
|
|
151
|
-
sqlite.run("UPDATE contact_channels SET status = 'revoked'");
|
|
152
|
-
|
|
153
|
-
const second = redeemA2AInvite({ sender: SENDER });
|
|
154
|
-
expect(second.alreadyConnected).toBe(true);
|
|
155
|
-
expect(second.contactId).toBe(first.contactId);
|
|
156
|
-
});
|
|
157
132
|
});
|
|
@@ -96,11 +96,13 @@ export function getA2AConfig(): A2AConfigResult {
|
|
|
96
96
|
const config = getConfig();
|
|
97
97
|
const enabled = config.a2a?.enabled ?? false;
|
|
98
98
|
|
|
99
|
-
// a2a is peer binding outside the human-trust ACL model — the gateway has no
|
|
100
|
-
// canonical a2a channel status, so channel existence is the readiness signal.
|
|
101
99
|
const contacts = searchContacts({ channelType: "a2a" });
|
|
102
100
|
const activeConnections = contacts.reduce((count, c) => {
|
|
103
|
-
return
|
|
101
|
+
return (
|
|
102
|
+
count +
|
|
103
|
+
c.channels.filter((ch) => ch.type === "a2a" && ch.status === "active")
|
|
104
|
+
.length
|
|
105
|
+
);
|
|
104
106
|
}, 0);
|
|
105
107
|
|
|
106
108
|
return { success: true, enabled, activeConnections };
|
|
@@ -268,9 +270,12 @@ export function redeemA2AInvite(params: {
|
|
|
268
270
|
setA2AConfig();
|
|
269
271
|
}
|
|
270
272
|
|
|
271
|
-
// 2. Check for existing contact with this sender
|
|
273
|
+
// 2. Check for existing active contact with this sender
|
|
272
274
|
const existing = findContactByAddress("a2a", params.sender.assistantId);
|
|
273
|
-
if (
|
|
275
|
+
if (
|
|
276
|
+
existing &&
|
|
277
|
+
existing.channels.some((ch) => ch.type === "a2a" && ch.status === "active")
|
|
278
|
+
) {
|
|
274
279
|
return { success: true, alreadyConnected: true, contactId: existing.id };
|
|
275
280
|
}
|
|
276
281
|
|
|
@@ -368,7 +373,10 @@ export async function acceptA2AInvite(params: {
|
|
|
368
373
|
// 2. Short-circuit if already connected — avoids a network round-trip
|
|
369
374
|
// and consuming a token on the sender side.
|
|
370
375
|
const existing = findContactByAddress("a2a", params.senderAssistantId);
|
|
371
|
-
if (
|
|
376
|
+
if (
|
|
377
|
+
existing &&
|
|
378
|
+
existing.channels.some((ch) => ch.type === "a2a" && ch.status === "active")
|
|
379
|
+
) {
|
|
372
380
|
return { success: true, alreadyConnected: true, contactId: existing.id };
|
|
373
381
|
}
|
|
374
382
|
|