@vellumai/assistant 0.7.3 → 0.8.1
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 +11 -0
- package/ARCHITECTURE.md +29 -28
- package/Dockerfile +6 -4
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
- package/bun.lock +3 -0
- package/docker-entrypoint.sh +16 -0
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
- package/eslint-rules/cli-no-daemon-internals.js +283 -0
- package/eslint.config.mjs +12 -0
- package/knip.json +3 -1
- package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
- package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
- package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4126 -959
- package/package.json +5 -1
- package/scripts/generate-openapi.ts +52 -4
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +107 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/annotate-risk-options.test.ts +291 -0
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/approval-cascade.test.ts +8 -16
- package/src/__tests__/approval-routes-http.test.ts +6 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
- package/src/__tests__/avatar-identity-sync.test.ts +87 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/call-constants.test.ts +10 -1
- package/src/__tests__/call-controller.test.ts +127 -0
- package/src/__tests__/call-site-routing-provider.test.ts +172 -45
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
- package/src/__tests__/config-loader-backfill.test.ts +526 -102
- package/src/__tests__/config-loader-corrupt.test.ts +68 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +14 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +198 -0
- package/src/__tests__/config-watcher.test.ts +6 -0
- package/src/__tests__/contacts-tools.test.ts +51 -199
- package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
- package/src/__tests__/context-search-agent-runner.test.ts +22 -138
- package/src/__tests__/context-search-conversations-source.test.ts +42 -16
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-source.test.ts +3 -26
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-window-manager.test.ts +389 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +3 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +38 -0
- package/src/__tests__/conversation-fork-crud.test.ts +241 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
- package/src/__tests__/conversation-lifecycle.test.ts +124 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +22 -7
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- package/src/__tests__/daemon-credential-client.test.ts +56 -1
- package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
- package/src/__tests__/db-proxy-transaction.test.ts +206 -0
- package/src/__tests__/external-plugin-loader.test.ts +458 -0
- package/src/__tests__/filing-service.test.ts +25 -22
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/history-repair.test.ts +89 -0
- package/src/__tests__/host-app-control-proxy.test.ts +109 -1
- package/src/__tests__/host-app-control-routes.test.ts +247 -1
- package/src/__tests__/host-browser-proxy.test.ts +416 -20
- package/src/__tests__/host-browser-routes.test.ts +325 -33
- package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +154 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
- package/src/__tests__/injector-chain.test.ts +24 -16
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +2 -2
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +146 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/managed-profile-guard.test.ts +131 -2
- package/src/__tests__/mcp-auth-routes.test.ts +1 -0
- package/src/__tests__/mcp-cli.test.ts +182 -220
- package/src/__tests__/mcp-health-check.test.ts +56 -27
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/notification-decision-fallback.test.ts +91 -0
- package/src/__tests__/notification-decision-strategy.test.ts +22 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -1888
- package/src/__tests__/oauth-commands-routes.test.ts +711 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/plugin-bootstrap.test.ts +31 -2
- package/src/__tests__/plugin-route-contribution.test.ts +31 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
- package/src/__tests__/plugin-types.test.ts +13 -11
- package/src/__tests__/process-message-background-slack.test.ts +46 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
- package/src/__tests__/provider-registry-ollama.test.ts +12 -4
- package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
- package/src/__tests__/relay-server.test.ts +164 -2
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +104 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
- package/src/__tests__/scheduler-recurrence.test.ts +87 -34
- package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
- package/src/__tests__/secret-response-routing.test.ts +7 -5
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/server-history-render.test.ts +82 -0
- package/src/__tests__/shell-credential-ref.test.ts +95 -3
- package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
- package/src/__tests__/skill-include-graph.test.ts +31 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +42 -16
- package/src/__tests__/skills.test.ts +39 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
- package/src/__tests__/tool-executor.test.ts +155 -0
- package/src/__tests__/update-bulletin-job.test.ts +96 -193
- package/src/__tests__/usage-cli.test.ts +11 -73
- package/src/__tests__/user-plugin-loader.test.ts +145 -0
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/voice-session-bridge.test.ts +3 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
- package/src/__tests__/web-search.test.ts +303 -2
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
- package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
- package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
- package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
- package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
- package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
- package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
- package/src/acp/__tests__/helpers/which-stub.ts +4 -2
- package/src/acp/resolve-agent.test.ts +25 -0
- package/src/acp/resolve-agent.ts +13 -2
- package/src/acp/session-manager.ts +14 -0
- package/src/agent/loop.ts +11 -0
- package/src/approvals/guardian-decision-primitive.ts +0 -13
- package/src/approvals/guardian-request-resolvers.ts +19 -102
- package/src/calls/call-constants.ts +5 -8
- package/src/calls/call-controller.ts +130 -67
- package/src/calls/relay-server.ts +42 -1
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +24 -5
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +1 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/commands/__tests__/avatar.test.ts +540 -0
- package/src/cli/commands/__tests__/backup.test.ts +236 -776
- package/src/cli/commands/__tests__/cache.test.ts +1 -1
- package/src/cli/commands/__tests__/changelog.test.ts +593 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
- package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
- package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
- package/src/cli/commands/__tests__/email-core.test.ts +579 -0
- package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
- package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
- package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
- package/src/cli/commands/__tests__/skills.test.ts +563 -0
- package/src/cli/commands/__tests__/status.test.ts +249 -0
- package/src/cli/commands/__tests__/stt.test.ts +320 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
- package/src/cli/commands/__tests__/tts.test.ts +321 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
- package/src/cli/commands/attachment.ts +8 -3
- package/src/cli/commands/audit.ts +95 -64
- package/src/cli/commands/auth.ts +61 -58
- package/src/cli/commands/avatar.ts +276 -390
- package/src/cli/commands/backup.ts +409 -505
- package/src/cli/commands/bash.ts +9 -5
- package/src/cli/commands/browser.ts +28 -9
- package/src/cli/commands/cache.ts +9 -4
- package/src/cli/commands/changelog.ts +414 -0
- package/src/cli/commands/channel-verification-sessions.ts +238 -317
- package/src/cli/commands/clients.ts +8 -3
- package/src/cli/commands/completions.ts +9 -9
- package/src/cli/commands/config.ts +102 -72
- package/src/cli/commands/contacts.ts +575 -696
- package/src/cli/commands/conversations-defer.ts +17 -69
- package/src/cli/commands/conversations-import.ts +90 -253
- package/src/cli/commands/conversations.ts +346 -436
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/domain.ts +128 -206
- package/src/cli/commands/email.ts +606 -794
- package/src/cli/commands/gateway.ts +8 -1
- package/src/cli/commands/image-generation.ts +157 -205
- package/src/cli/commands/inference-providers.ts +352 -0
- package/src/cli/commands/inference-session.ts +415 -0
- package/src/cli/commands/inference.ts +87 -65
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.ts +103 -287
- package/src/cli/commands/memory-v2.ts +163 -517
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +182 -345
- package/src/cli/commands/oauth/disconnect.ts +16 -215
- package/src/cli/commands/oauth/index.ts +49 -45
- package/src/cli/commands/oauth/mode.ts +43 -199
- package/src/cli/commands/oauth/ping.ts +17 -125
- package/src/cli/commands/oauth/providers.ts +732 -921
- package/src/cli/commands/oauth/request.ts +60 -350
- package/src/cli/commands/oauth/shared.ts +11 -121
- package/src/cli/commands/oauth/status.ts +31 -121
- package/src/cli/commands/oauth/token.ts +13 -55
- package/src/cli/commands/pending.ts +19 -10
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
- package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
- package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
- package/src/cli/commands/platform/connect.ts +16 -80
- package/src/cli/commands/platform/disconnect.ts +14 -112
- package/src/cli/commands/platform/index.ts +177 -246
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/sequence.ts +316 -360
- package/src/cli/commands/skills.ts +449 -671
- package/src/cli/commands/status.ts +58 -37
- package/src/cli/commands/stt.ts +94 -262
- package/src/cli/commands/task.ts +14 -40
- package/src/cli/commands/trust.ts +8 -3
- package/src/cli/commands/tts.ts +162 -167
- package/src/cli/commands/ui.ts +35 -42
- package/src/cli/commands/usage.ts +188 -126
- package/src/cli/commands/watchers.ts +8 -3
- package/src/cli/commands/webhooks.ts +99 -193
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/nested-value.ts +44 -0
- package/src/cli/lib/open-browser.ts +36 -0
- package/src/cli/lib/register-command.ts +19 -0
- package/src/cli/lib/time-ago.ts +34 -0
- package/src/cli/program.ts +2 -4
- package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
- package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
- package/src/cli/utils/conversation-id.ts +30 -0
- package/src/cli/utils/parse-duration.ts +41 -0
- package/src/config/acp-defaults.test.ts +5 -1
- package/src/config/acp-defaults.ts +11 -4
- package/src/config/bundled-skills/acp/TOOLS.json +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/contacts/SKILL.md +12 -45
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
- package/src/config/bundled-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +148 -33
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
- package/src/config/schemas/call-site-catalog.ts +29 -7
- package/src/config/schemas/llm-request-logs.ts +57 -0
- package/src/config/schemas/llm.ts +52 -2
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +33 -2
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/window-manager.ts +191 -5
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +23 -29
- package/src/daemon/config-watcher.ts +2 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
- package/src/daemon/conversation-agent-loop.ts +140 -107
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +68 -13
- package/src/daemon/conversation-process.ts +36 -19
- package/src/daemon/conversation-runtime-assembly.ts +14 -5
- package/src/daemon/conversation-slash.ts +175 -23
- package/src/daemon/conversation-store.ts +17 -10
- package/src/daemon/conversation-surfaces.ts +92 -26
- package/src/daemon/conversation-tool-setup.ts +33 -19
- package/src/daemon/conversation.ts +49 -10
- package/src/daemon/external-plugins-bootstrap.ts +18 -8
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +8 -126
- package/src/daemon/handlers/config-slack-channel.ts +10 -7
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/shared.ts +26 -0
- package/src/daemon/handlers/skills.ts +84 -5
- package/src/daemon/history-repair.ts +33 -6
- package/src/daemon/host-app-control-proxy.ts +44 -19
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +97 -36
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/host-transfer-proxy.ts +2 -2
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +128 -114
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +62 -14
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +12 -9
- package/src/daemon/message-types/messages.ts +28 -2
- package/src/daemon/message-types/sync.ts +60 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/process-message.ts +56 -23
- package/src/daemon/server.ts +23 -18
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/daemon/tool-side-effects.ts +6 -4
- package/src/daemon/wake-target-adapter.ts +11 -0
- package/src/documents/document-store.ts +35 -1
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +42 -56
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +149 -128
- package/src/home/__tests__/feed-types.test.ts +63 -131
- package/src/home/__tests__/feed-writer.test.ts +77 -278
- package/src/home/__tests__/post-connect-feed.test.ts +9 -12
- package/src/home/feed-types.ts +19 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +1 -3
- package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
- package/src/ipc/__tests__/email-ipc.test.ts +506 -0
- package/src/ipc/__tests__/exit-helper.test.ts +104 -0
- package/src/ipc/__tests__/streaming-client.test.ts +237 -0
- package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
- package/src/ipc/assistant-server.ts +148 -42
- package/src/ipc/cli-client.ts +370 -50
- package/src/ipc/routes/db-proxy-transaction.ts +151 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
- package/src/ipc/skill-routes/events.ts +30 -3
- package/src/ipc/skill-server.ts +99 -42
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
- package/src/live-voice/live-voice-session-manager.ts +11 -4
- package/src/live-voice/live-voice-session.ts +14 -6
- package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-types.test.ts +36 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
- package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
- package/src/memory/bookmark-crud.ts +179 -0
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
- package/src/memory/context-search/agent-protocol.ts +5 -1
- package/src/memory/context-search/agent-runner.ts +60 -85
- package/src/memory/context-search/limits.ts +1 -4
- package/src/memory/context-search/search.ts +23 -113
- package/src/memory/context-search/sources/conversations.ts +18 -6
- package/src/memory/context-search/sources/memory-v2.ts +40 -31
- package/src/memory/context-search/sources/memory.ts +9 -2
- package/src/memory/context-search/sources/workspace.ts +13 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +312 -10
- package/src/memory/conversation-queries.ts +9 -5
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +2 -1
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +108 -14
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/graph-search.test.ts +6 -5
- package/src/memory/graph/graph-search.ts +3 -4
- package/src/memory/graph/retriever.test.ts +12 -7
- package/src/memory/graph/retriever.ts +4 -5
- package/src/memory/graph/tool-handlers.ts +20 -11
- package/src/memory/graph/tools.ts +48 -9
- package/src/memory/indexer.ts +18 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
- package/src/memory/jobs/embed-concept-page.ts +261 -89
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +60 -7
- package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +97 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/memory-retrospective-constants.ts +13 -0
- package/src/memory/memory-retrospective-enqueue.ts +114 -0
- package/src/memory/memory-retrospective-job.ts +351 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
- package/src/memory/memory-retrospective-state.ts +162 -0
- package/src/memory/memory-retrospective-trigger-check.ts +91 -0
- package/src/memory/memory-v2-activation-log-store.ts +49 -5
- package/src/memory/memory-v2-concept-frequency.ts +4 -0
- package/src/memory/message-content.ts +38 -1
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
- package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
- package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
- package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
- package/src/memory/migrations/242-message-bookmarks.ts +38 -0
- package/src/memory/migrations/243-provider-connections.ts +68 -0
- package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
- package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
- package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
- package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
- package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
- package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -5
- package/src/memory/pkb/pkb-search.ts +4 -5
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/qdrant-client.ts +3 -0
- package/src/memory/schema/bookmarks.ts +38 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +29 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +5 -9
- package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
- package/src/memory/v2/__tests__/activation.test.ts +46 -9
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
- package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
- package/src/memory/v2/__tests__/injection.test.ts +768 -33
- package/src/memory/v2/__tests__/migration.test.ts +7 -3
- package/src/memory/v2/__tests__/page-index.test.ts +277 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +516 -0
- package/src/memory/v2/__tests__/sim.test.ts +163 -8
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +8 -35
- package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
- package/src/memory/v2/activation-store.ts +34 -5
- package/src/memory/v2/activation.ts +40 -27
- package/src/memory/v2/backfill-jobs.ts +17 -84
- package/src/memory/v2/consolidation-job.ts +92 -86
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +466 -115
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +42 -0
- package/src/memory/v2/prompts/consolidation.ts +14 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +307 -133
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +88 -34
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +20 -17
- package/src/memory/v2/sweep-job.ts +127 -102
- package/src/memory/v2/types.ts +16 -5
- package/src/memory/validation.ts +13 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
- package/src/notifications/__tests__/signal-registry.test.ts +17 -0
- package/src/notifications/adapters/platform.ts +171 -0
- package/src/notifications/conversation-pairing.ts +2 -2
- package/src/notifications/copy-composer.ts +61 -12
- package/src/notifications/decision-engine.ts +46 -0
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +28 -1
- package/src/notifications/home-feed-side-effect.ts +111 -0
- package/src/notifications/signal.ts +5 -0
- package/src/permissions/checker.ts +12 -0
- package/src/permissions/gateway-threshold-reader.ts +116 -8
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/permissions/prompter.ts +86 -96
- package/src/permissions/secret-prompter.ts +31 -31
- package/src/plugin-api/index.ts +13 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +62 -0
- package/src/plugins/defaults/injectors.ts +20 -5
- package/src/plugins/external-plugin-loader.ts +294 -0
- package/src/plugins/types.ts +46 -30
- package/src/plugins/user-loader.ts +64 -41
- package/src/proactive-artifact/job.test.ts +63 -8
- package/src/proactive-artifact/job.ts +20 -2
- package/src/proactive-artifact/message-copy.ts +18 -1
- package/src/proactive-artifact/trigger-state.test.ts +9 -0
- package/src/proactive-artifact/trigger-state.ts +4 -0
- package/src/prompts/__tests__/system-prompt.test.ts +105 -0
- package/src/prompts/system-prompt.ts +22 -1
- package/src/prompts/templates/SOUL.md +13 -28
- package/src/prompts/update-bulletin-job.ts +61 -73
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
- package/src/providers/__tests__/inference.test.ts +288 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +14 -32
- package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
- package/src/providers/anthropic/client.ts +95 -26
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +163 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +173 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +356 -0
- package/src/providers/inference/resolve-auth.ts +65 -0
- package/src/providers/model-catalog.ts +104 -6
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/provider-env-vars.ts +17 -7
- package/src/providers/provider-secret-catalog.ts +49 -30
- package/src/providers/provider-send-message.ts +41 -20
- package/src/providers/registry.ts +143 -159
- package/src/providers/retry.ts +18 -10
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
- package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
- package/src/runtime/actor-trust-resolver.ts +32 -10
- package/src/runtime/agent-wake.ts +35 -6
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +304 -8
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +1 -0
- package/src/runtime/channel-approvals.ts +3 -2
- package/src/runtime/guardian-reply-router.ts +0 -10
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/pending-interactions.ts +19 -15
- package/src/runtime/pre-first-message-gate.ts +83 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.ts +10 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +7 -21
- package/src/runtime/routes/audit-routes.ts +43 -0
- package/src/runtime/routes/auth-routes.ts +72 -0
- package/src/runtime/routes/avatar-routes.ts +273 -20
- package/src/runtime/routes/backup-routes.ts +406 -2
- package/src/runtime/routes/bookmark-routes.ts +154 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/consolidation-routes.ts +8 -9
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +192 -0
- package/src/runtime/routes/conversation-management-routes.ts +30 -43
- package/src/runtime/routes/conversation-query-routes.ts +373 -82
- package/src/runtime/routes/conversation-routes.ts +31 -10
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-bash-routes.ts +2 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/domain-routes.ts +167 -0
- package/src/runtime/routes/email-routes.ts +603 -0
- package/src/runtime/routes/errors.ts +2 -2
- package/src/runtime/routes/events-routes.ts +192 -0
- package/src/runtime/routes/filing-routes.ts +2 -3
- package/src/runtime/routes/home-feed-routes.ts +6 -78
- package/src/runtime/routes/host-app-control-routes.ts +44 -2
- package/src/runtime/routes/host-browser-routes.ts +103 -22
- package/src/runtime/routes/http-adapter.ts +2 -0
- package/src/runtime/routes/identity-routes.ts +5 -0
- package/src/runtime/routes/image-generation-routes.ts +99 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
- package/src/runtime/routes/index.ts +36 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/twilio.ts +1 -0
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-item-routes.test.ts +3 -9
- package/src/runtime/routes/memory-item-routes.ts +5 -6
- package/src/runtime/routes/memory-v2-routes.ts +105 -404
- package/src/runtime/routes/notification-routes.ts +2 -0
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-providers.ts +298 -8
- package/src/runtime/routes/platform-routes.ts +336 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -1
- package/src/runtime/routes/playground/reset-circuit.ts +2 -1
- package/src/runtime/routes/playground/state.ts +2 -1
- package/src/runtime/routes/publish-routes.ts +221 -0
- package/src/runtime/routes/schedule-routes.ts +82 -0
- package/src/runtime/routes/sequence-routes.ts +291 -0
- package/src/runtime/routes/settings-routes.ts +2 -10
- package/src/runtime/routes/skills-routes.ts +31 -1
- package/src/runtime/routes/stt-routes.ts +240 -3
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/tts-routes.ts +67 -0
- package/src/runtime/routes/types.ts +32 -0
- package/src/runtime/routes/user-routes-cli.ts +243 -0
- package/src/runtime/routes/webhook-routes.ts +165 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/scheduler.ts +200 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/secret-patterns.ts +3 -0
- package/src/sequence/engine.ts +38 -40
- package/src/skills/include-graph.ts +35 -13
- package/src/subagent/manager.ts +20 -15
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +15 -4
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
- package/src/tools/browser/cdp-client/factory.ts +66 -5
- package/src/tools/browser/runtime-check.ts +77 -0
- package/src/tools/document/document-tool.ts +20 -0
- package/src/tools/executor.ts +18 -2
- package/src/tools/memory/register.test.ts +10 -8
- package/src/tools/memory/register.ts +9 -1
- package/src/tools/network/__tests__/web-search.test.ts +156 -0
- package/src/tools/network/web-search.ts +280 -37
- package/src/tools/permission-checker.ts +28 -5
- package/src/tools/skills/load.ts +24 -20
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/tools/tool-name-aliases.ts +19 -0
- package/src/tools/types.ts +19 -1
- package/src/usage/attribution.ts +3 -2
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +301 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +90 -90
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
- package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
- package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
- package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
- package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
- package/src/workspace/migrations/registry.ts +28 -0
- package/src/workspace/migrations/runner.ts +13 -2
- package/src/workspace/migrations/types.ts +13 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -492
- package/src/__tests__/credentials-cli.test.ts +0 -1225
- package/src/__tests__/memory-admin-recall.test.ts +0 -213
- package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
- package/src/cli/commands/__tests__/email-download.test.ts +0 -260
- package/src/cli/commands/__tests__/email-list.test.ts +0 -216
- package/src/cli/commands/__tests__/email-register.test.ts +0 -186
- package/src/cli/commands/__tests__/email-send.test.ts +0 -416
- package/src/cli/commands/__tests__/email-status.test.ts +0 -185
- package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
- package/src/cli/commands/__tests__/routes.test.ts +0 -562
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
- package/src/cli/commands/autonomy.ts +0 -365
- package/src/cli/commands/memory.ts +0 -424
- package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
- package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
- package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
- package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
- package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
- package/src/cli/lib/daemon-avatar-client.ts +0 -37
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
- package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
- package/src/home/__tests__/emit-feed-event.test.ts +0 -169
- package/src/home/__tests__/feed-population-integration.test.ts +0 -312
- package/src/home/__tests__/feed-scheduler.test.ts +0 -222
- package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
- package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
- package/src/home/__tests__/rollup-producer.test.ts +0 -507
- package/src/home/assistant-feed-authoring.ts +0 -135
- package/src/home/emit-feed-event.ts +0 -169
- package/src/home/feed-scheduler.ts +0 -281
- package/src/home/platform-gmail-digest.ts +0 -163
- package/src/home/rewrite-command-preview.ts +0 -66
- package/src/home/rewrite-feed-title.ts +0 -58
- package/src/home/rollup-producer.ts +0 -426
- package/src/memory/admin.ts +0 -326
- package/src/memory/context-search/sources/pkb.ts +0 -477
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External plugin loader — builds a {@link Plugin} from a directory and
|
|
3
|
+
* registers it with the runtime.
|
|
4
|
+
*
|
|
5
|
+
* The convention this loader walks is currently **experimental**: surface
|
|
6
|
+
* set, manifest fields, and discovery shape may all change before the
|
|
7
|
+
* framework stabilizes. We keep this module's identifiers harness-neutral
|
|
8
|
+
* ("external") so the stable call path through the harness —
|
|
9
|
+
* `loadUserPlugins → loadExternalPlugin → registerPlugin` — does not
|
|
10
|
+
* need to be renamed when the convention shifts.
|
|
11
|
+
*
|
|
12
|
+
* <pluginDir>/
|
|
13
|
+
* package.json ← manifest.name comes from `name`
|
|
14
|
+
* (npm scope stripped); manifest.requires
|
|
15
|
+
* comes from `vellum.requires` if present
|
|
16
|
+
* hooks/
|
|
17
|
+
* <name>.ts ← default export → plugin.hooks[<name>]
|
|
18
|
+
* (today the runtime invokes "init" at
|
|
19
|
+
* bootstrap and "shutdown" at teardown;
|
|
20
|
+
* other filenames sit in the map for
|
|
21
|
+
* forward compatibility)
|
|
22
|
+
* tools/
|
|
23
|
+
* *.ts ← each file's default export → plugin.tools[]
|
|
24
|
+
* src/ ← internal helpers, ignored by the loader
|
|
25
|
+
*
|
|
26
|
+
* Per-surface, `.js` is preferred over `.ts` (compiled-binary semantics).
|
|
27
|
+
* Missing surface files are silently omitted (the harness treats absent
|
|
28
|
+
* fields as "this plugin contributes nothing here"). Surface files
|
|
29
|
+
* present without a usable default export are a hard failure: the
|
|
30
|
+
* loader logs with attribution and skips the plugin.
|
|
31
|
+
*
|
|
32
|
+
* This function owns the per-plugin isolation contract: it never throws,
|
|
33
|
+
* times out after `importTimeoutMs`, catches any error from the build or
|
|
34
|
+
* `registerPlugin` call, and logs an attributed entry. Callers can
|
|
35
|
+
* `await loadExternalPlugin(...)` in a loop with no per-iteration guard.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
39
|
+
import { readFile } from "node:fs/promises";
|
|
40
|
+
import { join } from "node:path";
|
|
41
|
+
import { pathToFileURL } from "node:url";
|
|
42
|
+
|
|
43
|
+
import { z } from "zod";
|
|
44
|
+
|
|
45
|
+
import { getLogger } from "../util/logger.js";
|
|
46
|
+
import { registerPlugin } from "./registry.js";
|
|
47
|
+
import type {
|
|
48
|
+
Plugin,
|
|
49
|
+
PluginHookFn,
|
|
50
|
+
PluginHooks,
|
|
51
|
+
PluginManifest,
|
|
52
|
+
PluginToolRegistration,
|
|
53
|
+
} from "./types.js";
|
|
54
|
+
|
|
55
|
+
const log = getLogger("external-plugin-loader");
|
|
56
|
+
|
|
57
|
+
/** Default upper bound on how long a single plugin load may take. */
|
|
58
|
+
const DEFAULT_IMPORT_TIMEOUT_MS = 10_000;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Zod schema for the subset of `package.json` the external loader reads.
|
|
62
|
+
*
|
|
63
|
+
* - `name` is the only required field; everything else is best-effort.
|
|
64
|
+
* - `vellum.requires` is forwarded to {@link PluginManifest.requires}
|
|
65
|
+
* verbatim (no merge with defaults) — empty objects propagate so the
|
|
66
|
+
* registry can reject under-specified plugins.
|
|
67
|
+
* - Unknown fields pass through (`passthrough`) so the loader does not
|
|
68
|
+
* destructively reshape the file when the rest of the npm ecosystem
|
|
69
|
+
* writes to it.
|
|
70
|
+
*/
|
|
71
|
+
const PluginPackageJsonSchema = z
|
|
72
|
+
.object({
|
|
73
|
+
name: z.string().min(1, "package.json `name` must be a non-empty string"),
|
|
74
|
+
version: z.string().optional(),
|
|
75
|
+
vellum: z
|
|
76
|
+
.object({
|
|
77
|
+
requires: z.record(z.string(), z.string()).optional(),
|
|
78
|
+
})
|
|
79
|
+
.passthrough()
|
|
80
|
+
.optional(),
|
|
81
|
+
})
|
|
82
|
+
.passthrough();
|
|
83
|
+
|
|
84
|
+
type PluginPackageJson = z.infer<typeof PluginPackageJsonSchema>;
|
|
85
|
+
|
|
86
|
+
export interface LoadExternalPluginOptions {
|
|
87
|
+
/**
|
|
88
|
+
* Maximum time to spend building the `Plugin` from disk before bailing.
|
|
89
|
+
* The build runs to completion in the background if it eventually
|
|
90
|
+
* resolves, but the loader has already moved on. Defaults to
|
|
91
|
+
* {@link DEFAULT_IMPORT_TIMEOUT_MS}.
|
|
92
|
+
*/
|
|
93
|
+
readonly importTimeoutMs?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Strip the npm scope from a package name. `@vellumai/simple-memory` →
|
|
98
|
+
* `simple-memory`; an unscoped name passes through unchanged.
|
|
99
|
+
*/
|
|
100
|
+
function stripScope(name: string): string {
|
|
101
|
+
const match = /^@[^/]+\/(.+)$/.exec(name);
|
|
102
|
+
return match ? match[1]! : name;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Dynamic-import `absolutePath` and return its default export. Throws when
|
|
107
|
+
* the module has no default export — callers attribute the error.
|
|
108
|
+
*/
|
|
109
|
+
async function importDefault<T>(absolutePath: string): Promise<T> {
|
|
110
|
+
const url = pathToFileURL(absolutePath).href;
|
|
111
|
+
const mod = (await import(url)) as { default?: T };
|
|
112
|
+
if (mod.default === undefined) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`module ${absolutePath} has no default export — external plugins must default-export their interface surfaces`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return mod.default;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface SurfaceFile {
|
|
121
|
+
/** Basename without `.js`/`.ts` extension. */
|
|
122
|
+
readonly name: string;
|
|
123
|
+
/** Absolute path on disk. */
|
|
124
|
+
readonly path: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* List every `.js`/`.ts` file directly under `dir`, deduplicating `.js`
|
|
129
|
+
* over `.ts` when both are present for the same basename. Returns entries
|
|
130
|
+
* sorted by basename so plugin authors get a deterministic per-plugin
|
|
131
|
+
* registration sequence; cross-plugin order remains the registry's job.
|
|
132
|
+
*
|
|
133
|
+
* Used to walk both `hooks/` and `tools/` — neither surface needs
|
|
134
|
+
* subdirectory recursion today, so this stays flat on purpose.
|
|
135
|
+
*/
|
|
136
|
+
function listSurfaceDir(dir: string): SurfaceFile[] {
|
|
137
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];
|
|
138
|
+
const entries = readdirSync(dir);
|
|
139
|
+
const byBase = new Map<string, string>();
|
|
140
|
+
for (const entry of entries) {
|
|
141
|
+
// `.d.ts` declaration files are TypeScript type-only artifacts shipped
|
|
142
|
+
// alongside compiled `.js`. They have no default-exported runtime
|
|
143
|
+
// function and would crash `importDefault`, so the walker filters
|
|
144
|
+
// them out before the `.js`/`.ts` extension check.
|
|
145
|
+
if (entry.endsWith(".d.ts")) continue;
|
|
146
|
+
const base =
|
|
147
|
+
entry.endsWith(".js") || entry.endsWith(".ts")
|
|
148
|
+
? entry.slice(0, -3)
|
|
149
|
+
: null;
|
|
150
|
+
if (base === null) continue;
|
|
151
|
+
const existing = byBase.get(base);
|
|
152
|
+
if (
|
|
153
|
+
existing === undefined ||
|
|
154
|
+
(existing.endsWith(".ts") && entry.endsWith(".js"))
|
|
155
|
+
) {
|
|
156
|
+
byBase.set(base, entry);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return [...byBase.keys()]
|
|
160
|
+
.sort()
|
|
161
|
+
.map((name) => ({ name, path: join(dir, byBase.get(name)!) }));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Walk every file under `<pluginDir>/hooks/` and import each as a
|
|
166
|
+
* lifecycle hook keyed by filename basename. The runtime today invokes
|
|
167
|
+
* `init` at bootstrap and `shutdown` at teardown; other filenames are
|
|
168
|
+
* loaded into the map for forward compatibility with future lifecycle
|
|
169
|
+
* events but stay inert.
|
|
170
|
+
*/
|
|
171
|
+
async function loadHooks(
|
|
172
|
+
pluginDir: string,
|
|
173
|
+
pluginName: string,
|
|
174
|
+
): Promise<PluginHooks | undefined> {
|
|
175
|
+
const files = listSurfaceDir(join(pluginDir, "hooks"));
|
|
176
|
+
if (files.length === 0) return undefined;
|
|
177
|
+
const hooks: PluginHooks = {};
|
|
178
|
+
for (const { name, path } of files) {
|
|
179
|
+
const fn = await importDefault<PluginHookFn>(path);
|
|
180
|
+
if (typeof fn !== "function") {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`external plugin ${pluginName}: hooks/${name} default export must be a function (got ${typeof fn})`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
hooks[name] = fn;
|
|
186
|
+
}
|
|
187
|
+
return hooks;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Build a `Plugin` object from the directory layout. Internal — the
|
|
192
|
+
* public entry point ({@link loadExternalPlugin}) wraps this in the
|
|
193
|
+
* timeout/try-catch/register triple.
|
|
194
|
+
*/
|
|
195
|
+
async function buildPluginFromDir(pluginDir: string): Promise<Plugin> {
|
|
196
|
+
const pkgPath = join(pluginDir, "package.json");
|
|
197
|
+
let rawPkg: unknown;
|
|
198
|
+
try {
|
|
199
|
+
rawPkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
|
200
|
+
} catch (err) {
|
|
201
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
202
|
+
throw new Error(
|
|
203
|
+
`package.json at ${pluginDir} could not be read or parsed: ${reason}`,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
const parsed = PluginPackageJsonSchema.safeParse(rawPkg);
|
|
207
|
+
if (!parsed.success) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`package.json at ${pluginDir} failed schema validation: ${parsed.error.message}`,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
const pkg: PluginPackageJson = parsed.data;
|
|
213
|
+
const name = stripScope(pkg.name);
|
|
214
|
+
const version = pkg.version && pkg.version.length > 0 ? pkg.version : "0.0.0";
|
|
215
|
+
|
|
216
|
+
// Default `requires` keeps the existing v1 negotiation working for
|
|
217
|
+
// plugins that have not yet opted into `vellum.requires`. Plugins that
|
|
218
|
+
// set `vellum.requires` get exactly what they declared — no merge.
|
|
219
|
+
const requires = pkg.vellum?.requires ?? { pluginRuntime: "v1" };
|
|
220
|
+
|
|
221
|
+
const manifest: PluginManifest = { name, version, requires };
|
|
222
|
+
const plugin: Plugin = { manifest };
|
|
223
|
+
|
|
224
|
+
const hooks = await loadHooks(pluginDir, name);
|
|
225
|
+
if (hooks !== undefined) plugin.hooks = hooks;
|
|
226
|
+
|
|
227
|
+
const tools: PluginToolRegistration[] = [];
|
|
228
|
+
for (const { path: toolPath } of listSurfaceDir(join(pluginDir, "tools"))) {
|
|
229
|
+
const tool = await importDefault<PluginToolRegistration>(toolPath);
|
|
230
|
+
if (
|
|
231
|
+
tool === null ||
|
|
232
|
+
typeof tool !== "object" ||
|
|
233
|
+
typeof (tool as { name?: unknown }).name !== "string"
|
|
234
|
+
) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`external plugin ${name}: ${toolPath} default export must be a Tool object with a string "name"`,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
tools.push(tool);
|
|
240
|
+
}
|
|
241
|
+
if (tools.length > 0) plugin.tools = tools;
|
|
242
|
+
|
|
243
|
+
return plugin;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Load the external plugin at `pluginDir` and register it.
|
|
248
|
+
*/
|
|
249
|
+
export async function loadExternalPlugin(
|
|
250
|
+
pluginDir: string,
|
|
251
|
+
opts: LoadExternalPluginOptions = {},
|
|
252
|
+
): Promise<void> {
|
|
253
|
+
const timeoutMs = opts.importTimeoutMs ?? DEFAULT_IMPORT_TIMEOUT_MS;
|
|
254
|
+
let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
|
|
255
|
+
try {
|
|
256
|
+
const timeoutSentinel = Symbol("external-plugin-load-timeout");
|
|
257
|
+
const buildPromise = buildPluginFromDir(pluginDir);
|
|
258
|
+
const timeoutPromise = new Promise<typeof timeoutSentinel>((resolve) => {
|
|
259
|
+
timeoutHandle = setTimeout(() => resolve(timeoutSentinel), timeoutMs);
|
|
260
|
+
});
|
|
261
|
+
const result = await Promise.race([buildPromise, timeoutPromise]);
|
|
262
|
+
if (result === timeoutSentinel) {
|
|
263
|
+
// Abandoned build — surface imports may still be running. Attach a
|
|
264
|
+
// terminal `.catch` so a late rejection does not surface as an
|
|
265
|
+
// unhandled-rejection crash. The closed-registration latch in
|
|
266
|
+
// `registry.ts` rejects any late `registerPlugin()` call from a
|
|
267
|
+
// surface module that finishes evaluating after this loader has
|
|
268
|
+
// moved on.
|
|
269
|
+
buildPromise.catch(() => {
|
|
270
|
+
/* swallow — see comment above */
|
|
271
|
+
});
|
|
272
|
+
log.warn(
|
|
273
|
+
{ pluginDir, timeoutMs },
|
|
274
|
+
`Timed out loading external plugin ${pluginDir} after ${timeoutMs}ms — skipping`,
|
|
275
|
+
);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
registerPlugin(result);
|
|
279
|
+
log.info(
|
|
280
|
+
{ pluginDir, name: result.manifest.name },
|
|
281
|
+
"loaded external plugin",
|
|
282
|
+
);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
// Per-plugin isolation: one bad external plugin must not crash the
|
|
285
|
+
// daemon. Surface the failure with attribution and move on.
|
|
286
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
287
|
+
log.error(
|
|
288
|
+
{ err, pluginDir },
|
|
289
|
+
`Failed to load external plugin ${pluginDir}: ${message}`,
|
|
290
|
+
);
|
|
291
|
+
} finally {
|
|
292
|
+
if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);
|
|
293
|
+
}
|
|
294
|
+
}
|
package/src/plugins/types.ts
CHANGED
|
@@ -93,30 +93,14 @@ export interface PluginManifest {
|
|
|
93
93
|
config?: unknown;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
// ─── Init context
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
/** Parsed config for this plugin (may be `unknown` until the manifest validates). */
|
|
105
|
-
config: unknown;
|
|
106
|
-
/** Resolved credential values keyed by the entries of `manifest.requiresCredential`. */
|
|
107
|
-
credentials: Record<string, string>;
|
|
108
|
-
/**
|
|
109
|
-
* Pino-compatible child logger bound to `{ plugin: <name> }`. Untyped here
|
|
110
|
-
* to avoid pulling pino into the types module.
|
|
111
|
-
*/
|
|
112
|
-
logger: unknown;
|
|
113
|
-
/** Absolute path to `<workspaceDir>/plugins-data/<plugin>/` (created by bootstrap). */
|
|
114
|
-
pluginStorageDir: string;
|
|
115
|
-
/** Assistant semver for compatibility checks inside the plugin. */
|
|
116
|
-
assistantVersion: string;
|
|
117
|
-
/** Capability → version-list map (`ASSISTANT_API_VERSIONS`) for defensive runtime checks. */
|
|
118
|
-
apiVersions: Record<string, string[]>;
|
|
119
|
-
}
|
|
96
|
+
// ─── Init / Shutdown context ─────────────────────────────────────────────────
|
|
97
|
+
// Public types — defined in `assistant/src/plugin-api/types.ts` and re-exported
|
|
98
|
+
// here so existing internal call sites keep working. Plugin authors will
|
|
99
|
+
// import these from `@vellumai/plugin-api` once that package is published.
|
|
100
|
+
export type {
|
|
101
|
+
PluginInitContext,
|
|
102
|
+
PluginShutdownContext,
|
|
103
|
+
} from "../plugin-api/types.js";
|
|
120
104
|
|
|
121
105
|
// ─── Middleware ──────────────────────────────────────────────────────────────
|
|
122
106
|
|
|
@@ -1077,19 +1061,51 @@ export interface PluginSkillRegistration {
|
|
|
1077
1061
|
|
|
1078
1062
|
// ─── Plugin ──────────────────────────────────────────────────────────────────
|
|
1079
1063
|
|
|
1064
|
+
/**
|
|
1065
|
+
* A plugin lifecycle hook. Receives a per-lifecycle context shape and
|
|
1066
|
+
* may return either a transformed context or `void`. Today's runtime
|
|
1067
|
+
* consumes only the resolved-or-rejected nature of the promise; the
|
|
1068
|
+
* `TCtx` return is reserved for future hooks that fan a transformed
|
|
1069
|
+
* context out to downstream plugins.
|
|
1070
|
+
*
|
|
1071
|
+
* Each known hook key has a documented context shape:
|
|
1072
|
+
* - `init` — {@link PluginInitContext}
|
|
1073
|
+
* - `shutdown` — {@link PluginShutdownContext}
|
|
1074
|
+
*
|
|
1075
|
+
* Unknown keys are populated by the loader for forward compatibility
|
|
1076
|
+
* but are not invoked by today's runtime.
|
|
1077
|
+
*/
|
|
1078
|
+
export type PluginHookFn<TCtx = unknown> = (
|
|
1079
|
+
ctx: TCtx,
|
|
1080
|
+
) => Promise<TCtx | void>;
|
|
1081
|
+
|
|
1082
|
+
/**
|
|
1083
|
+
* Map of lifecycle hooks contributed by a plugin. Keys match file
|
|
1084
|
+
* basenames under `<plugin>/hooks/` — the external loader populates one
|
|
1085
|
+
* entry per `hooks/<name>.{ts,js}` it finds. The runtime invokes
|
|
1086
|
+
* known keys (`init`, `shutdown`) at the matching lifecycle event;
|
|
1087
|
+
* unknown keys are forward-compat scaffolding.
|
|
1088
|
+
*
|
|
1089
|
+
* See `assistant/src/daemon/external-plugins-bootstrap.ts` for the
|
|
1090
|
+
* full lifecycle, and {@link PluginHookFn} for the per-entry signature.
|
|
1091
|
+
*/
|
|
1092
|
+
// The map stores hooks for arbitrary keys with arbitrary context shapes.
|
|
1093
|
+
// `any` (rather than `unknown`) is required so concrete plugin signatures
|
|
1094
|
+
// like `(ctx: PluginInitContext) => Promise<void>` and `() => Promise<void>`
|
|
1095
|
+
// both assign in/out of slot entries under strict-function-types contravariance.
|
|
1096
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1097
|
+
export type PluginHooks = Record<string, PluginHookFn<any>>;
|
|
1098
|
+
|
|
1080
1099
|
/**
|
|
1081
1100
|
* A registered plugin. Every field besides `manifest` is optional — a plugin
|
|
1082
1101
|
* may contribute any combination of middleware, injectors, and model-visible
|
|
1083
|
-
* capabilities. Lifecycle hooks
|
|
1084
|
-
* during daemon startup/shutdown.
|
|
1102
|
+
* capabilities. Lifecycle hooks live under `hooks`.
|
|
1085
1103
|
*/
|
|
1086
1104
|
export interface Plugin {
|
|
1087
1105
|
/** Static manifest validated by the registry. */
|
|
1088
1106
|
manifest: PluginManifest;
|
|
1089
|
-
/**
|
|
1090
|
-
|
|
1091
|
-
/** Optional shutdown hook. Runs during daemon shutdown in reverse-registration order. */
|
|
1092
|
-
onShutdown?(): Promise<void>;
|
|
1107
|
+
/** Lifecycle hooks (init, shutdown). See {@link PluginHooks}. */
|
|
1108
|
+
hooks?: PluginHooks;
|
|
1093
1109
|
/** Tool registrations visible to the model. */
|
|
1094
1110
|
tools?: PluginToolRegistration[];
|
|
1095
1111
|
/** HTTP route registrations served by the assistant. */
|
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* User plugin loader — discovers plugins under `<workspaceDir>/plugins/*`
|
|
3
|
-
*
|
|
2
|
+
* User plugin loader — discovers plugins under `<workspaceDir>/plugins/*` via
|
|
3
|
+
* one of two paths, gated by the contents of each candidate directory.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* `register.ts
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* **External plugin framework path** (`package.json` present **and** no
|
|
6
|
+
* `register.{ts,js}`): the harness delegates to {@link loadExternalPlugin},
|
|
7
|
+
* which builds a `Plugin` from the directory's interface dirs (`hooks/`,
|
|
8
|
+
* `tools/`) and registers it directly. This path is opt-in by the plugin
|
|
9
|
+
* author and currently experimental — see
|
|
10
|
+
* `assistant/src/plugins/external-plugin-loader.ts` for the full
|
|
11
|
+
* convention.
|
|
12
|
+
*
|
|
13
|
+
* **Legacy path** (`register.{ts,js}` present): the file is dynamic-imported
|
|
14
|
+
* and expected to call {@link registerPlugin} at import time as a side
|
|
15
|
+
* effect, populating the registry before {@link bootstrapPlugins} runs.
|
|
16
|
+
*
|
|
17
|
+
* The legacy path takes precedence when a directory contains both
|
|
18
|
+
* `package.json` and `register.{ts,js}` — a migration-friendly default
|
|
19
|
+
* that keeps existing plugins (including the in-repo `examples/plugins/echo`
|
|
20
|
+
* reference) working unchanged while we iterate the external-plugin
|
|
21
|
+
* convention. A directory matching neither path is skipped silently.
|
|
9
22
|
*
|
|
10
23
|
* The loader deliberately:
|
|
11
24
|
*
|
|
12
25
|
* - Uses `getWorkspaceDir()` so each instance loads its own plugin set
|
|
13
26
|
* when `VELLUM_WORKSPACE_DIR` is set.
|
|
14
|
-
* - Prefers
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - Treats any error from
|
|
18
|
-
* boundary
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* - Bounds each
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* daemon startup. Timed-out plugins are logged and skipped just like
|
|
25
|
-
* thrown-error plugins.
|
|
27
|
+
* - Prefers `.js` over `.ts` per surface file (compiled-binary semantics).
|
|
28
|
+
* The external loader applies the same rule per surface file; the
|
|
29
|
+
* legacy path picks between `register.js` and `register.ts`.
|
|
30
|
+
* - Treats any error from a plugin load as a per-plugin isolation
|
|
31
|
+
* boundary. {@link loadExternalPlugin} owns its own try/catch/timeout;
|
|
32
|
+
* the legacy path is wrapped here. One bad user plugin must not crash
|
|
33
|
+
* the daemon.
|
|
34
|
+
* - Bounds each plugin load with {@link USER_PLUGIN_IMPORT_TIMEOUT_MS}
|
|
35
|
+
* so a plugin whose top-level `await` hangs or whose module evaluation
|
|
36
|
+
* never resolves cannot stall daemon startup.
|
|
26
37
|
*
|
|
27
38
|
* Call order relative to the rest of the plugin system:
|
|
28
39
|
*
|
|
@@ -39,6 +50,7 @@ import { pathToFileURL } from "node:url";
|
|
|
39
50
|
|
|
40
51
|
import { getLogger } from "../util/logger.js";
|
|
41
52
|
import { getWorkspaceDir } from "../util/platform.js";
|
|
53
|
+
import { loadExternalPlugin } from "./external-plugin-loader.js";
|
|
42
54
|
import { closeRegistration } from "./registry.js";
|
|
43
55
|
|
|
44
56
|
const log = getLogger("user-plugin-loader");
|
|
@@ -55,9 +67,10 @@ const log = getLogger("user-plugin-loader");
|
|
|
55
67
|
const USER_PLUGIN_IMPORT_TIMEOUT_MS = 10_000;
|
|
56
68
|
|
|
57
69
|
/**
|
|
58
|
-
* Scan `getWorkspaceDir()/plugins/` for subdirectories
|
|
59
|
-
* `
|
|
60
|
-
*
|
|
70
|
+
* Scan `getWorkspaceDir()/plugins/` for subdirectories, then dispatch each
|
|
71
|
+
* one to the external loader (if `package.json` is present and there is no
|
|
72
|
+
* `register.{ts,js}`) or the legacy side-effect importer (if
|
|
73
|
+
* `register.{ts,js}` is present).
|
|
61
74
|
*
|
|
62
75
|
* Invariants:
|
|
63
76
|
*
|
|
@@ -68,24 +81,24 @@ const USER_PLUGIN_IMPORT_TIMEOUT_MS = 10_000;
|
|
|
68
81
|
* - Does not return plugin instances. The registry is the single source of
|
|
69
82
|
* truth for who got registered, and the caller inspects it directly.
|
|
70
83
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
84
|
+
* Caller responsibilities:
|
|
85
|
+
*
|
|
86
|
+
* - Must be invoked exactly once during daemon startup, before
|
|
87
|
+
* `bootstrapPlugins()` walks the registry.
|
|
88
|
+
* - Holds no locks during the import — bun's dynamic `import()` resolution
|
|
89
|
+
* is concurrency-safe.
|
|
74
90
|
*/
|
|
75
91
|
export async function loadUserPlugins(
|
|
76
92
|
options: { importTimeoutMs?: number } = {},
|
|
77
93
|
): Promise<void> {
|
|
78
|
-
const importTimeoutMs =
|
|
79
|
-
|
|
94
|
+
const importTimeoutMs = options.importTimeoutMs ?? USER_PLUGIN_IMPORT_TIMEOUT_MS;
|
|
95
|
+
|
|
80
96
|
const pluginsDir = join(getWorkspaceDir(), "plugins");
|
|
97
|
+
|
|
81
98
|
if (!existsSync(pluginsDir)) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
);
|
|
86
|
-
// Close the registration window even on the fast path so a late arrival
|
|
87
|
-
// from an unrelated source (e.g. a mis-ordered static import) still can't
|
|
88
|
-
// slip in after bootstrap walks the registry.
|
|
99
|
+
// The clean-install case. Closing the registration window keeps the
|
|
100
|
+
// post-loader invariant uniform: `bootstrapPlugins()` may rely on the
|
|
101
|
+
// registry being final by the time `loadUserPlugins()` resolves.
|
|
89
102
|
closeRegistration();
|
|
90
103
|
return;
|
|
91
104
|
}
|
|
@@ -118,10 +131,12 @@ export async function loadUserPlugins(
|
|
|
118
131
|
}
|
|
119
132
|
if (!stats.isDirectory()) continue;
|
|
120
133
|
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
134
|
+
// Path selection: the legacy side-effect path takes precedence when
|
|
135
|
+
// both a `register.{ts,js}` and a `package.json` are present.
|
|
136
|
+
// Migration-friendly: any plugin in the wild today that happens to
|
|
137
|
+
// ship a `package.json` keeps loading via its existing register entry.
|
|
138
|
+
// The external-plugin path only fires when the directory is
|
|
139
|
+
// unambiguously the new convention.
|
|
125
140
|
const jsPath = join(pluginDir, "register.js");
|
|
126
141
|
const tsPath = join(pluginDir, "register.ts");
|
|
127
142
|
let registerPath: string | undefined;
|
|
@@ -130,16 +145,24 @@ export async function loadUserPlugins(
|
|
|
130
145
|
} else if (existsSync(tsPath)) {
|
|
131
146
|
registerPath = tsPath;
|
|
132
147
|
}
|
|
133
|
-
|
|
148
|
+
|
|
149
|
+
if (registerPath === undefined) {
|
|
150
|
+
// External plugin framework path. `loadExternalPlugin` owns its own
|
|
151
|
+
// try/catch + timeout, so a `continue` is the entire branch here.
|
|
152
|
+
if (existsSync(join(pluginDir, "package.json"))) {
|
|
153
|
+
await loadExternalPlugin(pluginDir, { importTimeoutMs });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
134
156
|
log.debug(
|
|
135
157
|
{ pluginDir },
|
|
136
|
-
"loadUserPlugins: no register.{ts,js} — skipping",
|
|
158
|
+
"loadUserPlugins: no register.{ts,js} or package.json — skipping",
|
|
137
159
|
);
|
|
138
160
|
continue;
|
|
139
161
|
}
|
|
140
162
|
|
|
141
|
-
// `import()` with a `file://` URL
|
|
142
|
-
// and sidesteps platform-specific
|
|
163
|
+
// Legacy side-effect import path. `import()` with a `file://` URL
|
|
164
|
+
// works identically under Node and bun and sidesteps platform-specific
|
|
165
|
+
// absolute-path quirks on Windows.
|
|
143
166
|
const moduleUrl = pathToFileURL(registerPath).href;
|
|
144
167
|
let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
|
|
145
168
|
try {
|