@vellumai/assistant 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +6 -7
- package/Dockerfile +1 -0
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
- package/bun.lock +3 -0
- package/docs/architecture/security.md +18 -16
- package/knip.json +1 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- package/openapi.yaml +294 -107
- package/package.json +4 -2
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +6 -17
- package/src/__tests__/assistant-event-hub.test.ts +126 -77
- package/src/__tests__/assistant-event.test.ts +0 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/background-shell-host-bash.test.ts +34 -43
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/checker.test.ts +20 -34
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-lifecycle.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
- package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -4
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/cu-unified-flow.test.ts +33 -16
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +4 -1
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +289 -7
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +45 -75
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
- package/src/__tests__/host-cu-proxy.test.ts +56 -111
- package/src/__tests__/host-file-proxy.test.ts +44 -98
- package/src/__tests__/host-file-read-tool.test.ts +42 -21
- package/src/__tests__/host-shell-tool.test.ts +33 -68
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy.test.ts +43 -53
- package/src/__tests__/http-user-message-parity.test.ts +0 -6
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +10 -5
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -66
- package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +66 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -22
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +3 -12
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +0 -4
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +9 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
- package/src/__tests__/tool-executor.test.ts +12 -19
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +150 -0
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/backup-worker.test.ts +36 -8
- package/src/backup/__tests__/paths.test.ts +2 -2
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +36 -2
- package/src/backup/paths.ts +9 -6
- package/src/browser-session/events.ts +0 -9
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +0 -24
- package/src/calls/twilio-rest.ts +0 -38
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +1 -36
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/backup.ts +4 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +63 -5
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +231 -76
- package/src/cli/commands/keys.ts +4 -1
- package/src/cli/commands/memory-v2.ts +24 -52
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +14 -0
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +3 -14
- package/src/config/feature-flag-registry.json +30 -30
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +3 -3
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +1 -1
- package/src/config/schemas/llm.ts +31 -3
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +9 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +6 -6
- package/src/config/schemas/skills.ts +5 -5
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -17
- package/src/contacts/contacts-write.ts +1 -105
- package/src/context/window-manager.ts +44 -5
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
- package/src/daemon/conversation-agent-loop.ts +277 -36
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +83 -163
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +22 -28
- package/src/daemon/conversation-tool-setup.ts +3 -33
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +117 -233
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +23 -71
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-bash-proxy.ts +67 -45
- package/src/daemon/host-browser-proxy.ts +65 -27
- package/src/daemon/host-cu-proxy.ts +40 -39
- package/src/daemon/host-file-proxy.ts +58 -37
- package/src/daemon/host-transfer-proxy.ts +84 -46
- package/src/daemon/lifecycle.ts +49 -15
- package/src/daemon/message-types/conversations.ts +7 -0
- package/src/daemon/message-types/host-bash.ts +1 -0
- package/src/daemon/message-types/host-cu.ts +1 -0
- package/src/daemon/message-types/host-file.ts +1 -0
- package/src/daemon/message-types/host-transfer.ts +1 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +102 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -2
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +3 -1
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
- package/src/heartbeat/heartbeat-service.ts +23 -5
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +16 -3
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +3 -10
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/manager.ts +0 -5
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +29 -4
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +3 -21
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
- package/src/memory/graph/conversation-graph-memory.ts +35 -13
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- package/src/memory/jobs-store.ts +0 -1
- package/src/memory/jobs-worker.ts +2 -16
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +14 -0
- package/src/memory/migrations/registry.ts +24 -0
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +25 -0
- package/src/memory/search/semantic.ts +5 -16
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +289 -90
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +384 -15
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/activation.ts +168 -97
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +14 -12
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +182 -58
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +118 -42
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/skill-store.ts +55 -7
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/types.ts +10 -20
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +122 -21
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +12 -2
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/types.ts +1 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/config.ts +0 -74
- package/src/outbound-proxy/health.ts +0 -44
- package/src/outbound-proxy/index.ts +0 -22
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.ts +4 -1
- package/src/permissions/gateway-threshold-reader.ts +4 -1
- package/src/permissions/prompter.ts +9 -2
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/system-prompt.ts +34 -70
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +1 -6
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -1
- package/src/runtime/auth/route-policy.ts +11 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +22 -82
- package/src/runtime/http-types.ts +5 -0
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
- package/src/runtime/migrations/migration-transport.ts +46 -13
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +133 -79
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +7 -7
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/pending-interactions.ts +13 -4
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +45 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +120 -8
- package/src/runtime/routes/conversation-routes.ts +44 -528
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/documents-routes.ts +53 -18
- package/src/runtime/routes/events-routes.ts +59 -91
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/host-bash-routes.ts +3 -2
- package/src/runtime/routes/host-browser-routes.ts +9 -33
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +3 -2
- package/src/runtime/routes/host-transfer-routes.ts +11 -15
- package/src/runtime/routes/identity-routes.ts +78 -6
- package/src/runtime/routes/inbound-message-handler.ts +580 -137
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/index.ts +4 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/memory-v2-routes.ts +10 -15
- package/src/runtime/routes/migration-routes.ts +188 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +3 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +0 -16
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +6 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
- package/src/telemetry/usage-telemetry-reporter.ts +3 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/executor.ts +44 -31
- package/src/tools/host-filesystem/edit.ts +3 -2
- package/src/tools/host-filesystem/read.ts +3 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +4 -3
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +4 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/types.ts +12 -39
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
createLocalBackend,
|
|
9
9
|
} from "../../../browser-session/index.js";
|
|
10
10
|
import { getConfig } from "../../../config/loader.js";
|
|
11
|
+
import { HostBrowserProxy } from "../../../daemon/host-browser-proxy.js";
|
|
11
12
|
import { getLogger } from "../../../util/logger.js";
|
|
12
13
|
import type { ToolContext } from "../../types.js";
|
|
13
14
|
import { createCdpInspectClient } from "./cdp-inspect-client.js";
|
|
@@ -103,11 +104,10 @@ export interface GetCdpClientOptions {
|
|
|
103
104
|
* invocation based on the ToolContext and config. Three backends are
|
|
104
105
|
* considered in priority order:
|
|
105
106
|
*
|
|
106
|
-
* 1. **Extension** -- When `
|
|
107
|
-
* `
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* object exists but the underlying WebSocket is disconnected.
|
|
107
|
+
* 1. **Extension** -- When `HostBrowserProxy.instance` is available
|
|
108
|
+
* and `isAvailable()` returns `true` (i.e. a chrome extension
|
|
109
|
+
* connection exists in the registry). This prevents selecting
|
|
110
|
+
* the extension transport when no extension is connected.
|
|
111
111
|
* 2. **cdp-inspect** -- When `hostBrowser.cdpInspect.enabled` is
|
|
112
112
|
* `true` in config, construct a `CdpInspectClient` that attaches
|
|
113
113
|
* to an already-running Chrome via the DevTools JSON protocol.
|
|
@@ -183,17 +183,15 @@ export function buildPinnedCandidateList(
|
|
|
183
183
|
context: ToolContext,
|
|
184
184
|
mode: Exclude<BrowserMode, "auto">,
|
|
185
185
|
): BackendCandidate[] {
|
|
186
|
-
const { conversationId
|
|
186
|
+
const { conversationId } = context;
|
|
187
187
|
|
|
188
188
|
switch (mode) {
|
|
189
189
|
case "extension": {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
? "no host browser proxy provisioned for this conversation"
|
|
193
|
-
: "host browser proxy exists but is not connected";
|
|
190
|
+
const hostBrowserProxy = HostBrowserProxy.instance;
|
|
191
|
+
if (!hostBrowserProxy.isAvailable()) {
|
|
194
192
|
throw new CdpError(
|
|
195
193
|
"transport_error",
|
|
196
|
-
`Pinned mode "extension" unavailable:
|
|
194
|
+
`Pinned mode "extension" unavailable: no active extension connection`,
|
|
197
195
|
{
|
|
198
196
|
attemptDiagnostics: [
|
|
199
197
|
{
|
|
@@ -201,7 +199,7 @@ export function buildPinnedCandidateList(
|
|
|
201
199
|
inclusionReason: `pinned mode: extension`,
|
|
202
200
|
stage: "candidate_selection",
|
|
203
201
|
errorCode: "transport_error",
|
|
204
|
-
errorMessage:
|
|
202
|
+
errorMessage: "no active extension connection",
|
|
205
203
|
},
|
|
206
204
|
],
|
|
207
205
|
},
|
|
@@ -289,18 +287,16 @@ export function buildPinnedCandidateList(
|
|
|
289
287
|
* Exported for testing.
|
|
290
288
|
*/
|
|
291
289
|
export function buildCandidateList(context: ToolContext): BackendCandidate[] {
|
|
292
|
-
const { conversationId
|
|
290
|
+
const { conversationId } = context;
|
|
293
291
|
const candidates: BackendCandidate[] = [];
|
|
292
|
+
const hostBrowserProxy = HostBrowserProxy.instance;
|
|
294
293
|
|
|
295
|
-
// 1. Extension -- preferred when
|
|
296
|
-
//
|
|
297
|
-
|
|
298
|
-
// object exists (e.g. it was provisioned at conversation start)
|
|
299
|
-
// but the client has since disconnected.
|
|
300
|
-
if (hostBrowserProxy && hostBrowserProxy.isAvailable()) {
|
|
294
|
+
// 1. Extension -- preferred when the singleton proxy reports an active
|
|
295
|
+
// extension connection is available.
|
|
296
|
+
if (hostBrowserProxy.isAvailable()) {
|
|
301
297
|
candidates.push({
|
|
302
298
|
kind: "extension",
|
|
303
|
-
reason: "
|
|
299
|
+
reason: "extension connected via registry singleton",
|
|
304
300
|
create() {
|
|
305
301
|
const client = createExtensionCdpClient(
|
|
306
302
|
hostBrowserProxy,
|
|
@@ -315,10 +311,10 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
|
|
|
315
311
|
return { client, backend };
|
|
316
312
|
},
|
|
317
313
|
});
|
|
318
|
-
} else
|
|
314
|
+
} else {
|
|
319
315
|
log.debug(
|
|
320
316
|
{ conversationId },
|
|
321
|
-
"CDP factory:
|
|
317
|
+
"CDP factory: no active extension connection, skipping extension candidate",
|
|
322
318
|
);
|
|
323
319
|
}
|
|
324
320
|
|
|
@@ -348,63 +344,39 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
|
|
|
348
344
|
context.transportInterface === "macos" &&
|
|
349
345
|
cdpInspectConfig.desktopAuto.enabled
|
|
350
346
|
) {
|
|
351
|
-
// macOS desktop-auto: include cdp-inspect as a candidate unless
|
|
352
|
-
//
|
|
353
|
-
//
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
// `hostBrowserRegistryRouted` is true (set when
|
|
357
|
-
// `hostBrowserSenderOverride` was wired at turn-start).
|
|
358
|
-
// SSE-backed proxies (macOS without an extension connection) that
|
|
359
|
-
// report unavailable (e.g. non-interactive turns where
|
|
360
|
-
// clientConnected=false) should NOT suppress cdp-inspect — the
|
|
361
|
-
// SSE proxy was never expected to service browser requests.
|
|
362
|
-
// (b) the cooldown from a recent failure is still active.
|
|
363
|
-
//
|
|
364
|
-
// When no hostBrowserProxy is present at all (extension not
|
|
365
|
-
// provisioned for this conversation), cdp-inspect remains available
|
|
366
|
-
// as a fallback per the desktop-auto contract.
|
|
367
|
-
if (
|
|
368
|
-
hostBrowserProxy &&
|
|
369
|
-
!hostBrowserProxy.isAvailable() &&
|
|
370
|
-
context.hostBrowserRegistryRouted
|
|
371
|
-
) {
|
|
347
|
+
// macOS desktop-auto: include cdp-inspect as a candidate unless
|
|
348
|
+
// the cooldown from a recent failure is still active. The extension
|
|
349
|
+
// candidate is already first in the list, so it wins when connected.
|
|
350
|
+
const { cooldownMs } = cdpInspectConfig.desktopAuto;
|
|
351
|
+
if (isDesktopAutoCooldownActive(cooldownMs)) {
|
|
372
352
|
log.debug(
|
|
373
|
-
{
|
|
374
|
-
|
|
353
|
+
{
|
|
354
|
+
conversationId,
|
|
355
|
+
cooldownMs,
|
|
356
|
+
cooldownSince: _desktopAutoCooldownSince,
|
|
357
|
+
},
|
|
358
|
+
"CDP factory: desktop-auto cdp-inspect skipped (cooldown active)",
|
|
375
359
|
);
|
|
376
360
|
} else {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
wsConnectTimeoutMs: cdpInspectConfig.probeTimeoutMs,
|
|
397
|
-
});
|
|
398
|
-
const backend = createCdpInspectBackend({
|
|
399
|
-
isAvailable: () => true,
|
|
400
|
-
sendCdp: (command, signal) =>
|
|
401
|
-
dispatchThroughClient(client, command, signal),
|
|
402
|
-
dispose: () => client.dispose(),
|
|
403
|
-
});
|
|
404
|
-
return { client, backend };
|
|
405
|
-
},
|
|
406
|
-
});
|
|
407
|
-
}
|
|
361
|
+
candidates.push({
|
|
362
|
+
kind: "cdp-inspect",
|
|
363
|
+
reason: "desktopAuto: macOS turn, cdp-inspect auto-attempted",
|
|
364
|
+
create() {
|
|
365
|
+
const client = createCdpInspectClient(conversationId, {
|
|
366
|
+
host: cdpInspectConfig.host,
|
|
367
|
+
port: cdpInspectConfig.port,
|
|
368
|
+
discoveryTimeoutMs: cdpInspectConfig.probeTimeoutMs,
|
|
369
|
+
wsConnectTimeoutMs: cdpInspectConfig.probeTimeoutMs,
|
|
370
|
+
});
|
|
371
|
+
const backend = createCdpInspectBackend({
|
|
372
|
+
isAvailable: () => true,
|
|
373
|
+
sendCdp: (command, signal) =>
|
|
374
|
+
dispatchThroughClient(client, command, signal),
|
|
375
|
+
dispose: () => client.dispose(),
|
|
376
|
+
});
|
|
377
|
+
return { client, backend };
|
|
378
|
+
},
|
|
379
|
+
});
|
|
408
380
|
}
|
|
409
381
|
}
|
|
410
382
|
|
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
export {
|
|
2
|
-
CdpInspectClient,
|
|
3
2
|
type CdpInspectClientOptions,
|
|
4
3
|
type CdpInspectHelpers,
|
|
5
|
-
createCdpInspectClient,
|
|
6
4
|
} from "./cdp-inspect-client.js";
|
|
7
5
|
export { CdpError, type CdpErrorCode } from "./errors.js";
|
|
8
|
-
export {
|
|
9
|
-
createExtensionCdpClient,
|
|
10
|
-
ExtensionCdpClient,
|
|
11
|
-
} from "./extension-cdp-client.js";
|
|
12
|
-
export {
|
|
13
|
-
buildCandidateList,
|
|
14
|
-
buildChainedClient,
|
|
15
|
-
buildPinnedCandidateList,
|
|
16
|
-
getCdpClient,
|
|
17
|
-
type GetCdpClientOptions,
|
|
18
|
-
} from "./factory.js";
|
|
19
|
-
export { createLocalCdpClient, LocalCdpClient } from "./local-cdp-client.js";
|
|
6
|
+
export { type GetCdpClientOptions } from "./factory.js";
|
|
20
7
|
export type {
|
|
21
8
|
AttemptDiagnostic,
|
|
22
9
|
AttemptStage,
|
package/src/tools/executor.ts
CHANGED
|
@@ -22,7 +22,6 @@ import { getLogger } from "../util/logger.js";
|
|
|
22
22
|
import { resolveExecutionTarget } from "./execution-target.js";
|
|
23
23
|
import { executeWithTimeout, safeTimeoutMs } from "./execution-timeout.js";
|
|
24
24
|
import { PermissionChecker } from "./permission-checker.js";
|
|
25
|
-
import { SecretDetectionHandler } from "./secret-detection-handler.js";
|
|
26
25
|
import { extractAndSanitize } from "./sensitive-output-placeholders.js";
|
|
27
26
|
import { applyEdit } from "./shared/filesystem/edit-engine.js";
|
|
28
27
|
import { sandboxPolicy } from "./shared/filesystem/path-policy.js";
|
|
@@ -39,13 +38,11 @@ const log = getLogger("tool-executor");
|
|
|
39
38
|
export class ToolExecutor {
|
|
40
39
|
private prompter: PermissionPrompter;
|
|
41
40
|
private permissionChecker: PermissionChecker;
|
|
42
|
-
private secretDetectionHandler: SecretDetectionHandler;
|
|
43
41
|
private approvalHandler: ToolApprovalHandler;
|
|
44
42
|
|
|
45
43
|
constructor(prompter: PermissionPrompter) {
|
|
46
44
|
this.prompter = prompter;
|
|
47
45
|
this.permissionChecker = new PermissionChecker(prompter);
|
|
48
|
-
this.secretDetectionHandler = new SecretDetectionHandler(prompter);
|
|
49
46
|
this.approvalHandler = new ToolApprovalHandler();
|
|
50
47
|
}
|
|
51
48
|
|
|
@@ -105,6 +102,19 @@ export class ToolExecutor {
|
|
|
105
102
|
const startTime = Date.now();
|
|
106
103
|
let decision = "allow";
|
|
107
104
|
let riskLevel: string = RiskLevel.Low;
|
|
105
|
+
let permRiskMeta:
|
|
106
|
+
| {
|
|
107
|
+
riskLevel: string;
|
|
108
|
+
riskReason: string;
|
|
109
|
+
riskScopeOptions: Array<{ pattern: string; label: string }>;
|
|
110
|
+
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
111
|
+
isContainerized?: boolean;
|
|
112
|
+
}
|
|
113
|
+
| undefined;
|
|
114
|
+
let permMatchedTrustRuleId: string | undefined;
|
|
115
|
+
let permApprovalMode: string | undefined;
|
|
116
|
+
let permApprovalReason: string | undefined;
|
|
117
|
+
let permRiskThreshold: string | undefined;
|
|
108
118
|
const executionTarget = resolveExecutionTarget(name);
|
|
109
119
|
|
|
110
120
|
emitLifecycleEvent(context, {
|
|
@@ -167,15 +177,6 @@ export class ToolExecutor {
|
|
|
167
177
|
// Exception: requireFreshApproval tools always go through the
|
|
168
178
|
// permission check even when a grant was consumed - the grant does
|
|
169
179
|
// not substitute for an interactive human review.
|
|
170
|
-
let permRiskMeta:
|
|
171
|
-
| {
|
|
172
|
-
riskLevel: string;
|
|
173
|
-
riskReason: string;
|
|
174
|
-
riskScopeOptions: Array<{ pattern: string; label: string }>;
|
|
175
|
-
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
176
|
-
isContainerized?: boolean;
|
|
177
|
-
}
|
|
178
|
-
| undefined;
|
|
179
180
|
if (!gateResult.grantConsumed || context.requireFreshApproval) {
|
|
180
181
|
// Check permissions via the extracted PermissionChecker
|
|
181
182
|
const permResult = await this.permissionChecker.checkPermission(
|
|
@@ -192,6 +193,10 @@ export class ToolExecutor {
|
|
|
192
193
|
riskLevel = permResult.riskLevel;
|
|
193
194
|
decision = permResult.decision;
|
|
194
195
|
permRiskMeta = permResult.riskMeta;
|
|
196
|
+
permMatchedTrustRuleId = permResult.matchedTrustRuleId;
|
|
197
|
+
permApprovalMode = permResult.approvalMode;
|
|
198
|
+
permApprovalReason = permResult.approvalReason;
|
|
199
|
+
permRiskThreshold = permResult.riskThreshold;
|
|
195
200
|
|
|
196
201
|
if (!permResult.allowed) {
|
|
197
202
|
return {
|
|
@@ -202,12 +207,21 @@ export class ToolExecutor {
|
|
|
202
207
|
riskScopeOptions: permRiskMeta?.riskScopeOptions,
|
|
203
208
|
riskDirectoryScopeOptions: permRiskMeta?.riskDirectoryScopeOptions,
|
|
204
209
|
isContainerized: permRiskMeta?.isContainerized,
|
|
210
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
211
|
+
approvalMode: permApprovalMode,
|
|
212
|
+
approvalReason: permApprovalReason,
|
|
213
|
+
riskThreshold: permRiskThreshold,
|
|
205
214
|
};
|
|
206
215
|
}
|
|
207
216
|
|
|
208
217
|
if (permResult.wasPrompted) {
|
|
209
218
|
context.approvedViaPrompt = true;
|
|
210
219
|
}
|
|
220
|
+
} else {
|
|
221
|
+
// Grant consumed — permission check was skipped. Set provenance explicitly
|
|
222
|
+
// so the record shows how this execution was authorized.
|
|
223
|
+
permApprovalMode = "auto";
|
|
224
|
+
permApprovalReason = "grant_scoped_consumed";
|
|
211
225
|
}
|
|
212
226
|
|
|
213
227
|
// Execute the tool - proxy tools delegate to an external resolver.
|
|
@@ -231,6 +245,7 @@ export class ToolExecutor {
|
|
|
231
245
|
conversationId: context.conversationId,
|
|
232
246
|
requestId: context.requestId,
|
|
233
247
|
riskLevel,
|
|
248
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
234
249
|
decision: "error",
|
|
235
250
|
durationMs,
|
|
236
251
|
errorMessage: msg,
|
|
@@ -268,6 +283,7 @@ export class ToolExecutor {
|
|
|
268
283
|
conversationId: context.conversationId,
|
|
269
284
|
requestId: context.requestId,
|
|
270
285
|
riskLevel,
|
|
286
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
271
287
|
decision: "error",
|
|
272
288
|
durationMs,
|
|
273
289
|
errorMessage: msg,
|
|
@@ -334,6 +350,7 @@ export class ToolExecutor {
|
|
|
334
350
|
conversationId: context.conversationId,
|
|
335
351
|
requestId: context.requestId,
|
|
336
352
|
riskLevel,
|
|
353
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
337
354
|
decision: "deny",
|
|
338
355
|
reason: denialReason,
|
|
339
356
|
durationMs,
|
|
@@ -352,6 +369,7 @@ export class ToolExecutor {
|
|
|
352
369
|
conversationId: context.conversationId,
|
|
353
370
|
requestId: context.requestId,
|
|
354
371
|
riskLevel,
|
|
372
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
355
373
|
decision: "error",
|
|
356
374
|
durationMs,
|
|
357
375
|
errorMessage: errorMsg,
|
|
@@ -364,8 +382,6 @@ export class ToolExecutor {
|
|
|
364
382
|
|
|
365
383
|
// Sensitive output extraction: strip directives, replace raw values
|
|
366
384
|
// with placeholders, and attach bindings for agent-loop substitution.
|
|
367
|
-
// Runs before secret detection so that raw sensitive values are already
|
|
368
|
-
// replaced and won't trigger entropy-based redaction.
|
|
369
385
|
const { sanitizedContent, bindings } = extractAndSanitize(
|
|
370
386
|
execResult.content,
|
|
371
387
|
);
|
|
@@ -377,23 +393,6 @@ export class ToolExecutor {
|
|
|
377
393
|
};
|
|
378
394
|
}
|
|
379
395
|
|
|
380
|
-
// Secret detection on tool output
|
|
381
|
-
const secretResult = await this.secretDetectionHandler.handle(
|
|
382
|
-
execResult,
|
|
383
|
-
name,
|
|
384
|
-
input,
|
|
385
|
-
context,
|
|
386
|
-
executionTarget,
|
|
387
|
-
riskLevel,
|
|
388
|
-
decision,
|
|
389
|
-
startTime,
|
|
390
|
-
emitLifecycleEvent,
|
|
391
|
-
);
|
|
392
|
-
if (secretResult.earlyReturn) {
|
|
393
|
-
return secretResult.result;
|
|
394
|
-
}
|
|
395
|
-
execResult = secretResult.result;
|
|
396
|
-
|
|
397
396
|
const durationMs = Date.now() - startTime;
|
|
398
397
|
// Strip sensitiveBindings from lifecycle event to prevent raw values leaking
|
|
399
398
|
const { sensitiveBindings: _sb, ...safeResult } = execResult;
|
|
@@ -406,6 +405,7 @@ export class ToolExecutor {
|
|
|
406
405
|
conversationId: context.conversationId,
|
|
407
406
|
requestId: context.requestId,
|
|
408
407
|
riskLevel,
|
|
408
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
409
409
|
decision,
|
|
410
410
|
durationMs,
|
|
411
411
|
result: safeResult,
|
|
@@ -424,6 +424,18 @@ export class ToolExecutor {
|
|
|
424
424
|
isContainerized: permRiskMeta.isContainerized,
|
|
425
425
|
};
|
|
426
426
|
}
|
|
427
|
+
if (permMatchedTrustRuleId) {
|
|
428
|
+
execResult = { ...execResult, matchedTrustRuleId: permMatchedTrustRuleId };
|
|
429
|
+
}
|
|
430
|
+
if (permApprovalMode) {
|
|
431
|
+
execResult = { ...execResult, approvalMode: permApprovalMode };
|
|
432
|
+
}
|
|
433
|
+
if (permApprovalReason) {
|
|
434
|
+
execResult = { ...execResult, approvalReason: permApprovalReason };
|
|
435
|
+
}
|
|
436
|
+
if (permRiskThreshold) {
|
|
437
|
+
execResult = { ...execResult, riskThreshold: permRiskThreshold };
|
|
438
|
+
}
|
|
427
439
|
|
|
428
440
|
return execResult;
|
|
429
441
|
} catch (err) {
|
|
@@ -465,6 +477,7 @@ export class ToolExecutor {
|
|
|
465
477
|
conversationId: context.conversationId,
|
|
466
478
|
requestId: context.requestId,
|
|
467
479
|
riskLevel,
|
|
480
|
+
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
468
481
|
decision: "error",
|
|
469
482
|
durationMs,
|
|
470
483
|
errorMessage: msg,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
1
2
|
import { RiskLevel } from "../../permissions/types.js";
|
|
2
3
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
3
4
|
import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
|
|
@@ -85,8 +86,8 @@ class HostFileEditTool implements Tool {
|
|
|
85
86
|
|
|
86
87
|
// Proxy to connected client for execution on the user's machine
|
|
87
88
|
// when a capable client is available (managed/cloud-hosted mode).
|
|
88
|
-
if (
|
|
89
|
-
return
|
|
89
|
+
if (HostFileProxy.instance.isAvailable()) {
|
|
90
|
+
return HostFileProxy.instance.request(
|
|
90
91
|
{
|
|
91
92
|
operation: "edit",
|
|
92
93
|
path: rawPath,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { extname } from "node:path";
|
|
2
2
|
|
|
3
|
+
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
3
4
|
import { RiskLevel } from "../../permissions/types.js";
|
|
4
5
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
5
6
|
import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
|
|
@@ -57,8 +58,8 @@ class HostFileReadTool implements Tool {
|
|
|
57
58
|
// Proxy to connected client for execution on the user's machine
|
|
58
59
|
// when a capable client is available (managed/cloud-hosted mode),
|
|
59
60
|
// including image reads that need the host filesystem view.
|
|
60
|
-
if (
|
|
61
|
-
return
|
|
61
|
+
if (HostFileProxy.instance.isAvailable()) {
|
|
62
|
+
return HostFileProxy.instance.request(
|
|
62
63
|
{
|
|
63
64
|
operation: "read",
|
|
64
65
|
path: rawPath,
|
|
@@ -1,14 +1,44 @@
|
|
|
1
1
|
import { existsSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { afterEach, describe, expect, test } from "bun:test";
|
|
4
|
+
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
5
5
|
|
|
6
6
|
import type { ToolContext } from "../types.js";
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Singleton mock — must precede the tool import so bun's module mock applies.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
let mockProxyAvailable = false;
|
|
13
|
+
const toSandboxCalls: Array<{ sourcePath: string; destPath: string }> = [];
|
|
14
|
+
const toHostCalls: Array<{ sourcePath: string; destPath: string }> = [];
|
|
15
|
+
|
|
16
|
+
mock.module("../../daemon/host-transfer-proxy.js", () => ({
|
|
17
|
+
HostTransferProxy: {
|
|
18
|
+
get instance() {
|
|
19
|
+
return {
|
|
20
|
+
isAvailable: () => mockProxyAvailable,
|
|
21
|
+
requestToSandbox: (args: { sourcePath: string; destPath: string; overwrite?: boolean; conversationId: string }) => {
|
|
22
|
+
toSandboxCalls.push({ sourcePath: args.sourcePath, destPath: args.destPath });
|
|
23
|
+
return Promise.resolve({ content: "ok", isError: false });
|
|
24
|
+
},
|
|
25
|
+
requestToHost: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
|
|
26
|
+
toHostCalls.push({ sourcePath: args.sourcePath, destPath: args.destPath });
|
|
27
|
+
return Promise.resolve({ content: "ok", isError: false });
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const { hostFileTransferTool } = await import("./transfer.js");
|
|
8
35
|
|
|
9
36
|
const testDirs: string[] = [];
|
|
10
37
|
|
|
11
38
|
afterEach(() => {
|
|
39
|
+
mockProxyAvailable = false;
|
|
40
|
+
toSandboxCalls.length = 0;
|
|
41
|
+
toHostCalls.length = 0;
|
|
12
42
|
for (const dir of testDirs.splice(0)) {
|
|
13
43
|
rmSync(dir, { recursive: true, force: true });
|
|
14
44
|
}
|
|
@@ -25,7 +55,7 @@ function makeContext(workingDir: string): ToolContext {
|
|
|
25
55
|
}
|
|
26
56
|
|
|
27
57
|
// ---------------------------------------------------------------------------
|
|
28
|
-
// Local-mode tests (
|
|
58
|
+
// Local-mode tests (proxy unavailable — falls back to local copy)
|
|
29
59
|
// ---------------------------------------------------------------------------
|
|
30
60
|
|
|
31
61
|
describe("host_file_transfer local mode", () => {
|
|
@@ -176,93 +206,66 @@ describe("host_file_transfer local mode to_host", () => {
|
|
|
176
206
|
});
|
|
177
207
|
|
|
178
208
|
// ---------------------------------------------------------------------------
|
|
179
|
-
// Managed-mode tests (
|
|
209
|
+
// Managed-mode tests (singleton proxy available)
|
|
180
210
|
// ---------------------------------------------------------------------------
|
|
181
211
|
|
|
182
212
|
describe("host_file_transfer managed mode", () => {
|
|
183
213
|
test("relative path is pre-resolved before proxy call", async () => {
|
|
214
|
+
mockProxyAvailable = true;
|
|
184
215
|
const workingDir = makeTempDir();
|
|
185
216
|
const srcDir = makeTempDir();
|
|
186
217
|
const srcFile = join(srcDir, "source.txt");
|
|
187
218
|
writeFileSync(srcFile, "content");
|
|
188
219
|
|
|
189
|
-
const calls: Array<{ destPath: string }> = [];
|
|
190
|
-
const mockProxy = {
|
|
191
|
-
isAvailable: () => true,
|
|
192
|
-
requestToSandbox: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
|
|
193
|
-
calls.push({ destPath: args.destPath });
|
|
194
|
-
return Promise.resolve({ content: "ok", isError: false });
|
|
195
|
-
},
|
|
196
|
-
};
|
|
197
|
-
const ctx = { ...makeContext(workingDir), hostTransferProxy: mockProxy as any };
|
|
198
|
-
|
|
199
220
|
await hostFileTransferTool.execute(
|
|
200
221
|
{
|
|
201
222
|
source_path: srcFile,
|
|
202
223
|
dest_path: "relative/file.txt",
|
|
203
224
|
direction: "to_sandbox",
|
|
204
225
|
},
|
|
205
|
-
|
|
226
|
+
makeContext(workingDir),
|
|
206
227
|
);
|
|
207
228
|
|
|
208
|
-
expect(
|
|
209
|
-
expect(
|
|
229
|
+
expect(toSandboxCalls.length).toBe(1);
|
|
230
|
+
expect(toSandboxCalls[0].destPath).toBe(join(workingDir, "relative", "file.txt"));
|
|
210
231
|
});
|
|
211
232
|
|
|
212
233
|
test("to_host relative source is pre-resolved before proxy call", async () => {
|
|
234
|
+
mockProxyAvailable = true;
|
|
213
235
|
const workingDir = makeTempDir();
|
|
214
236
|
writeFileSync(join(workingDir, "doc.md"), "content");
|
|
215
237
|
|
|
216
|
-
const calls: Array<{ sourcePath: string }> = [];
|
|
217
|
-
const mockProxy = {
|
|
218
|
-
isAvailable: () => true,
|
|
219
|
-
requestToHost: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
|
|
220
|
-
calls.push({ sourcePath: args.sourcePath });
|
|
221
|
-
return Promise.resolve({ content: "ok", isError: false });
|
|
222
|
-
},
|
|
223
|
-
};
|
|
224
|
-
const ctx = { ...makeContext(workingDir), hostTransferProxy: mockProxy as any };
|
|
225
|
-
|
|
226
238
|
await hostFileTransferTool.execute(
|
|
227
239
|
{
|
|
228
240
|
source_path: "doc.md",
|
|
229
241
|
dest_path: "/Users/someone/Desktop/doc.md",
|
|
230
242
|
direction: "to_host",
|
|
231
243
|
},
|
|
232
|
-
|
|
244
|
+
makeContext(workingDir),
|
|
233
245
|
);
|
|
234
246
|
|
|
235
|
-
expect(
|
|
236
|
-
expect(
|
|
247
|
+
expect(toHostCalls.length).toBe(1);
|
|
248
|
+
expect(toHostCalls[0].sourcePath).toBe(join(workingDir, "doc.md"));
|
|
237
249
|
});
|
|
238
250
|
|
|
239
251
|
test("out-of-bounds path rejected before proxy call", async () => {
|
|
252
|
+
mockProxyAvailable = true;
|
|
240
253
|
const workingDir = makeTempDir();
|
|
241
254
|
const srcDir = makeTempDir();
|
|
242
255
|
const srcFile = join(srcDir, "source.txt");
|
|
243
256
|
writeFileSync(srcFile, "content");
|
|
244
257
|
|
|
245
|
-
const calls: Array<{ destPath: string }> = [];
|
|
246
|
-
const mockProxy = {
|
|
247
|
-
isAvailable: () => true,
|
|
248
|
-
requestToSandbox: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
|
|
249
|
-
calls.push({ destPath: args.destPath });
|
|
250
|
-
return Promise.resolve({ content: "ok", isError: false });
|
|
251
|
-
},
|
|
252
|
-
};
|
|
253
|
-
const ctx = { ...makeContext(workingDir), hostTransferProxy: mockProxy as any };
|
|
254
|
-
|
|
255
258
|
const result = await hostFileTransferTool.execute(
|
|
256
259
|
{
|
|
257
260
|
source_path: srcFile,
|
|
258
261
|
dest_path: "/etc/passwd",
|
|
259
262
|
direction: "to_sandbox",
|
|
260
263
|
},
|
|
261
|
-
|
|
264
|
+
makeContext(workingDir),
|
|
262
265
|
);
|
|
263
266
|
|
|
264
267
|
expect(result.isError).toBe(true);
|
|
265
268
|
expect(result.content).toContain("Invalid destination path");
|
|
266
|
-
expect(
|
|
269
|
+
expect(toSandboxCalls.length).toBe(0);
|
|
267
270
|
});
|
|
268
271
|
});
|
|
@@ -2,6 +2,7 @@ import { constants } from "node:fs";
|
|
|
2
2
|
import { copyFile, lstat, mkdir, realpath } from "node:fs/promises";
|
|
3
3
|
import { dirname, isAbsolute } from "node:path";
|
|
4
4
|
|
|
5
|
+
import { HostTransferProxy } from "../../daemon/host-transfer-proxy.js";
|
|
5
6
|
import { RiskLevel } from "../../permissions/types.js";
|
|
6
7
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
7
8
|
import { sandboxPolicy } from "../shared/filesystem/path-policy.js";
|
|
@@ -125,9 +126,9 @@ class HostFileTransferTool implements Tool {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
// Managed mode: delegate to the host transfer proxy when available.
|
|
128
|
-
if (
|
|
129
|
+
if (HostTransferProxy.instance.isAvailable()) {
|
|
129
130
|
if (direction === "to_host") {
|
|
130
|
-
return
|
|
131
|
+
return HostTransferProxy.instance.requestToHost(
|
|
131
132
|
{
|
|
132
133
|
sourcePath: resolvedSourcePath,
|
|
133
134
|
destPath,
|
|
@@ -137,7 +138,7 @@ class HostFileTransferTool implements Tool {
|
|
|
137
138
|
context.signal,
|
|
138
139
|
);
|
|
139
140
|
}
|
|
140
|
-
return
|
|
141
|
+
return HostTransferProxy.instance.requestToSandbox(
|
|
141
142
|
{
|
|
142
143
|
sourcePath,
|
|
143
144
|
destPath: resolvedDestPath,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
1
2
|
import { RiskLevel } from "../../permissions/types.js";
|
|
2
3
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
3
4
|
import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
|
|
@@ -55,8 +56,8 @@ class HostFileWriteTool implements Tool {
|
|
|
55
56
|
|
|
56
57
|
// Proxy to connected client for execution on the user's machine
|
|
57
58
|
// when a capable client is available (managed/cloud-hosted mode).
|
|
58
|
-
if (
|
|
59
|
-
return
|
|
59
|
+
if (HostFileProxy.instance.isAvailable()) {
|
|
60
|
+
return HostFileProxy.instance.request(
|
|
60
61
|
{
|
|
61
62
|
operation: "write",
|
|
62
63
|
path: rawPath,
|