@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
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
|
|
22
22
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
23
23
|
import type { UserDecision } from "../permissions/types.js";
|
|
24
|
+
import { isPermissionControlsV2Enabled } from "../permissions/v2-consent-policy.js";
|
|
24
25
|
import { getLogger } from "../util/logger.js";
|
|
25
26
|
import type { CesClient } from "./client.js";
|
|
26
27
|
|
|
@@ -173,13 +174,7 @@ export async function bridgeCesApproval(
|
|
|
173
174
|
signal?: AbortSignal;
|
|
174
175
|
},
|
|
175
176
|
): Promise<CesApprovalBridgeResult> {
|
|
176
|
-
const {
|
|
177
|
-
proposal,
|
|
178
|
-
renderedProposal,
|
|
179
|
-
proposalHash,
|
|
180
|
-
sessionId,
|
|
181
|
-
conversationId,
|
|
182
|
-
} = approval;
|
|
177
|
+
const { proposal, renderedProposal, proposalHash, sessionId } = approval;
|
|
183
178
|
|
|
184
179
|
// Non-interactive sessions have no client to respond — fail closed.
|
|
185
180
|
if (options?.isInteractive === false) {
|
|
@@ -194,6 +189,24 @@ export async function bridgeCesApproval(
|
|
|
194
189
|
return { outcome: "denied", userDecision: "deny" };
|
|
195
190
|
}
|
|
196
191
|
|
|
192
|
+
if (isPermissionControlsV2Enabled()) {
|
|
193
|
+
log.info(
|
|
194
|
+
{
|
|
195
|
+
event: "ces_approval_bridge_v2_suppressed",
|
|
196
|
+
proposalHash,
|
|
197
|
+
sessionId,
|
|
198
|
+
},
|
|
199
|
+
"CES approval request auto-approved without deterministic prompt under v2",
|
|
200
|
+
);
|
|
201
|
+
const v2Decision = mapUserDecisionToCesDecision("allow");
|
|
202
|
+
return recordCesGrant({
|
|
203
|
+
approval,
|
|
204
|
+
cesClient,
|
|
205
|
+
decision: v2Decision,
|
|
206
|
+
reason: "permission_controls_v2_auto_allow",
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
197
210
|
// Build the tool name and input for the confirmation prompt. The tool
|
|
198
211
|
// name uses a `ces:` prefix so the client can distinguish CES approval
|
|
199
212
|
// requests from regular tool confirmation prompts.
|
|
@@ -220,7 +233,6 @@ export async function bridgeCesApproval(
|
|
|
220
233
|
[], // No allowlist options — CES manages its own grant patterns
|
|
221
234
|
[], // No scope options — CES manages scope internally
|
|
222
235
|
undefined, // No file diff
|
|
223
|
-
undefined, // Not sandboxed
|
|
224
236
|
options?.conversationId,
|
|
225
237
|
"host", // CES operations target the host
|
|
226
238
|
false, // Persistent decisions are managed by CES, not trust.json
|
|
@@ -263,8 +275,29 @@ export async function bridgeCesApproval(
|
|
|
263
275
|
`CES approval bridge: guardian decision is "${cesDecision.grantDecision}"`,
|
|
264
276
|
);
|
|
265
277
|
|
|
266
|
-
|
|
267
|
-
|
|
278
|
+
return recordCesGrant({
|
|
279
|
+
approval,
|
|
280
|
+
cesClient,
|
|
281
|
+
decision: cesDecision,
|
|
282
|
+
reason: response.decisionContext,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function recordCesGrant({
|
|
287
|
+
approval,
|
|
288
|
+
cesClient,
|
|
289
|
+
decision,
|
|
290
|
+
reason,
|
|
291
|
+
}: {
|
|
292
|
+
approval: ApprovalRequired;
|
|
293
|
+
cesClient: CesClient;
|
|
294
|
+
decision: CesApprovalDecision;
|
|
295
|
+
reason?: string;
|
|
296
|
+
}): Promise<CesApprovalBridgeResult> {
|
|
297
|
+
const { proposal, proposalHash, sessionId, conversationId } = approval;
|
|
298
|
+
|
|
299
|
+
if (decision.grantDecision === "denied") {
|
|
300
|
+
return { outcome: "denied", userDecision: decision.userDecision };
|
|
268
301
|
}
|
|
269
302
|
|
|
270
303
|
// Commit the approved grant to CES via record_grant RPC.
|
|
@@ -275,12 +308,12 @@ export async function bridgeCesApproval(
|
|
|
275
308
|
decision: {
|
|
276
309
|
proposal,
|
|
277
310
|
proposalHash,
|
|
278
|
-
decision:
|
|
311
|
+
decision: decision.grantDecision,
|
|
279
312
|
decidedBy: "guardian",
|
|
280
313
|
decidedAt: new Date().toISOString(),
|
|
281
|
-
reason
|
|
282
|
-
ttl:
|
|
283
|
-
grantType:
|
|
314
|
+
reason,
|
|
315
|
+
ttl: decision.ttl,
|
|
316
|
+
grantType: decision.grantType,
|
|
284
317
|
},
|
|
285
318
|
sessionId,
|
|
286
319
|
conversationId,
|
|
@@ -324,7 +357,7 @@ export async function bridgeCesApproval(
|
|
|
324
357
|
proposalHash,
|
|
325
358
|
sessionId,
|
|
326
359
|
grantId,
|
|
327
|
-
userDecision:
|
|
360
|
+
userDecision: decision.userDecision,
|
|
328
361
|
},
|
|
329
362
|
"CES approval bridge: grant recorded successfully",
|
|
330
363
|
);
|
|
@@ -332,7 +365,7 @@ export async function bridgeCesApproval(
|
|
|
332
365
|
return {
|
|
333
366
|
outcome: "approved",
|
|
334
367
|
grantId,
|
|
335
|
-
userDecision:
|
|
368
|
+
userDecision: decision.userDecision,
|
|
336
369
|
};
|
|
337
370
|
} catch (err) {
|
|
338
371
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -130,16 +130,12 @@ export async function fetchManagedCatalog(): Promise<FetchManagedCatalogResult>
|
|
|
130
130
|
|
|
131
131
|
return { ok: true, descriptors };
|
|
132
132
|
} catch (err) {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
/Api-Key\s+\S+/gi,
|
|
136
|
-
"Api-Key [REDACTED]",
|
|
137
|
-
);
|
|
138
|
-
log.warn(`Failed to fetch managed CES catalog: ${safeMessage}`);
|
|
133
|
+
const errorName = err instanceof Error ? err.constructor.name : "Unknown";
|
|
134
|
+
log.warn(`Failed to fetch managed CES catalog (${errorName})`);
|
|
139
135
|
return {
|
|
140
136
|
ok: false,
|
|
141
137
|
descriptors: [],
|
|
142
|
-
error: `Failed to fetch managed CES catalog
|
|
138
|
+
error: `Failed to fetch managed CES catalog (${errorName})`,
|
|
143
139
|
};
|
|
144
140
|
}
|
|
145
141
|
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `isToolActiveForContext` host-tool capability gating.
|
|
3
|
+
*
|
|
4
|
+
* Two scenarios are verified:
|
|
5
|
+
* - chrome-extension is its own executor and is exempt from the hasNoClient
|
|
6
|
+
* gate (the extension's own popup UI gates commands; there is no SSE
|
|
7
|
+
* interactive approval channel, and chrome-extension turns intentionally
|
|
8
|
+
* run with `hasNoClient: true` because chrome-extension is not in
|
|
9
|
+
* `INTERACTIVE_INTERFACES`).
|
|
10
|
+
* - macos still requires a connected SSE client for interactive approval, so
|
|
11
|
+
* `hasNoClient: true` continues to deny all host tools on macos.
|
|
12
|
+
*
|
|
13
|
+
* The per-capability check (`supportsHostProxy(transport, capability)`) runs
|
|
14
|
+
* first and is authoritative for structural support, so host_bash and
|
|
15
|
+
* host_file_* are filtered out for chrome-extension regardless of the
|
|
16
|
+
* hasNoClient flag.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { describe, expect, test } from "bun:test";
|
|
20
|
+
|
|
21
|
+
import type { SkillProjectionCache } from "../conversation-skill-tools.js";
|
|
22
|
+
import {
|
|
23
|
+
HOST_TOOL_NAMES,
|
|
24
|
+
HOST_TOOL_TO_CAPABILITY,
|
|
25
|
+
isToolActiveForContext,
|
|
26
|
+
type SkillProjectionContext,
|
|
27
|
+
} from "../conversation-tool-setup.js";
|
|
28
|
+
|
|
29
|
+
function makeCtx(
|
|
30
|
+
overrides: Partial<SkillProjectionContext> = {},
|
|
31
|
+
): SkillProjectionContext {
|
|
32
|
+
return {
|
|
33
|
+
skillProjectionState: new Map(),
|
|
34
|
+
skillProjectionCache: {} as SkillProjectionCache,
|
|
35
|
+
coreToolNames: new Set<string>(),
|
|
36
|
+
toolsDisabledDepth: 0,
|
|
37
|
+
...overrides,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe("isToolActiveForContext — host tool capability gating", () => {
|
|
42
|
+
// macOS transport: SSE-based interactive approval required.
|
|
43
|
+
test("host_bash is active for macOS with a connected client", () => {
|
|
44
|
+
expect(
|
|
45
|
+
isToolActiveForContext(
|
|
46
|
+
"host_bash",
|
|
47
|
+
makeCtx({ hasNoClient: false, transportInterface: "macos" }),
|
|
48
|
+
),
|
|
49
|
+
).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("host_bash is NOT active for macOS when hasNoClient is true (security invariant)", () => {
|
|
53
|
+
// macOS uses an SSE-based interactive approval channel. Without a
|
|
54
|
+
// connected client the guardian auto-approve path could execute host
|
|
55
|
+
// commands unattended, so host tools must be denied.
|
|
56
|
+
expect(
|
|
57
|
+
isToolActiveForContext(
|
|
58
|
+
"host_bash",
|
|
59
|
+
makeCtx({ hasNoClient: true, transportInterface: "macos" }),
|
|
60
|
+
),
|
|
61
|
+
).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("host_file_read is NOT active for macOS when hasNoClient is true", () => {
|
|
65
|
+
expect(
|
|
66
|
+
isToolActiveForContext(
|
|
67
|
+
"host_file_read",
|
|
68
|
+
makeCtx({ hasNoClient: true, transportInterface: "macos" }),
|
|
69
|
+
),
|
|
70
|
+
).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("host_browser is active for macOS with a connected client", () => {
|
|
74
|
+
expect(
|
|
75
|
+
isToolActiveForContext(
|
|
76
|
+
"host_browser",
|
|
77
|
+
makeCtx({ hasNoClient: false, transportInterface: "macos" }),
|
|
78
|
+
),
|
|
79
|
+
).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("host_browser is NOT active for macOS when hasNoClient is true", () => {
|
|
83
|
+
// macOS requires a client for any host tool — the SSE interactive
|
|
84
|
+
// approval channel must be available regardless of capability.
|
|
85
|
+
expect(
|
|
86
|
+
isToolActiveForContext(
|
|
87
|
+
"host_browser",
|
|
88
|
+
makeCtx({ hasNoClient: true, transportInterface: "macos" }),
|
|
89
|
+
),
|
|
90
|
+
).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// chrome-extension transport: the extension is its own executor.
|
|
94
|
+
test("host_browser is active for chrome-extension even when hasNoClient is true", () => {
|
|
95
|
+
// chrome-extension turns run with `hasNoClient: true` by design because
|
|
96
|
+
// chrome-extension is not in `INTERACTIVE_INTERFACES` — it is not an
|
|
97
|
+
// SSE interactive channel. The extension gates host_browser commands
|
|
98
|
+
// via its own popup UI, so the hasNoClient gate must not filter
|
|
99
|
+
// host_browser out for chrome-extension transports.
|
|
100
|
+
expect(
|
|
101
|
+
isToolActiveForContext(
|
|
102
|
+
"host_browser",
|
|
103
|
+
makeCtx({
|
|
104
|
+
hasNoClient: true,
|
|
105
|
+
transportInterface: "chrome-extension",
|
|
106
|
+
}),
|
|
107
|
+
),
|
|
108
|
+
).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("host_browser is active for chrome-extension when hasNoClient is false", () => {
|
|
112
|
+
expect(
|
|
113
|
+
isToolActiveForContext(
|
|
114
|
+
"host_browser",
|
|
115
|
+
makeCtx({
|
|
116
|
+
hasNoClient: false,
|
|
117
|
+
transportInterface: "chrome-extension",
|
|
118
|
+
}),
|
|
119
|
+
),
|
|
120
|
+
).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("host_bash is NOT active for chrome-extension even when hasNoClient is true", () => {
|
|
124
|
+
// The per-capability check runs first and is authoritative: chrome-extension
|
|
125
|
+
// only supports `host_browser`, so `host_bash` must be filtered out.
|
|
126
|
+
expect(
|
|
127
|
+
isToolActiveForContext(
|
|
128
|
+
"host_bash",
|
|
129
|
+
makeCtx({
|
|
130
|
+
hasNoClient: true,
|
|
131
|
+
transportInterface: "chrome-extension",
|
|
132
|
+
}),
|
|
133
|
+
),
|
|
134
|
+
).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("host_file_read is NOT active for chrome-extension when hasNoClient is true", () => {
|
|
138
|
+
expect(
|
|
139
|
+
isToolActiveForContext(
|
|
140
|
+
"host_file_read",
|
|
141
|
+
makeCtx({
|
|
142
|
+
hasNoClient: true,
|
|
143
|
+
transportInterface: "chrome-extension",
|
|
144
|
+
}),
|
|
145
|
+
),
|
|
146
|
+
).toBe(false);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Backwards-compat fallback: no transport plumbed through.
|
|
150
|
+
test("host_bash falls back to hasNoClient gate when transport is undefined (client connected)", () => {
|
|
151
|
+
// Without a transport interface we cannot run the per-capability check,
|
|
152
|
+
// so we fall back to the coarse-grained `hasNoClient` behavior.
|
|
153
|
+
expect(
|
|
154
|
+
isToolActiveForContext(
|
|
155
|
+
"host_bash",
|
|
156
|
+
makeCtx({ hasNoClient: false, transportInterface: undefined }),
|
|
157
|
+
),
|
|
158
|
+
).toBe(true);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("host_bash falls back to hasNoClient gate when transport is undefined (no client)", () => {
|
|
162
|
+
expect(
|
|
163
|
+
isToolActiveForContext(
|
|
164
|
+
"host_bash",
|
|
165
|
+
makeCtx({ hasNoClient: true, transportInterface: undefined }),
|
|
166
|
+
),
|
|
167
|
+
).toBe(false);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("HOST_TOOL_NAMES derivation", () => {
|
|
172
|
+
test("HOST_TOOL_NAMES is derived from HOST_TOOL_TO_CAPABILITY", () => {
|
|
173
|
+
// Sanity check: every tool in the names set has a capability mapping.
|
|
174
|
+
// This is structurally enforced by the code (HOST_TOOL_NAMES is built
|
|
175
|
+
// from HOST_TOOL_TO_CAPABILITY.keys()), but we test it to make the
|
|
176
|
+
// invariant visible to readers and to catch any regression that
|
|
177
|
+
// splits the two collections back apart.
|
|
178
|
+
for (const name of HOST_TOOL_NAMES) {
|
|
179
|
+
expect(HOST_TOOL_TO_CAPABILITY.has(name)).toBe(true);
|
|
180
|
+
}
|
|
181
|
+
// Cardinality check: the two collections must have the same size so a
|
|
182
|
+
// future addition to HOST_TOOL_NAMES without a matching capability entry
|
|
183
|
+
// (or vice versa) would fail.
|
|
184
|
+
expect(HOST_TOOL_NAMES.size).toBe(HOST_TOOL_TO_CAPABILITY.size);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -24,6 +24,20 @@ const APP_REFRESH_DEBOUNCE_MS = 500;
|
|
|
24
24
|
|
|
25
25
|
export type AppSourceChangeCallback = (appId: string) => void;
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Module-level callback so tool-side-effects can ensure the watcher starts
|
|
29
|
+
* after the apps directory is created (e.g. on first app_create).
|
|
30
|
+
*/
|
|
31
|
+
let ensureWatcherStarted: (() => void) | null = null;
|
|
32
|
+
|
|
33
|
+
export function setEnsureAppSourceWatcher(fn: () => void): void {
|
|
34
|
+
ensureWatcherStarted = fn;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function ensureAppSourceWatcher(): void {
|
|
38
|
+
ensureWatcherStarted?.();
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
/**
|
|
28
42
|
* Resolve app ID from a relative path within the apps directory.
|
|
29
43
|
* Returns null if the path is not an app source file (e.g. dist/, records/).
|
|
@@ -48,12 +62,29 @@ function resolveAppIdFromRelPath(relPath: string): string | null {
|
|
|
48
62
|
|
|
49
63
|
export class AppSourceWatcher {
|
|
50
64
|
private watcher: FSWatcher | null = null;
|
|
65
|
+
private onChange: AppSourceChangeCallback | null = null;
|
|
51
66
|
private debouncer = new DebouncerMap({
|
|
52
67
|
defaultDelayMs: APP_REFRESH_DEBOUNCE_MS,
|
|
53
68
|
maxEntries: 50,
|
|
54
69
|
});
|
|
55
70
|
|
|
56
71
|
start(onChange: AppSourceChangeCallback): void {
|
|
72
|
+
this.onChange = onChange;
|
|
73
|
+
this.tryWatch();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Ensure the watcher is running. Call after app creation so the watcher
|
|
78
|
+
* starts if the apps directory was created after daemon startup.
|
|
79
|
+
*/
|
|
80
|
+
ensureStarted(): void {
|
|
81
|
+
if (this.watcher || !this.onChange) return;
|
|
82
|
+
this.tryWatch();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private tryWatch(): void {
|
|
86
|
+
if (this.watcher) return;
|
|
87
|
+
|
|
57
88
|
let appsDir: string;
|
|
58
89
|
try {
|
|
59
90
|
appsDir = getAppsDir();
|
|
@@ -67,6 +98,9 @@ export class AppSourceWatcher {
|
|
|
67
98
|
return;
|
|
68
99
|
}
|
|
69
100
|
|
|
101
|
+
const onChange = this.onChange;
|
|
102
|
+
if (!onChange) return;
|
|
103
|
+
|
|
70
104
|
try {
|
|
71
105
|
this.watcher = watch(appsDir, { recursive: true }, (_eventType, filename) => {
|
|
72
106
|
if (!filename) return;
|
|
@@ -78,6 +112,7 @@ export class AppSourceWatcher {
|
|
|
78
112
|
onChange(appId);
|
|
79
113
|
});
|
|
80
114
|
});
|
|
115
|
+
log.info("App source watcher started");
|
|
81
116
|
} catch (err) {
|
|
82
117
|
log.warn({ err }, "Failed to watch apps directory; source watching disabled");
|
|
83
118
|
}
|
|
@@ -118,6 +118,8 @@ export class ConfigWatcher {
|
|
|
118
118
|
onIdentityChanged?: () => void,
|
|
119
119
|
onSoundsConfigChanged?: () => void,
|
|
120
120
|
onAvatarChanged?: () => void,
|
|
121
|
+
onConfigChanged?: () => void,
|
|
122
|
+
onFeatureFlagsChanged?: () => void,
|
|
121
123
|
): void {
|
|
122
124
|
const workspaceDir = getWorkspaceDir();
|
|
123
125
|
|
|
@@ -130,6 +132,7 @@ export class ConfigWatcher {
|
|
|
130
132
|
const changed = await this.refreshConfigFromSources();
|
|
131
133
|
if (changed) {
|
|
132
134
|
onConversationEvict();
|
|
135
|
+
onConfigChanged?.();
|
|
133
136
|
const newConfig = getConfig();
|
|
134
137
|
const newMcpFingerprint = JSON.stringify(newConfig.mcp ?? {});
|
|
135
138
|
if (newMcpFingerprint !== prevMcpFingerprint) {
|
|
@@ -190,7 +193,7 @@ export class ConfigWatcher {
|
|
|
190
193
|
this.startAvatarWatcher(onAvatarChanged);
|
|
191
194
|
}
|
|
192
195
|
|
|
193
|
-
this.startFeatureFlagsWatcher();
|
|
196
|
+
this.startFeatureFlagsWatcher(onFeatureFlagsChanged);
|
|
194
197
|
this.startSignalsWatcher();
|
|
195
198
|
this.startSkillsWatchers(onConversationEvict);
|
|
196
199
|
}
|
|
@@ -266,7 +269,7 @@ export class ConfigWatcher {
|
|
|
266
269
|
}
|
|
267
270
|
}
|
|
268
271
|
|
|
269
|
-
private startFeatureFlagsWatcher(): void {
|
|
272
|
+
private startFeatureFlagsWatcher(onFeatureFlagsChanged?: () => void): void {
|
|
270
273
|
const protectedDir = process.env.GATEWAY_SECURITY_DIR
|
|
271
274
|
? process.env.GATEWAY_SECURITY_DIR
|
|
272
275
|
: join(homedir(), ".vellum", "protected");
|
|
@@ -297,6 +300,7 @@ export class ConfigWatcher {
|
|
|
297
300
|
"Feature flags file changed, invalidating cache",
|
|
298
301
|
);
|
|
299
302
|
clearFeatureFlagOverridesCache();
|
|
303
|
+
onFeatureFlagsChanged?.();
|
|
300
304
|
},
|
|
301
305
|
500,
|
|
302
306
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
2
2
|
import { isAllowDecision } from "../permissions/types.js";
|
|
3
|
+
import { isPermissionControlsV2Enabled } from "../permissions/v2-consent-policy.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Reserved pseudo tool name used for context overflow compression approval
|
|
@@ -26,6 +27,10 @@ export async function requestCompressionApproval(
|
|
|
26
27
|
prompter: PermissionPrompter,
|
|
27
28
|
opts?: { signal?: AbortSignal },
|
|
28
29
|
): Promise<CompressionApprovalResult> {
|
|
30
|
+
if (isPermissionControlsV2Enabled()) {
|
|
31
|
+
return { approved: true };
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
const result = await prompter.prompt(
|
|
30
35
|
CONTEXT_OVERFLOW_TOOL_NAME,
|
|
31
36
|
{
|
|
@@ -39,7 +44,6 @@ export async function requestCompressionApproval(
|
|
|
39
44
|
undefined,
|
|
40
45
|
undefined,
|
|
41
46
|
undefined,
|
|
42
|
-
undefined,
|
|
43
47
|
false,
|
|
44
48
|
opts?.signal,
|
|
45
49
|
);
|
|
@@ -932,10 +932,25 @@ export async function dispatchAgentEvent(
|
|
|
932
932
|
"assistant_turn",
|
|
933
933
|
deps.reqId,
|
|
934
934
|
);
|
|
935
|
+
|
|
936
|
+
// Format web search results into a human-readable string for the client.
|
|
937
|
+
let resultText = "";
|
|
938
|
+
if (Array.isArray(event.content) && event.content.length > 0) {
|
|
939
|
+
resultText = (event.content as unknown[])
|
|
940
|
+
.filter(
|
|
941
|
+
(r): r is { type: string; title: string; url: string } =>
|
|
942
|
+
typeof r === "object" &&
|
|
943
|
+
r != null &&
|
|
944
|
+
(r as { type?: string }).type === "web_search_result",
|
|
945
|
+
)
|
|
946
|
+
.map((r) => `${r.title}\n${r.url}`)
|
|
947
|
+
.join("\n\n");
|
|
948
|
+
}
|
|
949
|
+
|
|
935
950
|
deps.onEvent({
|
|
936
951
|
type: "tool_result",
|
|
937
|
-
toolName: "",
|
|
938
|
-
result:
|
|
952
|
+
toolName: "web_search",
|
|
953
|
+
result: resultText,
|
|
939
954
|
isError: event.isError,
|
|
940
955
|
conversationId: deps.ctx.conversationId,
|
|
941
956
|
toolUseId: event.toolUseId,
|