@vellumai/assistant 0.8.0 → 0.8.2
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 +2 -7
- package/Dockerfile +80 -5
- package/README.md +2 -2
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +21 -0
- package/docker-init-apt-root.sh +94 -0
- package/docker-kata-apt-env.sh +39 -0
- package/docs/plugins.md +88 -47
- package/docs/skills.md +9 -7
- 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/examples/plugins/echo/README.md +27 -27
- package/examples/plugins/echo/package.json +3 -0
- package/examples/plugins/echo/register.ts +31 -31
- package/knip.json +2 -1
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
- package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
- package/openapi.yaml +4462 -991
- package/package.json +5 -1
- package/scripts/generate-openapi.ts +135 -14
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +129 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-image-optimize.test.ts +11 -3
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
- package/src/__tests__/anthropic-provider.test.ts +137 -2
- package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/app-executors.test.ts +220 -4
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
- 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__/bundled-asset.test.ts +6 -6
- 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-availability-routes.test.ts +206 -0
- package/src/__tests__/channel-delivery-store.test.ts +289 -1
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
- package/src/__tests__/clawhub.test.ts +75 -16
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
- 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__/compactor-tail-resolution.test.ts +41 -0
- 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 +77 -23
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +35 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +278 -0
- package/src/__tests__/config-sounds-sync.test.ts +97 -0
- package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -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 +159 -18
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -4
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-search-workspace-source.test.ts +7 -0
- package/src/__tests__/context-token-estimator.test.ts +1 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +93 -92
- package/src/__tests__/conversation-agent-loop.test.ts +2 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +80 -3
- package/src/__tests__/conversation-fork-crud.test.ts +323 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +54 -18
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
- package/src/__tests__/conversation-lifecycle.test.ts +297 -0
- package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +25 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
- package/src/__tests__/conversation-queue.test.ts +4 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +80 -13
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-slash-queue.test.ts +59 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
- package/src/__tests__/conversation-sync-tags.test.ts +235 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +8 -8
- 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__/db-slack-external-content-normalization.test.ts +301 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
- package/src/__tests__/disk-pressure-tools.test.ts +1 -0
- package/src/__tests__/dm-backfill.test.ts +121 -10
- package/src/__tests__/document-tool-security.test.ts +258 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/edit-propagation.test.ts +33 -0
- package/src/__tests__/empty-response-pipeline.test.ts +0 -4
- package/src/__tests__/external-plugin-loader.test.ts +482 -0
- package/src/__tests__/filing-service.test.ts +163 -3
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +42 -69
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/helpers/tar-fixtures.ts +39 -0
- package/src/__tests__/helpers/wait-for.ts +21 -0
- package/src/__tests__/history-repair-pipeline.test.ts +0 -3
- package/src/__tests__/history-repair.test.ts +162 -0
- package/src/__tests__/host-app-control-proxy.test.ts +365 -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__/image-credentials.test.ts +1 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +156 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +410 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +248 -0
- package/src/__tests__/injector-chain.test.ts +10 -8
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +157 -39
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +107 -3
- package/src/__tests__/list-messages-page-latest.test.ts +55 -0
- package/src/__tests__/llm-call-pipeline.test.ts +0 -3
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +190 -2
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +222 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +100 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +145 -14
- package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
- package/src/__tests__/managed-store.test.ts +84 -192
- 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__/media-generate-image.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -2009
- package/src/__tests__/oauth-commands-routes.test.ts +863 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-provider.test.ts +24 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +48 -19
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
- package/src/__tests__/persistence-pipeline.test.ts +0 -2
- package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
- package/src/__tests__/platform.test.ts +2 -0
- package/src/__tests__/plugin-api-shim.test.ts +125 -0
- package/src/__tests__/plugin-bootstrap.test.ts +41 -38
- package/src/__tests__/plugin-external-api.test.ts +68 -0
- package/src/__tests__/plugin-registry.test.ts +0 -77
- package/src/__tests__/plugin-route-contribution.test.ts +31 -4
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -18
- package/src/__tests__/plugin-types.test.ts +15 -23
- package/src/__tests__/process-message-background-slack.test.ts +53 -0
- package/src/__tests__/process-message-display-content.test.ts +421 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
- package/src/__tests__/provider-error-scenarios.test.ts +111 -0
- package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +20 -12
- 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 +118 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +151 -0
- package/src/__tests__/schedule-store.test.ts +94 -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 +208 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/schema-transforms.test.ts +20 -0
- package/src/__tests__/search-skills-unified.test.ts +0 -5
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +12 -4
- package/src/__tests__/server-history-render.test.ts +43 -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-load-feature-flag.test.ts +1 -12
- package/src/__tests__/skill-load-tool.test.ts +29 -93
- package/src/__tests__/skill-memory.test.ts +23 -3
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
- package/src/__tests__/skills-install-extract.test.ts +49 -38
- package/src/__tests__/skills-install-staging.test.ts +159 -0
- package/src/__tests__/skills-uninstall.test.ts +9 -41
- package/src/__tests__/skills.test.ts +51 -58
- package/src/__tests__/slack-channel-config.test.ts +9 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/system-prompt.test.ts +737 -63
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/terminal-tools.test.ts +28 -1
- package/src/__tests__/thread-backfill.test.ts +557 -27
- package/src/__tests__/title-generate-pipeline.test.ts +0 -13
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
- package/src/__tests__/tool-error-pipeline.test.ts +0 -3
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +16 -4
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
- package/src/__tests__/turn-events-store.test.ts +256 -0
- package/src/__tests__/twilio-routes.test.ts +4 -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 +143 -5
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/voice-session-bridge.test.ts +198 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +108 -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 +170 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +241 -0
- package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -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-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
- package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
- package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -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/image-optimize.ts +13 -5
- package/src/approvals/guardian-request-resolvers.ts +32 -87
- package/src/calls/relay-server.ts +35 -0
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +74 -36
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +109 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -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 +578 -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__/schedules.test.ts +491 -0
- 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 +478 -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 +429 -434
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/default-action.ts +10 -53
- 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 +162 -516
- package/src/cli/commands/notifications.ts +342 -304
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +176 -297
- 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/plugins.ts +185 -0
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/schedules.ts +391 -0
- 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/telemetry.ts +40 -0
- 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__/cli-colors.test.ts +48 -0
- package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
- package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
- package/src/cli/lib/cli-colors.ts +12 -0
- package/src/cli/lib/confirm-prompt.ts +79 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/install-from-github.ts +304 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- 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/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +40 -6
- 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 +23 -21
- package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
- 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/document/SKILL.md +23 -3
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
- 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-skills/skill-management/SKILL.md +2 -2
- package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
- package/src/config/bundled-tool-registry.ts +6 -2
- package/src/config/feature-flag-registry.json +57 -1
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +140 -52
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +8 -7
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -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/channels.ts +8 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm-request-logs.ts +81 -0
- package/src/config/schemas/llm.ts +55 -2
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +32 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/config/skills.ts +3 -96
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/compactor.ts +1047 -0
- package/src/context/token-estimator.ts +2 -2
- package/src/context/window-manager.ts +197 -1334
- package/src/credential-execution/managed-catalog.ts +37 -0
- package/src/credential-health/credential-health-service.ts +280 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +113 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +183 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +26 -30
- package/src/daemon/config-watcher.ts +94 -29
- package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
- package/src/daemon/conversation-agent-loop.ts +293 -103
- package/src/daemon/conversation-error.ts +188 -33
- package/src/daemon/conversation-lifecycle.ts +80 -26
- package/src/daemon/conversation-messaging.ts +25 -6
- package/src/daemon/conversation-process.ts +85 -31
- package/src/daemon/conversation-runtime-assembly.ts +30 -6
- package/src/daemon/conversation-slash.ts +184 -25
- package/src/daemon/conversation-store.ts +24 -10
- package/src/daemon/conversation-surfaces.ts +76 -12
- package/src/daemon/conversation-tool-setup.ts +63 -21
- package/src/daemon/conversation.ts +81 -10
- package/src/daemon/external-plugins-bootstrap.ts +231 -185
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +13 -130
- package/src/daemon/handlers/config-slack-channel.ts +25 -10
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/shared.ts +14 -5
- package/src/daemon/handlers/skills.ts +166 -84
- package/src/daemon/history-repair.ts +61 -7
- package/src/daemon/host-app-control-proxy.ts +129 -29
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +96 -35
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +79 -70
- package/src/daemon/meet-host-supervisor.ts +20 -19
- package/src/daemon/memory-v2-startup.ts +58 -2
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +37 -9
- package/src/daemon/message-types/messages.ts +70 -1
- package/src/daemon/message-types/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +61 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +77 -26
- package/src/daemon/server.ts +34 -20
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/skill-memory-refresh.ts +29 -0
- 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 +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +79 -53
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +444 -0
- package/src/heartbeat/heartbeat-run-store.ts +3 -1
- package/src/heartbeat/heartbeat-service.ts +189 -127
- package/src/home/__tests__/feed-types.test.ts +99 -127
- 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 +41 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +2 -3
- package/src/index.ts +18 -1
- 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 +55 -6
- 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/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -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/mcp/client.ts +20 -4
- package/src/media/image-credentials.ts +3 -3
- package/src/memory/__tests__/bookmark-crud.test.ts +264 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-queries.test.ts +263 -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-graph-trigger-embed.test.ts +113 -0
- 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 +318 -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/__tests__/message-content.test.ts +35 -0
- package/src/memory/bookmark-crud.ts +211 -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 +80 -8
- package/src/memory/context-search/sources/memory-v2.ts +39 -14
- package/src/memory/context-search/sources/memory.ts +7 -0
- package/src/memory/context-search/sources/workspace.ts +17 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +368 -22
- package/src/memory/conversation-queries.ts +116 -12
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +20 -0
- package/src/memory/delivery-crud.ts +152 -5
- package/src/memory/embedding-backend.ts +6 -5
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/external-conversation-store.ts +66 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +92 -5
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/tool-handlers.ts +17 -7
- package/src/memory/graph/tools.ts +45 -6
- package/src/memory/indexer.ts +51 -29
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +86 -15
- package/src/memory/jobs/embed-concept-page.ts +65 -20
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +57 -3
- package/src/memory/llm-request-log-source-clickhouse.ts +324 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +64 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/llm-usage-store.ts +125 -5
- 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 +175 -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/109-external-conversation-bindings.ts +15 -4
- 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 +107 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +19 -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/247-external-conversation-binding-thread-id.ts +78 -0
- package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
- package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -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 +13 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/schema/bookmarks.ts +36 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +27 -0
- package/src/memory/schema/infrastructure.ts +12 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +1 -4
- package/src/memory/turn-events-store.ts +127 -2
- 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 +11 -12
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
- 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 +726 -18
- package/src/memory/v2/__tests__/migration.test.ts +94 -3
- package/src/memory/v2/__tests__/page-index.test.ts +360 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +309 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +138 -3
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +531 -0
- package/src/memory/v2/__tests__/sim.test.ts +45 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +445 -11
- package/src/memory/v2/__tests__/static-context.test.ts +7 -22
- package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
- 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 +85 -78
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +466 -109
- package/src/memory/v2/migration.ts +147 -20
- package/src/memory/v2/page-index.ts +221 -0
- package/src/memory/v2/page-store.ts +3 -0
- package/src/memory/v2/prompts/consolidation.ts +9 -7
- package/src/memory/v2/prompts/router.ts +195 -0
- package/src/memory/v2/prompts/sweep.ts +2 -2
- package/src/memory/v2/qdrant.ts +234 -93
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +323 -0
- package/src/memory/v2/sim.ts +25 -12
- package/src/memory/v2/skill-store.ts +204 -30
- package/src/memory/v2/static-context.ts +16 -9
- package/src/memory/v2/sweep-job.ts +122 -96
- package/src/memory/v2/types.ts +10 -6
- package/src/memory/validation.ts +13 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
- package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
- package/src/messaging/providers/slack/adapter.ts +43 -5
- package/src/messaging/providers/slack/client.ts +27 -0
- package/src/messaging/providers/slack/deep-link.ts +65 -0
- package/src/messaging/providers/slack/download.ts +104 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
- package/src/messaging/providers/slack/message-metadata.ts +27 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
- package/src/messaging/providers/slack/render-transcript.ts +69 -5
- package/src/messaging/providers/slack/types.ts +20 -1
- 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 +4 -3
- package/src/notifications/copy-composer.ts +15 -0
- package/src/notifications/decision-engine.ts +2 -1
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +48 -2
- package/src/notifications/home-feed-side-effect.ts +165 -0
- package/src/notifications/signal.ts +8 -1
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.ts +6 -2
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +14 -0
- package/src/permissions/ipc-risk-types.ts +3 -0
- package/src/permissions/question-prompter.test.ts +416 -0
- package/src/permissions/question-prompter.ts +294 -0
- package/src/platform/client.test.ts +1 -1
- package/src/platform/client.ts +1 -1
- package/src/plugin-api/constants.ts +26 -0
- package/src/plugin-api/index.ts +46 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +144 -0
- package/src/plugins/defaults/circuit-breaker.ts +0 -5
- package/src/plugins/defaults/compaction.ts +0 -4
- package/src/plugins/defaults/empty-response.ts +0 -2
- package/src/plugins/defaults/history-repair.ts +0 -2
- package/src/plugins/defaults/injectors.ts +55 -6
- package/src/plugins/defaults/llm-call.ts +0 -2
- package/src/plugins/defaults/memory-retrieval.ts +0 -1
- package/src/plugins/defaults/overflow-reduce.ts +0 -1
- package/src/plugins/defaults/persistence.ts +0 -2
- package/src/plugins/defaults/title-generate.ts +0 -5
- package/src/plugins/defaults/token-estimate.ts +0 -2
- package/src/plugins/defaults/tool-error.ts +0 -7
- package/src/plugins/defaults/tool-execute.ts +0 -2
- package/src/plugins/defaults/tool-result-truncate.ts +0 -4
- package/src/plugins/ensure-plugin-api-shim.ts +96 -0
- package/src/plugins/external-api.ts +104 -0
- package/src/plugins/external-plugin-loader.ts +367 -0
- package/src/plugins/feature-gate.ts +22 -0
- package/src/plugins/pipeline.ts +37 -0
- package/src/plugins/registry.ts +48 -80
- package/src/plugins/types.ts +74 -53
- package/src/plugins/user-loader.ts +85 -43
- package/src/proactive-artifact/aux-message-injector.ts +11 -0
- package/src/proactive-artifact/job.test.ts +49 -9
- package/src/proactive-artifact/job.ts +4 -0
- 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 +117 -0
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +72 -154
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +173 -0
- 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 +303 -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 +123 -54
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +170 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +210 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +401 -0
- package/src/providers/inference/resolve-auth.ts +73 -0
- package/src/providers/model-catalog.ts +386 -6
- package/src/providers/openai/chat-completions-provider.ts +10 -2
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/openrouter/client.ts +7 -0
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
- package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
- package/src/providers/provider-availability.ts +17 -2
- package/src/providers/provider-catalog-visibility.ts +36 -0
- 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 +151 -159
- package/src/providers/retry.ts +65 -11
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- 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 +64 -7
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +311 -9
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +3 -0
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +21 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/migrations/origin-mode.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- 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 +268 -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 +319 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +280 -4
- 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 +4 -4
- package/src/runtime/routes/__tests__/question-routes.test.ts +395 -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 +70 -3
- package/src/runtime/routes/acp-routes-list.test.ts +143 -0
- package/src/runtime/routes/acp-routes.ts +12 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +0 -18
- 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 +156 -0
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/channel-availability-routes.ts +121 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +233 -0
- package/src/runtime/routes/conversation-list-routes.ts +3 -20
- package/src/runtime/routes/conversation-management-routes.ts +47 -85
- package/src/runtime/routes/conversation-query-routes.ts +350 -97
- package/src/runtime/routes/conversation-routes.ts +121 -21
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/documents-routes.ts +25 -86
- 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/group-routes.ts +5 -0
- 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-conversation.ts +28 -8
- package/src/runtime/routes/inbound-message-handler.ts +236 -41
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +248 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +118 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
- package/src/runtime/routes/index.ts +42 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +285 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +84 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +361 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/slack/share.ts +4 -52
- package/src/runtime/routes/integrations/slack/token.ts +43 -0
- package/src/runtime/routes/integrations/twilio.ts +7 -13
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-v2-routes.ts +13 -398
- package/src/runtime/routes/notification-routes.ts +3 -1
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1097 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
- 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/question-routes.ts +259 -0
- package/src/runtime/routes/rename-conversation-routes.ts +2 -33
- package/src/runtime/routes/schedule-routes.ts +79 -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/subagents-routes.ts +57 -18
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/telemetry-routes.ts +27 -0
- package/src/runtime/routes/tts-routes.ts +93 -1
- 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/routes/workspace-routes.test.ts +43 -0
- package/src/runtime/routes/workspace-routes.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +39 -7
- package/src/runtime/sync/resource-sync-events.ts +117 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/schedule-store.ts +27 -2
- package/src/schedule/scheduler.ts +208 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/__tests__/untrusted-content.test.ts +86 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/security/untrusted-content.ts +93 -8
- package/src/sequence/engine.ts +38 -40
- package/src/skills/catalog-files.ts +1 -1
- package/src/skills/catalog-install.ts +233 -116
- package/src/skills/clawhub.ts +70 -13
- package/src/skills/managed-store.ts +4 -119
- package/src/skills/skillssh-registry.ts +27 -48
- package/src/subagent/manager.ts +28 -15
- package/src/telemetry/types.ts +113 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
- package/src/telemetry/usage-telemetry-reporter.ts +113 -7
- package/src/tools/apps/executors.ts +58 -7
- package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
- package/src/tools/ask-question/ask-question-tool.ts +304 -0
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +29 -14
- 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/computer-use/definitions.ts +3 -3
- package/src/tools/credentials/vault.ts +1 -1
- package/src/tools/document/document-tool.ts +124 -1
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +5 -2
- package/src/tools/host-filesystem/transfer.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +1 -1
- package/src/tools/memory/register.test.ts +3 -3
- 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 +14 -6
- package/src/tools/registry.ts +17 -7
- package/src/tools/schedule/create.ts +2 -2
- package/src/tools/schema-transforms.ts +7 -2
- package/src/tools/side-effects.ts +1 -0
- package/src/tools/skills/delete-managed.ts +4 -4
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/scaffold-managed.ts +3 -2
- package/src/tools/subagent/notify-parent.ts +1 -1
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/system/request-permission.ts +2 -2
- package/src/tools/terminal/safe-env.ts +60 -1
- package/src/tools/terminal/shell.ts +44 -0
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/types.ts +72 -21
- package/src/tools/ui-surface/definitions.ts +6 -5
- package/src/tts/__tests__/provider-adapters.test.ts +76 -2
- package/src/tts/providers/elevenlabs-provider.ts +75 -1
- package/src/types/onboarding-context.ts +2 -0
- package/src/usage/attribution.ts +3 -2
- package/src/util/errors.ts +17 -0
- package/src/util/platform.ts +10 -0
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +323 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +94 -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 +94 -5
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +117 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +95 -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/083-system-prompt-prefix-to-file.ts +191 -0
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
- package/src/workspace/migrations/registry.ts +30 -0
- package/src/workspace/migrations/runner.ts +46 -5
- package/src/workspace/migrations/types.ts +17 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/examples/plugins/echo/bun.lock +0 -25
- package/src/__tests__/context-search-pkb-source.test.ts +0 -498
- package/src/__tests__/context-window-manager.test.ts +0 -2093
- 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 -947
- 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/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- 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 -476
- package/src/memory/graph/compaction.ts +0 -299
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -137,9 +137,10 @@ describe("runWorkspaceMigrations", () => {
|
|
|
137
137
|
expect(m1.run).toHaveBeenCalledTimes(1);
|
|
138
138
|
expect(m2.run).toHaveBeenCalledTimes(1);
|
|
139
139
|
|
|
140
|
-
// Checkpoints saved: started m1, completed m1, started m2, failed m2
|
|
141
|
-
|
|
142
|
-
expect(
|
|
140
|
+
// Checkpoints saved: started m1, completed m1, started m2, failed m2,
|
|
141
|
+
// then the post-loop flip clearing isNewWorkspace = 5 writes.
|
|
142
|
+
expect(writeFileSyncFn).toHaveBeenCalledTimes(5);
|
|
143
|
+
expect(renameSyncFn).toHaveBeenCalledTimes(5);
|
|
143
144
|
|
|
144
145
|
// Verify the completed checkpoint contains m1
|
|
145
146
|
// The second write is the "completed" marker for m1
|
|
@@ -246,6 +247,33 @@ describe("runWorkspaceMigrations", () => {
|
|
|
246
247
|
expect(m1.run).not.toHaveBeenCalled();
|
|
247
248
|
});
|
|
248
249
|
|
|
250
|
+
test("skips failed migrations by default", async () => {
|
|
251
|
+
mockCheckpointContents = JSON.stringify({
|
|
252
|
+
applied: {
|
|
253
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "failed" },
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const m1 = makeMigration("001");
|
|
258
|
+
await runWorkspaceMigrations(WORKSPACE_DIR, [m1]);
|
|
259
|
+
|
|
260
|
+
expect(m1.run).not.toHaveBeenCalled();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("retries failed migrations that opt in", async () => {
|
|
264
|
+
mockCheckpointContents = JSON.stringify({
|
|
265
|
+
applied: {
|
|
266
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "failed" },
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const m1 = makeMigration("001");
|
|
271
|
+
m1.retryFailedCheckpoint = true;
|
|
272
|
+
await runWorkspaceMigrations(WORKSPACE_DIR, [m1]);
|
|
273
|
+
|
|
274
|
+
expect(m1.run).toHaveBeenCalledTimes(1);
|
|
275
|
+
});
|
|
276
|
+
|
|
249
277
|
test("supports async migrations", async () => {
|
|
250
278
|
const asyncMigration: WorkspaceMigration = {
|
|
251
279
|
id: "001",
|
|
@@ -278,6 +306,86 @@ describe("runWorkspaceMigrations", () => {
|
|
|
278
306
|
expect(m1.run).not.toHaveBeenCalled();
|
|
279
307
|
});
|
|
280
308
|
|
|
309
|
+
test("persists isNewWorkspace=true on first creation, then flips to false after sweep", async () => {
|
|
310
|
+
// No checkpoint file → fresh workspace.
|
|
311
|
+
const m1 = makeMigration("001");
|
|
312
|
+
let observed: boolean | undefined;
|
|
313
|
+
(m1.run as ReturnType<typeof mock>).mockImplementation(
|
|
314
|
+
(_dir: string, ctx?: { isNewWorkspace: boolean }) => {
|
|
315
|
+
observed = ctx?.isNewWorkspace;
|
|
316
|
+
},
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
await runWorkspaceMigrations(WORKSPACE_DIR, [m1]);
|
|
320
|
+
|
|
321
|
+
// The migration saw the new-workspace flag.
|
|
322
|
+
expect(observed).toBe(true);
|
|
323
|
+
|
|
324
|
+
// The first persisted checkpoint (m1's "started" save) carries the flag.
|
|
325
|
+
const firstSave = JSON.parse(
|
|
326
|
+
(writeFileSyncFn.mock.calls[0] as unknown[])[1] as string,
|
|
327
|
+
);
|
|
328
|
+
expect(firstSave.isNewWorkspace).toBe(true);
|
|
329
|
+
|
|
330
|
+
// The final persisted checkpoint clears the flag so subsequent boots
|
|
331
|
+
// treat this workspace as an upgrade.
|
|
332
|
+
const finalSave = JSON.parse(
|
|
333
|
+
(writeFileSyncFn.mock.calls.at(-1) as unknown[])[1] as string,
|
|
334
|
+
);
|
|
335
|
+
expect(finalSave.isNewWorkspace).toBe(false);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("preserves isNewWorkspace=true across a crash before seeding migrations run", async () => {
|
|
339
|
+
// Simulate a crash mid-first-boot: an earlier migration recorded its
|
|
340
|
+
// "started" marker (writing the checkpoint file) and the daemon then
|
|
341
|
+
// died before reaching the seeding migration. The persisted flag must
|
|
342
|
+
// survive the reboot so the seeding migration still observes the
|
|
343
|
+
// brand-new workspace.
|
|
344
|
+
mockCheckpointContents = JSON.stringify({
|
|
345
|
+
isNewWorkspace: true,
|
|
346
|
+
applied: {
|
|
347
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "started" },
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
const seedingMigration = makeMigration("seed");
|
|
352
|
+
let observed: boolean | undefined;
|
|
353
|
+
(seedingMigration.run as ReturnType<typeof mock>).mockImplementation(
|
|
354
|
+
(_dir: string, ctx?: { isNewWorkspace: boolean }) => {
|
|
355
|
+
observed = ctx?.isNewWorkspace;
|
|
356
|
+
},
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
const m1 = makeMigration("001");
|
|
360
|
+
await runWorkspaceMigrations(WORKSPACE_DIR, [m1, seedingMigration]);
|
|
361
|
+
|
|
362
|
+
expect(m1.run).toHaveBeenCalledTimes(1);
|
|
363
|
+
expect(seedingMigration.run).toHaveBeenCalledTimes(1);
|
|
364
|
+
expect(observed).toBe(true);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test("treats pre-existing checkpoint without isNewWorkspace field as upgrade", async () => {
|
|
368
|
+
// Workspaces created before this field was introduced have a checkpoint
|
|
369
|
+
// file with only `applied`. They must not be re-seeded.
|
|
370
|
+
mockCheckpointContents = JSON.stringify({
|
|
371
|
+
applied: {
|
|
372
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "completed" },
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const seedingMigration = makeMigration("seed");
|
|
377
|
+
let observed: boolean | undefined;
|
|
378
|
+
(seedingMigration.run as ReturnType<typeof mock>).mockImplementation(
|
|
379
|
+
(_dir: string, ctx?: { isNewWorkspace: boolean }) => {
|
|
380
|
+
observed = ctx?.isNewWorkspace;
|
|
381
|
+
},
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
await runWorkspaceMigrations(WORKSPACE_DIR, [seedingMigration]);
|
|
385
|
+
|
|
386
|
+
expect(observed).toBe(false);
|
|
387
|
+
});
|
|
388
|
+
|
|
281
389
|
test("warns on malformed checkpoint file", async () => {
|
|
282
390
|
mockCheckpointContents = "not valid json";
|
|
283
391
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { describe, expect, test } from "bun:test";
|
|
4
|
+
|
|
5
|
+
type Registry = {
|
|
6
|
+
flags: Array<{
|
|
7
|
+
key: string;
|
|
8
|
+
scope: string;
|
|
9
|
+
defaultEnabled: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const LEGACY_FLAGGED_RELEASE_NOTE_ALLOWLIST = new Map<string, string>([
|
|
14
|
+
[
|
|
15
|
+
"045-release-notes-meet-avatar.ts",
|
|
16
|
+
"Historical bulletin that already shipped before this guard existed.",
|
|
17
|
+
],
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const FLAGGED_FEATURE_LANGUAGE_PATTERNS: Array<{
|
|
21
|
+
label: string;
|
|
22
|
+
pattern: RegExp;
|
|
23
|
+
}> = [
|
|
24
|
+
{ label: "feature flag", pattern: /\bfeature[- ]flag(?:ged)?\b/i },
|
|
25
|
+
{ label: "rollout flag", pattern: /\brollout flag\b/i },
|
|
26
|
+
{ label: "behind ... flag", pattern: /\bbehind\b[^\n.]{0,120}\bflag\b/i },
|
|
27
|
+
{ label: "gated on", pattern: /\bgated on\b/i },
|
|
28
|
+
{ label: "when enabled", pattern: /\bwhen enabled\b/i },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function getRepoRoot(): string {
|
|
32
|
+
return join(process.cwd(), "..");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getReleaseNoteMigrationFiles(): string[] {
|
|
36
|
+
const migrationsDir = join(process.cwd(), "src", "workspace", "migrations");
|
|
37
|
+
return readdirSync(migrationsDir)
|
|
38
|
+
.filter((fileName) => /^\d+-release-notes-[a-z0-9-]+\.ts$/.test(fileName))
|
|
39
|
+
.sort();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function loadDefaultDisabledAssistantFlagKeys(): string[] {
|
|
43
|
+
const registryPath = join(
|
|
44
|
+
getRepoRoot(),
|
|
45
|
+
"meta",
|
|
46
|
+
"feature-flags",
|
|
47
|
+
"feature-flag-registry.json",
|
|
48
|
+
);
|
|
49
|
+
const registry = JSON.parse(readFileSync(registryPath, "utf-8")) as Registry;
|
|
50
|
+
return registry.flags
|
|
51
|
+
.filter((flag) => flag.scope === "assistant" && !flag.defaultEnabled)
|
|
52
|
+
.map((flag) => flag.key)
|
|
53
|
+
.sort();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function escapeRegExp(value: string): string {
|
|
57
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function featureFlagKeyPattern(key: string): RegExp {
|
|
61
|
+
const escaped = escapeRegExp(key);
|
|
62
|
+
if (key.includes("-")) {
|
|
63
|
+
return new RegExp(`(?:^|[^a-z0-9-])${escaped}(?:$|[^a-z0-9-])`, "i");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return new RegExp("[`'\"]" + escaped + "[`'\"]", "i");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
describe("workspace release-note migrations feature flag guard", () => {
|
|
70
|
+
test("new release-note migrations do not announce default-disabled feature-flagged work", () => {
|
|
71
|
+
const migrationsDir = join(process.cwd(), "src", "workspace", "migrations");
|
|
72
|
+
const defaultDisabledFlagKeys = loadDefaultDisabledAssistantFlagKeys();
|
|
73
|
+
const violations: string[] = [];
|
|
74
|
+
|
|
75
|
+
for (const fileName of getReleaseNoteMigrationFiles()) {
|
|
76
|
+
if (LEGACY_FLAGGED_RELEASE_NOTE_ALLOWLIST.has(fileName)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const content = readFileSync(join(migrationsDir, fileName), "utf-8");
|
|
81
|
+
|
|
82
|
+
for (const { label, pattern } of FLAGGED_FEATURE_LANGUAGE_PATTERNS) {
|
|
83
|
+
if (pattern.test(content)) {
|
|
84
|
+
violations.push(
|
|
85
|
+
`${fileName}: contains flagged-feature language "${label}"`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for (const key of defaultDisabledFlagKeys) {
|
|
91
|
+
if (featureFlagKeyPattern(key).test(content)) {
|
|
92
|
+
violations.push(
|
|
93
|
+
`${fileName}: references default-disabled assistant feature flag "${key}"`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (violations.length > 0) {
|
|
100
|
+
const message = [
|
|
101
|
+
"Release-note migrations write to UPDATES.md, which is processed without checking feature flags.",
|
|
102
|
+
"Do not announce features that are still behind default-disabled assistant flags or rollout flags.",
|
|
103
|
+
"Wait until GA and add a new append-only release-note migration with a new marker.",
|
|
104
|
+
"",
|
|
105
|
+
"Violations:",
|
|
106
|
+
...violations.map((violation) => ` - ${violation}`),
|
|
107
|
+
"",
|
|
108
|
+
"If this is an already-shipped historical bulletin, add a narrow entry to",
|
|
109
|
+
"LEGACY_FLAGGED_RELEASE_NOTE_ALLOWLIST in workspace-release-notes-feature-flag-guard.test.ts.",
|
|
110
|
+
].join("\n");
|
|
111
|
+
|
|
112
|
+
expect(violations, message).toEqual([]);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* in `afterAll` so the swap doesn't leak into other files.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
type
|
|
14
|
+
type WhichOptions = { PATH?: string; cwd?: string };
|
|
15
|
+
type WhichStub = (command: string, options?: WhichOptions) => string | null;
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Installs a process-global stub for Bun.which. Returns helpers to drive and
|
|
@@ -30,7 +31,8 @@ export function installWhichStub(): {
|
|
|
30
31
|
const originalWhich = Bun.which;
|
|
31
32
|
let whichStub: WhichStub = () => null;
|
|
32
33
|
|
|
33
|
-
(Bun as unknown as { which: WhichStub }).which = (cmd) =>
|
|
34
|
+
(Bun as unknown as { which: WhichStub }).which = (cmd, options) =>
|
|
35
|
+
whichStub(cmd, options);
|
|
34
36
|
|
|
35
37
|
function setWhich(arg: Record<string, string | null> | WhichStub): void {
|
|
36
38
|
whichStub = typeof arg === "function" ? arg : (cmd) => arg[cmd] ?? null;
|
|
@@ -161,6 +161,31 @@ describe("resolveAcpAgent", () => {
|
|
|
161
161
|
expect(result.hint).toBe("npm i -g @zed-industries/codex-acp");
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
test("binary preflight honors agent.env.PATH override (matches spawn env)", () => {
|
|
165
|
+
// The actual spawn merges `agentConfig.env` into the child env, so a
|
|
166
|
+
// per-agent PATH override wins over the daemon's PATH. The preflight
|
|
167
|
+
// must use the same PATH or it will reject configs that would have
|
|
168
|
+
// spawned successfully.
|
|
169
|
+
config.setConfig({
|
|
170
|
+
agents: {
|
|
171
|
+
custom: {
|
|
172
|
+
command: "my-binary",
|
|
173
|
+
args: [],
|
|
174
|
+
env: { PATH: "/opt/custom/bin" },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
which.setWhich((cmd, options) =>
|
|
179
|
+
cmd === "my-binary" && options?.PATH === "/opt/custom/bin"
|
|
180
|
+
? "/opt/custom/bin/my-binary"
|
|
181
|
+
: null,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const result = resolveAcpAgent("custom");
|
|
185
|
+
|
|
186
|
+
expect(result.ok).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
164
189
|
test("ok result when user config provides agent and binary is on PATH", () => {
|
|
165
190
|
config.setConfig({
|
|
166
191
|
agents: {
|
package/src/acp/resolve-agent.ts
CHANGED
|
@@ -65,6 +65,17 @@ function installHintFor(command: string): string {
|
|
|
65
65
|
: `Install '${command}' and ensure it is on PATH.`;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the binary using the same PATH the spawn will see. `AcpAgentProcess`
|
|
70
|
+
* spawns with `{ ...process.env, ...config.env }`, so a per-agent `env.PATH`
|
|
71
|
+
* override wins over the daemon's PATH. Mirror that here so a config that
|
|
72
|
+
* relies on a custom PATH to locate the binary doesn't fail preflight.
|
|
73
|
+
*/
|
|
74
|
+
function findAgentBinary(agent: AcpAgentConfig): string | null {
|
|
75
|
+
const PATH = agent.env?.PATH ?? process.env.PATH;
|
|
76
|
+
return Bun.which(agent.command, PATH != null ? { PATH } : undefined);
|
|
77
|
+
}
|
|
78
|
+
|
|
68
79
|
/**
|
|
69
80
|
* Resolve an id against user config first, then bundled defaults. Returns the
|
|
70
81
|
* resolved entry plus a `source` label so callers can surface "user override
|
|
@@ -122,7 +133,7 @@ export function resolveAcpAgent(id: string): ResolveAcpAgentResult {
|
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
const { agent } = found;
|
|
125
|
-
if (!
|
|
136
|
+
if (!findAgentBinary(agent)) {
|
|
126
137
|
return {
|
|
127
138
|
ok: false,
|
|
128
139
|
reason: "binary_not_found",
|
|
@@ -157,7 +168,7 @@ export function listAcpAgents(): {
|
|
|
157
168
|
const agents: AcpAgentEntry[] = mergedAgentIds(userAgents).map((id) => {
|
|
158
169
|
// Non-null: ids come from `mergedAgentIds` so the lookup always resolves.
|
|
159
170
|
const { agent, source } = lookupAgent(userAgents, id)!;
|
|
160
|
-
const available =
|
|
171
|
+
const available = findAgentBinary(agent) !== null;
|
|
161
172
|
const entry: AcpAgentEntry = {
|
|
162
173
|
id,
|
|
163
174
|
command: agent.command,
|
|
@@ -278,12 +278,26 @@ export class AcpSessionManager {
|
|
|
278
278
|
|
|
279
279
|
/**
|
|
280
280
|
* Kills the agent process and removes the session from tracking.
|
|
281
|
+
*
|
|
282
|
+
* Persists the buffered event log first so abort paths
|
|
283
|
+
* (`executeAcpAbort`, daemon shutdown) don't drop history. If the
|
|
284
|
+
* session is still in a non-terminal state, mark it cancelled so the
|
|
285
|
+
* persisted row reflects reality. The in-flight prompt's then/catch
|
|
286
|
+
* handler will short-circuit after teardown removes the entry.
|
|
281
287
|
*/
|
|
282
288
|
close(acpSessionId: string): void {
|
|
283
289
|
const entry = this.sessions.get(acpSessionId);
|
|
284
290
|
if (!entry) {
|
|
285
291
|
throw new Error(`ACP session "${acpSessionId}" not found`);
|
|
286
292
|
}
|
|
293
|
+
if (
|
|
294
|
+
entry.state.status === "running" ||
|
|
295
|
+
entry.state.status === "initializing"
|
|
296
|
+
) {
|
|
297
|
+
entry.state.status = "cancelled";
|
|
298
|
+
entry.state.completedAt = Date.now();
|
|
299
|
+
}
|
|
300
|
+
this.persistTerminal(acpSessionId, entry);
|
|
287
301
|
this.teardownSession(acpSessionId, entry);
|
|
288
302
|
}
|
|
289
303
|
|
|
@@ -21,6 +21,11 @@ const MAX_DIMENSION = 1568;
|
|
|
21
21
|
// Threshold below which we skip optimization — small images don't need it.
|
|
22
22
|
const OPTIMIZE_THRESHOLD_BYTES = 300 * 1024; // 300 KB
|
|
23
23
|
|
|
24
|
+
// Anthropic rejects any single image whose source payload exceeds 5 MB,
|
|
25
|
+
// regardless of pixel dimensions. Cap at ~3.5 MB raw so the base64-encoded
|
|
26
|
+
// form (raw * 4/3) stays comfortably under 5 MB even after re-encoding.
|
|
27
|
+
const MAX_TRANSPORT_BYTES = Math.floor(3.5 * 1024 * 1024); // ~3.5 MB raw
|
|
28
|
+
|
|
24
29
|
const JPEG_QUALITY = 80;
|
|
25
30
|
|
|
26
31
|
// Content-addressed disk cache to avoid re-running sips on the same image.
|
|
@@ -130,10 +135,13 @@ function runSips(inputBytes: Buffer): Buffer | null {
|
|
|
130
135
|
/**
|
|
131
136
|
* Decide whether an image needs to be rescaled before sending.
|
|
132
137
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
138
|
+
* Two independent gates apply:
|
|
139
|
+
* 1. Pixel dimensions — Anthropic rejects many-image requests when any
|
|
140
|
+
* image exceeds 2000 px on a side. A sparse screenshot can be under
|
|
141
|
+
* 300 KB while still being 3000+ px wide.
|
|
142
|
+
* 2. Byte size — Anthropic rejects any image whose source payload
|
|
143
|
+
* exceeds 5 MB. A 1500×1500 high-color screenshot can produce a >5 MB
|
|
144
|
+
* payload while staying well under the dimension cap.
|
|
137
145
|
*
|
|
138
146
|
* Exported for unit testing.
|
|
139
147
|
*/
|
|
@@ -141,8 +149,8 @@ export function shouldRescaleImage(
|
|
|
141
149
|
dims: { width: number; height: number } | null,
|
|
142
150
|
byteLength: number,
|
|
143
151
|
): boolean {
|
|
152
|
+
if (byteLength > MAX_TRANSPORT_BYTES) return true;
|
|
144
153
|
if (dims) {
|
|
145
|
-
// Dimensions known — they are the authoritative check.
|
|
146
154
|
return dims.width > MAX_DIMENSION || dims.height > MAX_DIMENSION;
|
|
147
155
|
}
|
|
148
156
|
// Dimensions unparseable — fall back to file size as a rough proxy.
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import { answerCall } from "../calls/call-domain.js";
|
|
15
15
|
import { findContactChannel } from "../contacts/contact-store.js";
|
|
16
|
+
import { upsertContactChannel } from "../contacts/contacts-write.js";
|
|
16
17
|
import { findConversation } from "../daemon/conversation-store.js";
|
|
17
|
-
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
18
18
|
import {
|
|
19
19
|
type CanonicalGuardianRequest,
|
|
20
20
|
getCanonicalGuardianRequest,
|
|
@@ -119,6 +119,12 @@ export type ResolverResult =
|
|
|
119
119
|
applied: true;
|
|
120
120
|
grantMinted?: boolean;
|
|
121
121
|
guardianReplyText?: string;
|
|
122
|
+
activatedContact?: {
|
|
123
|
+
sourceChannel: string;
|
|
124
|
+
externalUserId: string;
|
|
125
|
+
externalChatId?: string;
|
|
126
|
+
displayName?: string;
|
|
127
|
+
};
|
|
122
128
|
}
|
|
123
129
|
| { ok: false; reason: string };
|
|
124
130
|
|
|
@@ -206,21 +212,6 @@ const pendingInteractionResolver: GuardianRequestResolver = {
|
|
|
206
212
|
ctx.emissionContext,
|
|
207
213
|
);
|
|
208
214
|
|
|
209
|
-
const approved = decision.action !== "reject";
|
|
210
|
-
void emitFeedEvent({
|
|
211
|
-
source: "assistant",
|
|
212
|
-
title: approved ? "Tool Request Approved" : "Tool Request Denied",
|
|
213
|
-
summary: `${approved ? "Approved" : "Denied"} access to ${request.toolName ?? "unknown tool"}.`,
|
|
214
|
-
dedupKey: `guardian-approval:${request.id}`,
|
|
215
|
-
urgency: approved ? undefined : "medium",
|
|
216
|
-
detailPanel: { kind: "toolPermission" },
|
|
217
|
-
}).catch((err) => {
|
|
218
|
-
log.warn(
|
|
219
|
-
{ err, requestId: request.id },
|
|
220
|
-
"Failed to emit guardian approval feed event",
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
215
|
log.info(
|
|
225
216
|
{
|
|
226
217
|
event: "resolver_tool_approval_applied",
|
|
@@ -467,20 +458,6 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
467
458
|
}
|
|
468
459
|
}
|
|
469
460
|
|
|
470
|
-
void emitFeedEvent({
|
|
471
|
-
source: "assistant",
|
|
472
|
-
title: "Access Request Denied",
|
|
473
|
-
summary: `Denied access request.`,
|
|
474
|
-
dedupKey: `guardian-access:${request.id}`,
|
|
475
|
-
urgency: "medium",
|
|
476
|
-
detailPanel: { kind: "permissionChat" },
|
|
477
|
-
}).catch((err) => {
|
|
478
|
-
log.warn(
|
|
479
|
-
{ err, requestId: request.id },
|
|
480
|
-
"Failed to emit access request feed event",
|
|
481
|
-
);
|
|
482
|
-
});
|
|
483
|
-
|
|
484
461
|
return {
|
|
485
462
|
ok: true,
|
|
486
463
|
applied: true,
|
|
@@ -496,6 +473,21 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
496
473
|
// a verification session. The caller is already on the line and the
|
|
497
474
|
// relay server's in-call wait loop will detect the approved status.
|
|
498
475
|
if (channel === "phone") {
|
|
476
|
+
try {
|
|
477
|
+
upsertContactChannel({
|
|
478
|
+
sourceChannel: "phone",
|
|
479
|
+
externalUserId: requesterExternalUserId,
|
|
480
|
+
externalChatId: requesterChatId,
|
|
481
|
+
status: "active",
|
|
482
|
+
policy: "allow",
|
|
483
|
+
});
|
|
484
|
+
} catch (err) {
|
|
485
|
+
log.error(
|
|
486
|
+
{ err, requesterExternalUserId },
|
|
487
|
+
"Access request resolver: failed to activate voice caller as trusted contact",
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
499
491
|
log.info(
|
|
500
492
|
{
|
|
501
493
|
event: "resolver_access_request_voice_approved",
|
|
@@ -506,21 +498,16 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
506
498
|
"Access request resolver: voice approval — direct trusted-contact activation (no verification session)",
|
|
507
499
|
);
|
|
508
500
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
"Failed to emit access request feed event",
|
|
520
|
-
);
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
return { ok: true, applied: true };
|
|
501
|
+
return {
|
|
502
|
+
ok: true,
|
|
503
|
+
applied: true,
|
|
504
|
+
activatedContact: {
|
|
505
|
+
sourceChannel: "phone",
|
|
506
|
+
externalUserId: requesterExternalUserId,
|
|
507
|
+
...(requesterChatId ? { externalChatId: requesterChatId } : {}),
|
|
508
|
+
...(requesterDisplayName ? { displayName: requesterDisplayName } : {}),
|
|
509
|
+
},
|
|
510
|
+
};
|
|
524
511
|
}
|
|
525
512
|
|
|
526
513
|
// Non-voice approvals: mint an identity-bound verification session so the
|
|
@@ -738,20 +725,6 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
738
725
|
? `Access approved for ${requesterLabel}. Give them this verification code: \`${session.secret}\`. The code expires in 10 minutes.`
|
|
739
726
|
: `Access approved for ${requesterLabel}. Give them this verification code: \`${session.secret}\`. The code expires in 10 minutes. I could not notify them automatically, so please tell them to send the code manually.`;
|
|
740
727
|
|
|
741
|
-
void emitFeedEvent({
|
|
742
|
-
source: "assistant",
|
|
743
|
-
title: "Access Request Approved",
|
|
744
|
-
summary: `Granted access request.`,
|
|
745
|
-
dedupKey: `guardian-access:${request.id}`,
|
|
746
|
-
urgency: undefined,
|
|
747
|
-
detailPanel: { kind: "permissionChat" },
|
|
748
|
-
}).catch((err) => {
|
|
749
|
-
log.warn(
|
|
750
|
-
{ err, requestId: request.id },
|
|
751
|
-
"Failed to emit access request feed event",
|
|
752
|
-
);
|
|
753
|
-
});
|
|
754
|
-
|
|
755
728
|
return {
|
|
756
729
|
ok: true,
|
|
757
730
|
applied: true,
|
|
@@ -825,20 +798,6 @@ const toolGrantRequestResolver: GuardianRequestResolver = {
|
|
|
825
798
|
}
|
|
826
799
|
}
|
|
827
800
|
|
|
828
|
-
void emitFeedEvent({
|
|
829
|
-
source: "assistant",
|
|
830
|
-
title: "Tool Grant Denied",
|
|
831
|
-
summary: `Denied grant request for ${request.toolName ?? "unknown tool"}.`,
|
|
832
|
-
dedupKey: `guardian-grant:${request.id}`,
|
|
833
|
-
urgency: "medium",
|
|
834
|
-
detailPanel: { kind: "toolPermission" },
|
|
835
|
-
}).catch((err) => {
|
|
836
|
-
log.warn(
|
|
837
|
-
{ err, requestId: request.id },
|
|
838
|
-
"Failed to emit tool grant denial feed event",
|
|
839
|
-
);
|
|
840
|
-
});
|
|
841
|
-
|
|
842
801
|
return { ok: true, applied: true };
|
|
843
802
|
}
|
|
844
803
|
|
|
@@ -936,20 +895,6 @@ const toolGrantRequestResolver: GuardianRequestResolver = {
|
|
|
936
895
|
}
|
|
937
896
|
}
|
|
938
897
|
|
|
939
|
-
void emitFeedEvent({
|
|
940
|
-
source: "assistant",
|
|
941
|
-
title: "Tool Grant Approved",
|
|
942
|
-
summary: `Approved grant request for ${request.toolName ?? "unknown tool"}.`,
|
|
943
|
-
dedupKey: `guardian-grant:${request.id}`,
|
|
944
|
-
urgency: undefined,
|
|
945
|
-
detailPanel: { kind: "toolPermission" },
|
|
946
|
-
}).catch((err) => {
|
|
947
|
-
log.warn(
|
|
948
|
-
{ err, requestId: request.id },
|
|
949
|
-
"Failed to emit tool grant approval feed event",
|
|
950
|
-
);
|
|
951
|
-
});
|
|
952
|
-
|
|
953
898
|
return { ok: true, applied: true, grantMinted: false };
|
|
954
899
|
},
|
|
955
900
|
};
|
|
@@ -612,6 +612,12 @@ export class RelayConnection {
|
|
|
612
612
|
);
|
|
613
613
|
this.startNameCapture(outcome.assistantId, outcome.fromNumber);
|
|
614
614
|
return;
|
|
615
|
+
case "unverified_caller":
|
|
616
|
+
await this.handleUnverifiedCaller(
|
|
617
|
+
outcome.displayName,
|
|
618
|
+
outcome.isGuardian,
|
|
619
|
+
);
|
|
620
|
+
return;
|
|
615
621
|
case "verification":
|
|
616
622
|
if (this.controller && resolved.actorTrust.trustClass !== "unknown") {
|
|
617
623
|
this.controller.setTrustContext(
|
|
@@ -669,6 +675,35 @@ export class RelayConnection {
|
|
|
669
675
|
});
|
|
670
676
|
}
|
|
671
677
|
|
|
678
|
+
/** Speak verification guidance to a known-but-unverified caller, then disconnect. */
|
|
679
|
+
private async handleUnverifiedCaller(
|
|
680
|
+
displayName: string,
|
|
681
|
+
isGuardian: boolean,
|
|
682
|
+
): Promise<void> {
|
|
683
|
+
recordCallEvent(this.callSessionId, "inbound_acl_unverified_caller", {
|
|
684
|
+
callSessionId: this.callSessionId,
|
|
685
|
+
isGuardian,
|
|
686
|
+
});
|
|
687
|
+
this.connectionState = "disconnecting";
|
|
688
|
+
updateCallSession(this.callSessionId, {
|
|
689
|
+
status: "failed",
|
|
690
|
+
endedAt: Date.now(),
|
|
691
|
+
lastError: "Inbound voice ACL: caller channel unverified",
|
|
692
|
+
});
|
|
693
|
+
const action = isGuardian
|
|
694
|
+
? `To verify, open your assistant's contacts page, click Verify next to the phone channel, ` +
|
|
695
|
+
`and follow the prompts. Then call back once the verification session is active.`
|
|
696
|
+
: `Please reach out to the account guardian to start a new verification session, ` +
|
|
697
|
+
`then call back once the verification session is active.`;
|
|
698
|
+
const message =
|
|
699
|
+
`This number is registered as ${displayName}'s phone but has not been verified yet. ` +
|
|
700
|
+
action;
|
|
701
|
+
await speakSystemPrompt(this, message);
|
|
702
|
+
setTimeout(() => {
|
|
703
|
+
this.endSession("Inbound voice ACL: caller channel unverified");
|
|
704
|
+
}, getTtsPlaybackDelayMs());
|
|
705
|
+
}
|
|
706
|
+
|
|
672
707
|
/** Deny an inbound call with a TTS message and schedule disconnect. */
|
|
673
708
|
private async denyInboundCall(
|
|
674
709
|
from: string,
|
|
@@ -56,6 +56,13 @@ type SetupOutcome =
|
|
|
56
56
|
guardianName: string | null;
|
|
57
57
|
}
|
|
58
58
|
| { action: "name_capture"; assistantId: string; fromNumber: string }
|
|
59
|
+
| {
|
|
60
|
+
action: "unverified_caller";
|
|
61
|
+
assistantId: string;
|
|
62
|
+
fromNumber: string;
|
|
63
|
+
displayName: string;
|
|
64
|
+
isGuardian: boolean;
|
|
65
|
+
}
|
|
59
66
|
| { action: "deny"; message: string; logReason: string };
|
|
60
67
|
|
|
61
68
|
// ── Resolved context produced alongside the outcome ──────────────────
|
|
@@ -234,6 +241,35 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
234
241
|
};
|
|
235
242
|
}
|
|
236
243
|
|
|
244
|
+
// Known caller whose channel hasn't passed verification yet —
|
|
245
|
+
// mirrors the gateway's pre-intercept (twilio-voice-webhook.ts) so
|
|
246
|
+
// calls slipping past it (e.g. canonicalization mismatch between
|
|
247
|
+
// gateway and assistant DBs) still get useful guidance instead of
|
|
248
|
+
// the "I don't recognize this number" name-capture script.
|
|
249
|
+
const unverifiedStatuses = new Set(["unverified", "pending"]);
|
|
250
|
+
const memberChannel = actorTrust.memberRecord?.channel;
|
|
251
|
+
if (memberChannel && unverifiedStatuses.has(memberChannel.status)) {
|
|
252
|
+
log.info(
|
|
253
|
+
{
|
|
254
|
+
callSessionId: ctx.callSessionId,
|
|
255
|
+
from: ctx.from,
|
|
256
|
+
channelId: memberChannel.id,
|
|
257
|
+
channelStatus: memberChannel.status,
|
|
258
|
+
},
|
|
259
|
+
"Inbound voice ACL: known but unverified caller — returning verification guidance",
|
|
260
|
+
);
|
|
261
|
+
return {
|
|
262
|
+
outcome: {
|
|
263
|
+
action: "unverified_caller",
|
|
264
|
+
assistantId,
|
|
265
|
+
fromNumber: ctx.from,
|
|
266
|
+
displayName: actorTrust.memberRecord!.contact.displayName,
|
|
267
|
+
isGuardian: actorTrust.memberRecord!.contact.role === "guardian",
|
|
268
|
+
},
|
|
269
|
+
resolved,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
237
273
|
// Unknown caller — name capture flow
|
|
238
274
|
log.info(
|
|
239
275
|
{
|