@vellumai/assistant 0.7.0 → 0.7.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/ARCHITECTURE.md +38 -56
- package/Dockerfile +2 -0
- package/README.md +3 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +88 -142
- package/bun.lock +29 -26
- package/docs/architecture/security.md +38 -16
- package/docs/plugins.md +7 -9
- package/knip.json +2 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
- 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/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +9 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- 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 +869 -129
- package/package.json +8 -3
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- 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 +374 -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-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +29 -23
- 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 +235 -79
- package/src/__tests__/assistant-event.test.ts +10 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +44 -17
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -36
- package/src/__tests__/background-shell-host-bash.test.ts +46 -56
- 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 +50 -2
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/channel-readiness-service.test.ts +59 -1
- package/src/__tests__/checker.test.ts +23 -38
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-loader-backfill.test.ts +90 -155
- 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 +6 -48
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +14 -2
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- 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-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +40 -4
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +7 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -104
- package/src/__tests__/conversation-routes-slash-commands.test.ts +76 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -8
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- 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__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/credentials-cli.test.ts +5 -12
- package/src/__tests__/cu-unified-flow.test.ts +206 -27
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +102 -17
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +30 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -84
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +1007 -8
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-app-control-proxy.test.ts +602 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +270 -147
- package/src/__tests__/host-bash-routes.test.ts +294 -0
- package/src/__tests__/host-browser-proxy.test.ts +126 -198
- package/src/__tests__/host-browser-routes.test.ts +50 -54
- package/src/__tests__/host-cu-proxy.test.ts +78 -144
- package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
- package/src/__tests__/host-file-proxy.test.ts +62 -122
- package/src/__tests__/host-file-read-tool.test.ts +59 -21
- package/src/__tests__/host-file-routes-targeted.test.ts +262 -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 +53 -70
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
- package/src/__tests__/host-transfer-proxy.test.ts +145 -56
- package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
- package/src/__tests__/http-user-message-parity.test.ts +1 -6
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- package/src/__tests__/injector-chain.test.ts +10 -5
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -67
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -13
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- 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__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -11
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +172 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +26 -21
- package/src/__tests__/prechat-onboarding-contract.test.ts +34 -8
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +333 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -23
- package/src/__tests__/retry-backoff.test.ts +87 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +13 -18
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +1 -4
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +12 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -57
- 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 -12
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-channel-config.test.ts +9 -14
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +115 -14
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -7
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -17
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -8
- package/src/__tests__/tool-executor.test.ts +12 -20
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- 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__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +150 -0
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +47 -138
- package/src/__tests__/verification-control-plane-policy.test.ts +6 -11
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -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-memory-v2-init.test.ts +8 -30
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +94 -177
- package/src/backup/paths.ts +2 -15
- package/src/backup/restore.ts +107 -231
- package/src/browser-session/events.ts +0 -9
- package/src/bundler/app-bundler.ts +51 -3
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +4 -68
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +31 -141
- package/src/calls/twilio-routes.ts +12 -13
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +8 -42
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +18 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +64 -7
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +304 -76
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +15 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +13 -7
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +320 -53
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +0 -18
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +115 -19
- package/src/cli/program.ts +4 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +67 -10
- 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 +14 -44
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- 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 +12 -4
- package/src/config/env.ts +22 -26
- package/src/config/feature-flag-registry.json +40 -152
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +76 -102
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +8 -4
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -14
- package/src/config/schemas/heartbeat.ts +63 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +11 -7
- package/src/config/schemas/llm.ts +34 -11
- package/src/config/schemas/memory-lifecycle.ts +77 -24
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +57 -4
- package/src/config/schemas/platform.ts +6 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +7 -21
- package/src/config/schemas/skills.ts +5 -11
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -47
- package/src/contacts/contacts-write.ts +1 -132
- package/src/context/window-manager.ts +43 -5
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +46 -51
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +126 -5
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +4 -3
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +74 -7
- package/src/daemon/conversation-agent-loop.ts +309 -64
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +8 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +97 -172
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +144 -29
- package/src/daemon/conversation-tool-setup.ts +18 -87
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +134 -231
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +27 -72
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-app-control-proxy.ts +293 -0
- package/src/daemon/host-bash-proxy.ts +124 -92
- package/src/daemon/host-browser-proxy.ts +111 -88
- package/src/daemon/host-cu-proxy.ts +100 -104
- package/src/daemon/host-file-proxy.ts +136 -91
- 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 +303 -147
- package/src/daemon/lifecycle.ts +164 -132
- package/src/daemon/message-protocol.ts +3 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +18 -8
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +5 -0
- package/src/daemon/message-types/host-cu.ts +3 -0
- package/src/daemon/message-types/host-file.ts +5 -0
- package/src/daemon/message-types/host-transfer.ts +4 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +119 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -5
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +126 -108
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +5 -2
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +21 -9
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
- package/src/heartbeat/heartbeat-run-store.ts +236 -0
- package/src/heartbeat/heartbeat-service.ts +303 -54
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +41 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +33 -95
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +17 -11
- package/src/ipc/cli-client.ts +32 -1
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/manager.ts +0 -5
- 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/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -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/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -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 +32 -7
- package/src/memory/context-search/sources/memory-v2.ts +590 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +30 -5
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +18 -0
- package/src/memory/embedding-backend.ts +12 -42
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -8
- package/src/memory/graph/conversation-graph-memory.ts +35 -36
- package/src/memory/graph/graph-search.ts +8 -0
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/graph/retriever.ts +28 -0
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- 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 +66 -23
- package/src/memory/jobs-worker.ts +114 -79
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -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/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +19 -0
- package/src/memory/migrations/registry.ts +32 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +50 -20
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +40 -0
- package/src/memory/search/semantic.ts +12 -16
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +361 -180
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +424 -33
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/sim.test.ts +166 -6
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +152 -0
- package/src/memory/v2/activation.ts +215 -163
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +17 -17
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +241 -84
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +385 -88
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/qdrant.ts +99 -1
- package/src/memory/v2/sim.ts +126 -16
- package/src/memory/v2/skill-qdrant.ts +12 -3
- package/src/memory/v2/skill-store.ts +71 -8
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +63 -0
- package/src/memory/v2/types.ts +10 -20
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/gmail/types.ts +0 -49
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +123 -52
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +12 -2
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/types.ts +1 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/oauth/connect-orchestrator.ts +4 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +95 -0
- package/src/oauth/manual-token-connection.ts +26 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/index.ts +1 -59
- 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/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +7 -18
- package/src/permissions/gateway-threshold-reader.ts +6 -1
- package/src/permissions/prompter.ts +43 -3
- package/src/permissions/secret-prompter.ts +25 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/system-prompt.ts +37 -88
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +570 -52
- package/src/runtime/assistant-event.ts +2 -6
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -97
- package/src/runtime/auth/route-policy.ts +30 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-approvals.ts +6 -2
- 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-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +16 -402
- package/src/runtime/http-types.ts +5 -5
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- 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-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +296 -80
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- 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-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +421 -0
- package/src/runtime/migrations/migration-transport.ts +49 -16
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +457 -136
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -11
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +251 -74
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +329 -38
- package/src/runtime/migrations/vbundle-streaming-validator.ts +203 -28
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +328 -41
- package/src/runtime/pending-interactions.ts +48 -13
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +49 -168
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +333 -0
- 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/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-interception-types.ts +13 -0
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/btw-routes.ts +14 -37
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +46 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +156 -9
- package/src/runtime/routes/conversation-routes.ts +72 -539
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/document-pdf-renderer.ts +165 -0
- package/src/runtime/routes/documents-routes.ts +83 -18
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +68 -94
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- 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 +37 -6
- package/src/runtime/routes/host-browser-routes.ts +96 -25
- package/src/runtime/routes/host-cu-routes.ts +48 -13
- package/src/runtime/routes/host-file-routes.ts +35 -11
- package/src/runtime/routes/host-transfer-routes.ts +73 -37
- 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 +93 -49
- package/src/runtime/routes/inbound-message-handler.ts +581 -146
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -95
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- 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 +12 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +451 -16
- package/src/runtime/routes/migration-routes.ts +284 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +10 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- 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/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -18
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +63 -38
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-files.ts +2 -8
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/skills/remote-skill-policy.ts +5 -5
- 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/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +8 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +59 -15
- package/src/telemetry/usage-telemetry-reporter.ts +4 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/browser/__tests__/browser-status.test.ts +55 -135
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +145 -70
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +62 -91
- package/src/tools/browser/cdp-client/index.ts +1 -27
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +46 -31
- package/src/tools/host-filesystem/edit.ts +29 -2
- package/src/tools/host-filesystem/read.ts +29 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +35 -4
- package/src/tools/host-filesystem/write.ts +29 -2
- package/src/tools/host-terminal/host-shell.ts +62 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- 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/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/tool-approval-handler.ts +1 -5
- package/src/tools/types.ts +16 -39
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/hatched-date.ts +86 -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 +6 -4
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +54 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -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/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -904
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -296
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -431
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- 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 -754
- 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 -438
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/daemon/message-types/pairing.ts +0 -58
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/outbound-proxy/config.ts +0 -94
- package/src/outbound-proxy/health.ts +0 -62
- package/src/outbound-proxy/types.ts +0 -150
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/capability-tokens.ts +0 -190
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/signals/mcp-reload.ts +0 -18
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
|
@@ -2,18 +2,59 @@
|
|
|
2
2
|
* In-process pub/sub hub for assistant events.
|
|
3
3
|
*
|
|
4
4
|
* Provides subscribe / publish primitives used by the daemon send paths
|
|
5
|
-
* and the SSE route.
|
|
5
|
+
* and the SSE route.
|
|
6
|
+
*
|
|
7
|
+
* Subscribers are typed via a discriminated union:
|
|
8
|
+
* - **ClientEntry** — an SSE-connected client (macos, chrome-extension, …)
|
|
9
|
+
* with identity, capabilities, and timestamps.
|
|
10
|
+
* - **ProcessEntry** — an in-process consumer (future: file-append logger).
|
|
11
|
+
*
|
|
12
|
+
* Client-oriented queries (list, find-by-capability) are methods on the hub.
|
|
6
13
|
*/
|
|
7
14
|
|
|
15
|
+
import type { HostProxyCapability, InterfaceId } from "../channels/types.js";
|
|
16
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Message type → capability inference
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
const HOST_PREFIX_TO_CAPABILITY: Record<string, HostProxyCapability> = {
|
|
23
|
+
host_bash: "host_bash",
|
|
24
|
+
host_file: "host_file",
|
|
25
|
+
host_transfer: "host_file", // transfers piggyback on host_file capability
|
|
26
|
+
host_cu: "host_cu",
|
|
27
|
+
host_browser: "host_browser",
|
|
28
|
+
host_app_control: "host_app_control",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Infer the {@link HostProxyCapability} a message should be targeted at based
|
|
33
|
+
* on its `type` field. Returns `undefined` for message types that are not
|
|
34
|
+
* host-proxy messages (i.e. they should broadcast to all subscribers).
|
|
35
|
+
*/
|
|
36
|
+
export function capabilityForMessageType(
|
|
37
|
+
type: string,
|
|
38
|
+
): HostProxyCapability | undefined {
|
|
39
|
+
const stem = type.replace(/_(request|cancel)$/, "");
|
|
40
|
+
return HOST_PREFIX_TO_CAPABILITY[stem];
|
|
41
|
+
}
|
|
42
|
+
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
43
|
+
import { rewriteCommandPreview } from "../home/rewrite-command-preview.js";
|
|
44
|
+
import { redactSecrets } from "../security/secret-scanner.js";
|
|
45
|
+
import { appendEventToStream } from "../signals/event-stream.js";
|
|
46
|
+
import { summarizeToolInput } from "../tools/tool-input-summary.js";
|
|
47
|
+
import { getLogger } from "../util/logger.js";
|
|
8
48
|
import type { AssistantEvent } from "./assistant-event.js";
|
|
49
|
+
import { buildAssistantEvent } from "./assistant-event.js";
|
|
50
|
+
|
|
51
|
+
const log = getLogger("assistant-event-hub");
|
|
9
52
|
|
|
10
53
|
// ── Types ─────────────────────────────────────────────────────────────────────
|
|
11
54
|
|
|
12
|
-
/**
|
|
55
|
+
/** Filter that determines which events a subscriber receives. */
|
|
13
56
|
export type AssistantEventFilter = {
|
|
14
|
-
/**
|
|
15
|
-
assistantId: string;
|
|
16
|
-
/** When set, further restrict to this conversation. */
|
|
57
|
+
/** When set, restrict delivery to events for this conversation. */
|
|
17
58
|
conversationId?: string;
|
|
18
59
|
};
|
|
19
60
|
|
|
@@ -28,24 +69,58 @@ export interface AssistantEventSubscription {
|
|
|
28
69
|
readonly active: boolean;
|
|
29
70
|
}
|
|
30
71
|
|
|
31
|
-
// ──
|
|
72
|
+
// ── Subscriber entries (discriminated union) ─────────────────────────────────
|
|
32
73
|
|
|
33
|
-
interface
|
|
74
|
+
interface BaseSubscriberEntry {
|
|
34
75
|
filter: AssistantEventFilter;
|
|
35
76
|
callback: AssistantEventCallback;
|
|
36
77
|
active: boolean;
|
|
37
|
-
|
|
38
|
-
|
|
78
|
+
onEvict: () => void;
|
|
79
|
+
connectedAt: Date;
|
|
80
|
+
lastActiveAt: Date;
|
|
39
81
|
}
|
|
40
82
|
|
|
83
|
+
export interface ClientEntry extends BaseSubscriberEntry {
|
|
84
|
+
type: "client";
|
|
85
|
+
clientId: string;
|
|
86
|
+
interfaceId: InterfaceId;
|
|
87
|
+
capabilities: HostProxyCapability[];
|
|
88
|
+
machineName?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface ProcessEntry extends BaseSubscriberEntry {
|
|
92
|
+
type: "process";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type SubscriberEntry = ClientEntry | ProcessEntry;
|
|
96
|
+
|
|
97
|
+
/** Distributive Omit that preserves union discrimination. */
|
|
98
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown
|
|
99
|
+
? Omit<T, K>
|
|
100
|
+
: never;
|
|
101
|
+
|
|
102
|
+
/** Input shape for `subscribe()` — hub fills `active`, `connectedAt`, `lastActiveAt` and defaults `filter`/`onEvict`. */
|
|
103
|
+
export type SubscriberInput = DistributiveOmit<
|
|
104
|
+
SubscriberEntry,
|
|
105
|
+
"active" | "connectedAt" | "lastActiveAt" | "filter" | "onEvict"
|
|
106
|
+
> & {
|
|
107
|
+
filter?: AssistantEventFilter;
|
|
108
|
+
onEvict?: () => void;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// ── Hub ───────────────────────────────────────────────────────────────────────
|
|
112
|
+
|
|
41
113
|
/**
|
|
42
114
|
* Lightweight pub/sub hub for `AssistantEvent` messages.
|
|
43
115
|
*
|
|
44
|
-
* Filtering is applied at subscription level
|
|
45
|
-
* events
|
|
116
|
+
* Filtering is applied at subscription level:
|
|
117
|
+
* - `conversationId`: scoped events match subscribers with same conversationId
|
|
118
|
+
* or no conversationId filter (broadcast to all).
|
|
119
|
+
* - `targetCapability` (on publish): targeted events only reach subscribers
|
|
120
|
+
* whose capabilities include the target. Untargeted events fan out to all.
|
|
46
121
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
122
|
+
* Client connections register as subscribers with metadata and are queryable
|
|
123
|
+
* via `listClients()`, `getMostRecentClientByCapability()`, etc.
|
|
49
124
|
*/
|
|
50
125
|
export class AssistantEventHub {
|
|
51
126
|
private readonly subscribers = new Set<SubscriberEntry>();
|
|
@@ -58,26 +133,48 @@ export class AssistantEventHub {
|
|
|
58
133
|
/**
|
|
59
134
|
* Register a subscriber that will be called for each matching event.
|
|
60
135
|
*
|
|
136
|
+
* **Client deduplication:** When a client subscriber is registered with a
|
|
137
|
+
* `clientId` that already exists, all stale entries for that clientId are
|
|
138
|
+
* disposed first. This prevents subscriber stacking when clients reconnect
|
|
139
|
+
* (e.g. Chrome extension reload, SSE token refresh) before the old
|
|
140
|
+
* connection's abort signal fires.
|
|
141
|
+
*
|
|
61
142
|
* When the subscriber cap (`maxSubscribers`) has been reached, the **oldest**
|
|
62
143
|
* subscriber is evicted to make room: its `onEvict` callback is invoked (so
|
|
63
144
|
* it can close its SSE stream) and its entry is removed from the hub.
|
|
64
|
-
*
|
|
65
|
-
* The only case that throws is when `maxSubscribers` is 0 — there is nothing
|
|
66
|
-
* to evict and no room to add.
|
|
67
|
-
*
|
|
68
|
-
* @param options.onEvict Called if this subscriber is later evicted by a newer one.
|
|
69
|
-
* @returns A subscription handle. Call `dispose()` to unsubscribe.
|
|
70
145
|
*/
|
|
71
|
-
subscribe(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
146
|
+
subscribe(subscriber: SubscriberInput): AssistantEventSubscription {
|
|
147
|
+
// Deduplicate: dispose stale subscribers for the same clientId.
|
|
148
|
+
if (subscriber.type === "client") {
|
|
149
|
+
const stale: SubscriberEntry[] = [];
|
|
150
|
+
for (const existing of this.subscribers) {
|
|
151
|
+
if (
|
|
152
|
+
existing.type === "client" &&
|
|
153
|
+
existing.clientId === subscriber.clientId
|
|
154
|
+
) {
|
|
155
|
+
stale.push(existing);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const entry of stale) {
|
|
159
|
+
entry.active = false;
|
|
160
|
+
this.subscribers.delete(entry);
|
|
161
|
+
try {
|
|
162
|
+
entry.onEvict();
|
|
163
|
+
} catch {
|
|
164
|
+
/* ignore eviction callback errors */
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (stale.length > 0) {
|
|
168
|
+
log.info(
|
|
169
|
+
{ clientId: subscriber.clientId, count: stale.length },
|
|
170
|
+
"disposed stale subscribers for reconnecting client",
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
76
175
|
if (this.subscribers.size >= this.maxSubscribers) {
|
|
77
|
-
// Evict the oldest subscriber (Sets maintain insertion order).
|
|
78
176
|
const [oldest] = this.subscribers;
|
|
79
177
|
if (!oldest) {
|
|
80
|
-
// maxSubscribers is 0 — nothing to evict, nothing to add.
|
|
81
178
|
throw new RangeError(
|
|
82
179
|
`AssistantEventHub: subscriber cap reached (${this.maxSubscribers})`,
|
|
83
180
|
);
|
|
@@ -85,17 +182,35 @@ export class AssistantEventHub {
|
|
|
85
182
|
oldest.active = false;
|
|
86
183
|
this.subscribers.delete(oldest);
|
|
87
184
|
try {
|
|
88
|
-
oldest.onEvict
|
|
185
|
+
oldest.onEvict();
|
|
89
186
|
} catch {
|
|
90
187
|
/* ignore eviction callback errors */
|
|
91
188
|
}
|
|
92
189
|
}
|
|
190
|
+
|
|
191
|
+
const now = new Date();
|
|
93
192
|
const entry: SubscriberEntry = {
|
|
94
|
-
|
|
95
|
-
|
|
193
|
+
...subscriber,
|
|
194
|
+
filter: subscriber.filter ?? {},
|
|
195
|
+
onEvict: subscriber.onEvict ?? (() => {}),
|
|
96
196
|
active: true,
|
|
97
|
-
|
|
98
|
-
|
|
197
|
+
connectedAt: now,
|
|
198
|
+
lastActiveAt: now,
|
|
199
|
+
} as SubscriberEntry;
|
|
200
|
+
|
|
201
|
+
if (entry.type === "client") {
|
|
202
|
+
log.info(
|
|
203
|
+
{
|
|
204
|
+
clientId: entry.clientId,
|
|
205
|
+
interfaceId: entry.interfaceId,
|
|
206
|
+
capabilities: entry.capabilities,
|
|
207
|
+
},
|
|
208
|
+
"subscriber registered (client)",
|
|
209
|
+
);
|
|
210
|
+
} else {
|
|
211
|
+
log.info("subscriber registered (process)");
|
|
212
|
+
}
|
|
213
|
+
|
|
99
214
|
this.subscribers.add(entry);
|
|
100
215
|
|
|
101
216
|
return {
|
|
@@ -103,6 +218,17 @@ export class AssistantEventHub {
|
|
|
103
218
|
if (entry.active) {
|
|
104
219
|
entry.active = false;
|
|
105
220
|
this.subscribers.delete(entry);
|
|
221
|
+
if (entry.type === "client") {
|
|
222
|
+
log.info(
|
|
223
|
+
{
|
|
224
|
+
clientId: entry.clientId,
|
|
225
|
+
interfaceId: entry.interfaceId,
|
|
226
|
+
},
|
|
227
|
+
"subscriber unregistered (client)",
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
log.info("subscriber unregistered (process)");
|
|
231
|
+
}
|
|
106
232
|
}
|
|
107
233
|
},
|
|
108
234
|
get active() {
|
|
@@ -115,32 +241,67 @@ export class AssistantEventHub {
|
|
|
115
241
|
* Publish an event to all matching subscribers.
|
|
116
242
|
*
|
|
117
243
|
* Matching rules:
|
|
118
|
-
* - `
|
|
119
|
-
* -
|
|
244
|
+
* - if `targetClientId` is set, deliver only to the subscriber with that
|
|
245
|
+
* clientId, bypassing the conversation-id filter entirely (the web-origin
|
|
246
|
+
* event's conversationId differs from the macOS client's subscribed
|
|
247
|
+
* conversation).
|
|
248
|
+
* - if `filter.conversationId` is set (and `targetClientId` is not), the
|
|
249
|
+
* `event.conversationId` must equal it
|
|
250
|
+
* - if `targetCapability` is set, only subscribers whose capabilities include
|
|
251
|
+
* it receive the event; untargeted events go to all
|
|
120
252
|
*
|
|
121
253
|
* Fanout is isolated: a throwing or rejecting subscriber does not abort
|
|
122
|
-
* delivery to remaining subscribers.
|
|
123
|
-
* awaited and their errors collected; any errors are re-thrown together
|
|
124
|
-
* as an `AggregateError` after all callbacks have been invoked.
|
|
125
|
-
*
|
|
126
|
-
* Subscribers are snapshotted at the start of each publish call so that
|
|
127
|
-
* callbacks adding new subscriptions do not receive the in-flight event.
|
|
254
|
+
* delivery to remaining subscribers.
|
|
128
255
|
*/
|
|
129
|
-
async publish(
|
|
256
|
+
async publish(
|
|
257
|
+
event: AssistantEvent,
|
|
258
|
+
options?: { targetCapability?: HostProxyCapability; targetClientId?: string },
|
|
259
|
+
): Promise<void> {
|
|
260
|
+
if (event.conversationId) {
|
|
261
|
+
try {
|
|
262
|
+
appendEventToStream(event.conversationId, event);
|
|
263
|
+
} catch {
|
|
264
|
+
// Best-effort; file I/O failures must not block subscriber fanout.
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const targetCapability = options?.targetCapability;
|
|
269
|
+
const targetClientId = options?.targetClientId;
|
|
130
270
|
const snapshot = Array.from(this.subscribers);
|
|
131
271
|
const errors: unknown[] = [];
|
|
132
272
|
|
|
133
273
|
for (const entry of snapshot) {
|
|
134
274
|
if (!entry.active) continue;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
275
|
+
|
|
276
|
+
if (targetClientId != null) {
|
|
277
|
+
// Targeted: bypass conversation filter, deliver only to the named client.
|
|
278
|
+
if (entry.type !== "client" || entry.clientId !== targetClientId)
|
|
279
|
+
continue;
|
|
280
|
+
if (
|
|
281
|
+
targetCapability != null &&
|
|
282
|
+
!entry.capabilities.includes(targetCapability)
|
|
283
|
+
)
|
|
284
|
+
continue;
|
|
285
|
+
} else {
|
|
286
|
+
// Untargeted: existing conversation-scoped + capability logic.
|
|
287
|
+
if (
|
|
288
|
+
event.conversationId != null &&
|
|
289
|
+
entry.filter.conversationId != null &&
|
|
290
|
+
entry.filter.conversationId !== event.conversationId
|
|
291
|
+
)
|
|
292
|
+
continue;
|
|
293
|
+
|
|
294
|
+
// Capability targeting: targeted events only go to subscribers that
|
|
295
|
+
// declare the required capability.
|
|
296
|
+
if (targetCapability != null) {
|
|
297
|
+
if (
|
|
298
|
+
entry.type !== "client" ||
|
|
299
|
+
!entry.capabilities.includes(targetCapability)
|
|
300
|
+
)
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
144
305
|
try {
|
|
145
306
|
await entry.callback(event);
|
|
146
307
|
} catch (err) {
|
|
@@ -156,16 +317,27 @@ export class AssistantEventHub {
|
|
|
156
317
|
}
|
|
157
318
|
}
|
|
158
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Return the active client subscriber with the given clientId, or
|
|
322
|
+
* `undefined` if no such subscriber exists.
|
|
323
|
+
*/
|
|
324
|
+
getClientById(clientId: string): ClientEntry | undefined {
|
|
325
|
+
for (const entry of this.subscribers) {
|
|
326
|
+
if (entry.active && entry.type === "client" && entry.clientId === clientId)
|
|
327
|
+
return entry;
|
|
328
|
+
}
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
|
|
159
332
|
/**
|
|
160
333
|
* Returns true when at least one active subscriber would receive the given
|
|
161
|
-
* event based on the same
|
|
334
|
+
* event based on the same conversation matching rules as publish().
|
|
162
335
|
*/
|
|
163
336
|
hasSubscribersForEvent(
|
|
164
|
-
event: Pick<AssistantEvent, "
|
|
337
|
+
event: Pick<AssistantEvent, "conversationId">,
|
|
165
338
|
): boolean {
|
|
166
339
|
for (const entry of this.subscribers) {
|
|
167
340
|
if (!entry.active) continue;
|
|
168
|
-
if (entry.filter.assistantId !== event.assistantId) continue;
|
|
169
341
|
if (
|
|
170
342
|
event.conversationId != null &&
|
|
171
343
|
entry.filter.conversationId != null &&
|
|
@@ -178,6 +350,132 @@ export class AssistantEventHub {
|
|
|
178
350
|
return false;
|
|
179
351
|
}
|
|
180
352
|
|
|
353
|
+
// ── Client queries ──────────────────────────────────────────────────────────
|
|
354
|
+
|
|
355
|
+
private clientEntries(): ClientEntry[] {
|
|
356
|
+
const clients: ClientEntry[] = [];
|
|
357
|
+
for (const entry of this.subscribers) {
|
|
358
|
+
if (entry.active && entry.type === "client") {
|
|
359
|
+
clients.push(entry);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return clients.sort(
|
|
363
|
+
(a, b) => b.lastActiveAt.getTime() - a.lastActiveAt.getTime(),
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Return all active client subscribers, sorted by `lastActiveAt` descending.
|
|
369
|
+
*/
|
|
370
|
+
listClients(): ClientEntry[] {
|
|
371
|
+
return this.clientEntries();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Return all client subscribers that support the given capability,
|
|
376
|
+
* sorted by `lastActiveAt` descending.
|
|
377
|
+
*/
|
|
378
|
+
listClientsByCapability(capability: HostProxyCapability): ClientEntry[] {
|
|
379
|
+
return this.clientEntries().filter((c) =>
|
|
380
|
+
c.capabilities.includes(capability),
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Return the most recently active client that supports the given
|
|
386
|
+
* capability, or `undefined` if none exists.
|
|
387
|
+
*/
|
|
388
|
+
getMostRecentClientByCapability(
|
|
389
|
+
capability: HostProxyCapability,
|
|
390
|
+
): ClientEntry | undefined {
|
|
391
|
+
return this.listClientsByCapability(capability)[0];
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Return the best client for the given capability using an explicit
|
|
396
|
+
* interface preference order. Among clients that support `capability`,
|
|
397
|
+
* the one whose `interfaceId` appears earliest in `interfacePreference`
|
|
398
|
+
* wins. Within the same interface tier, `lastActiveAt` is the tiebreaker
|
|
399
|
+
* (most recent first). Clients not in the preference list are considered last.
|
|
400
|
+
*
|
|
401
|
+
* Used by {@link HostBrowserProxy} to prefer the Chrome Extension
|
|
402
|
+
* (`chrome-extension`) over the macOS SSE bridge (`macos`) when both are
|
|
403
|
+
* connected, so `chrome.debugger` is used ahead of the localhost:9222 path.
|
|
404
|
+
*/
|
|
405
|
+
getPreferredClientByCapability(
|
|
406
|
+
capability: HostProxyCapability,
|
|
407
|
+
interfacePreference: InterfaceId[],
|
|
408
|
+
): ClientEntry | undefined {
|
|
409
|
+
const clients = this.listClientsByCapability(capability);
|
|
410
|
+
if (clients.length === 0) return undefined;
|
|
411
|
+
// listClientsByCapability returns clients sorted by lastActiveAt desc
|
|
412
|
+
// (most recent first). A stable sort by preference index preserves that
|
|
413
|
+
// ordering within each interface tier.
|
|
414
|
+
return clients.sort((a, b) => {
|
|
415
|
+
const ai = interfacePreference.indexOf(a.interfaceId);
|
|
416
|
+
const bi = interfacePreference.indexOf(b.interfaceId);
|
|
417
|
+
const ea = ai === -1 ? interfacePreference.length : ai;
|
|
418
|
+
const eb = bi === -1 ? interfacePreference.length : bi;
|
|
419
|
+
return ea - eb;
|
|
420
|
+
})[0];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Return all client subscribers with the given interface type,
|
|
425
|
+
* sorted by `lastActiveAt` descending.
|
|
426
|
+
*/
|
|
427
|
+
listClientsByInterface(interfaceId: InterfaceId): ClientEntry[] {
|
|
428
|
+
return this.clientEntries().filter((c) => c.interfaceId === interfaceId);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Touch a client subscriber — update `lastActiveAt`. Used by heartbeat.
|
|
433
|
+
*/
|
|
434
|
+
touchClient(clientId: string): void {
|
|
435
|
+
const now = new Date();
|
|
436
|
+
for (const entry of this.subscribers) {
|
|
437
|
+
if (
|
|
438
|
+
entry.active &&
|
|
439
|
+
entry.type === "client" &&
|
|
440
|
+
entry.clientId === clientId
|
|
441
|
+
) {
|
|
442
|
+
entry.lastActiveAt = now;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Force-disconnect a client by disposing all subscribers for the given
|
|
449
|
+
* `clientId`. Returns the number of disposed entries.
|
|
450
|
+
*
|
|
451
|
+
* Used by `assistant clients disconnect <clientId>` to forcibly remove
|
|
452
|
+
* stale or unwanted client connections.
|
|
453
|
+
*/
|
|
454
|
+
disposeClient(clientId: string): number {
|
|
455
|
+
const targets: SubscriberEntry[] = [];
|
|
456
|
+
for (const entry of this.subscribers) {
|
|
457
|
+
if (entry.type === "client" && entry.clientId === clientId) {
|
|
458
|
+
targets.push(entry);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
for (const entry of targets) {
|
|
462
|
+
entry.active = false;
|
|
463
|
+
this.subscribers.delete(entry);
|
|
464
|
+
try {
|
|
465
|
+
entry.onEvict();
|
|
466
|
+
} catch {
|
|
467
|
+
/* ignore eviction callback errors */
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (targets.length > 0) {
|
|
471
|
+
log.info(
|
|
472
|
+
{ clientId, count: targets.length },
|
|
473
|
+
"force-disposed client subscribers",
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
return targets.length;
|
|
477
|
+
}
|
|
478
|
+
|
|
181
479
|
/** Number of currently active subscribers (useful for tests and caps). */
|
|
182
480
|
subscriberCount(): number {
|
|
183
481
|
return this.subscribers.size;
|
|
@@ -197,3 +495,223 @@ export class AssistantEventHub {
|
|
|
197
495
|
* Import and use this in daemon send paths and the SSE route.
|
|
198
496
|
*/
|
|
199
497
|
export const assistantEventHub = new AssistantEventHub({ maxSubscribers: 100 });
|
|
498
|
+
|
|
499
|
+
// ── Convenience: ServerMessage → AssistantEvent publish ───────────────────────
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Promise chain that serializes publishes so subscribers always observe
|
|
503
|
+
* events in send order.
|
|
504
|
+
*/
|
|
505
|
+
let _hubChain = Promise.resolve();
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Wraps a `ServerMessage` in an `AssistantEvent` envelope and publishes it
|
|
509
|
+
* to the process-level hub.
|
|
510
|
+
*
|
|
511
|
+
* When `conversationId` is omitted, it is auto-extracted from the message
|
|
512
|
+
* payload (if present).
|
|
513
|
+
*
|
|
514
|
+
* Target capability is inferred automatically from the message type — callers
|
|
515
|
+
* never need to specify it. Host-proxy messages (`host_bash_*`,
|
|
516
|
+
* `host_file_*`, `host_transfer_*`, `host_cu_*`, `host_browser_*`) are routed
|
|
517
|
+
* only to subscribers that declare the matching capability; all other messages
|
|
518
|
+
* broadcast to every subscriber.
|
|
519
|
+
*
|
|
520
|
+
* This is the primary entrypoint for emitting events — handlers, routes, and
|
|
521
|
+
* services should call this directly instead of threading a broadcast callback.
|
|
522
|
+
*/
|
|
523
|
+
export function broadcastMessage(
|
|
524
|
+
msg: ServerMessage,
|
|
525
|
+
conversationId?: string,
|
|
526
|
+
options?: { targetClientId?: string },
|
|
527
|
+
): void {
|
|
528
|
+
const resolvedConversationId = conversationId ?? extractConversationId(msg);
|
|
529
|
+
const targetClientId = options?.targetClientId;
|
|
530
|
+
|
|
531
|
+
// Confirmation-request side effects: feed event + canonical guardian request.
|
|
532
|
+
if (msg.type === "confirmation_request" && resolvedConversationId) {
|
|
533
|
+
void emitConfirmationFeedEvent(msg, resolvedConversationId);
|
|
534
|
+
void createCanonicalRequestForConfirmation(msg, resolvedConversationId);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// `conversation_list_invalidated` is a list-level system event — publish
|
|
538
|
+
// it unscoped so every subscriber refreshes its sidebar.
|
|
539
|
+
const scopedConversationId =
|
|
540
|
+
msg.type === "conversation_list_invalidated"
|
|
541
|
+
? undefined
|
|
542
|
+
: resolvedConversationId;
|
|
543
|
+
const event = buildAssistantEvent(msg, scopedConversationId);
|
|
544
|
+
const targetCapability = capabilityForMessageType(msg.type);
|
|
545
|
+
const publishOptions =
|
|
546
|
+
targetCapability != null || targetClientId != null
|
|
547
|
+
? { targetCapability, targetClientId }
|
|
548
|
+
: undefined;
|
|
549
|
+
_hubChain = _hubChain
|
|
550
|
+
.then(() => assistantEventHub.publish(event, publishOptions))
|
|
551
|
+
.then(() => {
|
|
552
|
+
// When a conversation title changes, also broadcast an unscoped
|
|
553
|
+
// `conversation_list_invalidated` so every connected client's sidebar
|
|
554
|
+
// refreshes — not just the client viewing this conversation.
|
|
555
|
+
if (msg.type === "conversation_title_updated") {
|
|
556
|
+
return assistantEventHub
|
|
557
|
+
.publish(
|
|
558
|
+
buildAssistantEvent({
|
|
559
|
+
type: "conversation_list_invalidated",
|
|
560
|
+
reason: "renamed",
|
|
561
|
+
}),
|
|
562
|
+
)
|
|
563
|
+
.catch((err: unknown) => {
|
|
564
|
+
log.warn(
|
|
565
|
+
{ err },
|
|
566
|
+
"Failed to publish conversation_list_invalidated after title update",
|
|
567
|
+
);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
})
|
|
571
|
+
.catch((err: unknown) => {
|
|
572
|
+
log.warn({ err }, "assistant-events hub subscriber threw during publish");
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function extractConversationId(msg: ServerMessage): string | undefined {
|
|
577
|
+
const record = msg as unknown as Record<string, unknown>;
|
|
578
|
+
if ("conversationId" in msg && typeof record.conversationId === "string") {
|
|
579
|
+
return record.conversationId as string;
|
|
580
|
+
}
|
|
581
|
+
return undefined;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// ── Canonical guardian request ────────────────────────────────────────────────
|
|
585
|
+
|
|
586
|
+
function resolveCanonicalRequestSourceType(
|
|
587
|
+
sourceChannel: string,
|
|
588
|
+
): "desktop" | "channel" | "voice" {
|
|
589
|
+
if (sourceChannel === "phone") return "voice";
|
|
590
|
+
if (sourceChannel === "vellum") return "desktop";
|
|
591
|
+
return "channel";
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Lazily load heavy dependencies and create a canonical guardian request +
|
|
596
|
+
* bridge for a confirmation_request message. Called fire-and-forget from
|
|
597
|
+
* broadcastMessage.
|
|
598
|
+
*/
|
|
599
|
+
async function createCanonicalRequestForConfirmation(
|
|
600
|
+
msg: ServerMessage & { type: "confirmation_request" },
|
|
601
|
+
conversationId: string,
|
|
602
|
+
): Promise<void> {
|
|
603
|
+
try {
|
|
604
|
+
const [
|
|
605
|
+
{ findConversation },
|
|
606
|
+
{ createCanonicalGuardianRequest, generateCanonicalRequestCode },
|
|
607
|
+
{ redactSecrets },
|
|
608
|
+
{ summarizeToolInput },
|
|
609
|
+
{ DAEMON_INTERNAL_ASSISTANT_ID },
|
|
610
|
+
{ bridgeConfirmationRequestToGuardian },
|
|
611
|
+
] = await Promise.all([
|
|
612
|
+
import("../daemon/conversation-store.js"),
|
|
613
|
+
import("../memory/canonical-guardian-store.js"),
|
|
614
|
+
import("../security/secret-scanner.js"),
|
|
615
|
+
import("../tools/tool-input-summary.js"),
|
|
616
|
+
import("./assistant-scope.js"),
|
|
617
|
+
import("./confirmation-request-guardian-bridge.js"),
|
|
618
|
+
]);
|
|
619
|
+
|
|
620
|
+
const conversation = findConversation(conversationId);
|
|
621
|
+
const trustContext = conversation?.trustContext;
|
|
622
|
+
const sourceChannel = trustContext?.sourceChannel ?? "vellum";
|
|
623
|
+
const inputRecord = msg.input as Record<string, unknown>;
|
|
624
|
+
const activityRaw =
|
|
625
|
+
(typeof inputRecord.activity === "string"
|
|
626
|
+
? inputRecord.activity
|
|
627
|
+
: undefined) ??
|
|
628
|
+
(typeof inputRecord.reason === "string" ? inputRecord.reason : undefined);
|
|
629
|
+
const canonicalRequest = createCanonicalGuardianRequest({
|
|
630
|
+
id: msg.requestId,
|
|
631
|
+
kind: "tool_approval",
|
|
632
|
+
sourceType: resolveCanonicalRequestSourceType(sourceChannel),
|
|
633
|
+
sourceChannel,
|
|
634
|
+
conversationId,
|
|
635
|
+
requesterExternalUserId: trustContext?.requesterExternalUserId,
|
|
636
|
+
requesterChatId: trustContext?.requesterChatId,
|
|
637
|
+
guardianExternalUserId: trustContext?.guardianExternalUserId,
|
|
638
|
+
guardianPrincipalId: trustContext?.guardianPrincipalId ?? undefined,
|
|
639
|
+
toolName: msg.toolName,
|
|
640
|
+
commandPreview:
|
|
641
|
+
redactSecrets(summarizeToolInput(msg.toolName, inputRecord)) ||
|
|
642
|
+
undefined,
|
|
643
|
+
riskLevel: msg.riskLevel,
|
|
644
|
+
activityText: activityRaw ? redactSecrets(activityRaw) : undefined,
|
|
645
|
+
executionTarget: msg.executionTarget,
|
|
646
|
+
status: "pending",
|
|
647
|
+
requestCode: generateCanonicalRequestCode(),
|
|
648
|
+
expiresAt: Date.now() + 5 * 60 * 1000,
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
if (trustContext && conversation) {
|
|
652
|
+
bridgeConfirmationRequestToGuardian({
|
|
653
|
+
canonicalRequest,
|
|
654
|
+
trustContext,
|
|
655
|
+
conversationId,
|
|
656
|
+
toolName: msg.toolName,
|
|
657
|
+
assistantId: conversation.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
} catch (err) {
|
|
661
|
+
log.debug(
|
|
662
|
+
{ err, conversationId },
|
|
663
|
+
"Failed to create canonical request from broadcast",
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// ── Feed events for confirmation requests ─────────────────────────────────────
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Emit a feed event when a confirmation request (tool approval prompt) is
|
|
672
|
+
* broadcast. Emits immediately with a technical preview, then rewrites
|
|
673
|
+
* into prose in the background and updates the feed item.
|
|
674
|
+
*/
|
|
675
|
+
async function emitConfirmationFeedEvent(
|
|
676
|
+
msg: ServerMessage & { type: "confirmation_request" },
|
|
677
|
+
conversationId: string,
|
|
678
|
+
): Promise<void> {
|
|
679
|
+
try {
|
|
680
|
+
const inputRecord = msg.input as Record<string, unknown>;
|
|
681
|
+
const commandPreview =
|
|
682
|
+
redactSecrets(summarizeToolInput(msg.toolName, inputRecord)) || undefined;
|
|
683
|
+
const technicalTitle = commandPreview
|
|
684
|
+
? `Requesting permission: ${commandPreview}`
|
|
685
|
+
: `Requesting approval to use ${msg.toolName}.`;
|
|
686
|
+
const dedupKey = `tool-approval:${msg.requestId}`;
|
|
687
|
+
|
|
688
|
+
await emitFeedEvent({
|
|
689
|
+
source: "assistant",
|
|
690
|
+
title: technicalTitle,
|
|
691
|
+
summary: technicalTitle,
|
|
692
|
+
dedupKey,
|
|
693
|
+
urgency: msg.riskLevel === "high" ? "high" : "medium",
|
|
694
|
+
conversationId,
|
|
695
|
+
detailPanel: { kind: "toolPermission" },
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
// Background: rewrite into prose and update the feed item.
|
|
699
|
+
if (commandPreview) {
|
|
700
|
+
const prose = await rewriteCommandPreview(msg.toolName, commandPreview);
|
|
701
|
+
if (prose) {
|
|
702
|
+
const proseTitle = `Requesting permission: ${prose}`;
|
|
703
|
+
await emitFeedEvent({
|
|
704
|
+
source: "assistant",
|
|
705
|
+
title: proseTitle,
|
|
706
|
+
summary: proseTitle,
|
|
707
|
+
dedupKey,
|
|
708
|
+
urgency: msg.riskLevel === "high" ? "high" : "medium",
|
|
709
|
+
conversationId,
|
|
710
|
+
detailPanel: { kind: "toolPermission" },
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
} catch (err) {
|
|
715
|
+
log.warn({ err }, "Failed to emit confirmation feed event from broadcast");
|
|
716
|
+
}
|
|
717
|
+
}
|