@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
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
getSkillRefCount,
|
|
10
10
|
getSkillToolNames,
|
|
11
11
|
getTool,
|
|
12
|
+
getToolOwner,
|
|
12
13
|
initializeTools,
|
|
13
14
|
registerSkillTools,
|
|
14
15
|
registerTool,
|
|
@@ -40,12 +41,11 @@ function makeFakeTool(name: string): Tool {
|
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
function makeSkillTool(name: string
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
44
|
+
function makeSkillTool(name: string): Tool {
|
|
45
|
+
// Ownership is recorded by the registry (via `registerSkillTools`), not by
|
|
46
|
+
// any field on the Tool itself. This helper is now a thin alias for
|
|
47
|
+
// makeFakeTool; the wrapper is kept so call sites stay readable.
|
|
48
|
+
return makeFakeTool(name);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
describe("tool registry host tools", () => {
|
|
@@ -195,11 +195,11 @@ describe("baseline characterization: core app tool surface", () => {
|
|
|
195
195
|
|
|
196
196
|
const tool = getTool("app_open");
|
|
197
197
|
expect(tool).toBeDefined();
|
|
198
|
-
expect(tool?.executionMode).toBe("proxy");
|
|
199
198
|
|
|
200
|
-
//
|
|
199
|
+
// app_open is core-owned (no skill owner) so it flows through
|
|
200
|
+
// `getAllToolDefinitions()` like any other core tool.
|
|
201
201
|
const definitionNames = getAllToolDefinitions().map((def) => def.name);
|
|
202
|
-
expect(definitionNames).
|
|
202
|
+
expect(definitionNames).toContain("app_open");
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
test("bundled app-builder skill has TOOLS.json manifest", async () => {
|
|
@@ -217,33 +217,27 @@ describe("baseline characterization: core app tool surface", () => {
|
|
|
217
217
|
});
|
|
218
218
|
});
|
|
219
219
|
|
|
220
|
-
describe("tool
|
|
220
|
+
describe("tool ownership metadata", () => {
|
|
221
221
|
beforeEach(() => {
|
|
222
222
|
__resetRegistryForTesting();
|
|
223
223
|
});
|
|
224
224
|
|
|
225
|
-
test("
|
|
226
|
-
|
|
227
|
-
...makeFakeTool("test-skill-origin-tool"),
|
|
228
|
-
origin: "skill",
|
|
229
|
-
ownerSkillId: "test-skill",
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
registerTool(skillTool);
|
|
225
|
+
test("registerTool does not record ownership (bare-install path)", () => {
|
|
226
|
+
registerTool(makeFakeTool("test-bare-tool"));
|
|
233
227
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
228
|
+
expect(getTool("test-bare-tool")).toBeDefined();
|
|
229
|
+
// `registerTool` is the bare-install path used by tests + core
|
|
230
|
+
// bootstraps; it does not record ownership. Tools that need an owner
|
|
231
|
+
// must go through `registerSkillTools(skillId, ...)` or its sibling
|
|
232
|
+
// entry points so the registry populates `ownersByName`.
|
|
233
|
+
expect(getToolOwner("test-bare-tool")).toBeUndefined();
|
|
238
234
|
});
|
|
239
235
|
|
|
240
|
-
test("core tools
|
|
236
|
+
test("core tools have no owner", async () => {
|
|
241
237
|
await initializeTools();
|
|
242
238
|
|
|
243
|
-
|
|
244
|
-
expect(
|
|
245
|
-
expect(coreTool?.origin).toBeUndefined();
|
|
246
|
-
expect(coreTool?.ownerSkillId).toBeUndefined();
|
|
239
|
+
expect(getTool("host_file_read")).toBeDefined();
|
|
240
|
+
expect(getToolOwner("host_file_read")).toBeUndefined();
|
|
247
241
|
});
|
|
248
242
|
});
|
|
249
243
|
|
|
@@ -252,66 +246,67 @@ describe("dynamic skill tool registry", () => {
|
|
|
252
246
|
__resetRegistryForTesting();
|
|
253
247
|
});
|
|
254
248
|
|
|
255
|
-
test("registers skill tools and retrieves them", () => {
|
|
256
|
-
|
|
257
|
-
makeSkillTool("sk_tool_a"
|
|
258
|
-
makeSkillTool("sk_tool_b"
|
|
259
|
-
];
|
|
260
|
-
registerSkillTools(tools);
|
|
249
|
+
test("registers skill tools and retrieves them with owner via getToolOwner", () => {
|
|
250
|
+
registerSkillTools("my-skill", [
|
|
251
|
+
makeSkillTool("sk_tool_a"),
|
|
252
|
+
makeSkillTool("sk_tool_b"),
|
|
253
|
+
]);
|
|
261
254
|
|
|
262
255
|
expect(getTool("sk_tool_a")).toBeDefined();
|
|
263
|
-
expect(
|
|
264
|
-
|
|
256
|
+
expect(getToolOwner("sk_tool_a")).toEqual({
|
|
257
|
+
kind: "skill",
|
|
258
|
+
id: "my-skill",
|
|
259
|
+
});
|
|
265
260
|
|
|
266
261
|
expect(getTool("sk_tool_b")).toBeDefined();
|
|
267
|
-
expect(
|
|
262
|
+
expect(getToolOwner("sk_tool_b")).toEqual({
|
|
263
|
+
kind: "skill",
|
|
264
|
+
id: "my-skill",
|
|
265
|
+
});
|
|
268
266
|
});
|
|
269
267
|
|
|
270
268
|
test("skips skill tool that collides with a core tool without throwing", async () => {
|
|
271
269
|
await initializeTools();
|
|
272
270
|
|
|
273
271
|
// host_file_read is a core tool registered during init
|
|
274
|
-
const
|
|
275
|
-
|
|
272
|
+
const accepted = registerSkillTools("rogue-skill", [
|
|
273
|
+
makeSkillTool("host_file_read"),
|
|
274
|
+
]);
|
|
276
275
|
|
|
277
276
|
// The colliding tool should be silently skipped
|
|
278
277
|
expect(accepted).toHaveLength(0);
|
|
279
278
|
// The core tool should still be in place (not overwritten)
|
|
280
|
-
|
|
281
|
-
expect(
|
|
279
|
+
expect(getTool("host_file_read")).toBeDefined();
|
|
280
|
+
expect(getToolOwner("host_file_read")).toBeUndefined();
|
|
282
281
|
});
|
|
283
282
|
|
|
284
283
|
test("allows replacement within the same owning skill", () => {
|
|
285
|
-
|
|
286
|
-
registerSkillTools([original]);
|
|
284
|
+
registerSkillTools("owner-skill", [makeSkillTool("sk_replaceable")]);
|
|
287
285
|
|
|
288
286
|
const replacement: Tool = {
|
|
289
|
-
...makeSkillTool("sk_replaceable"
|
|
287
|
+
...makeSkillTool("sk_replaceable"),
|
|
290
288
|
description: "Updated description",
|
|
291
289
|
};
|
|
292
290
|
// Should not throw
|
|
293
|
-
registerSkillTools([replacement]);
|
|
291
|
+
registerSkillTools("owner-skill", [replacement]);
|
|
294
292
|
|
|
295
293
|
const retrieved = getTool("sk_replaceable");
|
|
296
294
|
expect(retrieved?.description).toBe("Updated description");
|
|
297
295
|
});
|
|
298
296
|
|
|
299
297
|
test("rejects replacement from a different owning skill", () => {
|
|
300
|
-
|
|
301
|
-
registerSkillTools([original]);
|
|
298
|
+
registerSkillTools("skill-alpha", [makeSkillTool("sk_owned")]);
|
|
302
299
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
);
|
|
300
|
+
expect(() =>
|
|
301
|
+
registerSkillTools("skill-beta", [makeSkillTool("sk_owned")]),
|
|
302
|
+
).toThrow('already registered by skill "skill-alpha"');
|
|
307
303
|
});
|
|
308
304
|
|
|
309
305
|
test("unregisterSkillTools removes all tools for a skill", () => {
|
|
310
|
-
|
|
311
|
-
makeSkillTool("sk_rm_1"
|
|
312
|
-
makeSkillTool("sk_rm_2"
|
|
313
|
-
];
|
|
314
|
-
registerSkillTools(tools);
|
|
306
|
+
registerSkillTools("removable-skill", [
|
|
307
|
+
makeSkillTool("sk_rm_1"),
|
|
308
|
+
makeSkillTool("sk_rm_2"),
|
|
309
|
+
]);
|
|
315
310
|
expect(getTool("sk_rm_1")).toBeDefined();
|
|
316
311
|
expect(getTool("sk_rm_2")).toBeDefined();
|
|
317
312
|
|
|
@@ -319,24 +314,32 @@ describe("dynamic skill tool registry", () => {
|
|
|
319
314
|
|
|
320
315
|
expect(getTool("sk_rm_1")).toBeUndefined();
|
|
321
316
|
expect(getTool("sk_rm_2")).toBeUndefined();
|
|
317
|
+
// Ownership map is cleared in lockstep with the tools map.
|
|
318
|
+
expect(getToolOwner("sk_rm_1")).toBeUndefined();
|
|
319
|
+
expect(getToolOwner("sk_rm_2")).toBeUndefined();
|
|
322
320
|
});
|
|
323
321
|
|
|
324
322
|
test("unregisterSkillTools does not affect tools from other skills", () => {
|
|
325
|
-
registerSkillTools([makeSkillTool("sk_keep"
|
|
326
|
-
registerSkillTools([makeSkillTool("sk_remove"
|
|
323
|
+
registerSkillTools("keep-skill", [makeSkillTool("sk_keep")]);
|
|
324
|
+
registerSkillTools("nuke-skill", [makeSkillTool("sk_remove")]);
|
|
327
325
|
|
|
328
326
|
unregisterSkillTools("nuke-skill");
|
|
329
327
|
|
|
330
328
|
expect(getTool("sk_keep")).toBeDefined();
|
|
331
329
|
expect(getTool("sk_remove")).toBeUndefined();
|
|
330
|
+
expect(getToolOwner("sk_keep")).toEqual({
|
|
331
|
+
kind: "skill",
|
|
332
|
+
id: "keep-skill",
|
|
333
|
+
});
|
|
334
|
+
expect(getToolOwner("sk_remove")).toBeUndefined();
|
|
332
335
|
});
|
|
333
336
|
|
|
334
337
|
test("getSkillToolNames returns only skill tool names", async () => {
|
|
335
338
|
await initializeTools();
|
|
336
339
|
|
|
337
|
-
registerSkillTools([
|
|
338
|
-
makeSkillTool("sk_names_a"
|
|
339
|
-
makeSkillTool("sk_names_b"
|
|
340
|
+
registerSkillTools("names-skill", [
|
|
341
|
+
makeSkillTool("sk_names_a"),
|
|
342
|
+
makeSkillTool("sk_names_b"),
|
|
340
343
|
]);
|
|
341
344
|
|
|
342
345
|
const skillNames = getSkillToolNames();
|
|
@@ -350,19 +353,22 @@ describe("dynamic skill tool registry", () => {
|
|
|
350
353
|
test("registerSkillTools skips core-colliding tools but registers the rest", async () => {
|
|
351
354
|
await initializeTools();
|
|
352
355
|
|
|
353
|
-
const
|
|
354
|
-
makeSkillTool("sk_atomic_ok"
|
|
355
|
-
makeSkillTool("host_file_read"
|
|
356
|
-
];
|
|
357
|
-
|
|
358
|
-
const accepted = registerSkillTools(tools);
|
|
356
|
+
const accepted = registerSkillTools("atomic-skill", [
|
|
357
|
+
makeSkillTool("sk_atomic_ok"),
|
|
358
|
+
makeSkillTool("host_file_read"), // collides with core
|
|
359
|
+
]);
|
|
359
360
|
// Only the non-colliding tool should be accepted
|
|
360
361
|
expect(accepted).toHaveLength(1);
|
|
361
362
|
expect(accepted[0].name).toBe("sk_atomic_ok");
|
|
362
|
-
// The non-colliding tool should be registered
|
|
363
|
+
// The non-colliding tool should be registered with the correct owner
|
|
363
364
|
expect(getTool("sk_atomic_ok")).toBeDefined();
|
|
364
|
-
|
|
365
|
-
|
|
365
|
+
expect(getToolOwner("sk_atomic_ok")).toEqual({
|
|
366
|
+
kind: "skill",
|
|
367
|
+
id: "atomic-skill",
|
|
368
|
+
});
|
|
369
|
+
// The core tool should be untouched (no owner recorded)
|
|
370
|
+
expect(getTool("host_file_read")).toBeDefined();
|
|
371
|
+
expect(getToolOwner("host_file_read")).toBeUndefined();
|
|
366
372
|
});
|
|
367
373
|
});
|
|
368
374
|
|
|
@@ -372,17 +378,17 @@ describe("skill tool reference counting", () => {
|
|
|
372
378
|
});
|
|
373
379
|
|
|
374
380
|
test("ref count increments on each registerSkillTools call", () => {
|
|
375
|
-
registerSkillTools([makeSkillTool("rc_a"
|
|
381
|
+
registerSkillTools("rc-skill", [makeSkillTool("rc_a")]);
|
|
376
382
|
expect(getSkillRefCount("rc-skill")).toBe(1);
|
|
377
383
|
|
|
378
|
-
// Second session registers the same skill (same
|
|
379
|
-
registerSkillTools([makeSkillTool("rc_a"
|
|
384
|
+
// Second session registers the same skill (same owner id allows replacement)
|
|
385
|
+
registerSkillTools("rc-skill", [makeSkillTool("rc_a")]);
|
|
380
386
|
expect(getSkillRefCount("rc-skill")).toBe(2);
|
|
381
387
|
});
|
|
382
388
|
|
|
383
389
|
test("unregister decrements ref count but keeps tools when count > 0", () => {
|
|
384
|
-
registerSkillTools([makeSkillTool("rc_keep"
|
|
385
|
-
registerSkillTools([makeSkillTool("rc_keep"
|
|
390
|
+
registerSkillTools("rc-multi", [makeSkillTool("rc_keep")]);
|
|
391
|
+
registerSkillTools("rc-multi", [makeSkillTool("rc_keep")]);
|
|
386
392
|
expect(getSkillRefCount("rc-multi")).toBe(2);
|
|
387
393
|
|
|
388
394
|
unregisterSkillTools("rc-multi");
|
|
@@ -392,8 +398,8 @@ describe("skill tool reference counting", () => {
|
|
|
392
398
|
});
|
|
393
399
|
|
|
394
400
|
test("tools are removed only when last reference is unregistered", () => {
|
|
395
|
-
registerSkillTools([makeSkillTool("rc_last"
|
|
396
|
-
registerSkillTools([makeSkillTool("rc_last"
|
|
401
|
+
registerSkillTools("rc-final", [makeSkillTool("rc_last")]);
|
|
402
|
+
registerSkillTools("rc-final", [makeSkillTool("rc_last")]);
|
|
397
403
|
|
|
398
404
|
unregisterSkillTools("rc-final");
|
|
399
405
|
expect(getTool("rc_last")).toBeDefined();
|
|
@@ -225,7 +225,7 @@ import {
|
|
|
225
225
|
createVerificationSession,
|
|
226
226
|
} from "../memory/channel-verification-sessions.js";
|
|
227
227
|
import { addMessage, getMessages } from "../memory/conversation-crud.js";
|
|
228
|
-
import { getDb
|
|
228
|
+
import { getDb } from "../memory/db-connection.js";
|
|
229
229
|
import { initializeDb } from "../memory/db-init.js";
|
|
230
230
|
import { createInvite } from "../memory/invite-store.js";
|
|
231
231
|
import { resetTestTables } from "../memory/raw-query.js";
|
|
@@ -235,12 +235,13 @@ import {
|
|
|
235
235
|
getGuardianBinding,
|
|
236
236
|
} from "../runtime/channel-verification-service.js";
|
|
237
237
|
import { generateVoiceCode, hashVoiceCode } from "../util/voice-code.js";
|
|
238
|
+
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
238
239
|
import { createGuardianBinding } from "./helpers/create-guardian-binding.js";
|
|
239
240
|
|
|
240
241
|
initializeDb();
|
|
241
242
|
|
|
242
243
|
afterAll(() => {
|
|
243
|
-
|
|
244
|
+
resetDbForTesting();
|
|
244
245
|
});
|
|
245
246
|
|
|
246
247
|
// ── Mock WebSocket factory ──────────────────────────────────────────
|
|
@@ -423,16 +424,15 @@ describe("relay-server", () => {
|
|
|
423
424
|
includeDefaultFallback: false,
|
|
424
425
|
},
|
|
425
426
|
isProcessing: () => false,
|
|
426
|
-
persistUserMessage: async (
|
|
427
|
-
content: string
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
session.currentRequestId = requestId;
|
|
427
|
+
persistUserMessage: async (options: {
|
|
428
|
+
content: string;
|
|
429
|
+
requestId?: string;
|
|
430
|
+
}) => {
|
|
431
|
+
session.currentRequestId = options.requestId;
|
|
432
432
|
const message = await addMessage(
|
|
433
433
|
conversationId,
|
|
434
434
|
"user",
|
|
435
|
-
JSON.stringify([{ type: "text", text: content }]),
|
|
435
|
+
JSON.stringify([{ type: "text", text: options.content }]),
|
|
436
436
|
{
|
|
437
437
|
userMessageChannel: "phone",
|
|
438
438
|
assistantMessageChannel: "phone",
|
|
@@ -440,7 +440,7 @@ describe("relay-server", () => {
|
|
|
440
440
|
assistantMessageInterface: "phone",
|
|
441
441
|
},
|
|
442
442
|
);
|
|
443
|
-
return message.id;
|
|
443
|
+
return { id: message.id, deduplicated: false };
|
|
444
444
|
},
|
|
445
445
|
setChannelCapabilities: () => {},
|
|
446
446
|
setAssistantId: () => {},
|
|
@@ -51,17 +51,18 @@ import {
|
|
|
51
51
|
} from "../memory/attachments-store.js";
|
|
52
52
|
import * as conversationStore from "../memory/conversation-crud.js";
|
|
53
53
|
import { getOrCreateConversation } from "../memory/conversation-key-store.js";
|
|
54
|
-
import { getDb
|
|
54
|
+
import { getDb } from "../memory/db-connection.js";
|
|
55
55
|
import { initializeDb } from "../memory/db-init.js";
|
|
56
56
|
import * as deliveryChannels from "../memory/delivery-channels.js";
|
|
57
57
|
import { resetTestTables } from "../memory/raw-query.js";
|
|
58
58
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
59
59
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
60
|
+
import { resetDbForTesting } from "./db-test-helpers.js";
|
|
60
61
|
|
|
61
62
|
initializeDb();
|
|
62
63
|
|
|
63
64
|
afterAll(() => {
|
|
64
|
-
|
|
65
|
+
resetDbForTesting();
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
const TEST_TOKEN = "test-bearer-token-attach";
|
|
@@ -9,6 +9,17 @@ mock.module("../util/logger.js", () => ({
|
|
|
9
9
|
truncateForLog: (value: string) => value,
|
|
10
10
|
}));
|
|
11
11
|
|
|
12
|
+
// Stub the background-wake publisher so these store-level unit tests stay
|
|
13
|
+
// hermetic. `notifySchedulesChanged()` fires a debounced background-wake
|
|
14
|
+
// refresh on every mutation; left real, that 250ms timer performs a
|
|
15
|
+
// synchronous DB read plus a platform-client lookup which compete with the
|
|
16
|
+
// serialized async event delivery and can push a `sync_changed` past the
|
|
17
|
+
// wait deadline on loaded runners. Background-wake behavior is covered by the
|
|
18
|
+
// background-wake tests.
|
|
19
|
+
mock.module("../background-wake/publisher.js", () => ({
|
|
20
|
+
refreshBackgroundWakeIntent: () => {},
|
|
21
|
+
}));
|
|
22
|
+
|
|
12
23
|
import { SYNC_TAGS } from "../daemon/message-types/sync.js";
|
|
13
24
|
import { getDb } from "../memory/db-connection.js";
|
|
14
25
|
import { initializeDb } from "../memory/db-init.js";
|
|
@@ -38,7 +49,11 @@ function getRawDb(): import("bun:sqlite").Database {
|
|
|
38
49
|
}
|
|
39
50
|
|
|
40
51
|
async function waitFor(predicate: () => boolean): Promise<void> {
|
|
41
|
-
|
|
52
|
+
// Event delivery is async (serialized through the hub's broadcast chain),
|
|
53
|
+
// so poll until it lands. The deadline is generous to absorb scheduling
|
|
54
|
+
// jitter on loaded CI runners — the happy path returns the moment the
|
|
55
|
+
// predicate holds, so a larger budget costs nothing when events flow.
|
|
56
|
+
const deadline = Date.now() + 2000;
|
|
42
57
|
while (Date.now() < deadline) {
|
|
43
58
|
if (predicate()) return;
|
|
44
59
|
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
@@ -210,12 +210,57 @@ describe("scheduler conversation reuse", () => {
|
|
|
210
210
|
expect(runs2[0].conversationId).toBe(firstConversationId);
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
+
test("recurring schedule defaults to reuseConversation=true", async () => {
|
|
214
|
+
/**
|
|
215
|
+
* When no explicit reuseConversation is provided, recurring schedules
|
|
216
|
+
* default to true — subsequent runs reuse the same conversation.
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
// GIVEN a recurring schedule with no explicit reuseConversation
|
|
220
|
+
const rruleExpr = buildEveryMinuteRrule();
|
|
221
|
+
const schedule = createSchedule({
|
|
222
|
+
name: "Default Reuse Test",
|
|
223
|
+
cronExpression: rruleExpr,
|
|
224
|
+
message: "Default reuse message",
|
|
225
|
+
syntax: "rrule",
|
|
226
|
+
expression: rruleExpr,
|
|
227
|
+
// no explicit reuseConversation — should default to true for recurring
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// WHEN the schedule fires for the first time
|
|
231
|
+
forceScheduleDue(schedule.id);
|
|
232
|
+
|
|
233
|
+
const processMessage = async (conversationId: string, message: string) => {
|
|
234
|
+
processedMessages.push({ conversationId, message });
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const scheduler1 = startScheduler(processMessage, () => {});
|
|
238
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
239
|
+
scheduler1.stop();
|
|
240
|
+
|
|
241
|
+
expect(processedMessages).toHaveLength(1);
|
|
242
|
+
const firstConversationId = processedMessages[0].conversationId;
|
|
243
|
+
expect(firstConversationId).toBeTruthy();
|
|
244
|
+
|
|
245
|
+
// WHEN the schedule fires for the second time
|
|
246
|
+
forceScheduleDue(schedule.id);
|
|
247
|
+
processedMessages.length = 0;
|
|
248
|
+
|
|
249
|
+
const scheduler2 = startScheduler(processMessage, () => {});
|
|
250
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
251
|
+
scheduler2.stop();
|
|
252
|
+
|
|
253
|
+
// THEN the same conversation is reused
|
|
254
|
+
expect(processedMessages).toHaveLength(1);
|
|
255
|
+
expect(processedMessages[0].conversationId).toBe(firstConversationId);
|
|
256
|
+
});
|
|
257
|
+
|
|
213
258
|
test("recurring schedule with reuseConversation=false creates new conversation each run", async () => {
|
|
214
259
|
/**
|
|
215
|
-
*
|
|
260
|
+
* When explicitly opted out, each run creates a brand-new conversation.
|
|
216
261
|
*/
|
|
217
262
|
|
|
218
|
-
// GIVEN a recurring schedule with reuseConversation disabled
|
|
263
|
+
// GIVEN a recurring schedule with reuseConversation explicitly disabled
|
|
219
264
|
const rruleExpr = buildEveryMinuteRrule();
|
|
220
265
|
const schedule = createSchedule({
|
|
221
266
|
name: "No Reuse Test",
|
|
@@ -223,7 +268,7 @@ describe("scheduler conversation reuse", () => {
|
|
|
223
268
|
message: "New conv each run",
|
|
224
269
|
syntax: "rrule",
|
|
225
270
|
expression: rruleExpr,
|
|
226
|
-
//
|
|
271
|
+
reuseConversation: false, // explicitly opt out of conversation reuse
|
|
227
272
|
});
|
|
228
273
|
|
|
229
274
|
// WHEN the schedule fires for the first time
|
|
@@ -106,6 +106,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
106
106
|
provenanceFromTrustContext: () => undefined,
|
|
107
107
|
setConversationOriginChannelIfUnset: () => {},
|
|
108
108
|
setConversationOriginInterfaceIfUnset: () => {},
|
|
109
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
109
110
|
}));
|
|
110
111
|
|
|
111
112
|
mock.module("../runtime/local-actor-identity.js", () => ({
|
|
@@ -187,7 +188,10 @@ function makeRequest(
|
|
|
187
188
|
});
|
|
188
189
|
}
|
|
189
190
|
|
|
190
|
-
const persistUserMessageMock = mock(async () =>
|
|
191
|
+
const persistUserMessageMock = mock(async () => ({
|
|
192
|
+
id: "persisted-id",
|
|
193
|
+
deduplicated: false,
|
|
194
|
+
}));
|
|
191
195
|
const runAgentLoopMock = mock(async () => undefined);
|
|
192
196
|
|
|
193
197
|
function makeSendMessageDeps() {
|
|
@@ -25,7 +25,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
25
25
|
|
|
26
26
|
import type { CesClient } from "../credential-execution/client.js";
|
|
27
27
|
import * as encryptedStore from "../security/encrypted-store.js";
|
|
28
|
-
import { _setStorePath } from "../security/encrypted-store.js";
|
|
29
28
|
import {
|
|
30
29
|
_resetBackend,
|
|
31
30
|
deleteSecureKeyAsync,
|
|
@@ -36,6 +35,7 @@ import {
|
|
|
36
35
|
setCesReconnect,
|
|
37
36
|
setSecureKeyAsync,
|
|
38
37
|
} from "../security/secure-keys.js";
|
|
38
|
+
import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
|
|
39
39
|
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
// Use a temp directory for encrypted store tests
|
|
@@ -59,11 +59,11 @@ describe("secure-keys", () => {
|
|
|
59
59
|
rmSync(TEST_DIR, { recursive: true });
|
|
60
60
|
}
|
|
61
61
|
mkdirSync(TEST_DIR, { recursive: true });
|
|
62
|
-
|
|
62
|
+
setStorePathForTesting(STORE_PATH);
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
afterEach(() => {
|
|
66
|
-
|
|
66
|
+
setStorePathForTesting(null);
|
|
67
67
|
_resetBackend();
|
|
68
68
|
delete process.env.VELLUM_DEV;
|
|
69
69
|
delete process.env.VELLUM_DESKTOP_APP;
|