@vellumai/assistant 0.8.4 → 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 +3 -3
- package/bunfig.toml +6 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/knip.json +2 -1
- 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 +2748 -216
- 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__/anthropic-provider.test.ts +34 -37
- 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-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
- package/src/__tests__/audit-log-rotation.test.ts +72 -18
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +5 -5
- package/src/__tests__/call-controller.test.ts +3 -3
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +6 -5
- 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 +18 -27
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
- package/src/__tests__/computer-use-tools.test.ts +14 -18
- 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__/confirmation-request-guardian-bridge.test.ts +0 -1
- 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 +2 -1
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
- package/src/__tests__/conversation-agent-loop.test.ts +581 -54
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
- 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-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +61 -0
- package/src/__tests__/conversation-fork-crud.test.ts +239 -15
- 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 +53 -11
- 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-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
- 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 +6 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +40 -147
- 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-store.test.ts +1 -1
- 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 +218 -35
- 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 +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
- 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 +19 -19
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +6 -5
- package/src/__tests__/credential-vault-unit.test.ts +21 -21
- 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-page-surface.test.ts +2 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- 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 +236 -0
- package/src/__tests__/gemini-provider.test.ts +104 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +10 -7
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
- package/src/__tests__/heartbeat-service.test.ts +5 -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 +6 -5
- 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__/init-feature-flag-overrides.test.ts +5 -6
- 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__/list-messages-tool-merge.test.ts +70 -11
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +408 -9
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +16 -2
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- 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 +4 -6
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- 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 +4 -3
- package/src/__tests__/openai-provider.test.ts +54 -9
- package/src/__tests__/openai-responses-provider.test.ts +176 -14
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -2
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +11 -13
- package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- 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__/prune-jobs-changes-parser.test.ts +61 -0
- 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 +84 -84
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- 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__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +16 -18
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
- package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
- package/src/__tests__/skill-tool-factory.test.ts +97 -96
- 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 +6 -5
- 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 +2 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +183 -131
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
- package/src/__tests__/tool-executor.test.ts +64 -72
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
- 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-git-service.test.ts +6 -5
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- 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/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +6 -7
- package/src/agent/loop.ts +88 -0
- package/src/api/README.md +127 -0
- 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/api/events/relationship-state-updated.ts +25 -0
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +129 -0
- package/src/api/package.json +10 -0
- 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 +868 -0
- 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 +24 -0
- 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__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +176 -1
- package/src/cli/commands/memory-v3-render.ts +491 -0
- package/src/cli/commands/memory-v3.ts +567 -0
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +4 -0
- package/src/config/assistant-feature-flags.ts +39 -46
- package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
- package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- 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/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +8 -7
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +33 -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 +228 -1
- package/src/config/schemas/call-site-catalog.ts +21 -7
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +102 -2
- package/src/config/schemas/memory-v2.ts +272 -0
- package/src/config/schemas/memory.ts +2 -1
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/compactor.ts +52 -0
- package/src/context/token-estimator.ts +10 -5
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- 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 +2 -3
- 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 +390 -80
- package/src/daemon/conversation-agent-loop.ts +244 -90
- package/src/daemon/conversation-error.ts +64 -6
- package/src/daemon/conversation-lifecycle.ts +27 -22
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +38 -17
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +77 -32
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +40 -75
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +39 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +11 -3
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +4 -4
- package/src/daemon/host-file-proxy.ts +4 -4
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +10 -10
- package/src/daemon/lifecycle.ts +29 -26
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +11 -24
- package/src/daemon/message-types/conversations.ts +22 -27
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -14
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +25 -48
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/message-types/sync.ts +14 -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/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +62 -0
- package/src/daemon/tool-setup-types.ts +7 -0
- 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 +30 -1
- 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/home-greeting.ts +0 -9
- package/src/home/suggested-prompts.ts +27 -154
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/gateway-flag-listener.ts +123 -0
- 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 +35 -40
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- 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 +8 -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/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +423 -182
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +14 -0
- package/src/memory/db-maintenance.ts +30 -21
- 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/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- 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/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +66 -22
- package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
- package/src/memory/llm-request-log-source-local.ts +31 -0
- package/src/memory/llm-request-log-source.ts +40 -2
- package/src/memory/llm-request-log-store.ts +228 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-enqueue.ts +8 -1
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/memory-v2-activation-log-store.ts +110 -7
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- 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 +19 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/schema/conversations.ts +10 -2
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/schema/infrastructure.ts +21 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
- package/src/memory/v2/__tests__/injection.test.ts +127 -98
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +171 -3
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +128 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +240 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +112 -0
- package/src/memory/v2/harness/trace.ts +64 -0
- package/src/memory/v2/injection.ts +21 -15
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +171 -18
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +706 -0
- package/src/memory/v3/__tests__/filter.test.ts +560 -0
- package/src/memory/v3/__tests__/gate.test.ts +637 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
- package/src/memory/v3/__tests__/loop.test.ts +775 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +489 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +508 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
- package/src/memory/v3/__tests__/validate.test.ts +277 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +286 -0
- package/src/memory/v3/filter.ts +286 -0
- package/src/memory/v3/gate.ts +349 -0
- package/src/memory/v3/index-composition.ts +126 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +430 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +431 -0
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +347 -0
- package/src/memory/v3/traversal.ts +211 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +356 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +323 -0
- 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/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- 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/decision-engine.ts +1 -4
- 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 +40 -50
- 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/permissions/prompter.ts +3 -3
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +2 -2
- 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/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +20 -19
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +68 -29
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +39 -7
- package/src/prompts/system-prompt.ts +84 -221
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +9 -13
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/prompts/templates/system-sections.ts +230 -8
- package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +32 -66
- package/src/providers/call-site-routing.ts +42 -6
- package/src/providers/connection-model-compat.ts +61 -0
- package/src/providers/connection-resolution.ts +47 -14
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +70 -6
- 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/adapter-factory.ts +3 -0
- 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/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +78 -1
- package/src/providers/model-intents.ts +4 -4
- 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 +116 -15
- package/src/providers/openai/codex-models.ts +20 -0
- package/src/providers/openai/responses-provider.ts +87 -30
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +20 -5
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +50 -7
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/types.ts +9 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- 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/agent-wake.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +46 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- 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/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +12 -4
- package/src/runtime/pending-interactions.ts +0 -1
- 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 +204 -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 +76 -9
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -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/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +356 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +4 -10
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +159 -4
- package/src/runtime/routes/conversation-management-routes.ts +108 -26
- package/src/runtime/routes/conversation-query-routes.ts +200 -44
- package/src/runtime/routes/conversation-routes.ts +409 -521
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +35 -8
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/host-browser-routes.ts +10 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- 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/acl-enforcement.ts +96 -3
- 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 +10 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- 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-call-sites-routes.ts +32 -5
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +215 -5
- package/src/runtime/routes/memory-v3-routes.ts +474 -0
- package/src/runtime/routes/migration-routes.ts +32 -28
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +5 -4
- 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/routes/workspace-routes.ts +25 -10
- 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 +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/runtime/verification-outbound-actions.ts +73 -1
- 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/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +36 -28
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
- package/src/tools/browser/browser-execution.ts +16 -3
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
- package/src/tools/browser/cdp-client/factory.ts +100 -17
- package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
- package/src/tools/browser/cdp-client/types.ts +65 -0
- package/src/tools/browser/pinned-tabs.ts +96 -40
- package/src/tools/computer-use/definitions.ts +282 -336
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-tool.ts +189 -7
- package/src/tools/execution-target.ts +18 -23
- package/src/tools/executor.ts +24 -56
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -10
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- 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-fetch.ts +3 -9
- package/src/tools/network/web-search.ts +224 -76
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +150 -123
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +18 -44
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +32 -101
- package/src/tools/ui-surface/definitions.ts +104 -108
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/browser.ts +7 -2
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -2
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- 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 +6 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/daemon/query-complexity-router.ts +0 -75
- package/src/prompts/cache-boundary.ts +0 -8
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { connect, type Socket } from "node:net";
|
|
2
|
+
|
|
3
|
+
import { refreshOverridesFromGateway } from "../config/assistant-feature-flags.js";
|
|
4
|
+
import { SYNC_TAGS } from "../daemon/message-types/sync.js";
|
|
5
|
+
import { publishSyncInvalidation } from "../runtime/sync/sync-publisher.js";
|
|
6
|
+
import { getLogger } from "../util/logger.js";
|
|
7
|
+
import { resolveIpcSocketPath } from "./socket-path.js";
|
|
8
|
+
|
|
9
|
+
const log = getLogger("gateway-flag-listener");
|
|
10
|
+
|
|
11
|
+
const MAX_BACKOFF_MS = 30_000;
|
|
12
|
+
const INITIAL_BACKOFF_MS = 1_000;
|
|
13
|
+
|
|
14
|
+
let socket: Socket | null = null;
|
|
15
|
+
let stopped = false;
|
|
16
|
+
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
|
17
|
+
let currentBackoffMs = INITIAL_BACKOFF_MS;
|
|
18
|
+
|
|
19
|
+
function getSocketPath(): string {
|
|
20
|
+
return resolveIpcSocketPath("gateway").path;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function handleData(chunk: Buffer): void {
|
|
24
|
+
const lines = chunk.toString().split("\n");
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
const trimmed = line.trim();
|
|
27
|
+
if (!trimmed) continue;
|
|
28
|
+
try {
|
|
29
|
+
const msg = JSON.parse(trimmed) as { event?: string };
|
|
30
|
+
if (msg.event === "feature_flags_changed") {
|
|
31
|
+
log.info("Received feature_flags_changed event — refreshing overrides");
|
|
32
|
+
refreshOverridesFromGateway().catch((err) => {
|
|
33
|
+
log.warn({ err }, "Failed to refresh feature flag overrides");
|
|
34
|
+
});
|
|
35
|
+
// Fan out to every connected web client so React Query caches
|
|
36
|
+
// for `/v1/feature-flags/client-flag-values/` and
|
|
37
|
+
// `/v1/assistants/:id/feature-flags` invalidate immediately
|
|
38
|
+
// instead of waiting on a 5s polling tick.
|
|
39
|
+
publishSyncInvalidation([
|
|
40
|
+
SYNC_TAGS.featureFlagsClient,
|
|
41
|
+
SYNC_TAGS.featureFlagsAssistant,
|
|
42
|
+
]).catch((err) => {
|
|
43
|
+
log.warn({ err }, "Failed to broadcast feature-flags sync_changed");
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
// Ignore non-JSON lines (e.g. IPC responses on a shared socket)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function scheduleReconnect(): void {
|
|
53
|
+
if (stopped) return;
|
|
54
|
+
reconnectTimer = setTimeout(() => {
|
|
55
|
+
reconnectTimer = null;
|
|
56
|
+
connectToGateway();
|
|
57
|
+
}, currentBackoffMs);
|
|
58
|
+
currentBackoffMs = Math.min(currentBackoffMs * 2, MAX_BACKOFF_MS);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function connectToGateway(): void {
|
|
62
|
+
if (stopped) return;
|
|
63
|
+
|
|
64
|
+
const socketPath = getSocketPath();
|
|
65
|
+
const conn = connect(socketPath);
|
|
66
|
+
|
|
67
|
+
conn.on("connect", () => {
|
|
68
|
+
if (stopped) {
|
|
69
|
+
conn.destroy();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
log.info("Connected to gateway IPC for flag events");
|
|
73
|
+
currentBackoffMs = INITIAL_BACKOFF_MS;
|
|
74
|
+
socket = conn;
|
|
75
|
+
refreshOverridesFromGateway().catch((err) => {
|
|
76
|
+
log.warn({ err }, "Failed to refresh feature flag overrides on reconnect");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
let buffer = "";
|
|
81
|
+
conn.on("data", (chunk) => {
|
|
82
|
+
buffer += chunk.toString();
|
|
83
|
+
let newlineIdx: number;
|
|
84
|
+
while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
|
|
85
|
+
const line = buffer.slice(0, newlineIdx);
|
|
86
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
87
|
+
if (line.trim()) {
|
|
88
|
+
handleData(Buffer.from(line));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
conn.on("close", () => {
|
|
94
|
+
socket = null;
|
|
95
|
+
if (!stopped) {
|
|
96
|
+
log.debug("Gateway IPC connection closed — reconnecting");
|
|
97
|
+
scheduleReconnect();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
conn.on("error", (err) => {
|
|
102
|
+
log.debug({ err }, "Gateway IPC connection error");
|
|
103
|
+
conn.destroy();
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function startGatewayFlagListener(): void {
|
|
108
|
+
stopped = false;
|
|
109
|
+
currentBackoffMs = INITIAL_BACKOFF_MS;
|
|
110
|
+
connectToGateway();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function stopGatewayFlagListener(): void {
|
|
114
|
+
stopped = true;
|
|
115
|
+
if (reconnectTimer) {
|
|
116
|
+
clearTimeout(reconnectTimer);
|
|
117
|
+
reconnectTimer = null;
|
|
118
|
+
}
|
|
119
|
+
if (socket) {
|
|
120
|
+
socket.destroy();
|
|
121
|
+
socket = null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
__clearExternalToolProvidersForTesting,
|
|
20
20
|
__clearRegistryForTesting,
|
|
21
21
|
getTool,
|
|
22
|
+
getToolOwner,
|
|
22
23
|
} from "../../../tools/registry.js";
|
|
23
24
|
import {
|
|
24
25
|
__getActiveSessionCountForTesting,
|
|
@@ -55,7 +56,12 @@ afterEach(() => {
|
|
|
55
56
|
|
|
56
57
|
describe("host.registries.register_tools", () => {
|
|
57
58
|
test("installs proxy tools into the daemon's external tool registry", async () => {
|
|
59
|
+
// `skillId` lives at the top of the params object (one frame = one
|
|
60
|
+
// skill's batch). The per-tool manifest schema no longer carries an
|
|
61
|
+
// `owner` field — ownership flows in through this top-level key and
|
|
62
|
+
// is recorded in the registry's `ownersByName` map.
|
|
58
63
|
const result = (await registerToolsRoute.handler({
|
|
64
|
+
skillId: "demo-skill",
|
|
59
65
|
tools: [
|
|
60
66
|
{
|
|
61
67
|
name: "skill_demo_tool",
|
|
@@ -64,7 +70,6 @@ describe("host.registries.register_tools", () => {
|
|
|
64
70
|
defaultRiskLevel: "low",
|
|
65
71
|
category: "skill",
|
|
66
72
|
executionTarget: "sandbox",
|
|
67
|
-
ownerSkillId: "demo-skill",
|
|
68
73
|
},
|
|
69
74
|
],
|
|
70
75
|
})) as { registered: string[] };
|
|
@@ -72,13 +77,17 @@ describe("host.registries.register_tools", () => {
|
|
|
72
77
|
expect(result.registered).toEqual(["skill_demo_tool"]);
|
|
73
78
|
const installed = getTool("skill_demo_tool");
|
|
74
79
|
expect(installed).toBeDefined();
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
expect(
|
|
80
|
+
// Ownership lives on the registry — getToolOwner is the single source of
|
|
81
|
+
// truth. The Tool object itself no longer carries the kind.
|
|
82
|
+
expect(getToolOwner("skill_demo_tool")).toEqual({
|
|
83
|
+
kind: "skill",
|
|
84
|
+
id: "demo-skill",
|
|
85
|
+
});
|
|
78
86
|
});
|
|
79
87
|
|
|
80
88
|
test("proxy execute throws when no supervisor is attached", async () => {
|
|
81
89
|
await registerToolsRoute.handler({
|
|
90
|
+
skillId: "stub-skill",
|
|
82
91
|
tools: [
|
|
83
92
|
{
|
|
84
93
|
name: "skill_stub_tool",
|
|
@@ -86,7 +95,6 @@ describe("host.registries.register_tools", () => {
|
|
|
86
95
|
input_schema: { type: "object" },
|
|
87
96
|
defaultRiskLevel: "medium",
|
|
88
97
|
category: "skill",
|
|
89
|
-
ownerSkillId: "stub-skill",
|
|
90
98
|
},
|
|
91
99
|
],
|
|
92
100
|
});
|
|
@@ -106,16 +114,37 @@ describe("host.registries.register_tools", () => {
|
|
|
106
114
|
});
|
|
107
115
|
|
|
108
116
|
test("rejects empty tool list", async () => {
|
|
109
|
-
await expect(
|
|
117
|
+
await expect(
|
|
118
|
+
registerToolsRoute.handler({ skillId: "any-skill", tools: [] }),
|
|
119
|
+
).rejects.toThrow();
|
|
110
120
|
});
|
|
111
121
|
|
|
112
122
|
test("rejects missing required fields", async () => {
|
|
113
123
|
await expect(
|
|
114
124
|
registerToolsRoute.handler({
|
|
125
|
+
skillId: "any-skill",
|
|
115
126
|
tools: [{ name: "missing_rest" }],
|
|
116
127
|
}),
|
|
117
128
|
).rejects.toThrow();
|
|
118
129
|
});
|
|
130
|
+
|
|
131
|
+
test("rejects missing skillId", async () => {
|
|
132
|
+
// skillId is the only place ownership flows in over IPC — without it
|
|
133
|
+
// the registry can't claim the tools, so the handler must reject.
|
|
134
|
+
await expect(
|
|
135
|
+
registerToolsRoute.handler({
|
|
136
|
+
tools: [
|
|
137
|
+
{
|
|
138
|
+
name: "skill_orphan_tool",
|
|
139
|
+
description: "no owner",
|
|
140
|
+
input_schema: { type: "object" },
|
|
141
|
+
defaultRiskLevel: "low",
|
|
142
|
+
category: "skill",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
}),
|
|
146
|
+
).rejects.toThrow();
|
|
147
|
+
});
|
|
119
148
|
});
|
|
120
149
|
|
|
121
150
|
// ---------------------------------------------------------------------------
|
|
@@ -302,6 +331,7 @@ describe("lazy-external short-circuit", () => {
|
|
|
302
331
|
|
|
303
332
|
const result = (await registerToolsRoute.handler(
|
|
304
333
|
{
|
|
334
|
+
skillId: "demo-skill",
|
|
305
335
|
tools: [
|
|
306
336
|
{
|
|
307
337
|
name: "skill_demo_tool",
|
|
@@ -309,7 +339,6 @@ describe("lazy-external short-circuit", () => {
|
|
|
309
339
|
input_schema: {},
|
|
310
340
|
defaultRiskLevel: "low",
|
|
311
341
|
category: "skill",
|
|
312
|
-
ownerSkillId: "demo-skill",
|
|
313
342
|
},
|
|
314
343
|
],
|
|
315
344
|
},
|
|
@@ -17,13 +17,14 @@ import type { SkillIpcRoute } from "../skill-ipc-types.js";
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Shape mirrors the daemon's `addMessage()` positional signature:
|
|
20
|
-
* `(conversationId, role, content, metadata?, opts?)`.
|
|
21
|
-
*
|
|
20
|
+
* `(conversationId, role, content, metadata?, opts?)`. `role` is
|
|
21
|
+
* constrained to the `MessageRole` union. Metadata is a free-form
|
|
22
|
+
* record (validated downstream by `messageMetadataSchema` with a
|
|
22
23
|
* warn-and-store fallback). Only `skipIndexing` is recognised in `opts`.
|
|
23
24
|
*/
|
|
24
25
|
const MemoryAddMessageParams = z.object({
|
|
25
26
|
conversationId: z.string().min(1),
|
|
26
|
-
role: z.
|
|
27
|
+
role: z.enum(["user", "assistant", "system"]),
|
|
27
28
|
content: z.string(),
|
|
28
29
|
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
29
30
|
opts: z
|
|
@@ -22,12 +22,9 @@ import { z } from "zod";
|
|
|
22
22
|
import type { MeetHostSupervisor } from "../../daemon/meet-host-supervisor.js";
|
|
23
23
|
import { registerShutdownHook } from "../../daemon/shutdown-registry.js";
|
|
24
24
|
import { registerSkillRoute } from "../../runtime/skill-route-registry.js";
|
|
25
|
+
import { resolveExecutionTarget } from "../../tools/execution-target.js";
|
|
25
26
|
import { registerSkillTools } from "../../tools/registry.js";
|
|
26
|
-
import type {
|
|
27
|
-
ExecutionTarget,
|
|
28
|
-
Tool,
|
|
29
|
-
ToolDefinition,
|
|
30
|
-
} from "../../tools/types.js";
|
|
27
|
+
import type { ExecutionTarget, Tool } from "../../tools/types.js";
|
|
31
28
|
import { RiskLevel } from "../../tools/types.js";
|
|
32
29
|
import { getLogger } from "../../util/logger.js";
|
|
33
30
|
import type { SkillIpcRoute } from "../skill-ipc-types.js";
|
|
@@ -51,18 +48,19 @@ const ToolManifestSchema = z.object({
|
|
|
51
48
|
defaultRiskLevel: z.enum(["low", "medium", "high"]),
|
|
52
49
|
category: z.string().min(1),
|
|
53
50
|
executionTarget: z.enum(["sandbox", "host"]).optional(),
|
|
54
|
-
executionMode: z.enum(["local", "proxy"]).optional(),
|
|
55
|
-
// Required so disconnect can decrement the tool-registry refcount: a
|
|
56
|
-
// tool registered without an owner has no ref-counted entry to drop and
|
|
57
|
-
// would leak into the global registry on socket close.
|
|
58
|
-
ownerSkillId: z.string().min(1),
|
|
59
|
-
ownerSkillBundled: z.boolean().optional(),
|
|
60
|
-
ownerSkillVersionHash: z.string().optional(),
|
|
61
51
|
});
|
|
62
52
|
|
|
63
53
|
export type ToolManifest = z.infer<typeof ToolManifestSchema>;
|
|
64
54
|
|
|
55
|
+
// `skillId` lives at the params level rather than per-tool: a single
|
|
56
|
+
// `register_tools` IPC frame is always one skill's batch, ownership flows
|
|
57
|
+
// through `registerSkillTools(skillId, tools)` into the registry's
|
|
58
|
+
// `ownersByName` map, and the tools themselves stay free of owner
|
|
59
|
+
// metadata so callers cannot spoof ownership by forging a field on the
|
|
60
|
+
// manifest. Only skill-owned tools cross IPC — plugin and MCP tools live
|
|
61
|
+
// in-process on the assistant side.
|
|
65
62
|
const RegisterToolsParams = z.object({
|
|
63
|
+
skillId: z.string().min(1),
|
|
66
64
|
tools: z.array(ToolManifestSchema).min(1),
|
|
67
65
|
});
|
|
68
66
|
|
|
@@ -182,25 +180,18 @@ export function __getActiveSessionCountForTesting(): number {
|
|
|
182
180
|
* exercised end-to-end.
|
|
183
181
|
*/
|
|
184
182
|
function buildProxyTool(manifest: ToolManifest): Tool {
|
|
185
|
-
const definition: ToolDefinition = {
|
|
186
|
-
name: manifest.name,
|
|
187
|
-
description: manifest.description,
|
|
188
|
-
input_schema: manifest.input_schema as object,
|
|
189
|
-
};
|
|
190
183
|
// RiskLevel is a string enum whose values are "low" | "medium" | "high",
|
|
191
184
|
// matching the schema above exactly — the cast is a no-op at runtime.
|
|
192
185
|
return {
|
|
193
186
|
name: manifest.name,
|
|
194
187
|
description: manifest.description,
|
|
188
|
+
input_schema: manifest.input_schema as object,
|
|
195
189
|
category: manifest.category,
|
|
196
190
|
defaultRiskLevel: manifest.defaultRiskLevel as RiskLevel,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
ownerSkillBundled: manifest.ownerSkillBundled,
|
|
202
|
-
ownerSkillVersionHash: manifest.ownerSkillVersionHash,
|
|
203
|
-
getDefinition: () => definition,
|
|
191
|
+
executionTarget: resolveExecutionTarget({
|
|
192
|
+
name: manifest.name,
|
|
193
|
+
executionTarget: manifest.executionTarget as ExecutionTarget | undefined,
|
|
194
|
+
}),
|
|
204
195
|
execute: async () => {
|
|
205
196
|
// Only reached when no supervisor is attached (tests/boot race);
|
|
206
197
|
// the supervisor short-circuit above replaces this with the
|
|
@@ -218,7 +209,7 @@ async function handleRegisterTools(
|
|
|
218
209
|
params: Record<string, unknown> | undefined,
|
|
219
210
|
connection?: unknown,
|
|
220
211
|
): Promise<{ registered: string[] }> {
|
|
221
|
-
const { tools } = RegisterToolsParams.parse(params);
|
|
212
|
+
const { skillId, tools } = RegisterToolsParams.parse(params);
|
|
222
213
|
const conn = connection as SkillIpcConnection | undefined;
|
|
223
214
|
|
|
224
215
|
// Supervisor short-circuit: when a supervisor is registered, the
|
|
@@ -230,7 +221,11 @@ async function handleRegisterTools(
|
|
|
230
221
|
if (sessionSupervisor) {
|
|
231
222
|
if (conn) sessionSupervisor.setActiveConnection(conn);
|
|
232
223
|
log.info(
|
|
233
|
-
{
|
|
224
|
+
{
|
|
225
|
+
count: tools.length,
|
|
226
|
+
names: tools.map((t) => t.name),
|
|
227
|
+
ownerSkillId: skillId,
|
|
228
|
+
},
|
|
234
229
|
"Supervisor active: skipping in-memory tool re-registration; manifest proxies serve dispatches",
|
|
235
230
|
);
|
|
236
231
|
return { registered: tools.map((t) => t.name) };
|
|
@@ -240,23 +235,23 @@ async function handleRegisterTools(
|
|
|
240
235
|
// `registerExternalTools` is only consumed inside `initializeTools()` at
|
|
241
236
|
// daemon boot; IPC children connect after boot, so route through
|
|
242
237
|
// `registerSkillTools` into the live registry the agent-loop reads from.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
for (const skillId of ownerIds) {
|
|
254
|
-
conn.addSkillToolsOwner(skillId);
|
|
255
|
-
}
|
|
238
|
+
// Owner is stamped registry-side from `skillId`; the proxy `Tool` objects
|
|
239
|
+
// carry no owner field.
|
|
240
|
+
const accepted = registerSkillTools(skillId, proxies);
|
|
241
|
+
|
|
242
|
+
// `registerSkillTools` increments the registry refcount once per call;
|
|
243
|
+
// mirror that on the connection so disconnect issues exactly one matching
|
|
244
|
+
// decrement.
|
|
245
|
+
if (conn && accepted.length > 0) {
|
|
246
|
+
conn.addSkillToolsOwner(skillId);
|
|
256
247
|
}
|
|
257
248
|
|
|
258
249
|
log.info(
|
|
259
|
-
{
|
|
250
|
+
{
|
|
251
|
+
count: accepted.length,
|
|
252
|
+
names: accepted.map((t) => t.name),
|
|
253
|
+
ownerSkillId: skillId,
|
|
254
|
+
},
|
|
260
255
|
"Registered skill proxy tools via IPC",
|
|
261
256
|
);
|
|
262
257
|
return { registered: accepted.map((t) => t.name) };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `db-async-query.ts` — the runAsyncSqlite abstraction.
|
|
3
|
+
*
|
|
4
|
+
* The contract this PR locks in:
|
|
5
|
+
* 1. **The main event loop keeps ticking while a long SQLite
|
|
6
|
+
* statement is in flight via the sqlite3 CLI backend.** This is
|
|
7
|
+
* the structural anti-block assertion — a recursive `setImmediate`
|
|
8
|
+
* probe counts event-loop iterations during the operation; if
|
|
9
|
+
* anyone moves the slow path back onto the main thread,
|
|
10
|
+
* `bun:sqlite` is synchronous and tick counting collapses to ~0;
|
|
11
|
+
* this test fails loudly.
|
|
12
|
+
* 2. The CLI backend reports `backend: "sqlite3-cli"` and `ok: true`
|
|
13
|
+
* on success.
|
|
14
|
+
* 3. The in-process fallback backend executes the statement
|
|
15
|
+
* synchronously and reports `backend: "in-process-blocking"`.
|
|
16
|
+
* 4. Errors from sqlite3 surface as `ok: false` with the stderr
|
|
17
|
+
* preserved in `error`.
|
|
18
|
+
*/
|
|
19
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
20
|
+
|
|
21
|
+
const { getSqlite } = await import("../db-connection.js");
|
|
22
|
+
const { initializeDb } = await import("../db-init.js");
|
|
23
|
+
const { runAsyncSqlite, _resetFallbackWarning } =
|
|
24
|
+
await import("../db-async-query.js");
|
|
25
|
+
const { findSqlite3 } = await import("../../util/sqlite3-runtime.js");
|
|
26
|
+
|
|
27
|
+
initializeDb();
|
|
28
|
+
|
|
29
|
+
const sqlite3Available = findSqlite3() !== undefined;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
_resetFallbackWarning();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
function inflateAndDelete(byteTarget: number): void {
|
|
36
|
+
const sqlite = getSqlite();
|
|
37
|
+
sqlite.exec(
|
|
38
|
+
"CREATE TABLE IF NOT EXISTS async_bloat (id INTEGER PRIMARY KEY, payload BLOB)",
|
|
39
|
+
);
|
|
40
|
+
const pageSize = (
|
|
41
|
+
sqlite.query("PRAGMA page_size").get() as { page_size: number }
|
|
42
|
+
).page_size;
|
|
43
|
+
const rowsTarget = Math.max(1, Math.ceil(byteTarget / pageSize));
|
|
44
|
+
const payload = new Uint8Array(Math.max(1, pageSize - 64));
|
|
45
|
+
const insert = sqlite.prepare("INSERT INTO async_bloat (payload) VALUES (?)");
|
|
46
|
+
sqlite.exec("BEGIN");
|
|
47
|
+
for (let i = 0; i < rowsTarget; i++) {
|
|
48
|
+
insert.run(payload);
|
|
49
|
+
}
|
|
50
|
+
sqlite.exec("COMMIT");
|
|
51
|
+
sqlite.exec("DELETE FROM async_bloat");
|
|
52
|
+
sqlite.exec("DROP TABLE async_bloat");
|
|
53
|
+
sqlite.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe("runAsyncSqlite", () => {
|
|
57
|
+
test("returns ok=true for a trivial statement", async () => {
|
|
58
|
+
const result = await runAsyncSqlite("SELECT 1");
|
|
59
|
+
expect(result.ok).toBe(true);
|
|
60
|
+
expect(result.error).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("in-process fallback reports the right backend", async () => {
|
|
64
|
+
const result = await runAsyncSqlite("SELECT 1", {
|
|
65
|
+
forceBackend: "in-process-blocking",
|
|
66
|
+
});
|
|
67
|
+
expect(result.ok).toBe(true);
|
|
68
|
+
expect(result.backend).toBe("in-process-blocking");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("in-process fallback emits changes() count on stdout after a DELETE", async () => {
|
|
72
|
+
// Regression for Codex P1 on #31894: callers (e.g. prune jobs) rely
|
|
73
|
+
// on reading the row count off `result.stdout`. The CLI backend
|
|
74
|
+
// populates this naturally when the SQL ends with `SELECT changes();`,
|
|
75
|
+
// but `bun:sqlite`'s `exec()` discards SELECT results — so the
|
|
76
|
+
// in-process backend has to synthesize the same line, or the
|
|
77
|
+
// re-enqueue gate in pruneOld*Job silently never fires on hosts
|
|
78
|
+
// without the sqlite3 CLI.
|
|
79
|
+
const sqlite = getSqlite();
|
|
80
|
+
sqlite.exec(
|
|
81
|
+
"CREATE TABLE IF NOT EXISTS async_changes_probe (id INTEGER PRIMARY KEY)",
|
|
82
|
+
);
|
|
83
|
+
sqlite.exec("DELETE FROM async_changes_probe");
|
|
84
|
+
sqlite.exec(
|
|
85
|
+
"INSERT INTO async_changes_probe (id) VALUES (1),(2),(3),(4),(5)",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const result = await runAsyncSqlite(
|
|
89
|
+
"DELETE FROM async_changes_probe WHERE id <= 3; SELECT changes();",
|
|
90
|
+
{ forceBackend: "in-process-blocking" },
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
expect(result.ok).toBe(true);
|
|
94
|
+
expect(result.backend).toBe("in-process-blocking");
|
|
95
|
+
// The synthesized stdout matches what the CLI backend would emit:
|
|
96
|
+
// a bare integer on its own line. The exact format keeps the
|
|
97
|
+
// parser in cleanup.ts backend-agnostic.
|
|
98
|
+
expect(result.stdout).toBe("3\n");
|
|
99
|
+
|
|
100
|
+
sqlite.exec("DROP TABLE async_changes_probe");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test.if(sqlite3Available)(
|
|
104
|
+
"sqlite3 CLI backend reports the right backend on success",
|
|
105
|
+
async () => {
|
|
106
|
+
const result = await runAsyncSqlite("SELECT 1");
|
|
107
|
+
expect(result.ok).toBe(true);
|
|
108
|
+
expect(result.backend).toBe("sqlite3-cli");
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
test.if(sqlite3Available)(
|
|
113
|
+
"surfaces sqlite3 errors as ok=false with the message preserved",
|
|
114
|
+
async () => {
|
|
115
|
+
// Intentional SQL syntax error.
|
|
116
|
+
const result = await runAsyncSqlite("THIS IS NOT VALID SQL");
|
|
117
|
+
expect(result.ok).toBe(false);
|
|
118
|
+
expect(result.backend).toBe("sqlite3-cli");
|
|
119
|
+
expect(result.error).toBeTruthy();
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
test.if(sqlite3Available)(
|
|
124
|
+
"VACUUM via sqlite3 CLI keeps the event loop ticking (anti-block)",
|
|
125
|
+
async () => {
|
|
126
|
+
// Inflate the DB so VACUUM has measurable work to do. Without
|
|
127
|
+
// this the subprocess finishes in single-digit ms and the
|
|
128
|
+
// probe has no opportunity to record meaningful ticks.
|
|
129
|
+
inflateAndDelete(8 * 1024 * 1024);
|
|
130
|
+
|
|
131
|
+
// Probe the event loop with recursive setImmediate. This fires
|
|
132
|
+
// on every event-loop iteration with no minimum delay, so on a
|
|
133
|
+
// healthy unblocked loop it produces tens of thousands of ticks
|
|
134
|
+
// per second (vs. setInterval(1) which is capped by the host's
|
|
135
|
+
// timer resolution — observed at ~32 ms on GitHub Actions
|
|
136
|
+
// runners). If anyone moves VACUUM back onto the main thread,
|
|
137
|
+
// `bun:sqlite` is sync and tick count collapses to ~0; the
|
|
138
|
+
// assertion below fails loudly. The signal is intentionally
|
|
139
|
+
// binary: "many" vs "none".
|
|
140
|
+
let tickCount = 0;
|
|
141
|
+
let probing = true;
|
|
142
|
+
const tick = (): void => {
|
|
143
|
+
if (!probing) return;
|
|
144
|
+
tickCount += 1;
|
|
145
|
+
setImmediate(tick);
|
|
146
|
+
};
|
|
147
|
+
setImmediate(tick);
|
|
148
|
+
|
|
149
|
+
let result;
|
|
150
|
+
try {
|
|
151
|
+
result = await runAsyncSqlite("VACUUM");
|
|
152
|
+
} finally {
|
|
153
|
+
probing = false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
expect(result.ok).toBe(true);
|
|
157
|
+
expect(result.backend).toBe("sqlite3-cli");
|
|
158
|
+
|
|
159
|
+
// Any positive tick count proves the event loop wasn't blocked.
|
|
160
|
+
// A sync in-process VACUUM would collapse this to 0.
|
|
161
|
+
expect(tickCount).toBeGreaterThanOrEqual(1);
|
|
162
|
+
},
|
|
163
|
+
60_000,
|
|
164
|
+
);
|
|
165
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `db-maintenance.ts` (orchestration) and the underlying
|
|
3
|
+
* `db-async-query.ts` abstraction.
|
|
4
|
+
*
|
|
5
|
+
* The contract this PR locks in:
|
|
6
|
+
* 1. `runDbMaintenance` runs `VACUUM` through the async abstraction
|
|
7
|
+
* — when the `sqlite3` CLI is available, that means a subprocess
|
|
8
|
+
* and the daemon's main event loop keeps ticking. (The structural
|
|
9
|
+
* anti-block assertion lives in
|
|
10
|
+
* `db-async-query.test.ts`; here we focus on orchestration.)
|
|
11
|
+
* 2. The subprocess actually shrinks the on-disk page count when
|
|
12
|
+
* there's reclaimable space.
|
|
13
|
+
* 3. `maybeRunDbMaintenance` is genuinely async — callers can `await`
|
|
14
|
+
* it and observe completion.
|
|
15
|
+
* 4. The 24 h interval guard short-circuits a recent re-run.
|
|
16
|
+
*
|
|
17
|
+
* The per-file temp workspace is set up by `test-preload.ts`; tests just
|
|
18
|
+
* dynamic-import the DB modules so they resolve paths under that temp dir.
|
|
19
|
+
*/
|
|
20
|
+
import { Database } from "bun:sqlite";
|
|
21
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
22
|
+
|
|
23
|
+
const { getSqlite } = await import("../db-connection.js");
|
|
24
|
+
const { initializeDb } = await import("../db-init.js");
|
|
25
|
+
const { deleteMemoryCheckpoint, getMemoryCheckpoint } =
|
|
26
|
+
await import("../checkpoints.js");
|
|
27
|
+
const { maybeRunDbMaintenance } = await import("../db-maintenance.js");
|
|
28
|
+
const { getDbPath } = await import("../../util/platform.js");
|
|
29
|
+
|
|
30
|
+
initializeDb();
|
|
31
|
+
|
|
32
|
+
const MAINTENANCE_CHECKPOINT_KEY = "db_maintenance:last_run";
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
deleteMemoryCheckpoint(MAINTENANCE_CHECKPOINT_KEY);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/** Inflate the test DB with bloat that VACUUM can reclaim. */
|
|
39
|
+
function inflateAndDelete(byteTarget: number): void {
|
|
40
|
+
const sqlite = getSqlite();
|
|
41
|
+
sqlite.exec(
|
|
42
|
+
"CREATE TABLE IF NOT EXISTS bloat (id INTEGER PRIMARY KEY, payload BLOB)",
|
|
43
|
+
);
|
|
44
|
+
const pageSize = (
|
|
45
|
+
sqlite.query("PRAGMA page_size").get() as { page_size: number }
|
|
46
|
+
).page_size;
|
|
47
|
+
const rowsTarget = Math.max(1, Math.ceil(byteTarget / pageSize));
|
|
48
|
+
const payload = new Uint8Array(Math.max(1, pageSize - 64));
|
|
49
|
+
const insert = sqlite.prepare("INSERT INTO bloat (payload) VALUES (?)");
|
|
50
|
+
sqlite.exec("BEGIN");
|
|
51
|
+
for (let i = 0; i < rowsTarget; i++) {
|
|
52
|
+
insert.run(payload);
|
|
53
|
+
}
|
|
54
|
+
sqlite.exec("COMMIT");
|
|
55
|
+
sqlite.exec("DELETE FROM bloat");
|
|
56
|
+
sqlite.exec("DROP TABLE bloat");
|
|
57
|
+
// Force the WAL onto the main DB file so the bloat is visible on disk.
|
|
58
|
+
sqlite.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
describe("maybeRunDbMaintenance", () => {
|
|
62
|
+
test("returns a Promise that resolves", async () => {
|
|
63
|
+
const result = maybeRunDbMaintenance();
|
|
64
|
+
expect(result).toBeInstanceOf(Promise);
|
|
65
|
+
await result;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("respects the 24h interval and skips when last run was recent", async () => {
|
|
69
|
+
const now = Date.now();
|
|
70
|
+
const recent = now - 60_000;
|
|
71
|
+
const { setMemoryCheckpoint } = await import("../checkpoints.js");
|
|
72
|
+
setMemoryCheckpoint(MAINTENANCE_CHECKPOINT_KEY, String(recent));
|
|
73
|
+
|
|
74
|
+
await maybeRunDbMaintenance(now);
|
|
75
|
+
|
|
76
|
+
expect(getMemoryCheckpoint(MAINTENANCE_CHECKPOINT_KEY)).toBe(
|
|
77
|
+
String(recent),
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("stamps the checkpoint after a maintenance run", async () => {
|
|
82
|
+
const now = Date.now();
|
|
83
|
+
await maybeRunDbMaintenance(now);
|
|
84
|
+
|
|
85
|
+
expect(getMemoryCheckpoint(MAINTENANCE_CHECKPOINT_KEY)).toBe(String(now));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("VACUUM reclaims pages on a bloated DB", async () => {
|
|
89
|
+
const sqlite = getSqlite();
|
|
90
|
+
sqlite.exec("DROP TABLE IF EXISTS bloat");
|
|
91
|
+
sqlite.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
92
|
+
|
|
93
|
+
inflateAndDelete(8 * 1024 * 1024);
|
|
94
|
+
|
|
95
|
+
const dbPath = getDbPath();
|
|
96
|
+
// Read page_count from a fresh connection so we observe post-write
|
|
97
|
+
// ground truth without snapshot caching on the main test connection.
|
|
98
|
+
const readPageCount = (): number => {
|
|
99
|
+
const probe = new Database(dbPath, { readonly: true });
|
|
100
|
+
try {
|
|
101
|
+
return (
|
|
102
|
+
probe.query("PRAGMA page_count").get() as { page_count: number }
|
|
103
|
+
).page_count;
|
|
104
|
+
} finally {
|
|
105
|
+
probe.close();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const pagesBefore = readPageCount();
|
|
109
|
+
|
|
110
|
+
await maybeRunDbMaintenance();
|
|
111
|
+
|
|
112
|
+
const pagesAfter = readPageCount();
|
|
113
|
+
expect(pagesAfter).toBeLessThan(pagesBefore);
|
|
114
|
+
}, 60_000);
|
|
115
|
+
});
|