@vellumai/assistant 0.6.1 → 0.6.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/bun.lock +40 -40
- package/bunfig.toml +3 -0
- package/docker-entrypoint.sh +12 -2
- package/docs/architecture/memory.md +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +184 -69
- package/package.json +41 -41
- package/scripts/generate-openapi.ts +1 -2
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/assistant-event-hub.test.ts +30 -0
- package/src/__tests__/browser-fill-credential.test.ts +229 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/catalog-files.test.ts +862 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/checker.test.ts +104 -170
- package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +125 -48
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/context-overflow-approval.test.ts +21 -6
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +1 -1
- package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
- package/src/__tests__/conversation-directories-parse.test.ts +105 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-queue.test.ts +45 -2
- package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +4 -4
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +2 -2
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/gemini-provider.test.ts +2 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +707 -371
- package/src/__tests__/headless-browser-navigate.test.ts +389 -47
- package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
- package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
- package/src/__tests__/host-bash-proxy.test.ts +150 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
- package/src/__tests__/host-cu-proxy.test.ts +171 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
- package/src/__tests__/inline-command-runner.test.ts +7 -5
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/log-export-workspace.test.ts +190 -0
- package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +61 -2
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +101 -1
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/navigate-settings-tab.test.ts +14 -1
- package/src/__tests__/notification-broadcaster.test.ts +65 -0
- package/src/__tests__/oauth-apps-routes.test.ts +17 -12
- package/src/__tests__/oauth-cli.test.ts +707 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +50 -14
- package/src/__tests__/oauth-store.test.ts +1386 -182
- package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
- package/src/__tests__/onboarding-template-contract.test.ts +74 -55
- package/src/__tests__/openai-provider.test.ts +2 -2
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/pkb-autoinject.test.ts +96 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/require-fresh-approval.test.ts +40 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
- package/src/__tests__/slack-channel-config.test.ts +12 -15
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +72 -1
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/terminal-sandbox.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +11 -5
- package/src/__tests__/test-preload.ts +14 -0
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +62 -0
- package/src/__tests__/trust-store.test.ts +4 -4
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
- package/src/__tests__/workspace-policy.test.ts +2 -7
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/loop.ts +12 -35
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +55 -0
- package/src/cli/__tests__/run-assistant-command.ts +34 -7
- package/src/cli/__tests__/unknown-command.test.ts +33 -0
- package/src/cli/commands/browser-relay.ts +339 -409
- package/src/cli/commands/credentials.ts +3 -3
- package/src/cli/commands/default-action.ts +68 -1
- package/src/cli/commands/email.ts +18 -13
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +16 -2
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/providers.ts +200 -36
- package/src/cli/commands/oauth/shared.ts +5 -5
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +10 -3
- package/src/config/assistant-feature-flags.ts +59 -55
- package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/contacts/SKILL.md +3 -0
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +12 -7
- package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
- package/src/config/bundled-skills/outlook/SKILL.md +7 -0
- package/src/config/bundled-skills/settings/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/env-registry.ts +14 -0
- package/src/config/env.ts +21 -0
- package/src/config/feature-flag-registry.json +46 -7
- package/src/config/loader.ts +56 -1
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +46 -5
- package/src/config/schemas/host-browser.ts +66 -0
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +16 -0
- package/src/config/types.ts +0 -1
- package/src/context/post-turn-tool-result-truncation.ts +176 -0
- package/src/context/window-manager.ts +19 -1
- package/src/credential-execution/approval-bridge.ts +49 -16
- package/src/credential-execution/managed-catalog.ts +3 -7
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +6 -2
- package/src/daemon/context-overflow-approval.ts +5 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
- package/src/daemon/conversation-agent-loop.ts +74 -19
- package/src/daemon/conversation-attachments.ts +40 -1
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +66 -3
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +159 -20
- package/src/daemon/conversation-surfaces.ts +78 -12
- package/src/daemon/conversation-tool-setup.ts +74 -11
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +227 -11
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/conversations.ts +9 -139
- package/src/daemon/handlers/shared.ts +65 -0
- package/src/daemon/handlers/skills.ts +232 -37
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +191 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +86 -12
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/conversations.ts +59 -13
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/messages.ts +5 -6
- package/src/daemon/message-types/notifications.ts +12 -0
- package/src/daemon/message-types/settings.ts +12 -0
- package/src/daemon/message-types/skills.ts +10 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/server.ts +112 -35
- package/src/daemon/tool-side-effects.ts +6 -0
- package/src/daemon/transport-hints.ts +14 -0
- package/src/inbound/platform-callback-registration.ts +18 -17
- package/src/index.ts +1 -1
- package/src/mcp/client.ts +59 -24
- package/src/memory/app-store.ts +31 -1
- package/src/memory/conversation-crud.ts +38 -10
- package/src/memory/conversation-directories.ts +39 -0
- package/src/memory/conversation-group-migration.ts +65 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +12 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +177 -18
- package/src/memory/graph/capability-seed.ts +3 -5
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/retriever.ts +40 -22
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/group-crud.ts +25 -9
- package/src/memory/llm-usage-store.ts +45 -4
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +1 -0
- package/src/memory/schema/oauth.ts +18 -13
- package/src/messaging/provider.ts +1 -1
- package/src/notifications/broadcaster.ts +6 -0
- package/src/notifications/conversation-pairing.ts +12 -4
- package/src/notifications/emit-signal.ts +14 -0
- package/src/notifications/signal.ts +11 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +8 -8
- package/src/oauth/byo-connection.ts +7 -7
- package/src/oauth/connect-orchestrator.ts +23 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +16 -16
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +214 -100
- package/src/oauth/platform-connection.test.ts +5 -5
- package/src/oauth/platform-connection.ts +4 -4
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +127 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +7 -8
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/platform/client.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -21
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -96
- package/src/prompts/templates/SOUL.md +11 -11
- package/src/providers/anthropic/client.ts +1 -0
- package/src/providers/types.ts +1 -1
- package/src/runtime/AGENTS.md +23 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/assistant-event-hub.ts +24 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +6 -7
- package/src/runtime/auth/token-service.ts +8 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/chrome-extension-registry.ts +332 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +425 -70
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
- package/src/runtime/migrations/migration-transport.ts +6 -0
- package/src/runtime/migrations/migration-wizard.ts +22 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
- package/src/runtime/migrations/vbundle-importer.ts +55 -5
- package/src/runtime/pending-interactions.ts +29 -13
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/browser-cdp-routes.ts +229 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
- package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
- package/src/runtime/routes/conversation-management-routes.ts +108 -0
- package/src/runtime/routes/conversation-routes.ts +308 -28
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/group-routes.ts +22 -8
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/host-browser-routes.ts +279 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-routes.ts +259 -16
- package/src/runtime/routes/log-export/AGENTS.md +104 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
- package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
- package/src/runtime/routes/log-export-routes.ts +60 -25
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +87 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +9 -97
- package/src/runtime/routes/skills-routes.ts +52 -2
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/usage-routes.ts +8 -7
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/schedule/scheduler.ts +7 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +42 -25
- package/src/security/secure-keys.ts +118 -25
- package/src/security/token-manager.ts +23 -10
- package/src/skills/catalog-files.ts +492 -0
- package/src/skills/inline-command-runner.ts +12 -14
- package/src/subagent/manager.ts +131 -26
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +645 -340
- package/src/tools/browser/browser-manager.ts +36 -12
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
- package/src/tools/browser/cdp-client/errors.ts +34 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
- package/src/tools/browser/cdp-client/factory.ts +204 -0
- package/src/tools/browser/cdp-client/index.ts +14 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +52 -0
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/permission-checker.ts +77 -100
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -1
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/skills/sandbox-runner.ts +3 -6
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
- package/src/tools/terminal/sandbox.ts +4 -1
- package/src/tools/terminal/shell.ts +24 -21
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/types.ts +2 -3
- package/src/util/platform.ts +14 -19
- package/src/watcher/provider-types.ts +1 -1
- package/src/workspace/migrations/029-seed-pkb.ts +1 -0
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/top-level-renderer.ts +19 -1
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { v4 as uuid } from "uuid";
|
|
2
|
+
|
|
3
|
+
import type { ToolExecutionResult } from "../tools/types.js";
|
|
4
|
+
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
5
|
+
import { getLogger } from "../util/logger.js";
|
|
6
|
+
import type { ServerMessage } from "./message-protocol.js";
|
|
7
|
+
import type { HostBrowserRequest } from "./message-types/host-browser.js";
|
|
8
|
+
|
|
9
|
+
/** Distributive omit that preserves union variant fields. */
|
|
10
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown
|
|
11
|
+
? Omit<T, K>
|
|
12
|
+
: never;
|
|
13
|
+
|
|
14
|
+
/** Clean input type for callers — transport envelope fields are added by the proxy. */
|
|
15
|
+
export type HostBrowserInput = DistributiveOmit<
|
|
16
|
+
HostBrowserRequest,
|
|
17
|
+
"type" | "requestId" | "conversationId"
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
const log = getLogger("host-browser-proxy");
|
|
21
|
+
|
|
22
|
+
interface PendingRequest {
|
|
23
|
+
resolve: (result: ToolExecutionResult) => void;
|
|
24
|
+
reject: (err: Error) => void;
|
|
25
|
+
timer: ReturnType<typeof setTimeout>;
|
|
26
|
+
/** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
|
|
27
|
+
detachAbort: () => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class HostBrowserProxy {
|
|
31
|
+
private pending = new Map<string, PendingRequest>();
|
|
32
|
+
private sendToClient: (msg: ServerMessage) => void;
|
|
33
|
+
private onInternalResolve?: (requestId: string) => void;
|
|
34
|
+
private clientConnected = false;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
sendToClient: (msg: ServerMessage) => void,
|
|
38
|
+
onInternalResolve?: (requestId: string) => void,
|
|
39
|
+
) {
|
|
40
|
+
this.sendToClient = sendToClient;
|
|
41
|
+
this.onInternalResolve = onInternalResolve;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
updateSender(
|
|
45
|
+
sendToClient: (msg: ServerMessage) => void,
|
|
46
|
+
clientConnected: boolean,
|
|
47
|
+
): void {
|
|
48
|
+
this.sendToClient = sendToClient;
|
|
49
|
+
this.clientConnected = clientConnected;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
request(
|
|
53
|
+
input: HostBrowserInput,
|
|
54
|
+
conversationId: string,
|
|
55
|
+
signal?: AbortSignal,
|
|
56
|
+
): Promise<ToolExecutionResult> {
|
|
57
|
+
if (signal?.aborted) {
|
|
58
|
+
return Promise.resolve({ content: "Aborted", isError: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const requestId = uuid();
|
|
62
|
+
|
|
63
|
+
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
64
|
+
// CDP operations should be fast — 30 second default timeout matches host_file.
|
|
65
|
+
const timeoutSec = input.timeout_seconds ?? 30;
|
|
66
|
+
|
|
67
|
+
// Declared up-front so onAbort (defined before detachAbort is assigned)
|
|
68
|
+
// can close over a stable reference once it's wired below.
|
|
69
|
+
let detachAbort: () => void = () => {};
|
|
70
|
+
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
this.pending.delete(requestId);
|
|
73
|
+
detachAbort();
|
|
74
|
+
this.onInternalResolve?.(requestId);
|
|
75
|
+
log.warn(
|
|
76
|
+
{ requestId, cdpMethod: input.cdpMethod },
|
|
77
|
+
"Host browser proxy request timed out",
|
|
78
|
+
);
|
|
79
|
+
resolve({
|
|
80
|
+
content: "Host browser proxy timed out waiting for client response",
|
|
81
|
+
isError: true,
|
|
82
|
+
});
|
|
83
|
+
}, timeoutSec * 1000);
|
|
84
|
+
|
|
85
|
+
if (signal) {
|
|
86
|
+
const onAbort = () => {
|
|
87
|
+
if (this.pending.has(requestId)) {
|
|
88
|
+
clearTimeout(timer);
|
|
89
|
+
this.pending.delete(requestId);
|
|
90
|
+
// Abort fired — nothing to detach, but call the no-op for symmetry
|
|
91
|
+
// so callers can rely on detachAbort being idempotent.
|
|
92
|
+
detachAbort();
|
|
93
|
+
this.onInternalResolve?.(requestId);
|
|
94
|
+
try {
|
|
95
|
+
this.sendToClient({
|
|
96
|
+
type: "host_browser_cancel",
|
|
97
|
+
requestId,
|
|
98
|
+
} as ServerMessage);
|
|
99
|
+
} catch {
|
|
100
|
+
// Best-effort cancel notification — connection may already be closed.
|
|
101
|
+
}
|
|
102
|
+
resolve({ content: "Aborted", isError: true });
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
106
|
+
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.pending.set(requestId, { resolve, reject, timer, detachAbort });
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
this.sendToClient({
|
|
113
|
+
...input,
|
|
114
|
+
type: "host_browser_request",
|
|
115
|
+
requestId,
|
|
116
|
+
conversationId,
|
|
117
|
+
} as ServerMessage);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
// Sender threw synchronously (e.g. client transport error during
|
|
120
|
+
// event emission). Clean up pending state and timer so we don't
|
|
121
|
+
// leak an in-flight entry that nothing will ever resolve.
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
this.pending.delete(requestId);
|
|
124
|
+
detachAbort();
|
|
125
|
+
this.onInternalResolve?.(requestId);
|
|
126
|
+
log.warn(
|
|
127
|
+
{ requestId, cdpMethod: input.cdpMethod, err },
|
|
128
|
+
"Host browser proxy send failed",
|
|
129
|
+
);
|
|
130
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
resolve(
|
|
136
|
+
requestId: string,
|
|
137
|
+
response: { content: string; isError: boolean },
|
|
138
|
+
): void {
|
|
139
|
+
const entry = this.pending.get(requestId);
|
|
140
|
+
if (!entry) {
|
|
141
|
+
// Benign race, not an error. A late result frame with no matching
|
|
142
|
+
// pending entry means one of:
|
|
143
|
+
// - the proxy-side setTimeout has already resolved the caller;
|
|
144
|
+
// - the caller's AbortSignal fired and the entry was torn down;
|
|
145
|
+
// - a duplicate result frame was delivered (e.g. retry after a
|
|
146
|
+
// transient WS drop).
|
|
147
|
+
// Log at debug so operators don't chase false-positive "timeout"
|
|
148
|
+
// alerts on what is actually a cleanly-handled race.
|
|
149
|
+
log.debug(
|
|
150
|
+
{ requestId },
|
|
151
|
+
"Ignoring host_browser_result for unknown or already-resolved request",
|
|
152
|
+
);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
clearTimeout(entry.timer);
|
|
156
|
+
entry.detachAbort();
|
|
157
|
+
this.pending.delete(requestId);
|
|
158
|
+
entry.resolve({ content: response.content, isError: response.isError });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
hasPendingRequest(requestId: string): boolean {
|
|
162
|
+
return this.pending.has(requestId);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
isAvailable(): boolean {
|
|
166
|
+
return this.clientConnected;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
dispose(): void {
|
|
170
|
+
for (const [requestId, entry] of this.pending) {
|
|
171
|
+
clearTimeout(entry.timer);
|
|
172
|
+
entry.detachAbort();
|
|
173
|
+
this.onInternalResolve?.(requestId);
|
|
174
|
+
try {
|
|
175
|
+
this.sendToClient({
|
|
176
|
+
type: "host_browser_cancel",
|
|
177
|
+
requestId,
|
|
178
|
+
} as ServerMessage);
|
|
179
|
+
} catch {
|
|
180
|
+
// Best-effort cancel notification — connection may already be closed.
|
|
181
|
+
}
|
|
182
|
+
entry.reject(
|
|
183
|
+
new AssistantError(
|
|
184
|
+
"Host browser proxy disposed",
|
|
185
|
+
ErrorCode.INTERNAL_ERROR,
|
|
186
|
+
),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
this.pending.clear();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -57,6 +57,8 @@ interface PendingRequest {
|
|
|
57
57
|
resolve: (result: ToolExecutionResult) => void;
|
|
58
58
|
reject: (err: Error) => void;
|
|
59
59
|
timer: ReturnType<typeof setTimeout>;
|
|
60
|
+
/** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
|
|
61
|
+
detachAbort: () => void;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
// ---------------------------------------------------------------------------
|
|
@@ -152,8 +154,13 @@ export class HostCuProxy {
|
|
|
152
154
|
const requestId = uuid();
|
|
153
155
|
|
|
154
156
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
157
|
+
// Declared up-front so onAbort (defined before detachAbort is assigned)
|
|
158
|
+
// can close over a stable reference once it's wired below.
|
|
159
|
+
let detachAbort: () => void = () => {};
|
|
160
|
+
|
|
155
161
|
const timer = setTimeout(() => {
|
|
156
162
|
this.pending.delete(requestId);
|
|
163
|
+
detachAbort();
|
|
157
164
|
this.onInternalResolve?.(requestId);
|
|
158
165
|
log.warn({ requestId, toolName }, "Host CU proxy request timed out");
|
|
159
166
|
resolve({
|
|
@@ -162,13 +169,14 @@ export class HostCuProxy {
|
|
|
162
169
|
});
|
|
163
170
|
}, REQUEST_TIMEOUT_SEC * 1000);
|
|
164
171
|
|
|
165
|
-
this.pending.set(requestId, { resolve, reject, timer });
|
|
166
|
-
|
|
167
172
|
if (signal) {
|
|
168
173
|
const onAbort = () => {
|
|
169
174
|
if (this.pending.has(requestId)) {
|
|
170
175
|
clearTimeout(timer);
|
|
171
176
|
this.pending.delete(requestId);
|
|
177
|
+
// Abort fired — nothing to detach, but call the no-op for symmetry
|
|
178
|
+
// so callers can rely on detachAbort being idempotent.
|
|
179
|
+
detachAbort();
|
|
172
180
|
this.onInternalResolve?.(requestId);
|
|
173
181
|
try {
|
|
174
182
|
this.sendToClient({
|
|
@@ -182,17 +190,32 @@ export class HostCuProxy {
|
|
|
182
190
|
}
|
|
183
191
|
};
|
|
184
192
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
193
|
+
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
185
194
|
}
|
|
186
195
|
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
+
this.pending.set(requestId, { resolve, reject, timer, detachAbort });
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
this.sendToClient({
|
|
200
|
+
type: "host_cu_request",
|
|
201
|
+
requestId,
|
|
202
|
+
conversationId,
|
|
203
|
+
toolName,
|
|
204
|
+
input,
|
|
205
|
+
stepNumber,
|
|
206
|
+
reasoning,
|
|
207
|
+
} as ServerMessage);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
// Sender threw synchronously (e.g. client transport error during
|
|
210
|
+
// event emission). Clean up pending state and timer so we don't
|
|
211
|
+
// leak an in-flight entry that nothing will ever resolve.
|
|
212
|
+
clearTimeout(timer);
|
|
213
|
+
this.pending.delete(requestId);
|
|
214
|
+
detachAbort();
|
|
215
|
+
this.onInternalResolve?.(requestId);
|
|
216
|
+
log.warn({ requestId, toolName, err }, "Host CU proxy send failed");
|
|
217
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
218
|
+
}
|
|
196
219
|
});
|
|
197
220
|
}
|
|
198
221
|
|
|
@@ -203,6 +226,7 @@ export class HostCuProxy {
|
|
|
203
226
|
return;
|
|
204
227
|
}
|
|
205
228
|
clearTimeout(entry.timer);
|
|
229
|
+
entry.detachAbort();
|
|
206
230
|
this.pending.delete(requestId);
|
|
207
231
|
|
|
208
232
|
// Capture pre-update state so formatObservation sees the correct previous AX tree
|
|
@@ -388,6 +412,7 @@ export class HostCuProxy {
|
|
|
388
412
|
dispose(): void {
|
|
389
413
|
for (const [requestId, entry] of this.pending) {
|
|
390
414
|
clearTimeout(entry.timer);
|
|
415
|
+
entry.detachAbort();
|
|
391
416
|
this.onInternalResolve?.(requestId);
|
|
392
417
|
try {
|
|
393
418
|
this.sendToClient({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
|
+
import { readImageBase64 } from "../tools/shared/filesystem/image-read.js";
|
|
3
4
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
4
5
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
5
6
|
import { getLogger } from "../util/logger.js";
|
|
@@ -23,6 +24,10 @@ interface PendingRequest {
|
|
|
23
24
|
resolve: (result: ToolExecutionResult) => void;
|
|
24
25
|
reject: (err: Error) => void;
|
|
25
26
|
timer: ReturnType<typeof setTimeout>;
|
|
27
|
+
operation: HostFileInput["operation"];
|
|
28
|
+
path: string;
|
|
29
|
+
/** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
|
|
30
|
+
detachAbort: () => void;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
export class HostFileProxy {
|
|
@@ -61,8 +66,14 @@ export class HostFileProxy {
|
|
|
61
66
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
62
67
|
// File operations should be fast — 30 second timeout.
|
|
63
68
|
const timeoutSec = 30;
|
|
69
|
+
|
|
70
|
+
// Declared up-front so onAbort (defined before detachAbort is assigned)
|
|
71
|
+
// can close over a stable reference once it's wired below.
|
|
72
|
+
let detachAbort: () => void = () => {};
|
|
73
|
+
|
|
64
74
|
const timer = setTimeout(() => {
|
|
65
75
|
this.pending.delete(requestId);
|
|
76
|
+
detachAbort();
|
|
66
77
|
this.onInternalResolve?.(requestId);
|
|
67
78
|
log.warn(
|
|
68
79
|
{ requestId, operation: input.operation },
|
|
@@ -74,13 +85,14 @@ export class HostFileProxy {
|
|
|
74
85
|
});
|
|
75
86
|
}, timeoutSec * 1000);
|
|
76
87
|
|
|
77
|
-
this.pending.set(requestId, { resolve, reject, timer });
|
|
78
|
-
|
|
79
88
|
if (signal) {
|
|
80
89
|
const onAbort = () => {
|
|
81
90
|
if (this.pending.has(requestId)) {
|
|
82
91
|
clearTimeout(timer);
|
|
83
92
|
this.pending.delete(requestId);
|
|
93
|
+
// Abort fired — nothing to detach, but call the no-op for symmetry
|
|
94
|
+
// so callers can rely on detachAbort being idempotent.
|
|
95
|
+
detachAbort();
|
|
84
96
|
this.onInternalResolve?.(requestId);
|
|
85
97
|
try {
|
|
86
98
|
this.sendToClient({
|
|
@@ -94,20 +106,45 @@ export class HostFileProxy {
|
|
|
94
106
|
}
|
|
95
107
|
};
|
|
96
108
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
109
|
+
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
97
110
|
}
|
|
98
111
|
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
this.pending.set(requestId, {
|
|
113
|
+
resolve,
|
|
114
|
+
reject,
|
|
115
|
+
timer,
|
|
116
|
+
operation: input.operation,
|
|
117
|
+
path: input.path,
|
|
118
|
+
detachAbort,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
this.sendToClient({
|
|
123
|
+
...input,
|
|
124
|
+
type: "host_file_request",
|
|
125
|
+
requestId,
|
|
126
|
+
conversationId,
|
|
127
|
+
} as ServerMessage);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
// Sender threw synchronously (e.g. client transport error during
|
|
130
|
+
// event emission). Clean up pending state and timer so we don't
|
|
131
|
+
// leak an in-flight entry that nothing will ever resolve.
|
|
132
|
+
clearTimeout(timer);
|
|
133
|
+
this.pending.delete(requestId);
|
|
134
|
+
detachAbort();
|
|
135
|
+
this.onInternalResolve?.(requestId);
|
|
136
|
+
log.warn(
|
|
137
|
+
{ requestId, operation: input.operation, err },
|
|
138
|
+
"Host file proxy send failed",
|
|
139
|
+
);
|
|
140
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
141
|
+
}
|
|
105
142
|
});
|
|
106
143
|
}
|
|
107
144
|
|
|
108
145
|
resolve(
|
|
109
146
|
requestId: string,
|
|
110
|
-
response: { content: string; isError: boolean },
|
|
147
|
+
response: { content: string; isError: boolean; imageData?: string },
|
|
111
148
|
): void {
|
|
112
149
|
const entry = this.pending.get(requestId);
|
|
113
150
|
if (!entry) {
|
|
@@ -115,7 +152,17 @@ export class HostFileProxy {
|
|
|
115
152
|
return;
|
|
116
153
|
}
|
|
117
154
|
clearTimeout(entry.timer);
|
|
155
|
+
entry.detachAbort();
|
|
118
156
|
this.pending.delete(requestId);
|
|
157
|
+
if (
|
|
158
|
+
entry.operation === "read" &&
|
|
159
|
+
!response.isError &&
|
|
160
|
+
typeof response.imageData === "string" &&
|
|
161
|
+
response.imageData.length > 0
|
|
162
|
+
) {
|
|
163
|
+
entry.resolve(readImageBase64(response.imageData, entry.path));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
119
166
|
entry.resolve({ content: response.content, isError: response.isError });
|
|
120
167
|
}
|
|
121
168
|
|
|
@@ -130,6 +177,7 @@ export class HostFileProxy {
|
|
|
130
177
|
dispose(): void {
|
|
131
178
|
for (const [requestId, entry] of this.pending) {
|
|
132
179
|
clearTimeout(entry.timer);
|
|
180
|
+
entry.detachAbort();
|
|
133
181
|
this.onInternalResolve?.(requestId);
|
|
134
182
|
try {
|
|
135
183
|
this.sendToClient({
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { reconcileCallsOnStartup } from "../calls/call-recovery.js";
|
|
|
5
5
|
import { setRelayBroadcast } from "../calls/relay-server.js";
|
|
6
6
|
import { TwilioConversationRelayProvider } from "../calls/twilio-provider.js";
|
|
7
7
|
import { setVoiceBridgeDeps } from "../calls/voice-session-bridge.js";
|
|
8
|
+
import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
|
|
8
9
|
import {
|
|
9
10
|
getPlatformAssistantId,
|
|
10
11
|
getQdrantHttpPortEnv,
|
|
@@ -74,6 +75,11 @@ import {
|
|
|
74
75
|
mintPairingBearerToken,
|
|
75
76
|
resolveSigningKey,
|
|
76
77
|
} from "../runtime/auth/token-service.js";
|
|
78
|
+
import {
|
|
79
|
+
initCapabilityTokenSecret,
|
|
80
|
+
loadOrCreateCapabilityTokenSecret,
|
|
81
|
+
writeDaemonTokenFallback,
|
|
82
|
+
} from "../runtime/capability-tokens.js";
|
|
77
83
|
import { ensureVellumGuardianBinding } from "../runtime/guardian-vellum-migration.js";
|
|
78
84
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
79
85
|
import { startScheduler } from "../schedule/scheduler.js";
|
|
@@ -269,6 +275,29 @@ export async function runDaemon(): Promise<void> {
|
|
|
269
275
|
const signingKey = resolveSigningKey();
|
|
270
276
|
initAuthSigningKey(signingKey);
|
|
271
277
|
|
|
278
|
+
// Load (or generate + persist) the capability-token HMAC secret used
|
|
279
|
+
// to mint scoped tokens for the chrome extension pair endpoint.
|
|
280
|
+
// Wrapped in try/catch so a disk failure here never blocks startup —
|
|
281
|
+
// tokens can still be minted using a lazy on-demand load inside the
|
|
282
|
+
// capability-tokens module.
|
|
283
|
+
try {
|
|
284
|
+
initCapabilityTokenSecret(loadOrCreateCapabilityTokenSecret());
|
|
285
|
+
} catch (err) {
|
|
286
|
+
log.warn(
|
|
287
|
+
{ err },
|
|
288
|
+
"Failed to pre-load capability token secret — continuing startup (lazy load will handle subsequent calls)",
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Pre-populate the feature flag cache from the gateway so all
|
|
293
|
+
// subsequent sync isAssistantFeatureFlagEnabled() calls have data.
|
|
294
|
+
// Fired non-blocking so a slow or unreachable gateway doesn't delay
|
|
295
|
+
// daemon startup (the fetch has a 10s timeout that would otherwise
|
|
296
|
+
// stall the critical path).
|
|
297
|
+
void initFeatureFlagOverrides().catch((err) =>
|
|
298
|
+
log.warn({ err }, "Background feature flag init failed"),
|
|
299
|
+
);
|
|
300
|
+
|
|
272
301
|
seedInterfaceFiles();
|
|
273
302
|
|
|
274
303
|
log.info("Daemon startup: installing templates and initializing DB");
|
|
@@ -422,8 +451,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
422
451
|
|
|
423
452
|
// Ensure a vellum guardian binding exists so the identity system works
|
|
424
453
|
// without requiring a manual bootstrap step.
|
|
454
|
+
let localGuardianPrincipalId = "local";
|
|
425
455
|
try {
|
|
426
|
-
ensureVellumGuardianBinding(
|
|
456
|
+
localGuardianPrincipalId = ensureVellumGuardianBinding(
|
|
457
|
+
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
458
|
+
);
|
|
427
459
|
} catch (err) {
|
|
428
460
|
log.warn(
|
|
429
461
|
{ err },
|
|
@@ -431,6 +463,19 @@ export async function runDaemon(): Promise<void> {
|
|
|
431
463
|
);
|
|
432
464
|
}
|
|
433
465
|
|
|
466
|
+
// Write a dev-only fallback capability token to `~/.vellum/daemon-token`
|
|
467
|
+
// so developers can manually pair the chrome extension without the
|
|
468
|
+
// native messaging helper. Production pairing goes through
|
|
469
|
+
// `POST /v1/browser-extension-pair` via the native helper.
|
|
470
|
+
try {
|
|
471
|
+
writeDaemonTokenFallback(localGuardianPrincipalId);
|
|
472
|
+
} catch (err) {
|
|
473
|
+
log.warn(
|
|
474
|
+
{ err },
|
|
475
|
+
"Failed to write dev daemon-token fallback — continuing startup",
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
434
479
|
try {
|
|
435
480
|
syncUpdateBulletinOnStartup();
|
|
436
481
|
} catch (err) {
|
|
@@ -579,8 +624,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
579
624
|
}
|
|
580
625
|
}
|
|
581
626
|
|
|
582
|
-
await initializeProvidersAndTools(config);
|
|
583
|
-
|
|
584
627
|
// Start the DaemonServer (conversation manager) before Qdrant so HTTP
|
|
585
628
|
// routes can begin accepting requests while Qdrant initializes.
|
|
586
629
|
log.info("Daemon startup: starting DaemonServer");
|
|
@@ -690,7 +733,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
690
733
|
seedUninstalledCatalogSkillMemories,
|
|
691
734
|
} = await import("../memory/graph/capability-seed.js");
|
|
692
735
|
seedSkillGraphNodes();
|
|
693
|
-
seedCliGraphNodes();
|
|
736
|
+
await seedCliGraphNodes();
|
|
694
737
|
void seedUninstalledCatalogSkillMemories().catch((err) =>
|
|
695
738
|
log.warn(
|
|
696
739
|
{ err },
|
|
@@ -735,12 +778,17 @@ export async function runDaemon(): Promise<void> {
|
|
|
735
778
|
conversationId,
|
|
736
779
|
message,
|
|
737
780
|
undefined,
|
|
738
|
-
options
|
|
781
|
+
options
|
|
739
782
|
? {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
783
|
+
...(options.trustClass
|
|
784
|
+
? {
|
|
785
|
+
trustContext: {
|
|
786
|
+
sourceChannel: "vellum",
|
|
787
|
+
trustClass: options.trustClass,
|
|
788
|
+
},
|
|
789
|
+
}
|
|
790
|
+
: {}),
|
|
791
|
+
...(options.taskRunId ? { taskRunId: options.taskRunId } : {}),
|
|
744
792
|
}
|
|
745
793
|
: undefined,
|
|
746
794
|
);
|
|
@@ -763,6 +811,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
763
811
|
},
|
|
764
812
|
routingIntent: schedule.routingIntent,
|
|
765
813
|
routingHints: schedule.routingHints,
|
|
814
|
+
conversationMetadata: {
|
|
815
|
+
groupId: "system:scheduled",
|
|
816
|
+
scheduleJobId: schedule.id,
|
|
817
|
+
source: "schedule",
|
|
818
|
+
},
|
|
766
819
|
dedupeKey: `schedule:notify:${schedule.id}:${Date.now()}`,
|
|
767
820
|
throwOnError: true,
|
|
768
821
|
});
|
|
@@ -782,6 +835,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
782
835
|
scheduleId: schedule.id,
|
|
783
836
|
name: schedule.name,
|
|
784
837
|
},
|
|
838
|
+
conversationMetadata: {
|
|
839
|
+
groupId: "system:scheduled",
|
|
840
|
+
scheduleJobId: schedule.id,
|
|
841
|
+
source: "schedule",
|
|
842
|
+
},
|
|
785
843
|
dedupeKey: `schedule:complete:${schedule.id}:${Date.now()}`,
|
|
786
844
|
});
|
|
787
845
|
},
|
|
@@ -1150,6 +1208,21 @@ export async function runDaemon(): Promise<void> {
|
|
|
1150
1208
|
runtimeHttp = null;
|
|
1151
1209
|
}
|
|
1152
1210
|
|
|
1211
|
+
// Initialize providers and tools after the HTTP server is listening so
|
|
1212
|
+
// health-check and pairing requests can be served immediately. Wrapped in
|
|
1213
|
+
// its own try/catch so a failure here doesn't tear down the running HTTP
|
|
1214
|
+
// server (DaemonServer.start() already calls initializeProviders internally
|
|
1215
|
+
// and tools are resolved lazily at conversation creation time).
|
|
1216
|
+
try {
|
|
1217
|
+
log.info("Daemon startup: initializing providers and tools");
|
|
1218
|
+
await initializeProvidersAndTools(config);
|
|
1219
|
+
} catch (err) {
|
|
1220
|
+
log.warn(
|
|
1221
|
+
{ err },
|
|
1222
|
+
"Provider/tool initialization failed — continuing with degraded functionality",
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1153
1226
|
writePid(process.pid);
|
|
1154
1227
|
log.info({ pid: process.pid }, "Daemon started");
|
|
1155
1228
|
|
|
@@ -1178,10 +1251,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
1178
1251
|
if (!runtimeManager.isReady()) {
|
|
1179
1252
|
log.info("Downloading embedding runtime in background...");
|
|
1180
1253
|
await runtimeManager.ensureInstalled();
|
|
1181
|
-
// Reset the
|
|
1182
|
-
|
|
1254
|
+
// Reset the sticky local-backend failure flag so auto mode retries
|
|
1255
|
+
// local embeddings without evicting a worker that may already be live.
|
|
1256
|
+
const { resetLocalEmbeddingFailureState } =
|
|
1183
1257
|
await import("../memory/embedding-backend.js");
|
|
1184
|
-
|
|
1258
|
+
resetLocalEmbeddingFailureState();
|
|
1185
1259
|
log.info("Embedding runtime download complete");
|
|
1186
1260
|
}
|
|
1187
1261
|
} catch (err) {
|
|
@@ -23,6 +23,7 @@ export * from "./message-types/diagnostics.js";
|
|
|
23
23
|
export * from "./message-types/documents.js";
|
|
24
24
|
export * from "./message-types/guardian-actions.js";
|
|
25
25
|
export * from "./message-types/host-bash.js";
|
|
26
|
+
export * from "./message-types/host-browser.js";
|
|
26
27
|
export * from "./message-types/host-cu.js";
|
|
27
28
|
export * from "./message-types/host-file.js";
|
|
28
29
|
export * from "./message-types/inbox.js";
|
|
@@ -77,6 +78,10 @@ import type {
|
|
|
77
78
|
_GuardianActionsServerMessages,
|
|
78
79
|
} from "./message-types/guardian-actions.js";
|
|
79
80
|
import type { _HostBashServerMessages } from "./message-types/host-bash.js";
|
|
81
|
+
import type {
|
|
82
|
+
_HostBrowserClientMessages,
|
|
83
|
+
_HostBrowserServerMessages,
|
|
84
|
+
} from "./message-types/host-browser.js";
|
|
80
85
|
import type { _HostCuServerMessages } from "./message-types/host-cu.js";
|
|
81
86
|
import type { _HostFileServerMessages } from "./message-types/host-file.js";
|
|
82
87
|
import type {
|
|
@@ -157,6 +162,7 @@ export type ClientMessage =
|
|
|
157
162
|
| _ContactsClientMessages
|
|
158
163
|
| _WorkItemsClientMessages
|
|
159
164
|
| _BrowserClientMessages
|
|
165
|
+
| _HostBrowserClientMessages
|
|
160
166
|
| _SubagentsClientMessages
|
|
161
167
|
| _DocumentsClientMessages
|
|
162
168
|
| _GuardianActionsClientMessages
|
|
@@ -186,6 +192,7 @@ export type ServerMessage =
|
|
|
186
192
|
| _DocumentsServerMessages
|
|
187
193
|
| _GuardianActionsServerMessages
|
|
188
194
|
| _HostBashServerMessages
|
|
195
|
+
| _HostBrowserServerMessages
|
|
189
196
|
| _HostCuServerMessages
|
|
190
197
|
| _HostFileServerMessages
|
|
191
198
|
| _MemoryServerMessages
|