@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
|
@@ -229,26 +229,11 @@ function createFakeConversation(conversationId: string): Conversation {
|
|
|
229
229
|
},
|
|
230
230
|
persistUserMessage(
|
|
231
231
|
this: Conversation,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
id: string;
|
|
235
|
-
filename: string;
|
|
236
|
-
mimeType: string;
|
|
237
|
-
data: string;
|
|
238
|
-
extractedText?: string;
|
|
239
|
-
filePath?: string;
|
|
240
|
-
}>,
|
|
241
|
-
requestId?: string,
|
|
242
|
-
metadata?: Record<string, unknown>,
|
|
243
|
-
displayContent?: string,
|
|
244
|
-
): Promise<string> {
|
|
232
|
+
options: Parameters<typeof persistUserMessage>[1],
|
|
233
|
+
): Promise<{ id: string; deduplicated: boolean }> {
|
|
245
234
|
return persistUserMessage(
|
|
246
235
|
this as Parameters<typeof persistUserMessage>[0],
|
|
247
|
-
|
|
248
|
-
attachments,
|
|
249
|
-
requestId,
|
|
250
|
-
metadata,
|
|
251
|
-
displayContent,
|
|
236
|
+
options,
|
|
252
237
|
);
|
|
253
238
|
},
|
|
254
239
|
async runAgentLoop(
|
|
@@ -83,6 +83,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
83
83
|
content: string,
|
|
84
84
|
metadata?: Record<string, unknown>,
|
|
85
85
|
) => addMessageMock(conversationId, role, content, metadata),
|
|
86
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
86
87
|
}));
|
|
87
88
|
|
|
88
89
|
mock.module("../runtime/local-actor-identity.js", () => ({
|
|
@@ -149,7 +150,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
149
150
|
replyText: "Access approved. Verification code: 123456.",
|
|
150
151
|
});
|
|
151
152
|
|
|
152
|
-
const persistUserMessage = mock(async () =>
|
|
153
|
+
const persistUserMessage = mock(async () => ({
|
|
154
|
+
id: "should-not-be-called",
|
|
155
|
+
deduplicated: false,
|
|
156
|
+
}));
|
|
153
157
|
const runAgentLoop = mock(async () => undefined);
|
|
154
158
|
const session = {
|
|
155
159
|
setTrustContext: () => {},
|
|
@@ -233,7 +237,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
233
237
|
type: "not_consumed",
|
|
234
238
|
});
|
|
235
239
|
|
|
236
|
-
const persistUserMessage = mock(async () =>
|
|
240
|
+
const persistUserMessage = mock(async () => ({
|
|
241
|
+
id: "persisted-user-id",
|
|
242
|
+
deduplicated: false,
|
|
243
|
+
}));
|
|
237
244
|
const runAgentLoop = mock(async () => undefined);
|
|
238
245
|
const session = {
|
|
239
246
|
setTrustContext: () => {},
|
|
@@ -312,7 +319,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
312
319
|
type: "not_consumed",
|
|
313
320
|
});
|
|
314
321
|
|
|
315
|
-
const persistUserMessage = mock(async () =>
|
|
322
|
+
const persistUserMessage = mock(async () => ({
|
|
323
|
+
id: "persisted-user-id",
|
|
324
|
+
deduplicated: false,
|
|
325
|
+
}));
|
|
316
326
|
const runAgentLoop = mock(async () => undefined);
|
|
317
327
|
const session = {
|
|
318
328
|
setTrustContext: () => {},
|
|
@@ -397,7 +407,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
397
407
|
requestId: "tool-req-code-1",
|
|
398
408
|
});
|
|
399
409
|
|
|
400
|
-
const persistUserMessage = mock(async () =>
|
|
410
|
+
const persistUserMessage = mock(async () => ({
|
|
411
|
+
id: "should-not-be-called",
|
|
412
|
+
deduplicated: false,
|
|
413
|
+
}));
|
|
401
414
|
const runAgentLoop = mock(async () => undefined);
|
|
402
415
|
const session = {
|
|
403
416
|
setTrustContext: () => {},
|
|
@@ -477,7 +490,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
477
490
|
requestId: "pending-reject-1",
|
|
478
491
|
});
|
|
479
492
|
|
|
480
|
-
const persistUserMessage = mock(async () =>
|
|
493
|
+
const persistUserMessage = mock(async () => ({
|
|
494
|
+
id: "should-not-be-called",
|
|
495
|
+
deduplicated: false,
|
|
496
|
+
}));
|
|
481
497
|
const runAgentLoop = mock(async () => undefined);
|
|
482
498
|
const session = {
|
|
483
499
|
setTrustContext: () => {},
|
|
@@ -551,7 +567,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
551
567
|
type: "not_consumed",
|
|
552
568
|
});
|
|
553
569
|
|
|
554
|
-
const persistUserMessage = mock(async () =>
|
|
570
|
+
const persistUserMessage = mock(async () => ({
|
|
571
|
+
id: "persisted-user-id",
|
|
572
|
+
deduplicated: false,
|
|
573
|
+
}));
|
|
555
574
|
const runAgentLoop = mock(async () => undefined);
|
|
556
575
|
const session = {
|
|
557
576
|
setTrustContext: () => {},
|
|
@@ -627,7 +646,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
627
646
|
});
|
|
628
647
|
|
|
629
648
|
const mockGenerator = mock(async () => ({}));
|
|
630
|
-
const persistUserMessage = mock(async () =>
|
|
649
|
+
const persistUserMessage = mock(async () => ({
|
|
650
|
+
id: "persisted-user-id",
|
|
651
|
+
deduplicated: false,
|
|
652
|
+
}));
|
|
631
653
|
const runAgentLoop = mock(async () => undefined);
|
|
632
654
|
const session = {
|
|
633
655
|
setTrustContext: () => {},
|
|
@@ -704,7 +726,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
704
726
|
});
|
|
705
727
|
|
|
706
728
|
const mockGenerator = mock(async () => ({}));
|
|
707
|
-
const persistUserMessage = mock(async () =>
|
|
729
|
+
const persistUserMessage = mock(async () => ({
|
|
730
|
+
id: "persisted-user-id",
|
|
731
|
+
deduplicated: false,
|
|
732
|
+
}));
|
|
708
733
|
const runAgentLoop = mock(async () => undefined);
|
|
709
734
|
const session = {
|
|
710
735
|
setTrustContext: () => {},
|
|
@@ -82,6 +82,7 @@ const addMessageMock = mock(
|
|
|
82
82
|
_metadata?: Record<string, unknown>,
|
|
83
83
|
) => ({
|
|
84
84
|
id: role === "user" ? "persisted-user-id" : "persisted-assistant-id",
|
|
85
|
+
deduplicated: false,
|
|
85
86
|
}),
|
|
86
87
|
);
|
|
87
88
|
|
|
@@ -131,6 +132,8 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
131
132
|
content: string,
|
|
132
133
|
metadata?: Record<string, unknown>,
|
|
133
134
|
) => addMessageMock(conversationId, role, content, metadata),
|
|
135
|
+
extractImageSourcePaths: () => undefined,
|
|
136
|
+
getConversation: () => null,
|
|
134
137
|
getConversationOverrideProfile: () => "short-context",
|
|
135
138
|
getMessages: () => [],
|
|
136
139
|
provenanceFromTrustContext: (ctx: unknown) =>
|
|
@@ -139,6 +142,21 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
139
142
|
: { provenanceTrustClass: "unknown" },
|
|
140
143
|
setConversationOriginChannelIfUnset: () => {},
|
|
141
144
|
setConversationOriginInterfaceIfUnset: () => {},
|
|
145
|
+
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
mock.module("../memory/conversation-disk-view.js", () => ({
|
|
149
|
+
syncMessageToDisk: () => {},
|
|
150
|
+
updateMetaFile: () => {},
|
|
151
|
+
}));
|
|
152
|
+
|
|
153
|
+
mock.module("../memory/attachments-store.js", () => ({
|
|
154
|
+
getAttachmentsByIds: () => [],
|
|
155
|
+
getSourcePathsForAttachments: () => new Map(),
|
|
156
|
+
attachmentExists: () => false,
|
|
157
|
+
linkAttachmentToMessage: () => {},
|
|
158
|
+
attachInlineAttachmentToMessage: () => {},
|
|
159
|
+
validateAttachmentUpload: () => ({ ok: true }),
|
|
142
160
|
}));
|
|
143
161
|
|
|
144
162
|
mock.module("../daemon/conversation-process.js", () => ({
|
|
@@ -208,8 +226,13 @@ const _testAuthContext: AuthContext = {
|
|
|
208
226
|
|
|
209
227
|
function makeConversation() {
|
|
210
228
|
const persistUserMessage = mock(
|
|
211
|
-
async (
|
|
212
|
-
|
|
229
|
+
async (_options: {
|
|
230
|
+
content: string;
|
|
231
|
+
attachments?: unknown[];
|
|
232
|
+
requestId?: string;
|
|
233
|
+
metadata?: Record<string, unknown>;
|
|
234
|
+
clientMessageId?: string;
|
|
235
|
+
}) => ({ id: "persisted-user-id", deduplicated: false }),
|
|
213
236
|
);
|
|
214
237
|
const runAgentLoop = mock(
|
|
215
238
|
async (
|
|
@@ -238,12 +261,20 @@ function makeConversation() {
|
|
|
238
261
|
const events: unknown[] = [];
|
|
239
262
|
const messages: unknown[] = [];
|
|
240
263
|
const conversation = {
|
|
264
|
+
conversationId: "conv-slash-test",
|
|
265
|
+
messages,
|
|
266
|
+
processing: false,
|
|
267
|
+
abortController: null,
|
|
268
|
+
currentRequestId: undefined,
|
|
269
|
+
queue: { length: 0 },
|
|
241
270
|
setTrustContext: () => {},
|
|
242
271
|
updateClient: (_fn: unknown, _b: boolean) => {},
|
|
243
272
|
emitConfirmationStateChanged: () => {},
|
|
244
273
|
emitActivityState: () => {},
|
|
245
274
|
setTurnChannelContext: () => {},
|
|
246
275
|
setTurnInterfaceContext: () => {},
|
|
276
|
+
getTurnChannelContext: () => null,
|
|
277
|
+
getTurnInterfaceContext: () => null,
|
|
247
278
|
ensureActorScopedHistory: async () => {},
|
|
248
279
|
isProcessing: () => false,
|
|
249
280
|
hasAnyPendingConfirmation: () => false,
|
|
@@ -1102,6 +1102,84 @@ describe("stripInjectionsForCompaction preserves persistent blocks", () => {
|
|
|
1102
1102
|
});
|
|
1103
1103
|
});
|
|
1104
1104
|
|
|
1105
|
+
// ---------------------------------------------------------------------------
|
|
1106
|
+
// stripInjectionsForCompaction — memory/info wrapper shape
|
|
1107
|
+
// ---------------------------------------------------------------------------
|
|
1108
|
+
|
|
1109
|
+
describe("stripInjectionsForCompaction memory/info wrapper matching", () => {
|
|
1110
|
+
test("injected <info>…</info> static-memory block IS stripped", () => {
|
|
1111
|
+
const messages: Message[] = [
|
|
1112
|
+
{
|
|
1113
|
+
role: "user",
|
|
1114
|
+
content: [
|
|
1115
|
+
{ type: "text", text: "<info>\nessentials and threads\n</info>" },
|
|
1116
|
+
{ type: "text", text: "Hello" },
|
|
1117
|
+
],
|
|
1118
|
+
},
|
|
1119
|
+
];
|
|
1120
|
+
|
|
1121
|
+
const result = stripInjectionsForCompaction(messages);
|
|
1122
|
+
expect(result.length).toBe(1);
|
|
1123
|
+
expect(result[0].content.length).toBe(1);
|
|
1124
|
+
expect((result[0].content[0] as { type: "text"; text: string }).text).toBe(
|
|
1125
|
+
"Hello",
|
|
1126
|
+
);
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
test("injected <memory>…</memory> activation block IS stripped", () => {
|
|
1130
|
+
const messages: Message[] = [
|
|
1131
|
+
{
|
|
1132
|
+
role: "user",
|
|
1133
|
+
content: [
|
|
1134
|
+
{ type: "text", text: "<memory>\nactivated slugs\n</memory>" },
|
|
1135
|
+
{ type: "text", text: "Hello" },
|
|
1136
|
+
],
|
|
1137
|
+
},
|
|
1138
|
+
];
|
|
1139
|
+
|
|
1140
|
+
const result = stripInjectionsForCompaction(messages);
|
|
1141
|
+
expect(result.length).toBe(1);
|
|
1142
|
+
expect(result[0].content.length).toBe(1);
|
|
1143
|
+
expect((result[0].content[0] as { type: "text"; text: string }).text).toBe(
|
|
1144
|
+
"Hello",
|
|
1145
|
+
);
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
test("user text merely starting with <info>\\n (no closing tag) is NOT stripped", () => {
|
|
1149
|
+
const userText = "<info>\nHere is what I want to discuss about the markup";
|
|
1150
|
+
const messages: Message[] = [
|
|
1151
|
+
{
|
|
1152
|
+
role: "user",
|
|
1153
|
+
content: [{ type: "text", text: userText }],
|
|
1154
|
+
},
|
|
1155
|
+
];
|
|
1156
|
+
|
|
1157
|
+
const result = stripInjectionsForCompaction(messages);
|
|
1158
|
+
expect(result.length).toBe(1);
|
|
1159
|
+
expect(result[0].content.length).toBe(1);
|
|
1160
|
+
expect((result[0].content[0] as { type: "text"; text: string }).text).toBe(
|
|
1161
|
+
userText,
|
|
1162
|
+
);
|
|
1163
|
+
});
|
|
1164
|
+
|
|
1165
|
+
test("user text merely starting with <memory>\\n (no closing tag) is NOT stripped", () => {
|
|
1166
|
+
const userText = "<memory>\nplease remember to buy milk";
|
|
1167
|
+
const messages: Message[] = [
|
|
1168
|
+
{
|
|
1169
|
+
role: "user",
|
|
1170
|
+
content: [{ type: "text", text: userText }],
|
|
1171
|
+
},
|
|
1172
|
+
];
|
|
1173
|
+
|
|
1174
|
+
const result = stripInjectionsForCompaction(messages);
|
|
1175
|
+
expect(result.length).toBe(1);
|
|
1176
|
+
expect(result[0].content.length).toBe(1);
|
|
1177
|
+
expect((result[0].content[0] as { type: "text"; text: string }).text).toBe(
|
|
1178
|
+
userText,
|
|
1179
|
+
);
|
|
1180
|
+
});
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1105
1183
|
// ---------------------------------------------------------------------------
|
|
1106
1184
|
// applyRuntimeInjections with nowScratchpad
|
|
1107
1185
|
// ---------------------------------------------------------------------------
|
|
@@ -92,12 +92,13 @@ mock.module("../skills/tool-manifest.js", () => ({
|
|
|
92
92
|
}));
|
|
93
93
|
|
|
94
94
|
mock.module("../tools/skills/skill-tool-factory.js", () => ({
|
|
95
|
+
// Mirrors the real factory: no skillId in/out — ownership is recorded by
|
|
96
|
+
// the registry at `registerSkillTools(skillId, tools)` time.
|
|
95
97
|
createSkillToolsFromManifest: (
|
|
96
98
|
entries: SkillToolManifest["tools"],
|
|
97
|
-
skillId: string,
|
|
98
99
|
_skillDir: string,
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
_versionHash: string,
|
|
101
|
+
_bundled?: boolean,
|
|
101
102
|
): Tool[] => {
|
|
102
103
|
return entries.map((entry) => ({
|
|
103
104
|
name: entry.name,
|
|
@@ -105,10 +106,6 @@ mock.module("../tools/skills/skill-tool-factory.js", () => ({
|
|
|
105
106
|
category: entry.category,
|
|
106
107
|
defaultRiskLevel: RiskLevel.Medium,
|
|
107
108
|
executionTarget: "sandbox" as const,
|
|
108
|
-
origin: "skill" as const,
|
|
109
|
-
ownerSkillId: skillId,
|
|
110
|
-
ownerSkillVersionHash: versionHash,
|
|
111
|
-
ownerSkillBundled: bundled ?? undefined,
|
|
112
109
|
input_schema: entry.input_schema as object,
|
|
113
110
|
execute: async () => ({ content: "", isError: false }),
|
|
114
111
|
}));
|
|
@@ -116,18 +113,14 @@ mock.module("../tools/skills/skill-tool-factory.js", () => ({
|
|
|
116
113
|
}));
|
|
117
114
|
|
|
118
115
|
mock.module("../tools/registry.js", () => ({
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
for (const id of skillIds) {
|
|
129
|
-
mockSkillRefCount.set(id, (mockSkillRefCount.get(id) ?? 0) + 1);
|
|
130
|
-
}
|
|
116
|
+
// Matches the new signature: `registerSkillTools(skillId, tools)`. The
|
|
117
|
+
// skillId comes from the caller (conversation-skill-tools) and is the
|
|
118
|
+
// sole source of truth for ownership.
|
|
119
|
+
registerSkillTools: (skillId: string, tools: Tool[]) => {
|
|
120
|
+
const existing = mockRegisteredTools.get(skillId) ?? [];
|
|
121
|
+
existing.push(...tools);
|
|
122
|
+
mockRegisteredTools.set(skillId, existing);
|
|
123
|
+
mockSkillRefCount.set(skillId, (mockSkillRefCount.get(skillId) ?? 0) + 1);
|
|
131
124
|
return tools;
|
|
132
125
|
},
|
|
133
126
|
unregisterSkillTools: (skillId: string) => {
|
|
@@ -151,6 +144,22 @@ mock.module("../tools/registry.js", () => ({
|
|
|
151
144
|
}
|
|
152
145
|
return found;
|
|
153
146
|
},
|
|
147
|
+
// Mirrors the registry's `ownersByName` accessor: the mock derives the
|
|
148
|
+
// owning skillId from `mockRegisteredTools` (which is keyed by skillId)
|
|
149
|
+
// and reports it back as the `OwnerInfo` shape production callers expect.
|
|
150
|
+
getToolOwner: (
|
|
151
|
+
name: string,
|
|
152
|
+
): { kind: "skill" | "plugin" | "mcp"; id: string } | undefined => {
|
|
153
|
+
let ownerSkillId: string | undefined;
|
|
154
|
+
for (const [skillId, tools] of mockRegisteredTools.entries()) {
|
|
155
|
+
for (const tool of tools) {
|
|
156
|
+
if (tool.name === name) ownerSkillId = skillId;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return ownerSkillId === undefined
|
|
160
|
+
? undefined
|
|
161
|
+
: { kind: "skill", id: ownerSkillId };
|
|
162
|
+
},
|
|
154
163
|
getSkillToolNames: () => {
|
|
155
164
|
const names: string[] = [];
|
|
156
165
|
for (const tools of mockRegisteredTools.values()) {
|
|
@@ -1730,11 +1739,11 @@ describe("bundled skill: app-builder", () => {
|
|
|
1730
1739
|
expect(tools).toBeDefined();
|
|
1731
1740
|
expect(tools!.length).toBe(4);
|
|
1732
1741
|
|
|
1733
|
-
//
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1742
|
+
// Ownership is asserted by the fact that
|
|
1743
|
+
// `mockRegisteredTools.get("app-builder")` returned the tools — i.e. the
|
|
1744
|
+
// mock `registerSkillTools(skillId, tools)` was called with skillId
|
|
1745
|
+
// "app-builder", which is what the registry would record in production.
|
|
1746
|
+
// The Tool object itself no longer carries a kind/origin field.
|
|
1738
1747
|
});
|
|
1739
1748
|
});
|
|
1740
1749
|
|
|
@@ -2229,7 +2238,7 @@ describe("hash change re-prompt regressions (PR 35)", () => {
|
|
|
2229
2238
|
expect(sessionState.get("oncall")).toBe("v2:oncall-edited");
|
|
2230
2239
|
});
|
|
2231
2240
|
|
|
2232
|
-
test("registered tools carry updated
|
|
2241
|
+
test("registered tools carry updated owner after hash change re-registration", () => {
|
|
2233
2242
|
mockCatalog = [makeSkill("deploy")];
|
|
2234
2243
|
mockManifests = { deploy: makeManifest(["deploy_run"]) };
|
|
2235
2244
|
mockVersionHashes = { deploy: "v1:pre-edit" };
|
|
@@ -2238,12 +2247,14 @@ describe("hash change re-prompt regressions (PR 35)", () => {
|
|
|
2238
2247
|
...skillLoadMessages('<loaded_skill id="deploy" />'),
|
|
2239
2248
|
];
|
|
2240
2249
|
|
|
2241
|
-
// Turn 1
|
|
2250
|
+
// Turn 1: ownership is asserted by the mock registry's keying — the
|
|
2251
|
+
// tools landing under skillId "deploy" in `mockRegisteredTools` means
|
|
2252
|
+
// `registerSkillTools("deploy", tools)` was called, which is the only
|
|
2253
|
+
// path that records ownership in the real registry.
|
|
2242
2254
|
projectSkillTools(history, { previouslyActiveSkillIds: sessionState });
|
|
2243
2255
|
const toolsV1 = mockRegisteredTools.get("deploy");
|
|
2244
2256
|
expect(toolsV1).toBeDefined();
|
|
2245
2257
|
expect(toolsV1!.length).toBe(1);
|
|
2246
|
-
expect(toolsV1![0].ownerSkillId).toBe("deploy");
|
|
2247
2258
|
|
|
2248
2259
|
// Edit
|
|
2249
2260
|
mockVersionHashes = { deploy: "v2:post-edit" };
|
|
@@ -2253,121 +2264,6 @@ describe("hash change re-prompt regressions (PR 35)", () => {
|
|
|
2253
2264
|
const toolsV2 = mockRegisteredTools.get("deploy");
|
|
2254
2265
|
expect(toolsV2).toBeDefined();
|
|
2255
2266
|
expect(toolsV2!.length).toBeGreaterThanOrEqual(1);
|
|
2256
|
-
expect(toolsV2![0].ownerSkillId).toBe("deploy");
|
|
2257
|
-
});
|
|
2258
|
-
});
|
|
2259
|
-
|
|
2260
|
-
// ---------------------------------------------------------------------------
|
|
2261
|
-
// Version hash plumbing regression tests
|
|
2262
|
-
// Verify that createSkillToolsFromManifest receives the computed hash and
|
|
2263
|
-
// that projected tools carry ownerSkillVersionHash, which downstream
|
|
2264
|
-
// components (executor.ts) use to build policy context.
|
|
2265
|
-
// ---------------------------------------------------------------------------
|
|
2266
|
-
|
|
2267
|
-
describe("version hash plumbing to projected tools", () => {
|
|
2268
|
-
let sessionState: Map<string, string>;
|
|
2269
|
-
|
|
2270
|
-
beforeEach(() => {
|
|
2271
|
-
mockCatalog = [];
|
|
2272
|
-
mockManifests = {};
|
|
2273
|
-
mockRegisteredTools = new Map();
|
|
2274
|
-
mockUnregisteredSkillIds = [];
|
|
2275
|
-
mockSkillRefCount = new Map();
|
|
2276
|
-
mockVersionHashes = {};
|
|
2277
|
-
mockVersionHashErrors = new Set();
|
|
2278
|
-
sessionState = new Map<string, string>();
|
|
2279
|
-
});
|
|
2280
|
-
|
|
2281
|
-
test("projected tools carry ownerSkillVersionHash matching the computed hash", () => {
|
|
2282
|
-
mockCatalog = [makeSkill("deploy")];
|
|
2283
|
-
mockManifests = { deploy: makeManifest(["deploy_run", "deploy_status"]) };
|
|
2284
|
-
mockVersionHashes = { deploy: "v1:secure-hash-abc" };
|
|
2285
|
-
|
|
2286
|
-
const history: Message[] = [
|
|
2287
|
-
...skillLoadMessages('<loaded_skill id="deploy" />'),
|
|
2288
|
-
];
|
|
2289
|
-
|
|
2290
|
-
projectSkillTools(history, { previouslyActiveSkillIds: sessionState });
|
|
2291
|
-
|
|
2292
|
-
const tools = mockRegisteredTools.get("deploy");
|
|
2293
|
-
expect(tools).toBeDefined();
|
|
2294
|
-
expect(tools!.length).toBe(2);
|
|
2295
|
-
|
|
2296
|
-
// Every tool created for this skill must carry the version hash
|
|
2297
|
-
for (const tool of tools!) {
|
|
2298
|
-
expect(tool.ownerSkillVersionHash).toBe("v1:secure-hash-abc");
|
|
2299
|
-
}
|
|
2300
|
-
});
|
|
2301
|
-
|
|
2302
|
-
test("after hash change re-registration, new tools carry the updated hash", () => {
|
|
2303
|
-
mockCatalog = [makeSkill("deploy")];
|
|
2304
|
-
mockManifests = { deploy: makeManifest(["deploy_run"]) };
|
|
2305
|
-
mockVersionHashes = { deploy: "v1:hash-before" };
|
|
2306
|
-
|
|
2307
|
-
const history: Message[] = [
|
|
2308
|
-
...skillLoadMessages('<loaded_skill id="deploy" />'),
|
|
2309
|
-
];
|
|
2310
|
-
|
|
2311
|
-
// Turn 1: register with original hash
|
|
2312
|
-
projectSkillTools(history, { previouslyActiveSkillIds: sessionState });
|
|
2313
|
-
const toolsV1 = mockRegisteredTools.get("deploy");
|
|
2314
|
-
expect(toolsV1).toBeDefined();
|
|
2315
|
-
expect(toolsV1![0].ownerSkillVersionHash).toBe("v1:hash-before");
|
|
2316
|
-
|
|
2317
|
-
// Simulate file edit — hash changes
|
|
2318
|
-
mockVersionHashes = { deploy: "v2:hash-after" };
|
|
2319
|
-
|
|
2320
|
-
// Turn 2: re-registration with new hash
|
|
2321
|
-
projectSkillTools(history, { previouslyActiveSkillIds: sessionState });
|
|
2322
|
-
const toolsV2 = mockRegisteredTools.get("deploy");
|
|
2323
|
-
expect(toolsV2).toBeDefined();
|
|
2324
|
-
|
|
2325
|
-
// The most recently registered tool should carry the new hash
|
|
2326
|
-
const lastTool = toolsV2![toolsV2!.length - 1];
|
|
2327
|
-
expect(lastTool.ownerSkillVersionHash).toBe("v2:hash-after");
|
|
2328
|
-
});
|
|
2329
|
-
|
|
2330
|
-
test("tools for multiple co-active skills each carry their own version hash", () => {
|
|
2331
|
-
mockCatalog = [makeSkill("deploy"), makeSkill("oncall")];
|
|
2332
|
-
mockManifests = {
|
|
2333
|
-
deploy: makeManifest(["deploy_run"]),
|
|
2334
|
-
oncall: makeManifest(["oncall_page"]),
|
|
2335
|
-
};
|
|
2336
|
-
mockVersionHashes = {
|
|
2337
|
-
deploy: "v1:deploy-hash-123",
|
|
2338
|
-
oncall: "v1:oncall-hash-456",
|
|
2339
|
-
};
|
|
2340
|
-
|
|
2341
|
-
const history: Message[] = [
|
|
2342
|
-
...skillLoadMessages('<loaded_skill id="deploy" />'),
|
|
2343
|
-
...skillLoadMessages('<loaded_skill id="oncall" />'),
|
|
2344
|
-
];
|
|
2345
|
-
|
|
2346
|
-
projectSkillTools(history, { previouslyActiveSkillIds: sessionState });
|
|
2347
|
-
|
|
2348
|
-
const deployTools = mockRegisteredTools.get("deploy");
|
|
2349
|
-
expect(deployTools).toBeDefined();
|
|
2350
|
-
expect(deployTools![0].ownerSkillVersionHash).toBe("v1:deploy-hash-123");
|
|
2351
|
-
|
|
2352
|
-
const oncallTools = mockRegisteredTools.get("oncall");
|
|
2353
|
-
expect(oncallTools).toBeDefined();
|
|
2354
|
-
expect(oncallTools![0].ownerSkillVersionHash).toBe("v1:oncall-hash-456");
|
|
2355
|
-
});
|
|
2356
|
-
|
|
2357
|
-
test("default hash is used and plumbed when no explicit hash override is set", () => {
|
|
2358
|
-
mockCatalog = [makeSkill("deploy")];
|
|
2359
|
-
mockManifests = { deploy: makeManifest(["deploy_run"]) };
|
|
2360
|
-
// No mockVersionHashes override — mock returns 'v1:default-hash-deploy'
|
|
2361
|
-
|
|
2362
|
-
const history: Message[] = [
|
|
2363
|
-
...skillLoadMessages('<loaded_skill id="deploy" />'),
|
|
2364
|
-
];
|
|
2365
|
-
|
|
2366
|
-
projectSkillTools(history, { previouslyActiveSkillIds: sessionState });
|
|
2367
|
-
|
|
2368
|
-
const tools = mockRegisteredTools.get("deploy");
|
|
2369
|
-
expect(tools).toBeDefined();
|
|
2370
|
-
expect(tools![0].ownerSkillVersionHash).toBe("v1:default-hash-deploy");
|
|
2371
2267
|
});
|
|
2372
2268
|
});
|
|
2373
2269
|
|