@vellumai/assistant 0.8.5 → 0.8.6
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/AGENTS.md +33 -1
- package/ARCHITECTURE.md +1 -1
- package/bunfig.toml +6 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +1900 -166
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +3 -2
- package/src/__tests__/call-controller.test.ts +3 -2
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +3 -2
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +12 -12
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +12 -14
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
- package/src/__tests__/conversation-agent-loop.test.ts +488 -2
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +69 -8
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -5
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +26 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +5 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-resolver.test.ts +331 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +3 -2
- package/src/__tests__/openai-provider.test.ts +8 -9
- package/src/__tests__/openai-responses-provider.test.ts +70 -10
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/plugin-bootstrap.test.ts +9 -11
- package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +14 -16
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +38 -0
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/loop.ts +80 -0
- package/src/api/README.md +124 -2
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/{events → api/events}/relationship-state-updated.ts +3 -3
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +128 -3
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +687 -52
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/memory-v3-render.ts +147 -0
- package/src/cli/commands/memory-v3.ts +255 -4
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +23 -42
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +1 -1
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +90 -1
- package/src/config/schemas/memory-v2.ts +26 -0
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/token-estimator.ts +10 -5
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
- package/src/daemon/conversation-agent-loop.ts +132 -28
- package/src/daemon/conversation-error.ts +33 -5
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +29 -9
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +33 -48
- package/src/daemon/conversation.ts +26 -46
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +27 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/lifecycle.ts +12 -12
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- package/src/daemon/message-types/conversations.ts +20 -22
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -2
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +23 -38
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +28 -29
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +352 -112
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +4 -0
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-worker.ts +12 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
- package/src/memory/llm-request-log-source-local.ts +24 -0
- package/src/memory/llm-request-log-source.ts +31 -0
- package/src/memory/llm-request-log-store.ts +188 -3
- package/src/memory/memory-v2-activation-log-store.ts +95 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edges.test.ts +144 -1
- package/src/memory/v3/__tests__/filter.test.ts +48 -0
- package/src/memory/v3/__tests__/gate.test.ts +96 -33
- package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
- package/src/memory/v3/__tests__/loop.test.ts +250 -5
- package/src/memory/v3/__tests__/scouts.test.ts +49 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
- package/src/memory/v3/__tests__/traversal.test.ts +39 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
- package/src/memory/v3/__tests__/validate.test.ts +32 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edges.ts +58 -21
- package/src/memory/v3/filter.ts +27 -22
- package/src/memory/v3/gate.ts +51 -36
- package/src/memory/v3/index-composition.ts +18 -5
- package/src/memory/v3/loop.ts +65 -17
- package/src/memory/v3/scouts.ts +15 -4
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +44 -2
- package/src/memory/v3/traversal.ts +6 -1
- package/src/memory/v3/tree-walk.ts +6 -1
- package/src/memory/v3/validate.ts +56 -33
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugins/defaults/injectors.ts +2 -8
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/types.ts +57 -13
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +7 -11
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/call-site-routing.ts +33 -9
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +24 -3
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +110 -12
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +53 -53
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +18 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -4
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +9 -0
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/auth/route-policy.ts +10 -0
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/migrations/vbundle-builder.ts +3 -2
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/background-wake-routes.ts +188 -20
- package/src/runtime/routes/btw-routes.ts +4 -4
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +147 -0
- package/src/runtime/routes/conversation-management-routes.ts +39 -14
- package/src/runtime/routes/conversation-query-routes.ts +60 -10
- package/src/runtime/routes/conversation-routes.ts +186 -140
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/group-routes.ts +11 -0
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-v3-routes.ts +160 -2
- package/src/runtime/routes/migration-routes.ts +20 -13
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/tools/apps/definitions.ts +35 -21
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +268 -266
- package/src/tools/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +2 -5
- package/src/tools/executor.ts +18 -55
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-search.ts +199 -44
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +146 -103
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +17 -15
- package/src/tools/ui-surface/definitions.ts +98 -86
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/util/browser.ts +7 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -46,13 +46,17 @@ const ImageGenerationServiceSchema = BaseServiceSchema.extend({
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
const WebSearchServiceSchema = BaseServiceSchema.extend({
|
|
49
|
+
// Provider choice for app-executed search in Your Own mode, or the native
|
|
50
|
+
// hosted-search preference when set to `inference-provider-native`. In
|
|
51
|
+
// Managed mode, non-native inference providers can still use the platform
|
|
52
|
+
// managed search proxy through the app-executed `web_search` tool.
|
|
49
53
|
provider: z
|
|
50
54
|
.enum(VALID_WEB_SEARCH_PROVIDERS)
|
|
51
55
|
.default("inference-provider-native"),
|
|
52
56
|
});
|
|
53
57
|
|
|
54
58
|
const GoogleOAuthServiceSchema = BaseServiceSchema.extend({
|
|
55
|
-
mode: ServiceModeSchema.default("
|
|
59
|
+
mode: ServiceModeSchema.default("managed"),
|
|
56
60
|
});
|
|
57
61
|
|
|
58
62
|
const OutlookOAuthServiceSchema = BaseServiceSchema.extend({
|
|
@@ -68,7 +72,7 @@ const GitHubOAuthServiceSchema = BaseServiceSchema.extend({
|
|
|
68
72
|
});
|
|
69
73
|
|
|
70
74
|
const NotionOAuthServiceSchema = BaseServiceSchema.extend({
|
|
71
|
-
mode: ServiceModeSchema.default("
|
|
75
|
+
mode: ServiceModeSchema.default("managed"),
|
|
72
76
|
});
|
|
73
77
|
|
|
74
78
|
const TwitterOAuthServiceSchema = BaseServiceSchema.extend({
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { DrizzleDb } from "../memory/db-connection.js";
|
|
2
2
|
import {
|
|
3
3
|
createConnection,
|
|
4
|
-
disableManagedConnectionsForByokHatch,
|
|
5
4
|
getConnection,
|
|
6
5
|
MANAGED_CONNECTION_NAMES,
|
|
7
6
|
PROVIDERS_REQUIRING_BASE_URL_AND_MODELS,
|
|
@@ -123,9 +122,18 @@ const USER_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
|
|
|
123
122
|
},
|
|
124
123
|
};
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
/**
|
|
126
|
+
* The "auto" profile key. When active, the daemon injects the
|
|
127
|
+
* `switch_inference_profile` tool and lets the model self-select a profile
|
|
128
|
+
* per query. No provider/model — the resolver falls through to the call-site
|
|
129
|
+
* default (balanced or custom-balanced for BYOK).
|
|
130
|
+
*/
|
|
131
|
+
export const AUTO_PROFILE_KEY = "auto";
|
|
132
|
+
|
|
133
|
+
export const MANAGED_PROFILE_NAMES = new Set([
|
|
134
|
+
...Object.keys(MANAGED_PROFILE_TEMPLATES),
|
|
135
|
+
AUTO_PROFILE_KEY,
|
|
136
|
+
]);
|
|
129
137
|
|
|
130
138
|
export type SeedInferenceProfilesOptions = {
|
|
131
139
|
/**
|
|
@@ -263,21 +271,28 @@ export function seedInferenceProfiles(
|
|
|
263
271
|
profiles[name] = next as ProfileEntry;
|
|
264
272
|
}
|
|
265
273
|
|
|
274
|
+
// 1b. Auto profile — a metadata-only profile with no provider/model. When
|
|
275
|
+
// the user selects "Auto", the resolver falls through to the call-site
|
|
276
|
+
// default (balanced or custom-balanced), and the agent loop injects the
|
|
277
|
+
// switch_inference_profile tool so the model can self-select per query.
|
|
278
|
+
if (!preservedProfileNames.has(AUTO_PROFILE_KEY)) {
|
|
279
|
+
const previousAuto = readObject(profiles[AUTO_PROFILE_KEY]);
|
|
280
|
+
const autoEntry: Record<string, unknown> = {
|
|
281
|
+
source: "managed",
|
|
282
|
+
label: "Auto",
|
|
283
|
+
description:
|
|
284
|
+
"Automatically routes each query to the best profile — fast for simple questions, capable for complex ones",
|
|
285
|
+
};
|
|
286
|
+
if (previousAuto) {
|
|
287
|
+
if ("label" in previousAuto) autoEntry.label = previousAuto.label;
|
|
288
|
+
if ("status" in previousAuto) autoEntry.status = previousAuto.status;
|
|
289
|
+
}
|
|
290
|
+
profiles[AUTO_PROFILE_KEY] = autoEntry as ProfileEntry;
|
|
291
|
+
}
|
|
292
|
+
|
|
266
293
|
// 2. User profiles — only at hatch time for off-platform installations.
|
|
267
294
|
let userConnectionName: string | undefined;
|
|
268
295
|
if (options.isHatch && !isPlatform) {
|
|
269
|
-
// BYOK hatch: disable canonical managed connections so the picker doesn't
|
|
270
|
-
// surface unusable platform-auth options on day one. If the hatch overlay
|
|
271
|
-
// selected a managed profile, leave that connection active; the user has
|
|
272
|
-
// already chosen managed inference. Runs only here, only at hatch —
|
|
273
|
-
// `seedCanonicalConnections` leaves `status` alone on subsequent boots so
|
|
274
|
-
// a post-hatch user re-enable persists.
|
|
275
|
-
if (options.db) {
|
|
276
|
-
disableManagedConnectionsForByokHatch(options.db, {
|
|
277
|
-
excludeConnection: hatchSelectedManagedConnection,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
296
|
const hatchProvider = readString(readObject(llm.default)?.provider);
|
|
282
297
|
if (
|
|
283
298
|
hatchProvider &&
|
|
@@ -336,10 +351,15 @@ export function seedInferenceProfiles(
|
|
|
336
351
|
}
|
|
337
352
|
|
|
338
353
|
// Profile ordering — ensure all seeded profiles appear in the order array.
|
|
354
|
+
// "auto" is prepended so it appears first in the picker.
|
|
339
355
|
const profileOrder = Array.isArray(llm.profileOrder)
|
|
340
356
|
? (llm.profileOrder as string[])
|
|
341
357
|
: [];
|
|
342
358
|
const orderSet = new Set(profileOrder);
|
|
359
|
+
if (!orderSet.has(AUTO_PROFILE_KEY)) {
|
|
360
|
+
profileOrder.unshift(AUTO_PROFILE_KEY);
|
|
361
|
+
orderSet.add(AUTO_PROFILE_KEY);
|
|
362
|
+
}
|
|
343
363
|
for (const name of Object.keys(MANAGED_PROFILE_TEMPLATES)) {
|
|
344
364
|
if (!orderSet.has(name)) {
|
|
345
365
|
profileOrder.push(name);
|
|
@@ -154,11 +154,16 @@ function estimateGeminiImageTokens(width: number, height: number): number {
|
|
|
154
154
|
) {
|
|
155
155
|
return GEMINI_IMAGE_TOKENS_PER_TILE;
|
|
156
156
|
}
|
|
157
|
-
// Gemini
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const
|
|
157
|
+
// Gemini rescales both dimensions by a single aspect-preserving factor so
|
|
158
|
+
// the longest side is ≤3072px before tiling. Clamping each side
|
|
159
|
+
// independently would over-count tiles for extreme aspect ratios
|
|
160
|
+
// (e.g. 10000×1000 → 3072×307, not 3072×1000).
|
|
161
|
+
const scale = Math.min(
|
|
162
|
+
1,
|
|
163
|
+
GEMINI_IMAGE_MAX_DIMENSION / Math.max(width, height),
|
|
164
|
+
);
|
|
165
|
+
const tilesWide = Math.ceil((width * scale) / GEMINI_IMAGE_TILE_SIZE);
|
|
166
|
+
const tilesHigh = Math.ceil((height * scale) / GEMINI_IMAGE_TILE_SIZE);
|
|
162
167
|
return tilesWide * tilesHigh * GEMINI_IMAGE_TOKENS_PER_TILE;
|
|
163
168
|
}
|
|
164
169
|
|
|
@@ -212,3 +212,43 @@ export function discoverCes(): DiscoveryResult {
|
|
|
212
212
|
}
|
|
213
213
|
return discoverLocalCes();
|
|
214
214
|
}
|
|
215
|
+
|
|
216
|
+
/** How long to poll for the managed bootstrap socket before giving up. */
|
|
217
|
+
const MANAGED_DISCOVERY_TIMEOUT_MS = 3_000;
|
|
218
|
+
|
|
219
|
+
/** Delay between managed bootstrap-socket discovery attempts. */
|
|
220
|
+
const MANAGED_DISCOVERY_INTERVAL_MS = 100;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Discover CES, polling for the managed bootstrap socket with a short
|
|
224
|
+
* backoff before failing.
|
|
225
|
+
*
|
|
226
|
+
* The managed CES sidecar re-binds its bootstrap socket after each assistant
|
|
227
|
+
* session ends — it outlives any single assistant and accepts the next
|
|
228
|
+
* connection (see `credential-executor/src/managed-main.ts`). A reconnecting
|
|
229
|
+
* assistant (e.g. after a container restart) can therefore probe during the
|
|
230
|
+
* brief window before the socket is re-bound. A single existence check would
|
|
231
|
+
* race that window and incorrectly report the sidecar as unavailable; polling
|
|
232
|
+
* absorbs the gap.
|
|
233
|
+
*
|
|
234
|
+
* Local discovery is returned immediately — a missing binary will not appear
|
|
235
|
+
* by waiting, so there is nothing to poll for.
|
|
236
|
+
*/
|
|
237
|
+
export async function discoverCesWithRetry({
|
|
238
|
+
timeoutMs = MANAGED_DISCOVERY_TIMEOUT_MS,
|
|
239
|
+
intervalMs = MANAGED_DISCOVERY_INTERVAL_MS,
|
|
240
|
+
}: { timeoutMs?: number; intervalMs?: number } = {}): Promise<DiscoveryResult> {
|
|
241
|
+
// Only the managed bootstrap socket is worth polling for; a missing local
|
|
242
|
+
// binary will not appear by waiting.
|
|
243
|
+
if (!getIsContainerized()) {
|
|
244
|
+
return discoverCes();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const deadline = Date.now() + timeoutMs;
|
|
248
|
+
let result = discoverCes();
|
|
249
|
+
while (result.mode === "unavailable" && Date.now() < deadline) {
|
|
250
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
251
|
+
result = discoverCes();
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
@@ -29,7 +29,7 @@ import { ensureBun } from "../util/bun-runtime.js";
|
|
|
29
29
|
import { getLogger } from "../util/logger.js";
|
|
30
30
|
import type { CesTransport } from "./client.js";
|
|
31
31
|
import {
|
|
32
|
-
|
|
32
|
+
discoverCesWithRetry,
|
|
33
33
|
discoverLocalCes,
|
|
34
34
|
type DiscoveryResult,
|
|
35
35
|
type LocalDiscoverySuccess,
|
|
@@ -118,7 +118,11 @@ export function createCesProcessManager(
|
|
|
118
118
|
throw new Error("CES process manager is already running");
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
// Poll for the managed bootstrap socket with a short backoff. The CES
|
|
122
|
+
// sidecar re-binds its socket after each assistant session ends, so a
|
|
123
|
+
// reconnecting assistant can briefly race the re-bind; a single probe
|
|
124
|
+
// would otherwise fall back to local discovery and fail in managed mode.
|
|
125
|
+
discoveryResult = await discoverCesWithRetry();
|
|
122
126
|
if (discoveryResult.mode === "unavailable") {
|
|
123
127
|
// The managed sidecar bootstrap socket is not present — this happens
|
|
124
128
|
// when the instance pre-dates the socket volume mount (e.g. existing
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* - Scope coverage (grantedScopes vs provider defaultScopes)
|
|
8
8
|
* - Liveness ping (for providers with a pingUrl)
|
|
9
9
|
*
|
|
10
|
-
* Designed to run during the heartbeat cycle.
|
|
11
|
-
*
|
|
10
|
+
* Designed to run during the heartbeat cycle. The BYO liveness ping is
|
|
11
|
+
* routed through `withValidToken`, so a stale-but-refreshable access token
|
|
12
|
+
* is refreshed transparently before the ping fires — this prevents the
|
|
13
|
+
* heartbeat from misreporting a refreshable connection as `"revoked"`.
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
import { isTokenExpired } from "@vellumai/credential-storage";
|
|
@@ -22,6 +24,10 @@ import {
|
|
|
22
24
|
type OAuthConnectionRow,
|
|
23
25
|
type OAuthProviderRow,
|
|
24
26
|
} from "../oauth/oauth-store.js";
|
|
27
|
+
import {
|
|
28
|
+
TokenExpiredError,
|
|
29
|
+
withValidToken,
|
|
30
|
+
} from "../security/token-manager.js";
|
|
25
31
|
import { getLogger } from "../util/logger.js";
|
|
26
32
|
|
|
27
33
|
const log = getLogger("credential-health");
|
|
@@ -125,6 +131,45 @@ async function pingProvider(
|
|
|
125
131
|
}
|
|
126
132
|
}
|
|
127
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Map a pingProvider result onto a CredentialHealthResult, or null when the
|
|
136
|
+
* ping succeeded. `authErrorContext` distinguishes whether a 401/403 came
|
|
137
|
+
* after a refresh attempt (refreshable connection) or directly from the
|
|
138
|
+
* stored token (manual-token / no-refresh connection) — the latter is the
|
|
139
|
+
* historical message wording.
|
|
140
|
+
*/
|
|
141
|
+
type PingFailureContext = "after_refresh" | "no_refresh";
|
|
142
|
+
|
|
143
|
+
function pingResultToHealthFailure(
|
|
144
|
+
base: Omit<CredentialHealthResult, "status" | "details" | "canAutoRecover">,
|
|
145
|
+
provider: string,
|
|
146
|
+
connectionId: string,
|
|
147
|
+
pingResult: { ok: boolean; authError: boolean },
|
|
148
|
+
authErrorContext: PingFailureContext,
|
|
149
|
+
): CredentialHealthResult | null {
|
|
150
|
+
if (pingResult.ok) return null;
|
|
151
|
+
if (pingResult.authError) {
|
|
152
|
+
const suffix =
|
|
153
|
+
authErrorContext === "after_refresh" ? " after a refresh attempt" : "";
|
|
154
|
+
return {
|
|
155
|
+
...base,
|
|
156
|
+
status: "revoked",
|
|
157
|
+
details: `${provider} token was rejected (401/403)${suffix}. The token may have been revoked. Re-authorization required.`,
|
|
158
|
+
canAutoRecover: false,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
log.debug(
|
|
162
|
+
{ provider, connectionId },
|
|
163
|
+
"Credential ping failed with non-auth error",
|
|
164
|
+
);
|
|
165
|
+
return {
|
|
166
|
+
...base,
|
|
167
|
+
status: "ping_failed",
|
|
168
|
+
details: `${provider} liveness check failed (non-auth error). This may be transient.`,
|
|
169
|
+
canAutoRecover: false,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
128
173
|
// ── Core check ────────────────────────────────────────────────────────
|
|
129
174
|
|
|
130
175
|
interface CheckConnectionOpts {
|
|
@@ -192,14 +237,18 @@ async function checkConnection(
|
|
|
192
237
|
const token = tokenResult.value;
|
|
193
238
|
|
|
194
239
|
// 2. Check token expiry
|
|
195
|
-
|
|
240
|
+
//
|
|
241
|
+
// When the token is expired AND there is no refresh token, we have no path
|
|
242
|
+
// to recovery — short-circuit to "expired". When there IS a refresh token,
|
|
243
|
+
// we fall through so the ping (via withValidToken) can attempt a refresh
|
|
244
|
+
// and confirm whether the refresh token still works. Without that, we'd
|
|
245
|
+
// return "expiring" speculatively even when the refresh token was revoked.
|
|
246
|
+
if (isTokenExpired(expiresAt) && !hasRefreshToken) {
|
|
196
247
|
return {
|
|
197
248
|
...base,
|
|
198
|
-
status:
|
|
199
|
-
details:
|
|
200
|
-
|
|
201
|
-
: `Token for ${provider} is expired with no refresh token. Re-authorization required.`,
|
|
202
|
-
canAutoRecover: hasRefreshToken,
|
|
249
|
+
status: "expired",
|
|
250
|
+
details: `Token for ${provider} is expired with no refresh token. Re-authorization required.`,
|
|
251
|
+
canAutoRecover: false,
|
|
203
252
|
};
|
|
204
253
|
}
|
|
205
254
|
|
|
@@ -234,36 +283,51 @@ async function checkConnection(
|
|
|
234
283
|
}
|
|
235
284
|
|
|
236
285
|
// 4. Liveness ping
|
|
286
|
+
//
|
|
287
|
+
// For refreshable connections we route through withValidToken so an
|
|
288
|
+
// expired-but-refreshable token gets refreshed before the ping fires.
|
|
289
|
+
// Without this wrapping, the ping would hit 401 on a stale token and the
|
|
290
|
+
// connection would be misreported as "revoked" — even though the next real
|
|
291
|
+
// API call (which goes through BYOOAuthConnection.request → withValidToken)
|
|
292
|
+
// would have refreshed and succeeded.
|
|
237
293
|
if (pingUrl) {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
294
|
+
const runPing = (t: string) =>
|
|
295
|
+
pingProvider(t, pingUrl, pingMethod, pingHeaders, pingBody);
|
|
296
|
+
|
|
297
|
+
let pingResult: { ok: boolean; authError: boolean };
|
|
298
|
+
let authContext: PingFailureContext;
|
|
299
|
+
|
|
300
|
+
if (hasRefreshToken) {
|
|
301
|
+
try {
|
|
302
|
+
pingResult = await withValidToken(provider, runPing, { connectionId });
|
|
303
|
+
} catch (err) {
|
|
304
|
+
if (err instanceof TokenExpiredError) {
|
|
305
|
+
// Refresh itself failed (revoked refresh token, invalid_grant, etc.)
|
|
306
|
+
return {
|
|
307
|
+
...base,
|
|
308
|
+
status: "revoked",
|
|
309
|
+
details: `${provider} token refresh failed. The refresh token may have been revoked. Re-authorization required.`,
|
|
310
|
+
canAutoRecover: false,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
throw err;
|
|
253
314
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return {
|
|
261
|
-
...base,
|
|
262
|
-
status: "ping_failed",
|
|
263
|
-
details: `${provider} liveness check failed (non-auth error). This may be transient.`,
|
|
264
|
-
canAutoRecover: false,
|
|
265
|
-
};
|
|
315
|
+
authContext = "after_refresh";
|
|
316
|
+
} else {
|
|
317
|
+
// Manual-token provider or an OAuth provider whose initial flow
|
|
318
|
+
// didn't return a refresh_token — nothing to refresh, ping directly.
|
|
319
|
+
pingResult = await runPing(token);
|
|
320
|
+
authContext = "no_refresh";
|
|
266
321
|
}
|
|
322
|
+
|
|
323
|
+
const failure = pingResultToHealthFailure(
|
|
324
|
+
base,
|
|
325
|
+
provider,
|
|
326
|
+
connectionId,
|
|
327
|
+
pingResult,
|
|
328
|
+
authContext,
|
|
329
|
+
);
|
|
330
|
+
if (failure) return failure;
|
|
267
331
|
}
|
|
268
332
|
|
|
269
333
|
return {
|
|
@@ -434,10 +498,28 @@ async function checkManagedProvider(
|
|
|
434
498
|
canAutoRecover: true,
|
|
435
499
|
});
|
|
436
500
|
} else if (pingResp.status === 401 || pingResp.status === 403) {
|
|
501
|
+
// 401/403 from the upstream provider after the platform proxy
|
|
502
|
+
// forwarded the request. From the daemon side we can't tell
|
|
503
|
+
// whether the proxy attempted (and failed) a refresh-before-
|
|
504
|
+
// forward or skipped refresh entirely and forwarded a stale token.
|
|
505
|
+
// Either way it's not definitively unrecoverable — the next ping
|
|
506
|
+
// cycle may succeed if the platform re-refreshes. Demote to
|
|
507
|
+
// ping_failed so we don't fire a user-facing reconnect alert on
|
|
508
|
+
// what may be a transient platform-side miss. Only platform-
|
|
509
|
+
// attested 424 (CredentialRequiredError below) signals genuine
|
|
510
|
+
// unrecoverable failure.
|
|
511
|
+
log.debug(
|
|
512
|
+
{
|
|
513
|
+
provider: providerRow.provider,
|
|
514
|
+
connectionId: conn.id,
|
|
515
|
+
status: pingResp.status,
|
|
516
|
+
},
|
|
517
|
+
"Managed credential ping returned 401/403 — treating as potentially transient",
|
|
518
|
+
);
|
|
437
519
|
results.push({
|
|
438
520
|
...base,
|
|
439
|
-
status: "
|
|
440
|
-
details: `${providerRow.provider} managed
|
|
521
|
+
status: "ping_failed",
|
|
522
|
+
details: `${providerRow.provider} managed liveness check returned ${pingResp.status} from the upstream provider. The Vellum platform may not have refreshed the token before forwarding; will retry next cycle.`,
|
|
441
523
|
canAutoRecover: false,
|
|
442
524
|
});
|
|
443
525
|
} else {
|
|
@@ -450,8 +532,11 @@ async function checkManagedProvider(
|
|
|
450
532
|
}
|
|
451
533
|
} catch (err) {
|
|
452
534
|
const msg = err instanceof Error ? err.message : String(err);
|
|
453
|
-
// CredentialRequiredError
|
|
454
|
-
// the
|
|
535
|
+
// CredentialRequiredError corresponds to a 424 from the platform
|
|
536
|
+
// proxy — the platform attempted (and gave up on) refresh and is
|
|
537
|
+
// telling us the credential is genuinely unrecoverable. This is
|
|
538
|
+
// the only managed-path signal we trust enough to fire a user-
|
|
539
|
+
// facing reconnect alert.
|
|
455
540
|
if (
|
|
456
541
|
err &&
|
|
457
542
|
typeof err === "object" &&
|
|
@@ -461,7 +546,7 @@ async function checkManagedProvider(
|
|
|
461
546
|
results.push({
|
|
462
547
|
...base,
|
|
463
548
|
status: "revoked",
|
|
464
|
-
details: `${providerRow.provider} managed connection
|
|
549
|
+
details: `${providerRow.provider} managed connection cannot be refreshed by the Vellum platform. Reconnect on the Vellum platform.`,
|
|
465
550
|
canAutoRecover: false,
|
|
466
551
|
});
|
|
467
552
|
} else {
|
|
@@ -26,12 +26,9 @@
|
|
|
26
26
|
|
|
27
27
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
get: () => () => {},
|
|
33
|
-
}),
|
|
34
|
-
}));
|
|
29
|
+
import { createMockLoggerModule } from "../../__tests__/helpers/mock-logger.js";
|
|
30
|
+
|
|
31
|
+
mock.module("../../util/logger.js", () => createMockLoggerModule());
|
|
35
32
|
|
|
36
33
|
// ---------------------------------------------------------------------------
|
|
37
34
|
// Mock state — reset between tests.
|
|
@@ -44,10 +44,10 @@ mock.module("../../runtime/assistant-event.js", () => ({
|
|
|
44
44
|
...realEvent,
|
|
45
45
|
// Pass-through so `focus` / `conversationId` can be asserted directly
|
|
46
46
|
// on the captured event's `message` payload.
|
|
47
|
-
buildAssistantEvent: (
|
|
48
|
-
message
|
|
49
|
-
conversationId
|
|
50
|
-
|
|
47
|
+
buildAssistantEvent: (message: unknown, conversationId?: string) => ({
|
|
48
|
+
message,
|
|
49
|
+
conversationId,
|
|
50
|
+
}),
|
|
51
51
|
}));
|
|
52
52
|
|
|
53
53
|
// Stub DB helpers so the real `launchConversation` can run without a DB.
|
|
@@ -73,6 +73,7 @@ mock.module("../../memory/conversation-crud.js", () => ({
|
|
|
73
73
|
) => {
|
|
74
74
|
updateTitleCalls.push({ conversationId, title });
|
|
75
75
|
},
|
|
76
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
76
77
|
}));
|
|
77
78
|
|
|
78
79
|
// Stub conversation-store so the real `launchConversation` can hydrate
|
|
@@ -107,10 +108,7 @@ let processStartedPromise = new Promise<void>((resolve) => {
|
|
|
107
108
|
const realProcessMessage = await import("../process-message.js");
|
|
108
109
|
mock.module("../process-message.js", () => ({
|
|
109
110
|
...realProcessMessage,
|
|
110
|
-
processMessageInBackground: (
|
|
111
|
-
conversationId: string,
|
|
112
|
-
content: string,
|
|
113
|
-
) => {
|
|
111
|
+
processMessageInBackground: (conversationId: string, content: string) => {
|
|
114
112
|
processMessageCalls.push({ conversationId, content });
|
|
115
113
|
markProcessStarted();
|
|
116
114
|
return new Promise((resolve, reject) => {
|
|
@@ -177,8 +175,8 @@ function makeContext(
|
|
|
177
175
|
surfaceActionRequestIds: new Set<string>(),
|
|
178
176
|
currentTurnSurfaces: [],
|
|
179
177
|
isProcessing: () => false,
|
|
180
|
-
enqueueMessage: (
|
|
181
|
-
enqueueCalls.push({ content });
|
|
178
|
+
enqueueMessage: (options) => {
|
|
179
|
+
enqueueCalls.push({ content: options.content });
|
|
182
180
|
return { queued: false, requestId: "enq-req" };
|
|
183
181
|
},
|
|
184
182
|
getQueueDepth: () => 0,
|
|
@@ -256,7 +254,7 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
256
254
|
|
|
257
255
|
test("launches new conversation with inherited trust context and no chat message", async () => {
|
|
258
256
|
nextKeyStoreResult = { conversationId: "conv-launched-1" };
|
|
259
|
-
|
|
257
|
+
|
|
260
258
|
const originTrustContext: TrustContext = {
|
|
261
259
|
sourceChannel: "vellum",
|
|
262
260
|
trustClass: "guardian",
|
|
@@ -351,7 +349,7 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
351
349
|
|
|
352
350
|
test("omits originTrustContext when origin conversation has none", async () => {
|
|
353
351
|
nextKeyStoreResult = { conversationId: "conv-launched-3" };
|
|
354
|
-
|
|
352
|
+
|
|
355
353
|
// No `trustContext` on the origin context — simulating the
|
|
356
354
|
// no-inherited-guardian path.
|
|
357
355
|
const ctx = makeContext();
|
|
@@ -382,7 +380,7 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
382
380
|
|
|
383
381
|
test("handler returns before the seed turn resolves (fire-and-forget)", async () => {
|
|
384
382
|
nextKeyStoreResult = { conversationId: "conv-nonblocking" };
|
|
385
|
-
|
|
383
|
+
|
|
386
384
|
const ctx = makeContext();
|
|
387
385
|
registerCardSurface(ctx, "surface-4");
|
|
388
386
|
|
|
@@ -413,7 +411,7 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
413
411
|
|
|
414
412
|
test("seed turn rejection is swallowed by the helper's .catch()", async () => {
|
|
415
413
|
nextKeyStoreResult = { conversationId: "conv-seed-fails" };
|
|
416
|
-
|
|
414
|
+
|
|
417
415
|
const ctx = makeContext();
|
|
418
416
|
registerCardSurface(ctx, "surface-5");
|
|
419
417
|
|
|
@@ -449,7 +447,7 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
449
447
|
// message and triggering a full LLM round-trip on every click. The plan
|
|
450
448
|
// claimed to eliminate that round-trip; this test enforces it.
|
|
451
449
|
nextKeyStoreResult = { conversationId: "conv-pending-set" };
|
|
452
|
-
|
|
450
|
+
|
|
453
451
|
const ctx = makeContext();
|
|
454
452
|
registerCardSurface(ctx, "surface-pending");
|
|
455
453
|
// Simulate `ui_show` having stamped a pending entry for this surface
|
|
@@ -29,7 +29,6 @@ function mcpTool(name: string): Tool {
|
|
|
29
29
|
return {
|
|
30
30
|
name,
|
|
31
31
|
description: name,
|
|
32
|
-
origin: "mcp",
|
|
33
32
|
input_schema: def(name).input_schema,
|
|
34
33
|
} as unknown as Tool;
|
|
35
34
|
}
|
|
@@ -89,7 +88,7 @@ describe("createResolveToolsCallback — config.tools.exclude", () => {
|
|
|
89
88
|
});
|
|
90
89
|
|
|
91
90
|
test("excluded MCP tool is omitted from the resolved tool list", () => {
|
|
92
|
-
registerMcpTools([
|
|
91
|
+
registerMcpTools("test-server", [
|
|
93
92
|
mcpTool("mcp__server__navigate"),
|
|
94
93
|
mcpTool("mcp__server__click"),
|
|
95
94
|
]);
|
|
@@ -95,6 +95,7 @@ mock.module("../../security/secure-keys.js", () => ({
|
|
|
95
95
|
|
|
96
96
|
mock.module("../../memory/conversation-crud.js", () => ({
|
|
97
97
|
addMessage: async () => ({ id: "msg-123" }),
|
|
98
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
98
99
|
}));
|
|
99
100
|
|
|
100
101
|
mock.module("../../runtime/agent-wake.js", () => ({
|
|
@@ -108,6 +109,7 @@ mock.module("../../runtime/assistant-event-hub.js", () => ({
|
|
|
108
109
|
publish: publishSpy,
|
|
109
110
|
subscribe: subscribeSpy,
|
|
110
111
|
},
|
|
112
|
+
broadcastMessage: async () => {},
|
|
111
113
|
}));
|
|
112
114
|
|
|
113
115
|
mock.module("../../runtime/assistant-event.js", () => ({
|
|
@@ -163,14 +163,23 @@ describe("loadMeetManifestProxies", () => {
|
|
|
163
163
|
const capturedRoutes: SkillRoute[] = [];
|
|
164
164
|
const capturedHooks: string[] = [];
|
|
165
165
|
|
|
166
|
+
// Capture both the owner (first arg) and the provider (second arg) so
|
|
167
|
+
// we can assert the meet-join skill id flows through to the registry
|
|
168
|
+
// call. Ownership lives on the registry, not on the `Tool` object,
|
|
169
|
+
// so the only place to check it is on this argument.
|
|
170
|
+
const capturedOwners: Array<{ kind: string; id: string }> = [];
|
|
166
171
|
await loadMeetManifestProxies(supervisor, {
|
|
167
172
|
manifestPath,
|
|
168
|
-
registerTools: (p) =>
|
|
173
|
+
registerTools: (owner, p) => {
|
|
174
|
+
capturedOwners.push(owner);
|
|
175
|
+
capturedProviders.push(p);
|
|
176
|
+
},
|
|
169
177
|
registerRoute: (r) => capturedRoutes.push(r),
|
|
170
178
|
registerShutdown: (name) => capturedHooks.push(name),
|
|
171
179
|
});
|
|
172
180
|
|
|
173
181
|
expect(capturedProviders).toHaveLength(1);
|
|
182
|
+
expect(capturedOwners).toEqual([{ kind: "skill", id: "meet-join" }]);
|
|
174
183
|
const tools = capturedProviders[0]!();
|
|
175
184
|
expect(tools).toHaveLength(1);
|
|
176
185
|
const t = tools[0]!;
|
|
@@ -178,14 +187,10 @@ describe("loadMeetManifestProxies", () => {
|
|
|
178
187
|
expect(t.description).toBe("Fixture demo tool");
|
|
179
188
|
expect(t.category).toBe("meet");
|
|
180
189
|
expect(t.defaultRiskLevel).toBe(RiskLevel.Medium);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
expect(t.
|
|
185
|
-
expect(t.ownerSkillVersionHash).toBe(FIXTURE_MANIFEST.sourceHash);
|
|
186
|
-
expect(t.input_schema).toEqual(
|
|
187
|
-
FIXTURE_MANIFEST.tools[0]!.input_schema,
|
|
188
|
-
);
|
|
190
|
+
// Ownership now lives on the assistant-side registry's ownersByName map
|
|
191
|
+
// (recorded by registerSkillTools at the IPC boundary), not on the Tool
|
|
192
|
+
// object — the daemon-side projection doesn't carry the kind.
|
|
193
|
+
expect(t.input_schema).toEqual(FIXTURE_MANIFEST.tools[0]!.input_schema);
|
|
189
194
|
});
|
|
190
195
|
|
|
191
196
|
test("proxy tool execute dispatches through supervisor.dispatchTool and returns the result", async () => {
|
|
@@ -196,7 +201,11 @@ describe("loadMeetManifestProxies", () => {
|
|
|
196
201
|
|
|
197
202
|
await loadMeetManifestProxies(stub.supervisor, {
|
|
198
203
|
manifestPath,
|
|
199
|
-
|
|
204
|
+
// Mock signature mirrors `registerExternalTools(owner, provider)` —
|
|
205
|
+
// ownership is recorded by the registry-side argument, not by the
|
|
206
|
+
// `Tool` object. This test doesn't care which owner flows through;
|
|
207
|
+
// the round-trip dispatch behavior is what's under test.
|
|
208
|
+
registerTools: (_owner, p) => captured.push(p),
|
|
200
209
|
registerRoute: () => undefined,
|
|
201
210
|
registerShutdown: () => undefined,
|
|
202
211
|
});
|
|
@@ -238,7 +247,11 @@ describe("loadMeetManifestProxies", () => {
|
|
|
238
247
|
|
|
239
248
|
await loadMeetManifestProxies(stub.supervisor, {
|
|
240
249
|
manifestPath,
|
|
241
|
-
|
|
250
|
+
// Mock signature mirrors `registerExternalTools(owner, provider)` —
|
|
251
|
+
// ownership is recorded by the registry-side argument, not by the
|
|
252
|
+
// `Tool` object. This test doesn't care which owner flows through;
|
|
253
|
+
// the round-trip dispatch behavior is what's under test.
|
|
254
|
+
registerTools: (_owner, p) => captured.push(p),
|
|
242
255
|
registerRoute: () => undefined,
|
|
243
256
|
registerShutdown: () => undefined,
|
|
244
257
|
});
|
|
@@ -415,7 +428,7 @@ describe("loadMeetManifestProxies", () => {
|
|
|
415
428
|
await expect(
|
|
416
429
|
loadMeetManifestProxies(stub.supervisor, {
|
|
417
430
|
manifestPath,
|
|
418
|
-
registerTools: (p) => {
|
|
431
|
+
registerTools: (_owner, p) => {
|
|
419
432
|
providerInvoked = true;
|
|
420
433
|
p();
|
|
421
434
|
},
|
|
@@ -42,6 +42,7 @@ mock.module("../../memory/conversation-crud.js", () => ({
|
|
|
42
42
|
getMessageById: () => null,
|
|
43
43
|
updateMessageContent: () => {},
|
|
44
44
|
provenanceFromTrustContext: () => ({}),
|
|
45
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
45
46
|
}));
|
|
46
47
|
|
|
47
48
|
mock.module("../../memory/llm-request-log-store.js", () => ({
|