@vellumai/assistant 0.7.1 → 0.7.3
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/ARCHITECTURE.md +48 -50
- package/Dockerfile +1 -0
- package/README.md +1 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
- package/bun.lock +26 -26
- package/docs/architecture/memory.md +5 -2
- package/docs/architecture/security.md +20 -0
- package/docs/plugins.md +7 -9
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +52 -5
- package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
- package/node_modules/@vellumai/twilio-client/package.json +18 -0
- package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
- package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
- package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
- package/openapi.yaml +1020 -40
- package/package.json +6 -3
- package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
- package/src/__tests__/app-bundler.test.ts +170 -1
- package/src/__tests__/app-control-flow.test.ts +384 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-routes-http.test.ts +23 -6
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
- package/src/__tests__/assistant-event-hub.test.ts +157 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
- package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
- package/src/__tests__/btw-routes.test.ts +13 -4
- package/src/__tests__/call-controller.test.ts +49 -1
- package/src/__tests__/call-conversation-messages.test.ts +8 -2
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +62 -2
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +461 -147
- package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
- package/src/__tests__/config-watcher.test.ts +142 -71
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +3 -7
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop.test.ts +454 -5
- package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
- package/src/__tests__/conversation-error.test.ts +150 -3
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +36 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- package/src/__tests__/conversation-process-callsite.test.ts +43 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
- package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
- package/src/__tests__/credentials-cli.test.ts +12 -12
- package/src/__tests__/cu-unified-flow.test.ts +351 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +3 -4
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +968 -2
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +772 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +439 -47
- package/src/__tests__/host-bash-routes.test.ts +459 -0
- package/src/__tests__/host-browser-proxy.test.ts +24 -22
- package/src/__tests__/host-browser-routes.test.ts +39 -13
- package/src/__tests__/host-cu-proxy.test.ts +248 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
- package/src/__tests__/host-file-proxy.test.ts +301 -45
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +420 -0
- package/src/__tests__/host-file-write-tool.test.ts +42 -1
- package/src/__tests__/host-proxy-base.test.ts +312 -0
- package/src/__tests__/host-shell-tool.test.ts +22 -4
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +932 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
- package/src/__tests__/http-user-message-parity.test.ts +108 -1
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- package/src/__tests__/injector-chain.test.ts +18 -6
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
- package/src/__tests__/integration-status.test.ts +85 -5
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
- package/src/__tests__/managed-profile-guard.test.ts +18 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/relay-server.test.ts +15 -4
- package/src/__tests__/require-fresh-approval.test.ts +0 -1
- package/src/__tests__/retry-backoff.test.ts +87 -0
- package/src/__tests__/runtime-events-sse.test.ts +2 -2
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
- package/src/__tests__/skill-feature-flags.test.ts +43 -41
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
- package/src/__tests__/skill-load-inline-command.test.ts +0 -51
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +9 -14
- package/src/__tests__/suggestion-routes.test.ts +46 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +3 -5
- package/src/__tests__/twilio-validation.test.ts +93 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/approvals/guardian-decision-primitive.ts +13 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -17
- package/src/backup/__tests__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +51 -151
- package/src/backup/paths.ts +2 -18
- package/src/backup/restore.ts +107 -231
- package/src/backup/snapshot-lock.ts +2 -27
- package/src/bundler/app-bundler.ts +51 -3
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-conversation-messages.ts +46 -10
- package/src/calls/relay-server.ts +4 -44
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +33 -105
- package/src/calls/twilio-routes.ts +11 -12
- package/src/channels/types.ts +8 -7
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -5
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +137 -25
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +71 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +9 -6
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +303 -7
- package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
- package/src/cli/commands/oauth/connect.ts +127 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +16 -25
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +6 -2
- package/src/config/assistant-feature-flags.ts +79 -12
- package/src/config/bundled-skills/acp/SKILL.md +6 -0
- package/src/config/bundled-skills/acp/TOOLS.json +1 -22
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
- package/src/config/bundled-skills/app-control/SKILL.md +75 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
- package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
- package/src/config/bundled-skills/document/TOOLS.json +0 -8
- package/src/config/bundled-skills/followups/TOOLS.json +0 -12
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
- package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
- package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
- package/src/config/bundled-skills/settings/SKILL.md +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +0 -12
- package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
- package/src/config/bundled-skills/subagent/SKILL.md +6 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
- package/src/config/bundled-tool-registry.ts +21 -0
- package/src/config/env-registry.ts +0 -2
- package/src/config/env.ts +19 -20
- package/src/config/feature-flag-registry.json +47 -135
- package/src/config/loader.ts +197 -104
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +17 -9
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +64 -1
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +7 -10
- package/src/config/schemas/memory-lifecycle.ts +90 -24
- package/src/config/schemas/memory-v2.ts +121 -13
- package/src/config/schemas/platform.ts +49 -3
- package/src/config/schemas/services.ts +29 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -55
- package/src/contacts/contacts-write.ts +0 -27
- package/src/context/window-manager.ts +1 -2
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +12 -41
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +187 -5
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +89 -60
- package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
- package/src/daemon/conversation-agent-loop.ts +202 -61
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +9 -4
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-runtime-assembly.ts +28 -2
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +305 -4
- package/src/daemon/conversation-tool-setup.ts +66 -62
- package/src/daemon/conversation.ts +38 -24
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -2
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +389 -0
- package/src/daemon/host-bash-proxy.ts +117 -82
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +127 -86
- package/src/daemon/host-file-proxy.ts +129 -69
- package/src/daemon/host-proxy-base.ts +294 -0
- package/src/daemon/host-proxy-preactivation.ts +82 -0
- package/src/daemon/host-transfer-proxy.ts +338 -129
- package/src/daemon/lifecycle.ts +194 -145
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +14 -4
- package/src/daemon/message-protocol.ts +6 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +15 -8
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +4 -0
- package/src/daemon/message-types/host-cu.ts +2 -0
- package/src/daemon/message-types/host-file.ts +4 -0
- package/src/daemon/message-types/host-transfer.ts +3 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/process-message.ts +18 -1
- package/src/daemon/profiler-run-store.ts +5 -5
- package/src/daemon/shutdown-handlers.ts +0 -3
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +1 -1
- package/src/documents/document-store.ts +85 -0
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/filing/filing-service.ts +30 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
- package/src/heartbeat/heartbeat-run-store.ts +249 -0
- package/src/heartbeat/heartbeat-service.ts +459 -54
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/feed-scheduler.ts +18 -0
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +17 -92
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/platform-callback-registration.ts +8 -15
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +70 -3
- package/src/ipc/cli-client.ts +32 -1
- package/src/ipc/gateway-client.ts +37 -3
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/live-voice/protocol.ts +5 -7
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/mcp-auth-orchestrator.ts +213 -0
- package/src/mcp/mcp-auth-state.ts +133 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -0
- package/src/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
- package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
- package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
- package/src/memory/admin.ts +5 -9
- package/src/memory/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -0
- package/src/memory/auto-analysis-constants.ts +17 -0
- package/src/memory/auto-analysis-guard.ts +5 -15
- package/src/memory/canonical-guardian-store.ts +7 -7
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
- package/src/memory/context-search/agent-protocol.ts +6 -6
- package/src/memory/context-search/agent-runner.ts +51 -9
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +22 -9
- package/src/memory/context-search/sources/memory.ts +0 -1
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +5 -13
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +6 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
- package/src/memory/graph/conversation-graph-memory.ts +43 -78
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +10 -67
- package/src/memory/graph/graph-search.ts +9 -20
- package/src/memory/graph/retriever.test.ts +6 -0
- package/src/memory/graph/retriever.ts +34 -10
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/indexer.ts +54 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
- package/src/memory/jobs/embed-concept-page.ts +28 -2
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
- package/src/memory/jobs-store.ts +114 -22
- package/src/memory/jobs-worker.ts +193 -106
- package/src/memory/memory-v2-activation-log-store.ts +33 -15
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
- package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
- package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +49 -32
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +13 -67
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +387 -344
- package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
- package/src/memory/v2/__tests__/injection.test.ts +181 -169
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +154 -188
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +76 -2
- package/src/memory/v2/activation.ts +213 -239
- package/src/memory/v2/consolidation-job.ts +65 -17
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +123 -103
- package/src/memory/v2/prompts/consolidation.ts +348 -92
- package/src/memory/v2/qdrant.ts +198 -1
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +113 -77
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +91 -53
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +28 -5
- package/src/memory/v2/types.ts +10 -10
- package/src/messaging/providers/gmail/types.ts +0 -49
- package/src/messaging/providers/slack/adapter.ts +1 -31
- package/src/messaging/providers/slack/types.ts +0 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/copy-composer.ts +13 -0
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +6 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- package/src/outbound-proxy/index.ts +1 -37
- package/src/outbound-proxy/logging.ts +1 -1
- package/src/outbound-proxy/policy.ts +6 -5
- package/src/outbound-proxy/router.ts +2 -1
- package/src/permissions/approval-policy.test.ts +6 -275
- package/src/permissions/approval-policy.ts +0 -51
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +3 -17
- package/src/permissions/gateway-threshold-reader.ts +2 -0
- package/src/permissions/prompter.ts +34 -1
- package/src/permissions/secret-prompter.ts +6 -2
- package/src/plugins/defaults/injectors.ts +35 -2
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +867 -0
- package/src/proactive-artifact/job.ts +352 -0
- package/src/proactive-artifact/message-copy.ts +41 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +23 -24
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +151 -99
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +32 -0
- package/src/runtime/auth/same-actor.ts +216 -0
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-invite-transport.ts +2 -48
- package/src/runtime/channel-invite-transports/email.ts +1 -1
- package/src/runtime/channel-invite-transports/slack.ts +1 -1
- package/src/runtime/channel-invite-transports/telegram.ts +1 -1
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
- package/src/runtime/channel-invite-types.ts +54 -0
- package/src/runtime/channel-readiness-service.ts +32 -13
- package/src/runtime/channel-retry-sweep.ts +65 -1
- package/src/runtime/guardian-reply-router.ts +10 -0
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/local-actor-identity.ts +52 -11
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
- package/src/runtime/migrations/migration-transport.ts +7 -7
- package/src/runtime/migrations/vbundle-builder.ts +327 -60
- package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +245 -68
- package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
- package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +114 -0
- package/src/runtime/pending-interactions.ts +43 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
- package/src/runtime/routes/approval-interception-types.ts +13 -0
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/btw-routes.ts +14 -37
- package/src/runtime/routes/client-routes.ts +21 -2
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +65 -39
- package/src/runtime/routes/debug-bash-routes.ts +163 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +169 -0
- package/src/runtime/routes/documents-routes.ts +32 -75
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +38 -0
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-approval-interception.ts +2 -8
- package/src/runtime/routes/heartbeat-routes.ts +103 -38
- package/src/runtime/routes/host-app-control-routes.ts +134 -0
- package/src/runtime/routes/host-bash-routes.ts +56 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +66 -9
- package/src/runtime/routes/host-file-routes.ts +54 -5
- package/src/runtime/routes/host-transfer-routes.ts +122 -19
- package/src/runtime/routes/http-adapter.ts +1 -0
- package/src/runtime/routes/identity-intro-cache.ts +30 -0
- package/src/runtime/routes/identity-routes.ts +21 -180
- package/src/runtime/routes/inbound-message-handler.ts +78 -21
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +14 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.test.ts +41 -15
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +474 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- package/src/runtime/verification-templates.ts +4 -7
- package/src/schedule/integration-status.ts +66 -2
- package/src/schedule/recurrence-engine.ts +4 -1
- package/src/schedule/retry-backoff.ts +18 -0
- package/src/schedule/retry-policy.ts +82 -0
- package/src/schedule/run-script.ts +37 -5
- package/src/schedule/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -2
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +83 -39
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/security/secure-keys.ts +55 -0
- package/src/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- package/src/skills/catalog-files.ts +2 -8
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/remote-skill-policy.ts +10 -16
- package/src/skills/skill-file-provider.ts +1 -1
- package/src/skills/skill-file-types.ts +13 -0
- package/src/skills/skillssh-audit-types.ts +28 -0
- package/src/skills/skillssh-registry.ts +8 -21
- package/src/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- package/src/telemetry/types.ts +2 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/background-tool-registry.ts +17 -3
- package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +23 -24
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +2 -0
- package/src/tools/host-filesystem/edit.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +68 -0
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +68 -0
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +78 -3
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +68 -0
- package/src/tools/host-terminal/host-shell.ts +66 -1
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +12 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- package/src/tools/schedule/create.ts +6 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/schedule/update.ts +10 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
- package/src/tools/shared/filesystem/path-policy.ts +25 -1
- package/src/tools/skills/load.ts +0 -32
- package/src/tools/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +32 -11
- package/src/tools/types.ts +28 -2
- package/src/tts/provider-catalog.ts +3 -5
- package/src/usage/pricing.ts +1 -1
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/heartbeat-service.ts +19 -0
- package/src/workspace/migrations/003-seed-device-id.ts +1 -1
- package/src/workspace/migrations/006-services-config.ts +8 -5
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
- package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
- package/src/__tests__/twilio-rest.test.ts +0 -34
- package/src/backup/__tests__/backup-key.test.ts +0 -152
- package/src/backup/__tests__/backup-worker.test.ts +0 -782
- package/src/backup/__tests__/offsite-writer.test.ts +0 -641
- package/src/backup/__tests__/stream-crypt.test.ts +0 -228
- package/src/backup/backup-key.ts +0 -137
- package/src/backup/backup-worker.ts +0 -472
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- package/src/daemon/message-types/pairing.ts +0 -58
- package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -395
- package/src/outbound-proxy/config.ts +0 -20
- package/src/outbound-proxy/health.ts +0 -18
- package/src/outbound-proxy/types.ts +0 -150
- package/src/runtime/capability-tokens.ts +0 -190
- package/src/signals/bash.ts +0 -198
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -76,11 +76,6 @@ export interface SlackUser {
|
|
|
76
76
|
deleted?: boolean;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
export interface SlackUsersListResponse extends SlackApiResponse {
|
|
80
|
-
members: SlackUser[];
|
|
81
|
-
response_metadata?: { next_cursor?: string };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
79
|
export interface SlackUserInfoResponse extends SlackApiResponse {
|
|
85
80
|
user: SlackUser;
|
|
86
81
|
}
|
|
@@ -110,35 +105,8 @@ export interface SlackSearchMatch {
|
|
|
110
105
|
thread_ts?: string;
|
|
111
106
|
}
|
|
112
107
|
|
|
113
|
-
export interface SlackConversationInfoResponse extends SlackApiResponse {
|
|
114
|
-
channel: SlackConversation;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
108
|
export interface SlackConversationsOpenResponse extends SlackApiResponse {
|
|
118
109
|
channel: { id: string };
|
|
119
110
|
}
|
|
120
111
|
|
|
121
|
-
export type SlackReactionAddResponse = SlackApiResponse;
|
|
122
|
-
|
|
123
|
-
export type SlackConversationJoinResponse = SlackApiResponse & {
|
|
124
|
-
channel?: SlackConversation;
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
export type SlackConversationLeaveResponse = SlackApiResponse;
|
|
128
|
-
|
|
129
|
-
export interface SlackChatDeleteResponse extends SlackApiResponse {
|
|
130
|
-
channel: string;
|
|
131
|
-
ts: string;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export interface SlackChatUpdateResponse extends SlackApiResponse {
|
|
135
|
-
channel: string;
|
|
136
|
-
ts: string;
|
|
137
|
-
text: string;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
112
|
export type SlackConversationMarkResponse = SlackApiResponse;
|
|
141
|
-
|
|
142
|
-
export interface SlackPostEphemeralResponse extends SlackApiResponse {
|
|
143
|
-
message_ts: string;
|
|
144
|
-
}
|
|
@@ -133,7 +133,7 @@ The system produces **three distinct copy outputs** per notification:
|
|
|
133
133
|
|
|
134
134
|
| Output | Purpose | Verbosity |
|
|
135
135
|
| ------------------------- | ------------------------------------------------ | ------------------------ |
|
|
136
|
-
| `title` + `body` | Native notification popup (macOS
|
|
136
|
+
| `title` + `body` | Native notification popup (macOS banner) | Short and glanceable |
|
|
137
137
|
| `deliveryText` | Channel-native chat message text (Telegram) | Natural chat phrasing |
|
|
138
138
|
| Conversation seed message | Opening message in the notification conversation | Richer and context-aware |
|
|
139
139
|
|
|
@@ -185,7 +185,7 @@ Reminder. Take out the trash. Action required.
|
|
|
185
185
|
|
|
186
186
|
## Conversation Surfacing via `notification_conversation_created` Event (Creation-Only)
|
|
187
187
|
|
|
188
|
-
The `notification_conversation_created` SSE event is emitted **only when a brand-new conversation is actually created** by the broadcaster. Reused conversations do not trigger this event — the macOS
|
|
188
|
+
The `notification_conversation_created` SSE event is emitted **only when a brand-new conversation is actually created** by the broadcaster. Reused conversations do not trigger this event — the macOS client already knows about the conversation from the original creation.
|
|
189
189
|
|
|
190
190
|
This is enforced in `broadcaster.ts` by gating the event emission on `pairing.createdNewConversation === true`:
|
|
191
191
|
|
|
@@ -214,7 +214,7 @@ The SSE event payload:
|
|
|
214
214
|
}
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
-
The macOS
|
|
217
|
+
The macOS client listens for this event and surfaces the conversation in the sidebar, enabling deep-link navigation to the notification conversation.
|
|
218
218
|
|
|
219
219
|
### Per-Dispatch Conversation Callback
|
|
220
220
|
|
|
@@ -223,7 +223,7 @@ The macOS/iOS client listens for this event and surfaces the conversation in the
|
|
|
223
223
|
**Important distinction between the two callbacks:**
|
|
224
224
|
|
|
225
225
|
- **Per-dispatch `options.onConversationCreated`**: Fires for **both** new and reused vellum conversation pairings. Callers like `dispatchGuardianQuestion` rely on this to create delivery bookkeeping rows before `emitNotificationSignal()` returns, regardless of whether the conversation was newly created or reused.
|
|
226
|
-
- **Class-level `this.onConversationCreated` (SSE broadcast)**: Fires **only** when a brand-new conversation is created (`createdNewConversation === true && strategy === 'start_new_conversation'`). This emits the `notification_conversation_created` SSE event so macOS
|
|
226
|
+
- **Class-level `this.onConversationCreated` (SSE broadcast)**: Fires **only** when a brand-new conversation is created (`createdNewConversation === true && strategy === 'start_new_conversation'`). This emits the `notification_conversation_created` SSE event so macOS clients surface the new conversation in the sidebar. Reused conversations do not trigger this event because the client already knows about the conversation.
|
|
227
227
|
|
|
228
228
|
## Schedule Routing Metadata and Trigger-Time Enforcement
|
|
229
229
|
|
|
@@ -295,7 +295,7 @@ Local SSE via the daemon's broadcast mechanism. The `VellumAdapter` emits a `not
|
|
|
295
295
|
- `title` and `body` -- rendered notification copy
|
|
296
296
|
- `deepLinkMetadata` -- optional metadata for navigating to the relevant context (e.g. `{ conversationId }`)
|
|
297
297
|
|
|
298
|
-
The macOS
|
|
298
|
+
The macOS client posts a native `UNUserNotificationCenter` notification from this payload. When the user taps the notification, the client uses `deepLinkMetadata` to navigate to the relevant conversation.
|
|
299
299
|
|
|
300
300
|
### Telegram (when guardian binding exists)
|
|
301
301
|
|
|
@@ -480,7 +480,7 @@ Three SQLite tables form the audit chain:
|
|
|
480
480
|
|
|
481
481
|
### Client Delivery Ack
|
|
482
482
|
|
|
483
|
-
For vellum (macOS
|
|
483
|
+
For vellum (macOS) deliveries, the audit trail now extends past the SSE broadcast to the actual OS notification post. The `notification_intent` message carries an optional `deliveryId` that the client echoes back in a `notification_intent_result` ack after `UNUserNotificationCenter.add()` completes (or fails).
|
|
484
484
|
|
|
485
485
|
The ack populates three columns on `notification_deliveries`:
|
|
486
486
|
|
|
@@ -541,10 +541,10 @@ Preferences are sanitized against prompt injection (angle brackets replaced with
|
|
|
541
541
|
The decision engine and preference extractor pick their per-call LLM config
|
|
542
542
|
from the unified `llm` block. Override defaults by setting either of:
|
|
543
543
|
|
|
544
|
-
| Key | Type
|
|
545
|
-
| ------------------------------------ |
|
|
546
|
-
| `llm.callSites.notificationDecision` | object
|
|
547
|
-
| `llm.callSites.preferenceExtraction` | object
|
|
544
|
+
| Key | Type | Default | Description |
|
|
545
|
+
| ------------------------------------ | ------ | --------- | -------------------------------------------------------------------------- |
|
|
546
|
+
| `llm.callSites.notificationDecision` | object | _(unset)_ | Provider/model/effort/etc. override for the decision engine call site |
|
|
547
|
+
| `llm.callSites.preferenceExtraction` | object | _(unset)_ | Provider/model/effort/etc. override for the preference extractor call site |
|
|
548
548
|
|
|
549
549
|
When a call site override is unset, the resolver falls back to `llm.default`.
|
|
550
550
|
|
|
@@ -211,7 +211,7 @@ export class NotificationBroadcaster {
|
|
|
211
211
|
);
|
|
212
212
|
|
|
213
213
|
// For the vellum channel, merge the conversationId into deep-link metadata
|
|
214
|
-
// so the macOS
|
|
214
|
+
// so the macOS client can navigate directly to the notification conversation.
|
|
215
215
|
let deepLinkTarget = decision.deepLinkTarget;
|
|
216
216
|
if (channel === "vellum" && pairing.conversationId) {
|
|
217
217
|
deepLinkTarget = {
|
|
@@ -505,6 +505,19 @@ const TEMPLATES: Partial<Record<NotificationSourceEventName, CopyTemplate>> = {
|
|
|
505
505
|
body: str(payload.body, "A watcher event requires your attention"),
|
|
506
506
|
}),
|
|
507
507
|
|
|
508
|
+
"heartbeat.alert": (payload) => {
|
|
509
|
+
const body = str(
|
|
510
|
+
payload.summary,
|
|
511
|
+
str(payload.body, "Your assistant found something worth your attention."),
|
|
512
|
+
);
|
|
513
|
+
return {
|
|
514
|
+
title: str(payload.title, "Heartbeat Alert"),
|
|
515
|
+
body,
|
|
516
|
+
conversationTitle: str(payload.conversationTitle, "Heartbeat"),
|
|
517
|
+
conversationSeedMessage: body,
|
|
518
|
+
};
|
|
519
|
+
},
|
|
520
|
+
|
|
508
521
|
"tool_confirmation.required_action": (payload) => ({
|
|
509
522
|
title: "Tool Confirmation",
|
|
510
523
|
body: str(payload.toolName, "A tool") + " requires your confirmation",
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
* fields like `toolName`.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type GuardianQuestionRequestKind =
|
|
10
10
|
| "pending_question"
|
|
11
11
|
| "tool_approval"
|
|
12
12
|
| "tool_grant_request"
|
|
13
13
|
| "access_request";
|
|
14
|
-
|
|
14
|
+
type GuardianQuestionInstructionMode = "approval" | "answer";
|
|
15
15
|
|
|
16
16
|
interface GuardianRequestKindModeConfig {
|
|
17
17
|
defaultMode: GuardianQuestionInstructionMode;
|
|
@@ -48,12 +48,12 @@ interface GuardianQuestionPayloadBaseWithDiscriminator extends GuardianQuestionP
|
|
|
48
48
|
[key: string]: unknown;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
interface GuardianRequestModeInput {
|
|
52
52
|
kind: unknown;
|
|
53
53
|
toolName?: unknown;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
interface GuardianRequestTextInput {
|
|
57
57
|
requestCode: string;
|
|
58
58
|
questionText?: string | null;
|
|
59
59
|
toolName?: string | null;
|
|
@@ -136,7 +136,7 @@ export type GuardianQuestionPayload =
|
|
|
136
136
|
| ToolGrantGuardianPayload
|
|
137
137
|
| AccessRequestGuardianPayload;
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
interface GuardianQuestionModeResolution {
|
|
140
140
|
mode: GuardianQuestionInstructionMode;
|
|
141
141
|
requestKind: GuardianQuestionRequestKind | null;
|
|
142
142
|
}
|
|
@@ -101,6 +101,10 @@ export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
|
101
101
|
description:
|
|
102
102
|
"OAuth credential health issue detected (expired, revoked, missing scopes)",
|
|
103
103
|
},
|
|
104
|
+
{
|
|
105
|
+
id: "heartbeat.alert",
|
|
106
|
+
description: "Heartbeat found something worth surfacing to the guardian",
|
|
107
|
+
},
|
|
104
108
|
] as const;
|
|
105
109
|
|
|
106
110
|
export type NotificationSourceEventName =
|
package/src/oauth/AGENTS.md
CHANGED
|
@@ -54,7 +54,9 @@ Most existing logos come from [Simple Icons](https://simpleicons.org) (CC0-licen
|
|
|
54
54
|
|
|
55
55
|
If the service is not on Simple Icons, source or create an SVG and convert it the same way. The result must be a true vector PDF (not a rasterized image wrapped in PDF) so it scales cleanly.
|
|
56
56
|
|
|
57
|
-
The `logoUrl` field in `seed-providers.ts`
|
|
57
|
+
The `logoUrl` field in `seed-providers.ts` serves as the remote fallback (most providers use a Simple Icons CDN URL like `https://cdn.simpleicons.org/acme`). The client renders the local PDF first, then falls back to `logoUrl`, then to an initials avatar.
|
|
58
|
+
|
|
59
|
+
For brands Simple Icons doesn't host (e.g. Salesforce, which Simple Icons removed for trademark reasons), use the same `glincker/thesvg` source via jsDelivr — `https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/<key>/default.svg`. The recognised `logoUrl` prefixes are enforced by `oauth-provider-seed-logos.test.ts`; if you need a third source, extend that allowlist alongside the manifest in `clients/shared/Resources/integration-logos-manifest.json`.
|
|
58
60
|
|
|
59
61
|
### 5. Secret patterns (if applicable) — `../security/secret-patterns.ts`
|
|
60
62
|
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
_clearAllOAuthConnectStates,
|
|
5
|
+
clearExpiredOAuthConnectStates,
|
|
6
|
+
getOAuthConnectState,
|
|
7
|
+
setOAuthConnectComplete,
|
|
8
|
+
setOAuthConnectError,
|
|
9
|
+
setOAuthConnectPending,
|
|
10
|
+
} from "../oauth-connect-state.js";
|
|
11
|
+
|
|
12
|
+
describe("oauth-connect-state", () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
_clearAllOAuthConnectStates();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("setOAuthConnectPending → getOAuthConnectState returns pending", () => {
|
|
18
|
+
setOAuthConnectPending("state-1", "google");
|
|
19
|
+
const result = getOAuthConnectState("state-1");
|
|
20
|
+
expect(result).toMatchObject({ status: "pending", service: "google" });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("setOAuthConnectComplete without accountInfo → returns complete", () => {
|
|
24
|
+
setOAuthConnectComplete("state-1", "google");
|
|
25
|
+
const result = getOAuthConnectState("state-1");
|
|
26
|
+
expect(result).toMatchObject({ status: "complete", service: "google" });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("setOAuthConnectComplete with accountInfo → returns complete with accountInfo", () => {
|
|
30
|
+
setOAuthConnectComplete("state-1", "google", "user@example.com");
|
|
31
|
+
const result = getOAuthConnectState("state-1");
|
|
32
|
+
expect(result).toMatchObject({
|
|
33
|
+
status: "complete",
|
|
34
|
+
service: "google",
|
|
35
|
+
accountInfo: "user@example.com",
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("setOAuthConnectComplete with grantedScopes → returns complete with grantedScopes", () => {
|
|
40
|
+
setOAuthConnectComplete("state-1", "google", "user@example.com", ["scope:read", "scope:write"]);
|
|
41
|
+
const result = getOAuthConnectState("state-1");
|
|
42
|
+
expect(result).toMatchObject({
|
|
43
|
+
status: "complete",
|
|
44
|
+
service: "google",
|
|
45
|
+
accountInfo: "user@example.com",
|
|
46
|
+
grantedScopes: ["scope:read", "scope:write"],
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("setOAuthConnectError → returns error with message", () => {
|
|
51
|
+
setOAuthConnectError("state-1", "google", "token exchange failed");
|
|
52
|
+
const result = getOAuthConnectState("state-1");
|
|
53
|
+
expect(result).toMatchObject({
|
|
54
|
+
status: "error",
|
|
55
|
+
service: "google",
|
|
56
|
+
error: "token exchange failed",
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("re-setting same state token overwrites previous", () => {
|
|
61
|
+
setOAuthConnectPending("state-1", "google");
|
|
62
|
+
setOAuthConnectComplete("state-1", "google", "user@example.com");
|
|
63
|
+
const result = getOAuthConnectState("state-1");
|
|
64
|
+
expect(result?.status).toBe("complete");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("getOAuthConnectState returns null for unknown state", () => {
|
|
68
|
+
expect(getOAuthConnectState("nonexistent")).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("_clearAllOAuthConnectStates removes all entries", () => {
|
|
72
|
+
setOAuthConnectPending("state-1", "google");
|
|
73
|
+
setOAuthConnectPending("state-2", "github");
|
|
74
|
+
_clearAllOAuthConnectStates();
|
|
75
|
+
expect(getOAuthConnectState("state-1")).toBeNull();
|
|
76
|
+
expect(getOAuthConnectState("state-2")).toBeNull();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("clearExpiredOAuthConnectStates removes expired pending entries", () => {
|
|
80
|
+
setOAuthConnectPending("state-1", "google");
|
|
81
|
+
// Advance Date.now by 6 minutes past PENDING_TTL_MS (5 min)
|
|
82
|
+
const originalNow = Date.now;
|
|
83
|
+
Date.now = () => originalNow() + 6 * 60 * 1000;
|
|
84
|
+
clearExpiredOAuthConnectStates();
|
|
85
|
+
Date.now = originalNow;
|
|
86
|
+
expect(getOAuthConnectState("state-1")).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("clearExpiredOAuthConnectStates removes expired complete entries (past 60s grace)", () => {
|
|
90
|
+
setOAuthConnectComplete("state-1", "google");
|
|
91
|
+
const originalNow = Date.now;
|
|
92
|
+
Date.now = () => originalNow() + 2 * 60 * 1000; // advance 2 minutes past 60s grace
|
|
93
|
+
clearExpiredOAuthConnectStates();
|
|
94
|
+
Date.now = originalNow;
|
|
95
|
+
expect(getOAuthConnectState("state-1")).toBeNull();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("clearExpiredOAuthConnectStates removes expired error entries (past 60s grace)", () => {
|
|
99
|
+
setOAuthConnectError("state-1", "google", "token exchange failed");
|
|
100
|
+
const originalNow = Date.now;
|
|
101
|
+
Date.now = () => originalNow() + 2 * 60 * 1000; // advance 2 minutes past 60s grace
|
|
102
|
+
clearExpiredOAuthConnectStates();
|
|
103
|
+
Date.now = originalNow;
|
|
104
|
+
expect(getOAuthConnectState("state-1")).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("clearExpiredOAuthConnectStates does not remove non-expired pending entries", () => {
|
|
108
|
+
setOAuthConnectPending("state-1", "google");
|
|
109
|
+
clearExpiredOAuthConnectStates(); // called without advancing time
|
|
110
|
+
expect(getOAuthConnectState("state-1")).not.toBeNull();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("sweep-on-insert: setOAuthConnectPending purges expired entries before inserting new one", () => {
|
|
114
|
+
// 1. Add an entry that will expire
|
|
115
|
+
setOAuthConnectPending("expired-state", "google");
|
|
116
|
+
|
|
117
|
+
// 2. Advance Date.now past the PENDING_TTL_MS (5 min)
|
|
118
|
+
const originalNow = Date.now;
|
|
119
|
+
Date.now = () => originalNow() + 6 * 60 * 1000;
|
|
120
|
+
|
|
121
|
+
// 3. Insert a new entry — this should trigger clearExpiredOAuthConnectStates() internally
|
|
122
|
+
setOAuthConnectPending("new-state", "github");
|
|
123
|
+
|
|
124
|
+
// 4. Restore Date.now before assertions (getOAuthConnectState also calls clearExpiredOAuthConnectStates)
|
|
125
|
+
Date.now = originalNow;
|
|
126
|
+
|
|
127
|
+
// The expired entry must have been swept out during the insert
|
|
128
|
+
// Use the map directly via getOAuthConnectState — expired-state is gone
|
|
129
|
+
// We call _clearAllOAuthConnectStates in beforeEach so we know the map started empty.
|
|
130
|
+
// After the insert the map should only contain "new-state".
|
|
131
|
+
const expiredResult = getOAuthConnectState("expired-state");
|
|
132
|
+
expect(expiredResult).toBeNull();
|
|
133
|
+
|
|
134
|
+
const newResult = getOAuthConnectState("new-state");
|
|
135
|
+
expect(newResult).toMatchObject({ status: "pending", service: "github" });
|
|
136
|
+
});
|
|
137
|
+
});
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* - Running identity verifiers
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
import { emitPostConnectNudge } from "../home/post-connect-feed.js";
|
|
22
23
|
import type { TokenEndpointAuthMethod } from "../security/oauth2.js";
|
|
23
24
|
import { prepareOAuth2Flow, startOAuth2Flow } from "../security/oauth2.js";
|
|
24
25
|
import { getLogger } from "../util/logger.js";
|
|
@@ -80,6 +81,7 @@ export interface OAuthConnectOptions {
|
|
|
80
81
|
success: boolean;
|
|
81
82
|
service: string;
|
|
82
83
|
accountInfo?: string;
|
|
84
|
+
grantedScopes?: string[];
|
|
83
85
|
error?: string;
|
|
84
86
|
}) => void;
|
|
85
87
|
}
|
|
@@ -250,10 +252,12 @@ export async function orchestrateOAuthConnect(
|
|
|
250
252
|
},
|
|
251
253
|
"Deferred OAuth2 flow completed — tokens stored",
|
|
252
254
|
);
|
|
255
|
+
void emitPostConnectNudge(options.service);
|
|
253
256
|
options.onDeferredComplete?.({
|
|
254
257
|
success: true,
|
|
255
258
|
service: options.service,
|
|
256
259
|
accountInfo: stored.accountInfo ?? parsedAccountIdentifier,
|
|
260
|
+
grantedScopes: result.grantedScopes,
|
|
257
261
|
});
|
|
258
262
|
} catch (err) {
|
|
259
263
|
log.error(
|
|
@@ -371,6 +375,8 @@ export async function orchestrateOAuthConnect(
|
|
|
371
375
|
"orchestrateOAuthConnect: tokens stored, connect complete",
|
|
372
376
|
);
|
|
373
377
|
|
|
378
|
+
void emitPostConnectNudge(options.service);
|
|
379
|
+
|
|
374
380
|
return {
|
|
375
381
|
success: true,
|
|
376
382
|
deferred: false,
|
|
@@ -62,7 +62,10 @@ mock.module("../platform/client.js", () => ({
|
|
|
62
62
|
// ---------------------------------------------------------------------------
|
|
63
63
|
|
|
64
64
|
import { BYOOAuthConnection } from "./byo-connection.js";
|
|
65
|
-
import {
|
|
65
|
+
import {
|
|
66
|
+
resolveEffectiveBaseUrl,
|
|
67
|
+
resolveOAuthConnection,
|
|
68
|
+
} from "./connection-resolver.js";
|
|
66
69
|
import { PlatformOAuthConnection } from "./platform-connection.js";
|
|
67
70
|
|
|
68
71
|
// ---------------------------------------------------------------------------
|
|
@@ -214,3 +217,65 @@ describe("resolveOAuthConnection", () => {
|
|
|
214
217
|
).rejects.toThrow(/No active OAuth connection found/);
|
|
215
218
|
});
|
|
216
219
|
});
|
|
220
|
+
|
|
221
|
+
describe("resolveEffectiveBaseUrl", () => {
|
|
222
|
+
const fallback = "https://login.salesforce.com";
|
|
223
|
+
|
|
224
|
+
test("uses instance_url from JSON-string metadata for Salesforce", () => {
|
|
225
|
+
const metadata = JSON.stringify({
|
|
226
|
+
instance_url: "https://acme.my.salesforce.com",
|
|
227
|
+
issued_at: "1714000000000",
|
|
228
|
+
});
|
|
229
|
+
expect(resolveEffectiveBaseUrl("salesforce", fallback, metadata)).toBe(
|
|
230
|
+
"https://acme.my.salesforce.com",
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("uses instance_url from already-parsed object metadata", () => {
|
|
235
|
+
const metadata = { instance_url: "https://na162.salesforce.com" };
|
|
236
|
+
expect(resolveEffectiveBaseUrl("salesforce", fallback, metadata)).toBe(
|
|
237
|
+
"https://na162.salesforce.com",
|
|
238
|
+
);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("falls back to seed baseUrl when metadata is null", () => {
|
|
242
|
+
expect(resolveEffectiveBaseUrl("salesforce", fallback, null)).toBe(
|
|
243
|
+
fallback,
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("falls back to seed baseUrl when instance_url is empty string", () => {
|
|
248
|
+
const metadata = JSON.stringify({ instance_url: "" });
|
|
249
|
+
expect(resolveEffectiveBaseUrl("salesforce", fallback, metadata)).toBe(
|
|
250
|
+
fallback,
|
|
251
|
+
);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test("falls back to seed baseUrl when metadata is unparseable JSON", () => {
|
|
255
|
+
expect(
|
|
256
|
+
resolveEffectiveBaseUrl("salesforce", fallback, "{ not valid json"),
|
|
257
|
+
).toBe(fallback);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("falls back to seed baseUrl when instance_url is the wrong type", () => {
|
|
261
|
+
const metadata = JSON.stringify({ instance_url: 12345 });
|
|
262
|
+
expect(resolveEffectiveBaseUrl("salesforce", fallback, metadata)).toBe(
|
|
263
|
+
fallback,
|
|
264
|
+
);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test("ignores instance_url for non-Salesforce providers", () => {
|
|
268
|
+
// A different provider whose token response happens to include an
|
|
269
|
+
// instance_url-shaped field MUST NOT have its baseUrl rewritten.
|
|
270
|
+
const metadata = JSON.stringify({
|
|
271
|
+
instance_url: "https://attacker.example.com",
|
|
272
|
+
});
|
|
273
|
+
expect(
|
|
274
|
+
resolveEffectiveBaseUrl(
|
|
275
|
+
"google",
|
|
276
|
+
"https://gmail.googleapis.com/gmail/v1/users/me",
|
|
277
|
+
metadata,
|
|
278
|
+
),
|
|
279
|
+
).toBe("https://gmail.googleapis.com/gmail/v1/users/me");
|
|
280
|
+
});
|
|
281
|
+
});
|
|
@@ -116,11 +116,65 @@ export async function resolveOAuthConnection(
|
|
|
116
116
|
return new BYOOAuthConnection({
|
|
117
117
|
id: conn.id,
|
|
118
118
|
provider: conn.provider,
|
|
119
|
-
baseUrl,
|
|
119
|
+
baseUrl: resolveEffectiveBaseUrl(conn.provider, baseUrl, conn.metadata),
|
|
120
120
|
accountInfo: conn.accountInfo,
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Resolve the effective API base URL for a connection, preferring per-tenant
|
|
126
|
+
* values stored on the connection's `metadata` over the provider's static
|
|
127
|
+
* seed value when applicable.
|
|
128
|
+
*
|
|
129
|
+
* Salesforce is the only provider that needs this: every org has its own
|
|
130
|
+
* API instance host (``acme.my.salesforce.com``, ``na162.salesforce.com``)
|
|
131
|
+
* which is returned in the OAuth token response as ``instance_url`` and
|
|
132
|
+
* captured into ``oauth_connection.metadata`` by ``storeOAuth2Tokens``.
|
|
133
|
+
* The seed's ``baseUrl`` for Salesforce is the login domain
|
|
134
|
+
* (``https://login.salesforce.com``) — correct for the OAuth handshake but
|
|
135
|
+
* wrong for REST API calls. Pulling the per-connection ``instance_url``
|
|
136
|
+
* here avoids forcing every caller to override ``baseUrl`` per-request.
|
|
137
|
+
*
|
|
138
|
+
* For all other providers the seed value is correct (single API domain),
|
|
139
|
+
* so we return it unchanged.
|
|
140
|
+
*
|
|
141
|
+
* If a future provider needs the same treatment, generalize via a
|
|
142
|
+
* declarative ``baseUrlMetadataKey`` field on the seed entry rather than
|
|
143
|
+
* adding more provider-name branches here.
|
|
144
|
+
*/
|
|
145
|
+
export function resolveEffectiveBaseUrl(
|
|
146
|
+
provider: string,
|
|
147
|
+
fallbackBaseUrl: string,
|
|
148
|
+
rawMetadata: unknown,
|
|
149
|
+
): string {
|
|
150
|
+
if (provider !== "salesforce") return fallbackBaseUrl;
|
|
151
|
+
|
|
152
|
+
const metadata = parseConnectionMetadata(rawMetadata);
|
|
153
|
+
const instanceUrl = metadata?.instance_url;
|
|
154
|
+
if (typeof instanceUrl === "string" && instanceUrl.length > 0) {
|
|
155
|
+
return instanceUrl;
|
|
156
|
+
}
|
|
157
|
+
return fallbackBaseUrl;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function parseConnectionMetadata(
|
|
161
|
+
raw: unknown,
|
|
162
|
+
): Record<string, unknown> | undefined {
|
|
163
|
+
if (raw == null) return undefined;
|
|
164
|
+
if (typeof raw === "object") {
|
|
165
|
+
return raw as Record<string, unknown>;
|
|
166
|
+
}
|
|
167
|
+
if (typeof raw !== "string") return undefined;
|
|
168
|
+
try {
|
|
169
|
+
const parsed = JSON.parse(raw);
|
|
170
|
+
return typeof parsed === "object" && parsed !== null
|
|
171
|
+
? (parsed as Record<string, unknown>)
|
|
172
|
+
: undefined;
|
|
173
|
+
} catch {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
124
178
|
// ---------------------------------------------------------------------------
|
|
125
179
|
// Platform connection ID resolution
|
|
126
180
|
// ---------------------------------------------------------------------------
|
|
@@ -43,9 +43,7 @@ export interface ConnectionAccessTokenResult {
|
|
|
43
43
|
* providers (e.g. credential-health checks) must resolve the path through here
|
|
44
44
|
* rather than assuming the OAuth access-token path.
|
|
45
45
|
*/
|
|
46
|
-
|
|
47
|
-
provider: string,
|
|
48
|
-
): string | null {
|
|
46
|
+
function manualTokenAccessCredentialKey(provider: string): string | null {
|
|
49
47
|
switch (provider) {
|
|
50
48
|
case "slack_channel":
|
|
51
49
|
return credentialKey("slack_channel", "bot_token");
|
|
@@ -19,10 +19,6 @@ import {
|
|
|
19
19
|
upsertApp,
|
|
20
20
|
} from "./oauth-store.js";
|
|
21
21
|
|
|
22
|
-
// Re-export from the centralized resolver so existing callers that import
|
|
23
|
-
// from this module continue to work without changes.
|
|
24
|
-
export { manualTokenAccessCredentialKey } from "./credential-token-resolver.js";
|
|
25
|
-
|
|
26
22
|
const log = getLogger("manual-token-connection");
|
|
27
23
|
|
|
28
24
|
/** Sentinel client_id used for non-OAuth providers that don't have a real app. */
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory OAuth connect flow status map.
|
|
3
|
+
*
|
|
4
|
+
* Tracks the current state of daemon-owned OAuth connect flows so the CLI
|
|
5
|
+
* can poll for completion via the IPC route.
|
|
6
|
+
*/
|
|
7
|
+
type OAuthConnectState =
|
|
8
|
+
| { status: "pending"; service: string; expiresAt: number }
|
|
9
|
+
| { status: "complete"; service: string; accountInfo?: string; grantedScopes?: string[]; completedAt: number }
|
|
10
|
+
| { status: "error"; service: string; error: string; failedAt: number };
|
|
11
|
+
|
|
12
|
+
const activeOAuthConnectFlows = new Map<string, OAuthConnectState>();
|
|
13
|
+
|
|
14
|
+
const PENDING_TTL_MS = 5 * 60 * 1000; // 5 min — matches oauth-callback-registry.ts:14
|
|
15
|
+
const COMPLETION_GRACE_MS = 60 * 1000; // 60s so the polling CLI gets one final read
|
|
16
|
+
|
|
17
|
+
export function setOAuthConnectPending(state: string, service: string): void {
|
|
18
|
+
clearExpiredOAuthConnectStates();
|
|
19
|
+
activeOAuthConnectFlows.set(state, {
|
|
20
|
+
status: "pending",
|
|
21
|
+
service,
|
|
22
|
+
expiresAt: Date.now() + PENDING_TTL_MS,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function setOAuthConnectComplete(
|
|
27
|
+
state: string,
|
|
28
|
+
service: string,
|
|
29
|
+
accountInfo?: string,
|
|
30
|
+
grantedScopes?: string[],
|
|
31
|
+
): void {
|
|
32
|
+
clearExpiredOAuthConnectStates();
|
|
33
|
+
activeOAuthConnectFlows.set(state, {
|
|
34
|
+
status: "complete",
|
|
35
|
+
service,
|
|
36
|
+
accountInfo,
|
|
37
|
+
grantedScopes,
|
|
38
|
+
completedAt: Date.now(),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function setOAuthConnectError(
|
|
43
|
+
state: string,
|
|
44
|
+
service: string,
|
|
45
|
+
error: string,
|
|
46
|
+
): void {
|
|
47
|
+
clearExpiredOAuthConnectStates();
|
|
48
|
+
activeOAuthConnectFlows.set(state, {
|
|
49
|
+
status: "error",
|
|
50
|
+
service,
|
|
51
|
+
error,
|
|
52
|
+
failedAt: Date.now(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getOAuthConnectState(state: string): OAuthConnectState | null {
|
|
57
|
+
clearExpiredOAuthConnectStates();
|
|
58
|
+
return activeOAuthConnectFlows.get(state) ?? null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function clearExpiredOAuthConnectStates(): void {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
for (const [key, state] of activeOAuthConnectFlows) {
|
|
64
|
+
if (state.status === "pending" && now > state.expiresAt) {
|
|
65
|
+
activeOAuthConnectFlows.delete(key);
|
|
66
|
+
} else if (state.status === "complete" && now > state.completedAt + COMPLETION_GRACE_MS) {
|
|
67
|
+
activeOAuthConnectFlows.delete(key);
|
|
68
|
+
} else if (state.status === "error" && now > state.failedAt + COMPLETION_GRACE_MS) {
|
|
69
|
+
activeOAuthConnectFlows.delete(key);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Test-only helper — clears all state for test isolation. */
|
|
75
|
+
export function _clearAllOAuthConnectStates(): void {
|
|
76
|
+
activeOAuthConnectFlows.clear();
|
|
77
|
+
}
|