@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
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { createHash, randomBytes } from "node:crypto";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
GetContactIpcResponseSchema,
|
|
6
|
-
MarkChannelRevokedIpcResponseSchema,
|
|
7
|
-
} from "@vellumai/gateway-client/gateway-ipc-contracts";
|
|
3
|
+
import { MarkChannelRevokedIpcResponseSchema } from "@vellumai/gateway-client/gateway-ipc-contracts";
|
|
8
4
|
|
|
9
5
|
import { startVerificationCall } from "../../calls/call-domain.js";
|
|
10
6
|
import type { ChannelId } from "../../channels/types.js";
|
|
@@ -15,8 +11,7 @@ import {
|
|
|
15
11
|
getChannelById,
|
|
16
12
|
getContact,
|
|
17
13
|
} from "../../contacts/contact-store.js";
|
|
18
|
-
import {
|
|
19
|
-
import type { ContactChannel } from "../../contacts/types.js";
|
|
14
|
+
import type { ChannelStatus } from "../../contacts/types.js";
|
|
20
15
|
import { ipcCallPersistent } from "../../ipc/gateway-client.js";
|
|
21
16
|
import { getBindingByChannelChat } from "../../memory/external-conversation-store.js";
|
|
22
17
|
import { resolveGuardianName } from "../../prompts/user-reference.js";
|
|
@@ -33,7 +28,6 @@ import {
|
|
|
33
28
|
findActiveSession,
|
|
34
29
|
getGuardianBinding,
|
|
35
30
|
getPendingSession,
|
|
36
|
-
isGuardianBoundForChannel,
|
|
37
31
|
revokeBinding,
|
|
38
32
|
revokePendingSessions,
|
|
39
33
|
updateSessionDelivery,
|
|
@@ -82,64 +76,23 @@ export function getReadinessService(): ChannelReadinessService {
|
|
|
82
76
|
return _readinessService;
|
|
83
77
|
}
|
|
84
78
|
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
// Gateway delivery lookup
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Resolve the gateway-owned delivery (ACL source of truth) for a contact
|
|
91
|
-
* channel, matching on type and either address or externalChatId. Returns
|
|
92
|
-
* `undefined` when the gateway is unreachable or has no binding for it.
|
|
93
|
-
*/
|
|
94
|
-
async function deliveryForChannel(
|
|
95
|
-
channel: Pick<ContactChannel, "type" | "address" | "externalChatId">,
|
|
96
|
-
): Promise<GuardianDelivery | undefined> {
|
|
97
|
-
const guardians = await getGuardianDelivery({ channelTypes: [channel.type] });
|
|
98
|
-
if (!guardians) return undefined;
|
|
99
|
-
return guardians.find(
|
|
100
|
-
(g) =>
|
|
101
|
-
g.channelType === channel.type &&
|
|
102
|
-
((channel.address && g.address === channel.address) ||
|
|
103
|
-
(channel.externalChatId != null &&
|
|
104
|
-
g.externalChatId === channel.externalChatId)),
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Read a contact channel's verified state from the gateway contact-channel read
|
|
110
|
-
* (ACL source of truth). Covers all contacts, not just guardian deliveries.
|
|
111
|
-
* Returns `undefined` when the gateway is unreachable or has no such channel.
|
|
112
|
-
*/
|
|
113
|
-
async function gatewayContactChannelState(
|
|
114
|
-
channel: Pick<ContactChannel, "id" | "contactId">,
|
|
115
|
-
): Promise<{ status: string; verifiedAt: number | null } | undefined> {
|
|
116
|
-
const result = await ipcCallPersistent("contacts_get_rich", {
|
|
117
|
-
contactId: channel.contactId,
|
|
118
|
-
});
|
|
119
|
-
if (!result || (result as { contact?: unknown }).contact == null) {
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
const { contact } = GetContactIpcResponseSchema.parse(result);
|
|
123
|
-
const ch = contact.channels.find((c) => c.id === channel.id);
|
|
124
|
-
return ch ? { status: ch.status, verifiedAt: ch.verifiedAt } : undefined;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
79
|
// ---------------------------------------------------------------------------
|
|
128
80
|
// Extracted business logic functions
|
|
129
81
|
// ---------------------------------------------------------------------------
|
|
130
82
|
|
|
131
|
-
export
|
|
83
|
+
export function createInboundChallenge(
|
|
132
84
|
channel?: ChannelId,
|
|
133
85
|
rebind?: boolean,
|
|
134
86
|
conversationId?: string,
|
|
135
|
-
):
|
|
87
|
+
): ChannelVerificationSessionResult {
|
|
88
|
+
const resolvedAssistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
136
89
|
const resolvedChannel = channel ?? "telegram";
|
|
137
90
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (
|
|
91
|
+
const existingBinding = getGuardianBinding(
|
|
92
|
+
resolvedAssistantId,
|
|
93
|
+
resolvedChannel,
|
|
94
|
+
);
|
|
95
|
+
if (existingBinding && !rebind) {
|
|
143
96
|
return {
|
|
144
97
|
success: false,
|
|
145
98
|
error: "already_bound",
|
|
@@ -162,13 +115,13 @@ export async function createInboundChallenge(
|
|
|
162
115
|
};
|
|
163
116
|
}
|
|
164
117
|
|
|
165
|
-
export
|
|
118
|
+
export function getVerificationStatus(
|
|
166
119
|
channel?: ChannelId,
|
|
167
|
-
):
|
|
120
|
+
): ChannelVerificationSessionResult {
|
|
168
121
|
const resolvedAssistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
169
122
|
const resolvedChannel = channel ?? "telegram";
|
|
170
123
|
|
|
171
|
-
const binding =
|
|
124
|
+
const binding = getGuardianBinding(resolvedAssistantId, resolvedChannel);
|
|
172
125
|
|
|
173
126
|
// Read the contact directly to get displayName — getGuardianBinding is a
|
|
174
127
|
// compatibility shim that doesn't carry metadataJson.
|
|
@@ -236,10 +189,7 @@ export async function revokeVerificationForChannel(
|
|
|
236
189
|
|
|
237
190
|
// Capture binding before revoking so we can downgrade the guardian's
|
|
238
191
|
// channel — without this, the guardian would still pass the ACL check.
|
|
239
|
-
const bindingBeforeRevoke =
|
|
240
|
-
assistantId,
|
|
241
|
-
resolvedChannel,
|
|
242
|
-
);
|
|
192
|
+
const bindingBeforeRevoke = getGuardianBinding(assistantId, resolvedChannel);
|
|
243
193
|
if (!bindingBeforeRevoke) {
|
|
244
194
|
return {
|
|
245
195
|
success: true,
|
|
@@ -256,16 +206,13 @@ export async function revokeVerificationForChannel(
|
|
|
256
206
|
|
|
257
207
|
// Relay the ACL downgrade to the gateway (source of truth). The gateway's
|
|
258
208
|
// mark_channel_revoked enforces the guardian guard and dual-writes the
|
|
259
|
-
// contact-channel status back to the assistant DB.
|
|
260
|
-
// delivery's live status, not the assistant DB column, so a redundant revoke
|
|
261
|
-
// is still skipped for an already-revoked binding.
|
|
209
|
+
// contact-channel status back to the assistant DB.
|
|
262
210
|
if (contactResult) {
|
|
263
|
-
const
|
|
264
|
-
const deliveryStatus = delivery?.status;
|
|
211
|
+
const channelStatus: ChannelStatus = contactResult.channel.status;
|
|
265
212
|
if (
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
213
|
+
channelStatus === "active" ||
|
|
214
|
+
channelStatus === "pending" ||
|
|
215
|
+
channelStatus === "unverified"
|
|
269
216
|
) {
|
|
270
217
|
const result = await ipcCallPersistent("mark_channel_revoked", {
|
|
271
218
|
contactChannelId: contactResult.channel.id,
|
|
@@ -347,10 +294,7 @@ export async function verifyTrustedContact(
|
|
|
347
294
|
};
|
|
348
295
|
}
|
|
349
296
|
|
|
350
|
-
|
|
351
|
-
// (ACL SoT), which covers all contacts — not just guardian deliveries.
|
|
352
|
-
const gwState = await gatewayContactChannelState(channel);
|
|
353
|
-
if (gwState?.status === "active" && gwState.verifiedAt != null) {
|
|
297
|
+
if (channel.status === "active" && channel.verifiedAt != null) {
|
|
354
298
|
return {
|
|
355
299
|
success: false,
|
|
356
300
|
error: "already_verified",
|
|
@@ -635,7 +579,7 @@ export async function handleChannelVerificationSession(
|
|
|
635
579
|
...publicResult,
|
|
636
580
|
});
|
|
637
581
|
} else {
|
|
638
|
-
const result =
|
|
582
|
+
const result = createInboundChallenge(
|
|
639
583
|
channel,
|
|
640
584
|
msg.rebind,
|
|
641
585
|
msg.conversationId,
|
|
@@ -646,7 +590,7 @@ export async function handleChannelVerificationSession(
|
|
|
646
590
|
});
|
|
647
591
|
}
|
|
648
592
|
} else if (msg.action === "status") {
|
|
649
|
-
const result =
|
|
593
|
+
const result = getVerificationStatus(channel);
|
|
650
594
|
broadcastMessage({
|
|
651
595
|
type: "channel_verification_session_response",
|
|
652
596
|
...result,
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
3
|
import { peekAcpSessionManager } from "../../acp/index.js";
|
|
4
|
-
import { resolveCanonicalGuardianRequest } from "../../memory/canonical-guardian-store.js";
|
|
5
4
|
import { clearAll, getConversation } from "../../memory/conversation-crud.js";
|
|
6
5
|
import { resolveConversationId } from "../../memory/conversation-key-store.js";
|
|
7
6
|
import { broadcastMessage } from "../../runtime/assistant-event-hub.js";
|
|
8
7
|
import { resolveCapabilities } from "../../runtime/capabilities.js";
|
|
9
|
-
import * as pendingInteractions from "../../runtime/pending-interactions.js";
|
|
10
8
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
11
9
|
import { createAbortReason } from "../../util/abort-reasons.js";
|
|
12
10
|
import { UserError } from "../../util/errors.js";
|
|
@@ -391,81 +389,6 @@ export function steerToMessage(
|
|
|
391
389
|
return { steered: true };
|
|
392
390
|
}
|
|
393
391
|
|
|
394
|
-
/**
|
|
395
|
-
* Supersede an open `ask_question` prompt when a new chat message is enqueued
|
|
396
|
-
* for the same conversation.
|
|
397
|
-
*
|
|
398
|
-
* A queued message while a clarification question is open means the user chose
|
|
399
|
-
* to move on rather than answer it. Steering to that message aborts the parked
|
|
400
|
-
* turn — which settles the open question via its turn-abort signal — repairs
|
|
401
|
-
* the dangling `tool_use`, and drains the message, instead of stranding it
|
|
402
|
-
* behind a prompt no one is going to answer. Only `ask_question` prompts
|
|
403
|
-
* (`kind: "question"`) trigger this; pending confirmations are handled
|
|
404
|
-
* separately by the enqueue path's auto-deny.
|
|
405
|
-
*
|
|
406
|
-
* Returns `true` when a parked question was found and a steer was issued.
|
|
407
|
-
*/
|
|
408
|
-
export function steerOnEnqueuedMessageIfQuestionParked(
|
|
409
|
-
conversationId: string,
|
|
410
|
-
enqueuedRequestId: string,
|
|
411
|
-
): boolean {
|
|
412
|
-
const hasParkedQuestion = pendingInteractions
|
|
413
|
-
.getByConversation(conversationId)
|
|
414
|
-
.some((interaction) => interaction.kind === "question");
|
|
415
|
-
if (!hasParkedQuestion) return false;
|
|
416
|
-
steerToMessage(conversationId, enqueuedRequestId);
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Supersede interactions left pending by an in-flight turn when a new message
|
|
422
|
-
* is enqueued for a busy conversation. Centralized so every ingress path (the
|
|
423
|
-
* HTTP send handler and the CLI signal path) gets identical handling:
|
|
424
|
-
*
|
|
425
|
-
* 1. Auto-deny pending confirmations — notify the client and sync the
|
|
426
|
-
* canonical guardian record *before* clearing the prompter-owned
|
|
427
|
-
* confirmations, so a later guardian reply can't match a stale "pending"
|
|
428
|
-
* record and fail with `pending_interaction_not_found`.
|
|
429
|
-
* 2. Supersede a parked ask_question by steering to the enqueued message.
|
|
430
|
-
*
|
|
431
|
-
* Order matters: the steer aborts the turn, which denies the prompter's
|
|
432
|
-
* confirmations as a side effect, so the canonical/notification sync must run
|
|
433
|
-
* first. `removeByConversation` preserves `question` entries, so the parked
|
|
434
|
-
* question is still registered for the steer even after the confirmation sweep.
|
|
435
|
-
*/
|
|
436
|
-
export function supersedePendingInteractionsOnEnqueue(
|
|
437
|
-
conversationId: string,
|
|
438
|
-
enqueuedRequestId: string,
|
|
439
|
-
): void {
|
|
440
|
-
const conversation = findConversation(conversationId);
|
|
441
|
-
if (!conversation) return;
|
|
442
|
-
|
|
443
|
-
if (conversation.hasAnyPendingConfirmation()) {
|
|
444
|
-
for (const interaction of pendingInteractions.getByConversation(
|
|
445
|
-
conversationId,
|
|
446
|
-
)) {
|
|
447
|
-
if (interaction.kind === "confirmation") {
|
|
448
|
-
// sendToClient (wired to the SSE hub) delivers the denial to clients.
|
|
449
|
-
conversation.emitConfirmationStateChanged({
|
|
450
|
-
conversationId,
|
|
451
|
-
requestId: interaction.requestId,
|
|
452
|
-
state: "denied" as const,
|
|
453
|
-
source: "auto_deny" as const,
|
|
454
|
-
});
|
|
455
|
-
// Sync the canonical guardian record so stale "pending" rows aren't
|
|
456
|
-
// matched by later guardian reply routing.
|
|
457
|
-
resolveCanonicalGuardianRequest(interaction.requestId, "pending", {
|
|
458
|
-
status: "denied",
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
conversation.denyAllPendingConfirmations();
|
|
463
|
-
pendingInteractions.removeByConversation(conversationId);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
steerOnEnqueuedMessageIfQuestionParked(conversationId, enqueuedRequestId);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
392
|
// ---------------------------------------------------------------------------
|
|
470
393
|
// HTTP handler (delegates to shared logic)
|
|
471
394
|
// ---------------------------------------------------------------------------
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -966,10 +966,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
966
966
|
}
|
|
967
967
|
}
|
|
968
968
|
|
|
969
|
-
// `startMemoryJobsWorker` selects the worker implementation based on
|
|
970
|
-
// `memory.worker.enabled` (in-process vs. a separate OS process).
|
|
971
|
-
// Shutdown stops whichever worker is actually running — see
|
|
972
|
-
// shutdown-handlers.ts.
|
|
973
969
|
log.info("Daemon startup: starting memory worker");
|
|
974
970
|
bgRefs.memoryWorker = startMemoryJobsWorker();
|
|
975
971
|
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
import { getConfig, invalidateConfigCache } from "../config/loader.js";
|
|
9
9
|
import { getMcpServerManager } from "../mcp/manager.js";
|
|
10
|
-
import { migrateLegacyMcpHeaders } from "../mcp/mcp-header-store.js";
|
|
11
10
|
import { createMcpToolsFromServer } from "../tools/mcp/mcp-tool-factory.js";
|
|
12
11
|
import { registerMcpTools, unregisterAllMcpTools } from "../tools/registry.js";
|
|
13
12
|
import { getLogger } from "../util/logger.js";
|
|
@@ -56,15 +55,6 @@ async function doReload(): Promise<McpReloadResult> {
|
|
|
56
55
|
try {
|
|
57
56
|
const manager = getMcpServerManager();
|
|
58
57
|
|
|
59
|
-
// 0. Migrate any legacy plaintext headers from config.json into
|
|
60
|
-
// the credential store before loading config for server startup.
|
|
61
|
-
// No-ops when no legacy headers remain; errors are logged, not thrown.
|
|
62
|
-
try {
|
|
63
|
-
await migrateLegacyMcpHeaders();
|
|
64
|
-
} catch (err) {
|
|
65
|
-
log.warn({ err }, "Legacy MCP header migration failed — continuing");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
58
|
// 1. Validate new config before tearing down existing servers.
|
|
69
59
|
// If the config is broken we abort early, preserving the current
|
|
70
60
|
// working MCP setup instead of leaving zero servers.
|
|
@@ -59,18 +59,6 @@ function configWithV2(enabled: boolean): AssistantConfig {
|
|
|
59
59
|
return { memory: { v2: { enabled } } } as unknown as AssistantConfig;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** Poll until `m` has been called at least `n` times, or `timeoutMs` elapses. */
|
|
63
|
-
async function waitForCalls(
|
|
64
|
-
m: { mock: { calls: unknown[] } },
|
|
65
|
-
n: number,
|
|
66
|
-
timeoutMs = 1000,
|
|
67
|
-
): Promise<void> {
|
|
68
|
-
const start = Date.now();
|
|
69
|
-
while (m.mock.calls.length < n && Date.now() - start < timeoutMs) {
|
|
70
|
-
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
62
|
afterEach(() => {
|
|
75
63
|
seedSkill.mockClear();
|
|
76
64
|
seedCli.mockClear();
|
|
@@ -140,64 +128,4 @@ describe("maybeReseedCapabilitiesAfterManagedCredential", () => {
|
|
|
140
128
|
|
|
141
129
|
expect(seedCli).toHaveBeenCalledTimes(1);
|
|
142
130
|
});
|
|
143
|
-
|
|
144
|
-
test("enqueues the v3 maintain pass even when one catalog reseed rejects", async () => {
|
|
145
|
-
proxyState.prereqs = true;
|
|
146
|
-
v3State.live = true;
|
|
147
|
-
seedSkill.mockImplementationOnce(async () => {
|
|
148
|
-
throw new Error('Embedding backend "gemini" is not configured');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true));
|
|
152
|
-
|
|
153
|
-
// The CLI catalog seeded, so v3 must still rebuild its lanes — a single
|
|
154
|
-
// catalog failure cannot suppress the maintain pass.
|
|
155
|
-
expect(seedCli).toHaveBeenCalledTimes(1);
|
|
156
|
-
expect(enqueueJob).toHaveBeenCalledTimes(1);
|
|
157
|
-
expect(enqueueJob).toHaveBeenCalledWith("memory_v3_maintain", {});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test("enqueues the v3 maintain pass without blocking when a catalog reseed exceeds the timeout", async () => {
|
|
161
|
-
proxyState.prereqs = true;
|
|
162
|
-
v3State.live = true;
|
|
163
|
-
// Skill reseed never settles — mirrors the wedged getCatalog()/embed seen in
|
|
164
|
-
// the field. The CLI reseed completes normally.
|
|
165
|
-
seedSkill.mockImplementationOnce(() => new Promise<void>(() => {}));
|
|
166
|
-
|
|
167
|
-
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true), {
|
|
168
|
-
reseedTimeoutMs: 20,
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// An unbounded `Promise.all` barrier would hang here forever; the bounded
|
|
172
|
-
// barrier lets the CLI catalog's maintain pass enqueue regardless.
|
|
173
|
-
expect(seedCli).toHaveBeenCalledTimes(1);
|
|
174
|
-
expect(enqueueJob).toHaveBeenCalledTimes(1);
|
|
175
|
-
expect(enqueueJob).toHaveBeenCalledWith("memory_v3_maintain", {});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
test("re-enqueues the v3 maintain pass when a straggler catalog finishes after the timeout", async () => {
|
|
179
|
-
proxyState.prereqs = true;
|
|
180
|
-
v3State.live = true;
|
|
181
|
-
let resolveSkill!: () => void;
|
|
182
|
-
seedSkill.mockImplementationOnce(
|
|
183
|
-
() =>
|
|
184
|
-
new Promise<void>((resolve) => {
|
|
185
|
-
resolveSkill = resolve;
|
|
186
|
-
}),
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true), {
|
|
190
|
-
reseedTimeoutMs: 10,
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
// Post-barrier enqueue fires once even though the skill catalog is still
|
|
194
|
-
// embedding.
|
|
195
|
-
expect(enqueueJob).toHaveBeenCalledTimes(1);
|
|
196
|
-
|
|
197
|
-
// The straggler lands; maintain re-enqueues so its late capability rows are
|
|
198
|
-
// reconciled without waiting out the 6h backstop.
|
|
199
|
-
resolveSkill();
|
|
200
|
-
await waitForCalls(enqueueJob, 2);
|
|
201
|
-
expect(enqueueJob).toHaveBeenCalledTimes(2);
|
|
202
|
-
});
|
|
203
131
|
});
|
|
@@ -49,36 +49,6 @@ export function maybeSeedMemoryV2CliCommands(config: AssistantConfig): void {
|
|
|
49
49
|
.catch((err) => log.warn({ err }, "Failed to seed v2 CLI-command entries"));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/**
|
|
53
|
-
* Default upper bound on how long
|
|
54
|
-
* {@link maybeReseedCapabilitiesAfterManagedCredential} waits for the capability
|
|
55
|
-
* reseeds before enqueuing the v3 maintain pass. The reseeds keep running
|
|
56
|
-
* detached past this bound — it only stops the barrier from waiting on a wedged
|
|
57
|
-
* catalog (a stalled `getCatalog()` or a managed-proxy embed that never
|
|
58
|
-
* returns). A straggler that finishes later re-enqueues maintain.
|
|
59
|
-
*/
|
|
60
|
-
const RESEED_BARRIER_TIMEOUT_MS = 120_000;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Resolve to `true` if `p` settles within `ms`, or `false` if the timeout wins.
|
|
64
|
-
* Always clears the timer, so a `p` that settles first leaves no pending timer
|
|
65
|
-
* keeping the event loop (or a test) alive.
|
|
66
|
-
*/
|
|
67
|
-
async function settledWithin(
|
|
68
|
-
p: Promise<unknown>,
|
|
69
|
-
ms: number,
|
|
70
|
-
): Promise<boolean> {
|
|
71
|
-
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
72
|
-
const timedOut = new Promise<false>((resolve) => {
|
|
73
|
-
timer = setTimeout(() => resolve(false), ms);
|
|
74
|
-
});
|
|
75
|
-
try {
|
|
76
|
-
return await Promise.race([p.then(() => true), timedOut]);
|
|
77
|
-
} finally {
|
|
78
|
-
if (timer) clearTimeout(timer);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
52
|
/**
|
|
83
53
|
* Re-seed the v2 skill and CLI-command capability entries once a managed-proxy
|
|
84
54
|
* credential lands, closing the first-boot race where the daemon's startup seed
|
|
@@ -113,23 +83,9 @@ async function settledWithin(
|
|
|
113
83
|
* dense store and its lane-invalidation stage forces a rebuild against the now-
|
|
114
84
|
* populated index, so v3 surfaces the skill/CLI pages within seconds instead of
|
|
115
85
|
* waiting out the backstop.
|
|
116
|
-
*
|
|
117
|
-
* The maintain enqueue must NOT be gated on both catalogs settling. The two
|
|
118
|
-
* embeds are independent, and a single wedged catalog (a stalled `getCatalog()`
|
|
119
|
-
* or a managed-proxy embed that never returns) would otherwise block the v3 lane
|
|
120
|
-
* rebuild indefinitely, so the catalog that DID seed never reaches the selector.
|
|
121
|
-
* The barrier is therefore bounded by `reseedTimeoutMs`: maintain is enqueued
|
|
122
|
-
* once the barrier resolves (the pass is idempotent and reconciles whatever the
|
|
123
|
-
* page index currently holds), and a straggler catalog that finishes after the
|
|
124
|
-
* timeout re-enqueues maintain so its late rows are picked up without waiting out
|
|
125
|
-
* the backstop.
|
|
126
|
-
*
|
|
127
|
-
* `reseedTimeoutMs` is injectable for tests; production uses
|
|
128
|
-
* {@link RESEED_BARRIER_TIMEOUT_MS}.
|
|
129
86
|
*/
|
|
130
87
|
export async function maybeReseedCapabilitiesAfterManagedCredential(
|
|
131
88
|
config: AssistantConfig,
|
|
132
|
-
opts: { reseedTimeoutMs?: number } = {},
|
|
133
89
|
): Promise<void> {
|
|
134
90
|
if (!config.memory.v2.enabled) return;
|
|
135
91
|
|
|
@@ -159,59 +115,35 @@ export async function maybeReseedCapabilitiesAfterManagedCredential(
|
|
|
159
115
|
],
|
|
160
116
|
];
|
|
161
117
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
seed().then(
|
|
167
|
-
() =>
|
|
118
|
+
await Promise.all(
|
|
119
|
+
catalogs.map(async ([label, seed]) => {
|
|
120
|
+
try {
|
|
121
|
+
await seed();
|
|
168
122
|
log.info(
|
|
169
123
|
`Memory v2 ${label} entries seeded after managed proxy credential update`,
|
|
170
|
-
)
|
|
171
|
-
(err
|
|
124
|
+
);
|
|
125
|
+
} catch (err) {
|
|
172
126
|
log.warn(
|
|
173
127
|
{ err },
|
|
174
128
|
`Failed to seed v2 ${label} entries after managed proxy credential update`,
|
|
175
|
-
)
|
|
176
|
-
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}),
|
|
177
132
|
);
|
|
178
133
|
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
// Resolve the gate + enqueuer once and reuse for the post-barrier enqueue and
|
|
183
|
-
// the straggler re-enqueue below.
|
|
134
|
+
// The stores (and the page index) are now populated; when v3 is live, kick a
|
|
135
|
+
// maintain pass so it embeds the capability rows into `memory_v3_sections` and
|
|
136
|
+
// invalidates its lanes immediately rather than waiting out the 6h backstop.
|
|
184
137
|
const { isMemoryV3Live } = await import("../config/memory-v3-gate.js");
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
enqueueMemoryJob("memory_v3_maintain", {});
|
|
191
|
-
} catch (err) {
|
|
192
|
-
log.warn(
|
|
193
|
-
{ err },
|
|
194
|
-
"Failed to enqueue memory_v3_maintain after managed proxy credential update",
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// Bound the barrier so a wedged catalog can't block the maintain enqueue
|
|
200
|
-
// indefinitely; the reseeds keep running detached past the timeout.
|
|
201
|
-
const timeoutMs = opts.reseedTimeoutMs ?? RESEED_BARRIER_TIMEOUT_MS;
|
|
202
|
-
const allReseeds = Promise.allSettled(reseeds);
|
|
203
|
-
const settledInTime = await settledWithin(allReseeds, timeoutMs);
|
|
204
|
-
|
|
205
|
-
await enqueueMaintain();
|
|
206
|
-
|
|
207
|
-
if (!settledInTime) {
|
|
138
|
+
if (!isMemoryV3Live(config)) return;
|
|
139
|
+
try {
|
|
140
|
+
const { enqueueMemoryJob } = await import("../memory/jobs-store.js");
|
|
141
|
+
enqueueMemoryJob("memory_v3_maintain", {});
|
|
142
|
+
} catch (err) {
|
|
208
143
|
log.warn(
|
|
209
|
-
{
|
|
210
|
-
"
|
|
144
|
+
{ err },
|
|
145
|
+
"Failed to enqueue memory_v3_maintain after managed proxy credential update",
|
|
211
146
|
);
|
|
212
|
-
// The straggler is still embedding; re-enqueue maintain once it lands so its
|
|
213
|
-
// late capability rows are reconciled without waiting out the 6h backstop.
|
|
214
|
-
void allReseeds.then(() => enqueueMaintain());
|
|
215
147
|
}
|
|
216
148
|
}
|
|
217
149
|
|
|
@@ -4,7 +4,6 @@ import type { CompactionCircuitClosedEvent } from "../../api/events/compaction-c
|
|
|
4
4
|
import type { CompactionCircuitOpenEvent } from "../../api/events/compaction-circuit-open.js";
|
|
5
5
|
import type { ConversationErrorEvent } from "../../api/events/conversation-error.js";
|
|
6
6
|
import type { ConversationListInvalidatedEvent } from "../../api/events/conversation-list-invalidated.js";
|
|
7
|
-
import type { ConversationNoticeEvent } from "../../api/events/conversation-notice.js";
|
|
8
7
|
import type { ConversationTitleUpdatedEvent } from "../../api/events/conversation-title-updated.js";
|
|
9
8
|
import type { GenerationCancelledEvent } from "../../api/events/generation-cancelled.js";
|
|
10
9
|
import type { GenerationHandoffEvent } from "../../api/events/generation-handoff.js";
|
|
@@ -544,7 +543,6 @@ export type _ConversationsServerMessages =
|
|
|
544
543
|
| CompactionCircuitOpenEvent
|
|
545
544
|
| CompactionCircuitClosedEvent
|
|
546
545
|
| ConversationErrorEvent
|
|
547
|
-
| ConversationNoticeEvent
|
|
548
546
|
| ConversationInfo
|
|
549
547
|
| ConversationTitleUpdatedEvent
|
|
550
548
|
| ConversationListResponse
|
|
@@ -3,21 +3,14 @@
|
|
|
3
3
|
import {
|
|
4
4
|
type CardSurfaceData,
|
|
5
5
|
CardSurfaceDataSchema,
|
|
6
|
-
type FileUploadSurfaceData,
|
|
7
|
-
FileUploadSurfaceDataSchema,
|
|
8
6
|
} from "../../api/surfaces.js";
|
|
9
7
|
|
|
10
8
|
// Surface `data` shapes are wire payloads owned by `@vellumai/assistant-api`.
|
|
11
|
-
// Card
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
export {
|
|
16
|
-
type CardSurfaceData,
|
|
17
|
-
CardSurfaceDataSchema,
|
|
18
|
-
type FileUploadSurfaceData,
|
|
19
|
-
FileUploadSurfaceDataSchema,
|
|
20
|
-
};
|
|
9
|
+
// Card is migrated (canonical Zod schema); the remaining types below are still
|
|
10
|
+
// hand-written interfaces pending migration. Re-exported so the daemon's
|
|
11
|
+
// surface protocol barrel (`message-protocol.ts`) keeps surfacing them to
|
|
12
|
+
// daemon consumers under their canonical names.
|
|
13
|
+
export { type CardSurfaceData, CardSurfaceDataSchema };
|
|
21
14
|
|
|
22
15
|
// === Surface type definitions ===
|
|
23
16
|
|
|
@@ -162,6 +155,13 @@ export interface DynamicPageSurfaceData {
|
|
|
162
155
|
preview?: DynamicPagePreview;
|
|
163
156
|
}
|
|
164
157
|
|
|
158
|
+
export interface FileUploadSurfaceData {
|
|
159
|
+
prompt: string;
|
|
160
|
+
acceptedTypes?: string[];
|
|
161
|
+
maxFiles?: number;
|
|
162
|
+
maxSizeBytes?: number;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
165
|
export interface TableColumn {
|
|
166
166
|
id: string;
|
|
167
167
|
label: string;
|
package/src/daemon/server.ts
CHANGED
|
@@ -48,6 +48,7 @@ import { parseIdentityFields } from "./handlers/identity.js";
|
|
|
48
48
|
import type { ConversationCreateOptions } from "./handlers/shared.js";
|
|
49
49
|
import { setGlobalSkillIpcSender } from "./meet-host-supervisor.js";
|
|
50
50
|
import { refreshSkillCapabilityMemories } from "./skill-memory-refresh.js";
|
|
51
|
+
import { WorkspaceToolsWatcher } from "./workspace-tools-watcher.js";
|
|
51
52
|
|
|
52
53
|
const log = getLogger("server");
|
|
53
54
|
|
|
@@ -307,6 +308,8 @@ export class DaemonServer {
|
|
|
307
308
|
|
|
308
309
|
this.appSourceWatcher.start((appId) => this.handleAppSourceChange(appId));
|
|
309
310
|
|
|
311
|
+
WorkspaceToolsWatcher.getInstance().start();
|
|
312
|
+
|
|
310
313
|
// Broadcast contacts_changed to all clients when any contact mutation occurs.
|
|
311
314
|
this.unsubscribeContactChange = onContactChange(() => {
|
|
312
315
|
broadcastMessage({ type: "contacts_changed" });
|
|
@@ -321,6 +324,7 @@ export class DaemonServer {
|
|
|
321
324
|
this.evictor.stop();
|
|
322
325
|
this.configWatcher.stop();
|
|
323
326
|
this.appSourceWatcher.stop();
|
|
327
|
+
WorkspaceToolsWatcher.getInstance().stop();
|
|
324
328
|
this.cliIpc.stop();
|
|
325
329
|
this.skillIpc.stop();
|
|
326
330
|
if (this.unsubscribeContactChange) {
|
|
@@ -5,7 +5,6 @@ import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
|
|
|
5
5
|
import type { McpServerManager } from "../mcp/manager.js";
|
|
6
6
|
import { getSqlite, resetDb } from "../memory/db-connection.js";
|
|
7
7
|
import type { QdrantManager } from "../memory/qdrant-manager.js";
|
|
8
|
-
import { stopMemoryWorkerProcess } from "../memory/worker-control.js";
|
|
9
8
|
import type { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
10
9
|
import { browserManager } from "../tools/browser/browser-manager.js";
|
|
11
10
|
import { cleanupShellOutputTempFiles } from "../tools/shared/shell-output.js";
|
|
@@ -118,27 +117,8 @@ export function installShutdownHandlers(deps: ShutdownDeps): void {
|
|
|
118
117
|
await browserManager.closeAllPages();
|
|
119
118
|
cleanupShellOutputTempFiles();
|
|
120
119
|
deps.scheduler.stop();
|
|
121
|
-
|
|
122
|
-
// Stop the in-process memory worker if one was started on the daemon's
|
|
123
|
-
// event loop (memory.worker.enabled = false).
|
|
124
120
|
deps.getMemoryWorker()?.stop();
|
|
125
121
|
|
|
126
|
-
// Stop the out-of-process memory worker if it's actually running. This is
|
|
127
|
-
// keyed off live state rather than config: the worker may have been
|
|
128
|
-
// spawned at startup (memory.worker.enabled = true) or out of band via
|
|
129
|
-
// `assistant memory worker start`, so we stop whatever is actually there.
|
|
130
|
-
try {
|
|
131
|
-
const workerStatus = stopMemoryWorkerProcess();
|
|
132
|
-
if (workerStatus.status === "running") {
|
|
133
|
-
log.info(
|
|
134
|
-
{ pid: workerStatus.pid },
|
|
135
|
-
"Sent SIGTERM to memory worker process",
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
} catch (err) {
|
|
139
|
-
log.warn({ err }, "Failed to stop memory worker process (non-fatal)");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
122
|
if (deps.mcpManager) {
|
|
143
123
|
try {
|
|
144
124
|
await deps.mcpManager.stop();
|
|
@@ -124,13 +124,4 @@ export interface ToolSetupContext extends SurfaceConversationContext {
|
|
|
124
124
|
* return `undefined` for the in-flight (background) subagent.
|
|
125
125
|
*/
|
|
126
126
|
currentTurnOverrideProfile?: string;
|
|
127
|
-
/**
|
|
128
|
-
* Whether the current turn has no human present to answer clarification
|
|
129
|
-
* prompts. Resolved once per turn by the agent loop — honoring an explicit
|
|
130
|
-
* per-run `isInteractive` option (e.g. scheduled/background turns) over the
|
|
131
|
-
* live client state — so tool execution sees turn-level interactivity rather
|
|
132
|
-
* than re-deriving it from `hasNoClient`/`headlessLock`, which would read a
|
|
133
|
-
* scheduled turn running on a client-attached conversation as interactive.
|
|
134
|
-
*/
|
|
135
|
-
currentTurnIsNonInteractive?: boolean;
|
|
136
127
|
}
|