@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,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace migration `076-home-feed-notification-only`.
|
|
3
|
+
*
|
|
4
|
+
* Rewrites `<workspace>/data/home-feed.json` from the legacy v1 schema
|
|
5
|
+
* (mixed `nudge | digest | action | thread` types with `source`,
|
|
6
|
+
* `author`, `minTimeAway` fields) into the collapsed v2 schema (single
|
|
7
|
+
* `notification` type, no source/author/minTimeAway).
|
|
8
|
+
*
|
|
9
|
+
* Behaviour:
|
|
10
|
+
* - Missing file → no-op.
|
|
11
|
+
* - Malformed JSON → log and no-op (daemon startup must never block;
|
|
12
|
+
* the writer's `readHomeFeed()` already treats unreadable files as
|
|
13
|
+
* empty so the next append cycle naturally rewrites a clean file).
|
|
14
|
+
* - Already v2 → no-op (idempotent).
|
|
15
|
+
* - v1 (or any non-v2 shape with an `items` array): drop entries
|
|
16
|
+
* whose `type !== "action"` (legacy nudge/digest/thread items have
|
|
17
|
+
* no v2 analogue and weren't surfaced as live notifications anyway,
|
|
18
|
+
* per PR 15 of the home-notif-feed-revamp plan); for kept entries
|
|
19
|
+
* drop `source` / `author` / `minTimeAway` and rewrite `type` to
|
|
20
|
+
* `"notification"`. Persist as `{ version: 2, items, updatedAt }`.
|
|
21
|
+
*
|
|
22
|
+
* Idempotent: running the migration a second time on a v2 file is a
|
|
23
|
+
* no-op. The runner's checkpoint also skips re-runs, but this in-file
|
|
24
|
+
* guard keeps the migration safe even if the checkpoint is wiped.
|
|
25
|
+
*
|
|
26
|
+
* `down()` is a no-op — the legacy v1 fields (`source`, `author`,
|
|
27
|
+
* `minTimeAway`, the four item types) were dropped during the
|
|
28
|
+
* forward migration and cannot be recovered. Rolling back to v1 from
|
|
29
|
+
* v2 would also leave the writer producing a shape the older code
|
|
30
|
+
* cannot parse, so a real rollback would require reverting the writer
|
|
31
|
+
* code in lockstep.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
35
|
+
import { join } from "node:path";
|
|
36
|
+
|
|
37
|
+
import { getLogger } from "../../util/logger.js";
|
|
38
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
39
|
+
|
|
40
|
+
const log = getLogger("workspace-migration-076-home-feed-notification-only");
|
|
41
|
+
|
|
42
|
+
const HOME_FEED_RELATIVE_PATH = join("data", "home-feed.json");
|
|
43
|
+
|
|
44
|
+
/** v2 file format. Mirrors `HomeFeedFile` in `home/feed-types.ts`. */
|
|
45
|
+
interface V2HomeFeedFile {
|
|
46
|
+
version: 2;
|
|
47
|
+
items: V2FeedItem[];
|
|
48
|
+
updatedAt: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* v2 item shape. Inlined rather than imported from `home/feed-types.ts`
|
|
53
|
+
* so the migration stays self-contained — per AGENTS.md migrations
|
|
54
|
+
* should minimise cross-module coupling so they remain stable as code
|
|
55
|
+
* around them evolves.
|
|
56
|
+
*/
|
|
57
|
+
interface V2FeedItem {
|
|
58
|
+
id: string;
|
|
59
|
+
type: "notification";
|
|
60
|
+
priority: number;
|
|
61
|
+
title: string;
|
|
62
|
+
summary: string;
|
|
63
|
+
timestamp: string;
|
|
64
|
+
status: string;
|
|
65
|
+
expiresAt?: string;
|
|
66
|
+
actions?: unknown[];
|
|
67
|
+
urgency?: string;
|
|
68
|
+
conversationId?: string;
|
|
69
|
+
detailPanel?: unknown;
|
|
70
|
+
createdAt: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const homeFeedNotificationOnlyMigration: WorkspaceMigration = {
|
|
74
|
+
id: "home-feed-notification-only-v2",
|
|
75
|
+
description:
|
|
76
|
+
"Rewrite home-feed.json into v2 schema (single 'notification' type)",
|
|
77
|
+
|
|
78
|
+
run(workspaceDir: string): void {
|
|
79
|
+
const path = join(workspaceDir, HOME_FEED_RELATIVE_PATH);
|
|
80
|
+
if (!existsSync(path)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let raw: unknown;
|
|
85
|
+
try {
|
|
86
|
+
raw = JSON.parse(readFileSync(path, "utf-8"));
|
|
87
|
+
} catch (err) {
|
|
88
|
+
// Daemon startup must never block on a parse failure here. The
|
|
89
|
+
// writer's read path also treats malformed files as empty, so
|
|
90
|
+
// skipping the migration just means the next append cycle will
|
|
91
|
+
// overwrite the file with a fresh v2 snapshot.
|
|
92
|
+
log.warn(
|
|
93
|
+
{ err, path },
|
|
94
|
+
"Failed to parse home-feed.json; skipping migration",
|
|
95
|
+
);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!isPlainObject(raw)) {
|
|
100
|
+
log.warn({ path }, "home-feed.json is not an object; skipping migration");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (raw.version === 2) {
|
|
105
|
+
// Already migrated.
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const rawItems = Array.isArray(raw.items) ? raw.items : [];
|
|
110
|
+
const items: V2FeedItem[] = [];
|
|
111
|
+
for (const entry of rawItems) {
|
|
112
|
+
const migrated = migrateItem(entry);
|
|
113
|
+
if (migrated) items.push(migrated);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const next: V2HomeFeedFile = {
|
|
117
|
+
version: 2,
|
|
118
|
+
items,
|
|
119
|
+
updatedAt: new Date().toISOString(),
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
writeFileSync(path, JSON.stringify(next, null, 2), "utf-8");
|
|
124
|
+
log.info(
|
|
125
|
+
{ path, items: items.length },
|
|
126
|
+
"Rewrote home-feed.json to v2 schema",
|
|
127
|
+
);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
log.warn(
|
|
130
|
+
{ err, path },
|
|
131
|
+
"Failed to write migrated home-feed.json; leaving prior file in place",
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
down(_workspaceDir: string): void {
|
|
137
|
+
// Lossy migration — legacy fields (source/author/minTimeAway and
|
|
138
|
+
// nudge/digest/thread items) cannot be reconstructed. The writer
|
|
139
|
+
// code itself only emits v2 now, so rolling back would also leave
|
|
140
|
+
// the file in a shape the v1 reader could not parse without
|
|
141
|
+
// reverting feed-writer.ts in lockstep.
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Convert a single legacy item into a v2 item, or return `null` to
|
|
147
|
+
* drop it. Only `type === "action"` items survive — legacy
|
|
148
|
+
* nudge/digest/thread entries have no v2 analogue and were not
|
|
149
|
+
* surfaced as live notifications by PR 4's wiring (only assistant-
|
|
150
|
+
* authored `action` items reached the live feed via
|
|
151
|
+
* `home-feed-side-effect.ts`).
|
|
152
|
+
*/
|
|
153
|
+
function migrateItem(entry: unknown): V2FeedItem | null {
|
|
154
|
+
if (!isPlainObject(entry)) return null;
|
|
155
|
+
if (entry.type !== "action") return null;
|
|
156
|
+
|
|
157
|
+
// Required fields — fail-soft on missing critical strings rather
|
|
158
|
+
// than throwing, so a single bad legacy entry does not lose the
|
|
159
|
+
// rest of the items.
|
|
160
|
+
if (
|
|
161
|
+
typeof entry.id !== "string" ||
|
|
162
|
+
typeof entry.title !== "string" ||
|
|
163
|
+
typeof entry.summary !== "string" ||
|
|
164
|
+
typeof entry.timestamp !== "string" ||
|
|
165
|
+
typeof entry.createdAt !== "string"
|
|
166
|
+
) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const priority =
|
|
170
|
+
typeof entry.priority === "number" && Number.isInteger(entry.priority)
|
|
171
|
+
? entry.priority
|
|
172
|
+
: 50;
|
|
173
|
+
const status = typeof entry.status === "string" ? entry.status : "new";
|
|
174
|
+
|
|
175
|
+
const out: V2FeedItem = {
|
|
176
|
+
id: entry.id,
|
|
177
|
+
type: "notification",
|
|
178
|
+
priority,
|
|
179
|
+
title: entry.title,
|
|
180
|
+
summary: entry.summary,
|
|
181
|
+
timestamp: entry.timestamp,
|
|
182
|
+
status,
|
|
183
|
+
createdAt: entry.createdAt,
|
|
184
|
+
};
|
|
185
|
+
if (typeof entry.expiresAt === "string") out.expiresAt = entry.expiresAt;
|
|
186
|
+
if (Array.isArray(entry.actions)) out.actions = entry.actions;
|
|
187
|
+
if (typeof entry.urgency === "string") out.urgency = entry.urgency;
|
|
188
|
+
if (typeof entry.conversationId === "string") {
|
|
189
|
+
out.conversationId = entry.conversationId;
|
|
190
|
+
}
|
|
191
|
+
if (isPlainObject(entry.detailPanel)) out.detailPanel = entry.detailPanel;
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
196
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
197
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace migration `080-restrict-vercel-api-token-metadata`.
|
|
3
|
+
*
|
|
4
|
+
* Repairs legacy Vercel API token credential metadata that was stored
|
|
5
|
+
* with overly permissive policy (e.g. `bash` in allowedTools and
|
|
6
|
+
* injection templates targeting `api.vercel.com`). Rewrites the
|
|
7
|
+
* Vercel record to the hardened policy:
|
|
8
|
+
*
|
|
9
|
+
* - `allowedTools: ["publish_page", "unpublish_page"]`
|
|
10
|
+
* - `allowedDomains: []`
|
|
11
|
+
* - `injectionTemplates` removed
|
|
12
|
+
*
|
|
13
|
+
* Behaviour:
|
|
14
|
+
* - Missing metadata file -> no-op.
|
|
15
|
+
* - Malformed JSON -> log and no-op.
|
|
16
|
+
* - Unrecognized future schema version -> no-op.
|
|
17
|
+
* - No `vercel`/`api_token` credential record -> no-op.
|
|
18
|
+
* - Already matches target policy -> no-op (no rewrite, no updatedAt bump).
|
|
19
|
+
* - Non-Vercel credential records are never modified.
|
|
20
|
+
*
|
|
21
|
+
* Idempotent: running twice produces no second write. The runner's
|
|
22
|
+
* checkpoint also prevents re-runs, but this in-file guard keeps the
|
|
23
|
+
* migration safe even if the checkpoint is wiped.
|
|
24
|
+
*
|
|
25
|
+
* This migration never touches secure secret values — only the
|
|
26
|
+
* metadata policy fields.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
30
|
+
import { join } from "node:path";
|
|
31
|
+
|
|
32
|
+
import { getLogger } from "../../util/logger.js";
|
|
33
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
34
|
+
|
|
35
|
+
const log = getLogger(
|
|
36
|
+
"workspace-migration-080-restrict-vercel-api-token-metadata",
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const METADATA_RELATIVE_PATH = join("data", "credentials", "metadata.json");
|
|
40
|
+
|
|
41
|
+
/** Known on-disk schema versions we can safely handle. */
|
|
42
|
+
const KNOWN_VERSIONS = new Set([1, 2, 3, 4, 5]);
|
|
43
|
+
|
|
44
|
+
/** The hardened target policy for the Vercel API token. */
|
|
45
|
+
const TARGET_ALLOWED_TOOLS = ["publish_page", "unpublish_page"];
|
|
46
|
+
const TARGET_ALLOWED_DOMAINS: string[] = [];
|
|
47
|
+
|
|
48
|
+
export const restrictVercelApiTokenMetadataMigration: WorkspaceMigration = {
|
|
49
|
+
id: "080-restrict-vercel-api-token-metadata",
|
|
50
|
+
description:
|
|
51
|
+
"Restrict existing Vercel API token metadata to publish tools only",
|
|
52
|
+
|
|
53
|
+
run(workspaceDir: string): void {
|
|
54
|
+
const metadataPath = join(workspaceDir, METADATA_RELATIVE_PATH);
|
|
55
|
+
if (!existsSync(metadataPath)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let raw: string;
|
|
60
|
+
try {
|
|
61
|
+
raw = readFileSync(metadataPath, "utf-8");
|
|
62
|
+
} catch (err) {
|
|
63
|
+
log.warn(
|
|
64
|
+
{ err, path: metadataPath },
|
|
65
|
+
"Failed to read credentials metadata; skipping migration",
|
|
66
|
+
);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let parsed: unknown;
|
|
71
|
+
try {
|
|
72
|
+
parsed = JSON.parse(raw);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
log.warn(
|
|
75
|
+
{ err, path: metadataPath },
|
|
76
|
+
"Failed to parse credentials metadata JSON; skipping migration",
|
|
77
|
+
);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!isPlainObject(parsed)) {
|
|
82
|
+
log.warn(
|
|
83
|
+
{ path: metadataPath },
|
|
84
|
+
"Credentials metadata is not an object; skipping migration",
|
|
85
|
+
);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Respect unrecognized future schema versions — do not touch the file.
|
|
90
|
+
const version = typeof parsed.version === "number" ? parsed.version : 1;
|
|
91
|
+
if (!KNOWN_VERSIONS.has(version)) {
|
|
92
|
+
log.info(
|
|
93
|
+
{ version, path: metadataPath },
|
|
94
|
+
"Credentials metadata has unrecognized version; skipping migration",
|
|
95
|
+
);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const credentials = Array.isArray(parsed.credentials)
|
|
100
|
+
? parsed.credentials
|
|
101
|
+
: [];
|
|
102
|
+
|
|
103
|
+
// Find the Vercel API token record.
|
|
104
|
+
const vercelIdx = credentials.findIndex(
|
|
105
|
+
(c: unknown) =>
|
|
106
|
+
isPlainObject(c) && c.service === "vercel" && c.field === "api_token",
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (vercelIdx === -1) {
|
|
110
|
+
// No Vercel credential — nothing to repair.
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const vercelRecord = credentials[vercelIdx] as Record<string, unknown>;
|
|
115
|
+
|
|
116
|
+
// Check if already matches target policy.
|
|
117
|
+
if (alreadyMatchesTarget(vercelRecord)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Rewrite the Vercel record to the target policy.
|
|
122
|
+
vercelRecord.allowedTools = TARGET_ALLOWED_TOOLS;
|
|
123
|
+
vercelRecord.allowedDomains = TARGET_ALLOWED_DOMAINS;
|
|
124
|
+
delete vercelRecord.injectionTemplates;
|
|
125
|
+
vercelRecord.updatedAt = Date.now();
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
writeFileSync(metadataPath, JSON.stringify(parsed, null, 2), "utf-8");
|
|
129
|
+
log.info(
|
|
130
|
+
{ path: metadataPath },
|
|
131
|
+
"Repaired Vercel API token metadata to hardened policy",
|
|
132
|
+
);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
log.warn(
|
|
135
|
+
{ err, path: metadataPath },
|
|
136
|
+
"Failed to write repaired credentials metadata; leaving prior file in place",
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
down(_workspaceDir: string): void {
|
|
142
|
+
// Cannot recover the original vulnerable policy — and we would not
|
|
143
|
+
// want to even if we could. This is a security hardening migration.
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Returns true when the Vercel record already matches the target
|
|
149
|
+
* hardened policy, meaning no rewrite is necessary.
|
|
150
|
+
*/
|
|
151
|
+
function alreadyMatchesTarget(record: Record<string, unknown>): boolean {
|
|
152
|
+
const tools = record.allowedTools;
|
|
153
|
+
const domains = record.allowedDomains;
|
|
154
|
+
|
|
155
|
+
if (!Array.isArray(tools) || tools.length !== TARGET_ALLOWED_TOOLS.length) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const sortedTools = [...tools].sort();
|
|
159
|
+
const sortedTarget = [...TARGET_ALLOWED_TOOLS].sort();
|
|
160
|
+
for (let i = 0; i < sortedTools.length; i++) {
|
|
161
|
+
if (sortedTools[i] !== sortedTarget[i]) return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!Array.isArray(domains) || domains.length !== 0) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// injectionTemplates must be absent or undefined.
|
|
169
|
+
if (
|
|
170
|
+
"injectionTemplates" in record &&
|
|
171
|
+
record.injectionTemplates !== undefined &&
|
|
172
|
+
record.injectionTemplates !== null
|
|
173
|
+
) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
181
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
182
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace migration `081-backfill-bash-allowed-tools-for-injection-credentials`.
|
|
3
|
+
*
|
|
4
|
+
* After migration 080 stripped Vercel's injection templates and locked
|
|
5
|
+
* its `allowedTools` to `["publish_page", "unpublish_page"]`, the new
|
|
6
|
+
* shell.ts credential policy enforcement (`isToolAllowed("bash", meta.allowedTools)`)
|
|
7
|
+
* would reject every other service that legitimately uses proxied bash
|
|
8
|
+
* via injection templates — because their `allowedTools` was never populated.
|
|
9
|
+
*
|
|
10
|
+
* This migration backfills `"bash"` into `allowedTools` for any credential
|
|
11
|
+
* that:
|
|
12
|
+
* 1. Has a non-empty `injectionTemplates` array (i.e., it uses proxied bash).
|
|
13
|
+
* 2. Has empty or missing `allowedTools`.
|
|
14
|
+
*
|
|
15
|
+
* Credentials that already have populated `allowedTools` (like the
|
|
16
|
+
* now-hardened Vercel credential) are NOT touched.
|
|
17
|
+
*
|
|
18
|
+
* Behaviour:
|
|
19
|
+
* - Missing metadata file -> no-op.
|
|
20
|
+
* - Malformed JSON -> log and no-op.
|
|
21
|
+
* - Unrecognized future schema version -> no-op.
|
|
22
|
+
* - No qualifying credentials -> no-op (no rewrite).
|
|
23
|
+
* - Already backfilled -> no-op (idempotent).
|
|
24
|
+
*
|
|
25
|
+
* Idempotent: running twice produces no second write.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
|
|
31
|
+
import { getLogger } from "../../util/logger.js";
|
|
32
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
33
|
+
|
|
34
|
+
const log = getLogger(
|
|
35
|
+
"workspace-migration-081-backfill-bash-allowed-tools-for-injection-credentials",
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const METADATA_RELATIVE_PATH = join("data", "credentials", "metadata.json");
|
|
39
|
+
|
|
40
|
+
/** Known on-disk schema versions we can safely handle. */
|
|
41
|
+
const KNOWN_VERSIONS = new Set([1, 2, 3, 4, 5]);
|
|
42
|
+
|
|
43
|
+
export const backfillBashAllowedToolsForInjectionCredentialsMigration: WorkspaceMigration =
|
|
44
|
+
{
|
|
45
|
+
id: "081-backfill-bash-allowed-tools-for-injection-credentials",
|
|
46
|
+
description:
|
|
47
|
+
"Backfill bash into allowedTools for credentials with injection templates",
|
|
48
|
+
|
|
49
|
+
run(workspaceDir: string): void {
|
|
50
|
+
const metadataPath = join(workspaceDir, METADATA_RELATIVE_PATH);
|
|
51
|
+
if (!existsSync(metadataPath)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let raw: string;
|
|
56
|
+
try {
|
|
57
|
+
raw = readFileSync(metadataPath, "utf-8");
|
|
58
|
+
} catch (err) {
|
|
59
|
+
log.warn(
|
|
60
|
+
{ err, path: metadataPath },
|
|
61
|
+
"Failed to read credentials metadata; skipping migration",
|
|
62
|
+
);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let parsed: unknown;
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(raw);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
log.warn(
|
|
71
|
+
{ err, path: metadataPath },
|
|
72
|
+
"Failed to parse credentials metadata JSON; skipping migration",
|
|
73
|
+
);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!isPlainObject(parsed)) {
|
|
78
|
+
log.warn(
|
|
79
|
+
{ path: metadataPath },
|
|
80
|
+
"Credentials metadata is not an object; skipping migration",
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Respect unrecognized future schema versions — do not touch the file.
|
|
86
|
+
const version = typeof parsed.version === "number" ? parsed.version : 1;
|
|
87
|
+
if (!KNOWN_VERSIONS.has(version)) {
|
|
88
|
+
log.info(
|
|
89
|
+
{ version, path: metadataPath },
|
|
90
|
+
"Credentials metadata has unrecognized version; skipping migration",
|
|
91
|
+
);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const credentials = Array.isArray(parsed.credentials)
|
|
96
|
+
? parsed.credentials
|
|
97
|
+
: [];
|
|
98
|
+
|
|
99
|
+
let modified = false;
|
|
100
|
+
|
|
101
|
+
for (const cred of credentials) {
|
|
102
|
+
if (!isPlainObject(cred)) continue;
|
|
103
|
+
|
|
104
|
+
// Only target credentials with non-empty injectionTemplates.
|
|
105
|
+
if (!hasNonEmptyInjectionTemplates(cred)) continue;
|
|
106
|
+
|
|
107
|
+
// Only target credentials with empty or missing allowedTools.
|
|
108
|
+
if (hasPopulatedAllowedTools(cred)) continue;
|
|
109
|
+
|
|
110
|
+
// Backfill "bash" into allowedTools.
|
|
111
|
+
cred.allowedTools = ["bash"];
|
|
112
|
+
cred.updatedAt = Date.now();
|
|
113
|
+
modified = true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!modified) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
writeFileSync(metadataPath, JSON.stringify(parsed, null, 2), "utf-8");
|
|
122
|
+
log.info(
|
|
123
|
+
{ path: metadataPath },
|
|
124
|
+
"Backfilled bash into allowedTools for credentials with injection templates",
|
|
125
|
+
);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
log.warn(
|
|
128
|
+
{ err, path: metadataPath },
|
|
129
|
+
"Failed to write backfilled credentials metadata; leaving prior file in place",
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
down(_workspaceDir: string): void {
|
|
135
|
+
// This is a forward-only data repair. Rolling back would re-break
|
|
136
|
+
// proxied bash for affected services.
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Returns true when the credential has a non-empty `injectionTemplates` array.
|
|
142
|
+
*/
|
|
143
|
+
function hasNonEmptyInjectionTemplates(
|
|
144
|
+
record: Record<string, unknown>,
|
|
145
|
+
): boolean {
|
|
146
|
+
const templates = record.injectionTemplates;
|
|
147
|
+
return Array.isArray(templates) && templates.length > 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Returns true when the credential has a populated (non-empty) `allowedTools` array.
|
|
152
|
+
*/
|
|
153
|
+
function hasPopulatedAllowedTools(record: Record<string, unknown>): boolean {
|
|
154
|
+
const tools = record.allowedTools;
|
|
155
|
+
return Array.isArray(tools) && tools.length > 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
159
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
160
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace migration `082-backfill-managed-profile-labels`.
|
|
3
|
+
*
|
|
4
|
+
* Backfills `label` on the three canonical managed inference profiles
|
|
5
|
+
* (`balanced`, `quality-optimized`, `cost-optimized`) when the on-disk
|
|
6
|
+
* profile is missing it.
|
|
7
|
+
*
|
|
8
|
+
* Why this is needed
|
|
9
|
+
* ------------------
|
|
10
|
+
* Migration 052 (`seed-default-inference-profiles`) seeds the three
|
|
11
|
+
* canonical Anthropic profiles with provider/model/maxTokens/effort/
|
|
12
|
+
* thinking but **no `label`** field. The runtime profile seeder
|
|
13
|
+
* (`seedInferenceProfiles`) materializes labels on its second pass —
|
|
14
|
+
* but only when the profile didn't already exist. In platform mode
|
|
15
|
+
* (`IS_PLATFORM=true`) it deliberately defers to the existing on-disk
|
|
16
|
+
* entry to avoid clobbering platform-supplied overlay fragments, so the
|
|
17
|
+
* label never gets written.
|
|
18
|
+
*
|
|
19
|
+
* Net result: a fresh Cloud-hosted assistant (Marina QA #5, 0.8.1) shows
|
|
20
|
+
* raw slugs in the profile picker — `balanced`, `quality-optimized`,
|
|
21
|
+
* `cost-optimized` — instead of the human labels `Balanced`, `Quality`,
|
|
22
|
+
* `Speed`. This migration heals existing installs by writing the bare
|
|
23
|
+
* template label when absent.
|
|
24
|
+
*
|
|
25
|
+
* Behavior
|
|
26
|
+
* --------
|
|
27
|
+
* - Missing config.json -> no-op.
|
|
28
|
+
* - Malformed JSON -> log and no-op.
|
|
29
|
+
* - `llm.profiles` absent -> no-op.
|
|
30
|
+
* - For each canonical name: backfill `label` only when the key is
|
|
31
|
+
* absent on disk. An explicit `null` (user cleared the label) is
|
|
32
|
+
* preserved. A user-set string is preserved.
|
|
33
|
+
* - Non-canonical profile names are never touched.
|
|
34
|
+
*
|
|
35
|
+
* Idempotent: running twice produces no second write.
|
|
36
|
+
*
|
|
37
|
+
* Does NOT skip on `VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH`: the platform
|
|
38
|
+
* overlay supplies its own label when it cares, and the runtime seeder's
|
|
39
|
+
* `preservedProfileNames` skip path will defer to that overlay-supplied
|
|
40
|
+
* label on every boot. This migration only fills the gap when no source
|
|
41
|
+
* (overlay, migration 052, or seeder) ever wrote a label.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
45
|
+
import { join } from "node:path";
|
|
46
|
+
|
|
47
|
+
import { getLogger } from "../../util/logger.js";
|
|
48
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
49
|
+
|
|
50
|
+
const log = getLogger("workspace-migration-082-backfill-managed-profile-labels");
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Bare template labels for the canonical managed profile triplet. Kept in
|
|
54
|
+
* sync with `MANAGED_PROFILE_TEMPLATES` in
|
|
55
|
+
* `assistant/src/config/seed-inference-profiles.ts`. Duplicated here
|
|
56
|
+
* intentionally — migrations are forward-only and self-contained per the
|
|
57
|
+
* workspace migrations AGENTS contract; future renames in the seeder
|
|
58
|
+
* must NOT retroactively change the data this migration writes.
|
|
59
|
+
*/
|
|
60
|
+
const CANONICAL_MANAGED_PROFILE_LABELS: Record<string, string> = {
|
|
61
|
+
balanced: "Balanced",
|
|
62
|
+
"quality-optimized": "Quality",
|
|
63
|
+
"cost-optimized": "Speed",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const backfillManagedProfileLabelsMigration: WorkspaceMigration = {
|
|
67
|
+
id: "082-backfill-managed-profile-labels",
|
|
68
|
+
description:
|
|
69
|
+
"Backfill label on canonical managed inference profiles when absent",
|
|
70
|
+
|
|
71
|
+
run(workspaceDir: string): void {
|
|
72
|
+
const configPath = join(workspaceDir, "config.json");
|
|
73
|
+
if (!existsSync(configPath)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let raw: string;
|
|
78
|
+
try {
|
|
79
|
+
raw = readFileSync(configPath, "utf-8");
|
|
80
|
+
} catch (err) {
|
|
81
|
+
log.warn(
|
|
82
|
+
{ err, path: configPath },
|
|
83
|
+
"Failed to read config.json; skipping migration",
|
|
84
|
+
);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let parsed: unknown;
|
|
89
|
+
try {
|
|
90
|
+
parsed = JSON.parse(raw);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
log.warn(
|
|
93
|
+
{ err, path: configPath },
|
|
94
|
+
"Failed to parse config.json; skipping migration",
|
|
95
|
+
);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!isPlainObject(parsed)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const llm = readObject(parsed.llm);
|
|
104
|
+
if (!llm) return;
|
|
105
|
+
|
|
106
|
+
const profiles = readObject(llm.profiles);
|
|
107
|
+
if (!profiles) return;
|
|
108
|
+
|
|
109
|
+
let modified = false;
|
|
110
|
+
|
|
111
|
+
for (const [name, label] of Object.entries(
|
|
112
|
+
CANONICAL_MANAGED_PROFILE_LABELS,
|
|
113
|
+
)) {
|
|
114
|
+
const profile = readObject(profiles[name]);
|
|
115
|
+
if (!profile) continue;
|
|
116
|
+
// Only backfill when the key is absent. Explicit `null` (user cleared
|
|
117
|
+
// the label) and any user-set string both signal intent and survive.
|
|
118
|
+
if ("label" in profile) continue;
|
|
119
|
+
profile.label = label;
|
|
120
|
+
modified = true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!modified) return;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
writeFileSync(configPath, JSON.stringify(parsed, null, 2) + "\n", "utf-8");
|
|
127
|
+
log.info(
|
|
128
|
+
{ path: configPath },
|
|
129
|
+
"Backfilled missing labels on canonical managed inference profiles",
|
|
130
|
+
);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
log.warn(
|
|
133
|
+
{ err, path: configPath },
|
|
134
|
+
"Failed to write backfilled config.json; leaving prior file in place",
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
down(_workspaceDir: string): void {
|
|
140
|
+
// Forward-only data repair. Rolling back would re-break the picker
|
|
141
|
+
// for installs whose only label source was this migration.
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
function readObject(value: unknown): Record<string, unknown> | null {
|
|
146
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
return value as Record<string, unknown>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
153
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
154
|
+
}
|