@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
|
@@ -68,22 +68,30 @@ import {
|
|
|
68
68
|
type ForwardedCdpEvent,
|
|
69
69
|
onCdpEvent,
|
|
70
70
|
} from "../browser-session/index.js";
|
|
71
|
+
import { HostBrowserProxy } from "../daemon/host-browser-proxy.js";
|
|
71
72
|
import { getDb } from "../memory/db-connection.js";
|
|
72
73
|
import { initializeDb } from "../memory/db-init.js";
|
|
74
|
+
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
75
|
+
import { mintToken } from "../runtime/auth/token-service.js";
|
|
73
76
|
import {
|
|
74
77
|
mintHostBrowserCapability,
|
|
75
78
|
resetCapabilityTokenSecretForTests,
|
|
76
79
|
setCapabilityTokenSecretForTests,
|
|
77
80
|
} from "../runtime/capability-tokens.js";
|
|
78
|
-
import {
|
|
79
|
-
__resetChromeExtensionRegistryForTests,
|
|
80
|
-
getChromeExtensionRegistry,
|
|
81
|
-
} from "../runtime/chrome-extension-registry.js";
|
|
82
81
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
83
|
-
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
84
82
|
|
|
85
83
|
initializeDb();
|
|
86
84
|
|
|
85
|
+
function mintSseToken(guardianId: string): string {
|
|
86
|
+
return mintToken({
|
|
87
|
+
aud: "vellum-daemon",
|
|
88
|
+
sub: `actor:self:${guardianId}`,
|
|
89
|
+
scope_profile: "actor_client_v1",
|
|
90
|
+
policy_epoch: 1,
|
|
91
|
+
ttlSeconds: 3600,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
87
95
|
// ── Helpers ─────────────────────────────────────────────────────────
|
|
88
96
|
|
|
89
97
|
async function waitFor(
|
|
@@ -102,11 +110,12 @@ async function waitFor(
|
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
async function waitForRegistryEntry(
|
|
105
|
-
|
|
113
|
+
_guardianId: string,
|
|
106
114
|
timeoutMs = 2000,
|
|
107
115
|
): Promise<void> {
|
|
108
116
|
await waitFor(
|
|
109
|
-
() =>
|
|
117
|
+
() =>
|
|
118
|
+
assistantEventHub.getMostRecentClientByCapability("host_browser") != null,
|
|
110
119
|
timeoutMs,
|
|
111
120
|
);
|
|
112
121
|
}
|
|
@@ -124,8 +133,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
124
133
|
const db = getDb();
|
|
125
134
|
db.run("DELETE FROM contact_channels");
|
|
126
135
|
db.run("DELETE FROM contacts");
|
|
127
|
-
|
|
128
|
-
__resetChromeExtensionRegistryForTests();
|
|
136
|
+
HostBrowserProxy.reset();
|
|
129
137
|
__resetBrowserSessionEventsForTests();
|
|
130
138
|
|
|
131
139
|
// Pick a non-colliding port in the same band as the other
|
|
@@ -139,8 +147,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
139
147
|
|
|
140
148
|
afterEach(async () => {
|
|
141
149
|
await server?.stop();
|
|
142
|
-
|
|
143
|
-
__resetChromeExtensionRegistryForTests();
|
|
150
|
+
HostBrowserProxy.reset();
|
|
144
151
|
__resetBrowserSessionEventsForTests();
|
|
145
152
|
resetCapabilityTokenSecretForTests();
|
|
146
153
|
});
|
|
@@ -154,6 +161,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
154
161
|
const mockExt = createMockChromeExtension({
|
|
155
162
|
runtimeBaseUrl,
|
|
156
163
|
token,
|
|
164
|
+
sseToken: mintSseToken(guardianId),
|
|
157
165
|
resultTransport: "ws",
|
|
158
166
|
});
|
|
159
167
|
await mockExt.start();
|
|
@@ -195,6 +203,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
195
203
|
const mockExt = createMockChromeExtension({
|
|
196
204
|
runtimeBaseUrl,
|
|
197
205
|
token,
|
|
206
|
+
sseToken: mintSseToken(guardianId),
|
|
198
207
|
resultTransport: "ws",
|
|
199
208
|
});
|
|
200
209
|
await mockExt.start();
|
|
@@ -224,6 +233,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
224
233
|
const mockExt = createMockChromeExtension({
|
|
225
234
|
runtimeBaseUrl,
|
|
226
235
|
token,
|
|
236
|
+
sseToken: mintSseToken(guardianId),
|
|
227
237
|
resultTransport: "ws",
|
|
228
238
|
});
|
|
229
239
|
await mockExt.start();
|
|
@@ -301,37 +311,21 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
301
311
|
const mockExt = createMockChromeExtension({
|
|
302
312
|
runtimeBaseUrl,
|
|
303
313
|
token,
|
|
314
|
+
sseToken: mintSseToken(guardianId),
|
|
304
315
|
resultTransport: "ws",
|
|
305
316
|
});
|
|
306
317
|
await mockExt.start();
|
|
307
318
|
await mockExt.waitForConnection();
|
|
308
319
|
await waitForRegistryEntry(guardianId);
|
|
309
320
|
|
|
310
|
-
// Grab the initial timestamps so we can verify that keepalive
|
|
311
|
-
// bumps lastKeepaliveAt but NOT lastActiveAt (routing field).
|
|
312
|
-
const connBefore = getChromeExtensionRegistry().get(guardianId)!;
|
|
313
|
-
const lastActiveBefore = connBefore.lastActiveAt;
|
|
314
|
-
|
|
315
|
-
// Small delay to ensure Date.now() advances at least 1ms.
|
|
316
|
-
await new Promise((r) => setTimeout(r, 15));
|
|
317
|
-
|
|
318
321
|
// Send a keepalive frame (the extension sends these periodically
|
|
319
322
|
// to prevent the runtime from considering the connection stale).
|
|
320
323
|
// The frame may contain extra keys (e.g. timestamp) that the
|
|
321
324
|
// runtime should silently ignore (lenient validation).
|
|
322
325
|
mockExt.sendRaw(JSON.stringify({ type: "keepalive", ts: Date.now() }));
|
|
323
326
|
|
|
324
|
-
//
|
|
325
|
-
|
|
326
|
-
await waitFor(() => {
|
|
327
|
-
const conn = getChromeExtensionRegistry().get(guardianId);
|
|
328
|
-
return conn !== undefined && (conn.lastKeepaliveAt ?? 0) > 0;
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
const connAfter = getChromeExtensionRegistry().get(guardianId)!;
|
|
332
|
-
expect(connAfter.lastKeepaliveAt).toBeGreaterThan(0);
|
|
333
|
-
// lastActiveAt must remain unchanged — keepalives must not affect routing.
|
|
334
|
-
expect(connAfter.lastActiveAt).toBe(lastActiveBefore);
|
|
327
|
+
// Small delay to let the keepalive frame process.
|
|
328
|
+
await new Promise((r) => setTimeout(r, 15));
|
|
335
329
|
|
|
336
330
|
// Verify the socket is still alive by sending a normal host_browser_event
|
|
337
331
|
// frame after the keepalive — if the socket had been torn down, this
|
|
@@ -356,6 +350,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
356
350
|
const mockExt = createMockChromeExtension({
|
|
357
351
|
runtimeBaseUrl,
|
|
358
352
|
token,
|
|
353
|
+
sseToken: mintSseToken(guardianId),
|
|
359
354
|
resultTransport: "ws",
|
|
360
355
|
});
|
|
361
356
|
await mockExt.start();
|
|
@@ -404,6 +399,7 @@ describe("host_browser WS event + invalidation e2e", () => {
|
|
|
404
399
|
const mockExt = createMockChromeExtension({
|
|
405
400
|
runtimeBaseUrl,
|
|
406
401
|
token,
|
|
402
|
+
sseToken: mintSseToken(guardianId),
|
|
407
403
|
resultTransport: "ws",
|
|
408
404
|
});
|
|
409
405
|
await mockExt.start();
|
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
import { afterEach, describe, expect, jest, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { afterEach, describe, expect, jest, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
const sentMessages: unknown[] = [];
|
|
4
|
+
const resolvedInteractionIds: string[] = [];
|
|
5
|
+
let mockHasClient = false;
|
|
6
|
+
|
|
7
|
+
mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
8
|
+
broadcastMessage: (msg: unknown) => sentMessages.push(msg),
|
|
9
|
+
assistantEventHub: {
|
|
10
|
+
getMostRecentClientByCapability: (cap: string) =>
|
|
11
|
+
cap === "host_cu" && mockHasClient ? { id: "mock-client" } : null,
|
|
12
|
+
},
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
mock.module("../runtime/pending-interactions.js", () => ({
|
|
16
|
+
resolve: (requestId: string) => {
|
|
17
|
+
resolvedInteractionIds.push(requestId);
|
|
18
|
+
return undefined;
|
|
19
|
+
},
|
|
20
|
+
get: () => undefined,
|
|
21
|
+
getByKind: () => [],
|
|
22
|
+
getByConversation: () => [],
|
|
23
|
+
removeByConversation: () => {},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
const { HostCuProxy } = await import("../daemon/host-cu-proxy.js");
|
|
4
27
|
|
|
5
28
|
describe("HostCuProxy", () => {
|
|
6
29
|
let proxy: InstanceType<typeof HostCuProxy>;
|
|
7
|
-
let sentMessages: unknown[];
|
|
8
|
-
let sendToClient: (msg: unknown) => void;
|
|
9
|
-
let resolvedRequestIds: string[];
|
|
10
30
|
|
|
11
31
|
function setup(maxSteps?: number) {
|
|
12
|
-
sentMessages =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
proxy = new HostCuProxy(
|
|
16
|
-
sendToClient as never,
|
|
17
|
-
(requestId: string) => resolvedRequestIds.push(requestId),
|
|
18
|
-
maxSteps,
|
|
19
|
-
);
|
|
32
|
+
sentMessages.length = 0;
|
|
33
|
+
resolvedInteractionIds.length = 0;
|
|
34
|
+
mockHasClient = false;
|
|
35
|
+
proxy = new HostCuProxy(maxSteps);
|
|
20
36
|
}
|
|
21
37
|
|
|
22
38
|
afterEach(() => {
|
|
@@ -888,87 +904,54 @@ describe("HostCuProxy", () => {
|
|
|
888
904
|
});
|
|
889
905
|
|
|
890
906
|
// -------------------------------------------------------------------------
|
|
891
|
-
//
|
|
907
|
+
// pendingInteractions.resolve callback
|
|
892
908
|
// -------------------------------------------------------------------------
|
|
893
909
|
|
|
894
|
-
describe("
|
|
895
|
-
test("
|
|
896
|
-
|
|
897
|
-
resolvedRequestIds = [];
|
|
898
|
-
const throwingSend = () => {
|
|
899
|
-
throw new Error("transport down");
|
|
900
|
-
};
|
|
901
|
-
proxy = new HostCuProxy(throwingSend as never, (requestId: string) =>
|
|
902
|
-
resolvedRequestIds.push(requestId),
|
|
903
|
-
);
|
|
910
|
+
describe("pendingInteractions.resolve callback", () => {
|
|
911
|
+
test("fires when abort signal fires", async () => {
|
|
912
|
+
setup();
|
|
904
913
|
|
|
905
|
-
|
|
906
|
-
// executor. A throw there surfaces as a rejected promise.
|
|
914
|
+
const controller = new AbortController();
|
|
907
915
|
const resultPromise = proxy.request(
|
|
908
916
|
"computer_use_click",
|
|
909
917
|
{ element_id: 1 },
|
|
910
918
|
"session-1",
|
|
911
919
|
1,
|
|
920
|
+
undefined,
|
|
921
|
+
controller.signal,
|
|
912
922
|
);
|
|
913
923
|
|
|
914
|
-
|
|
924
|
+
const sent = sentMessages[0] as Record<string, unknown>;
|
|
925
|
+
const requestId = sent.requestId as string;
|
|
915
926
|
|
|
916
|
-
|
|
917
|
-
expect(resolvedRequestIds).toHaveLength(1);
|
|
927
|
+
controller.abort();
|
|
918
928
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
// from the failed request.
|
|
922
|
-
sentMessages = [];
|
|
923
|
-
proxy.updateSender(
|
|
924
|
-
((msg: unknown) => sentMessages.push(msg)) as never,
|
|
925
|
-
true,
|
|
926
|
-
);
|
|
927
|
-
const okPromise = proxy.request(
|
|
928
|
-
"computer_use_click",
|
|
929
|
-
{ element_id: 2 },
|
|
930
|
-
"session-1",
|
|
931
|
-
2,
|
|
932
|
-
);
|
|
933
|
-
expect(sentMessages).toHaveLength(1);
|
|
934
|
-
const okRequestId = (sentMessages[0] as Record<string, unknown>)
|
|
935
|
-
.requestId as string;
|
|
936
|
-
expect(proxy.hasPendingRequest(okRequestId)).toBe(true);
|
|
937
|
-
proxy.resolve(okRequestId, { axTree: "Button [2]" });
|
|
938
|
-
const okResult = await okPromise;
|
|
939
|
-
expect(okResult.isError).toBe(false);
|
|
940
|
-
expect(okResult.content).toContain("Button [2]");
|
|
929
|
+
await resultPromise;
|
|
930
|
+
expect(resolvedInteractionIds).toContain(requestId);
|
|
941
931
|
});
|
|
942
|
-
});
|
|
943
932
|
|
|
944
|
-
|
|
945
|
-
// onInternalResolve callback
|
|
946
|
-
// -------------------------------------------------------------------------
|
|
947
|
-
|
|
948
|
-
describe("onInternalResolve", () => {
|
|
949
|
-
test("calls onInternalResolve when abort signal fires", async () => {
|
|
933
|
+
test("fires on dispose", async () => {
|
|
950
934
|
setup();
|
|
951
935
|
|
|
952
|
-
const controller = new AbortController();
|
|
953
936
|
const resultPromise = proxy.request(
|
|
954
937
|
"computer_use_click",
|
|
955
938
|
{ element_id: 1 },
|
|
956
939
|
"session-1",
|
|
957
940
|
1,
|
|
958
|
-
undefined,
|
|
959
|
-
controller.signal,
|
|
960
941
|
);
|
|
961
942
|
|
|
962
943
|
const sent = sentMessages[0] as Record<string, unknown>;
|
|
963
944
|
const requestId = sent.requestId as string;
|
|
964
945
|
|
|
965
|
-
|
|
946
|
+
proxy.dispose();
|
|
966
947
|
|
|
967
|
-
|
|
968
|
-
|
|
948
|
+
// dispose rejects pending requests — catch to avoid unhandled rejection
|
|
949
|
+
await resultPromise.catch(() => {});
|
|
950
|
+
|
|
951
|
+
expect(resolvedInteractionIds).toContain(requestId);
|
|
969
952
|
});
|
|
970
953
|
|
|
971
|
-
test("
|
|
954
|
+
test("does not fire on normal client-initiated resolve", async () => {
|
|
972
955
|
setup();
|
|
973
956
|
|
|
974
957
|
const resultPromise = proxy.request(
|
|
@@ -981,12 +964,10 @@ describe("HostCuProxy", () => {
|
|
|
981
964
|
const sent = sentMessages[0] as Record<string, unknown>;
|
|
982
965
|
const requestId = sent.requestId as string;
|
|
983
966
|
|
|
984
|
-
proxy.
|
|
985
|
-
|
|
986
|
-
// dispose rejects pending requests — catch to avoid unhandled rejection
|
|
987
|
-
await resultPromise.catch(() => {});
|
|
967
|
+
proxy.resolve(requestId, { axTree: "Button [1]" });
|
|
988
968
|
|
|
989
|
-
|
|
969
|
+
await resultPromise;
|
|
970
|
+
expect(resolvedInteractionIds).toEqual([]);
|
|
990
971
|
});
|
|
991
972
|
});
|
|
992
973
|
|
|
@@ -995,52 +976,16 @@ describe("HostCuProxy", () => {
|
|
|
995
976
|
// -------------------------------------------------------------------------
|
|
996
977
|
|
|
997
978
|
describe("isAvailable", () => {
|
|
998
|
-
test("returns false
|
|
979
|
+
test("returns false when no client with host_cu capability is connected", () => {
|
|
999
980
|
setup();
|
|
981
|
+
mockHasClient = false;
|
|
1000
982
|
expect(proxy.isAvailable()).toBe(false);
|
|
1001
983
|
});
|
|
1002
984
|
|
|
1003
|
-
test("returns true
|
|
985
|
+
test("returns true when a client with host_cu capability is connected", () => {
|
|
1004
986
|
setup();
|
|
1005
|
-
|
|
987
|
+
mockHasClient = true;
|
|
1006
988
|
expect(proxy.isAvailable()).toBe(true);
|
|
1007
989
|
});
|
|
1008
|
-
|
|
1009
|
-
test("returns false after updateSender with clientConnected=false", () => {
|
|
1010
|
-
setup();
|
|
1011
|
-
proxy.updateSender(sendToClient as never, true);
|
|
1012
|
-
proxy.updateSender(sendToClient as never, false);
|
|
1013
|
-
expect(proxy.isAvailable()).toBe(false);
|
|
1014
|
-
});
|
|
1015
|
-
});
|
|
1016
|
-
|
|
1017
|
-
// -------------------------------------------------------------------------
|
|
1018
|
-
// updateSender
|
|
1019
|
-
// -------------------------------------------------------------------------
|
|
1020
|
-
|
|
1021
|
-
describe("updateSender", () => {
|
|
1022
|
-
test("uses updated sender for new requests", async () => {
|
|
1023
|
-
setup();
|
|
1024
|
-
|
|
1025
|
-
const newMessages: unknown[] = [];
|
|
1026
|
-
proxy.updateSender((msg) => newMessages.push(msg), true);
|
|
1027
|
-
|
|
1028
|
-
const resultPromise = proxy.request(
|
|
1029
|
-
"computer_use_click",
|
|
1030
|
-
{ element_id: 1 },
|
|
1031
|
-
"session-1",
|
|
1032
|
-
1,
|
|
1033
|
-
);
|
|
1034
|
-
|
|
1035
|
-
expect(sentMessages).toHaveLength(0); // Old sender not used
|
|
1036
|
-
expect(newMessages).toHaveLength(1); // New sender used
|
|
1037
|
-
|
|
1038
|
-
const sent = newMessages[0] as Record<string, unknown>;
|
|
1039
|
-
proxy.resolve(sent.requestId as string, {
|
|
1040
|
-
axTree: "Button [1]",
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
await resultPromise;
|
|
1044
|
-
});
|
|
1045
990
|
});
|
|
1046
991
|
});
|
|
@@ -1,4 +1,27 @@
|
|
|
1
|
-
import { afterEach, describe, expect, jest, test } from "bun:test";
|
|
1
|
+
import { afterEach, describe, expect, jest, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
const sentMessages: unknown[] = [];
|
|
4
|
+
const resolvedInteractionIds: string[] = [];
|
|
5
|
+
let mockHasClient = false;
|
|
6
|
+
|
|
7
|
+
mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
8
|
+
broadcastMessage: (msg: unknown) => sentMessages.push(msg),
|
|
9
|
+
assistantEventHub: {
|
|
10
|
+
getMostRecentClientByCapability: (cap: string) =>
|
|
11
|
+
cap === "host_file" && mockHasClient ? { id: "mock-client" } : null,
|
|
12
|
+
},
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
mock.module("../runtime/pending-interactions.js", () => ({
|
|
16
|
+
resolve: (requestId: string) => {
|
|
17
|
+
resolvedInteractionIds.push(requestId);
|
|
18
|
+
return undefined;
|
|
19
|
+
},
|
|
20
|
+
get: () => undefined,
|
|
21
|
+
getByKind: () => [],
|
|
22
|
+
getByConversation: () => [],
|
|
23
|
+
removeByConversation: () => {},
|
|
24
|
+
}));
|
|
2
25
|
|
|
3
26
|
const { HostFileProxy } = await import("../daemon/host-file-proxy.js");
|
|
4
27
|
|
|
@@ -10,17 +33,17 @@ const PNG_HEADER = Buffer.from([
|
|
|
10
33
|
|
|
11
34
|
describe("HostFileProxy", () => {
|
|
12
35
|
let proxy: InstanceType<typeof HostFileProxy>;
|
|
13
|
-
let sentMessages: unknown[];
|
|
14
|
-
let sendToClient: (msg: unknown) => void;
|
|
15
36
|
|
|
16
|
-
function setup(
|
|
17
|
-
sentMessages =
|
|
18
|
-
|
|
19
|
-
|
|
37
|
+
function setup() {
|
|
38
|
+
sentMessages.length = 0;
|
|
39
|
+
resolvedInteractionIds.length = 0;
|
|
40
|
+
mockHasClient = false;
|
|
41
|
+
proxy = new (HostFileProxy as any)();
|
|
20
42
|
}
|
|
21
43
|
|
|
22
44
|
afterEach(() => {
|
|
23
45
|
proxy?.dispose();
|
|
46
|
+
HostFileProxy.reset();
|
|
24
47
|
});
|
|
25
48
|
|
|
26
49
|
describe("request/resolve lifecycle (happy path)", () => {
|
|
@@ -271,24 +294,17 @@ describe("HostFileProxy", () => {
|
|
|
271
294
|
});
|
|
272
295
|
|
|
273
296
|
describe("isAvailable", () => {
|
|
274
|
-
test("returns false
|
|
297
|
+
test("returns false when no client with host_file capability is connected", () => {
|
|
275
298
|
setup();
|
|
299
|
+
mockHasClient = false;
|
|
276
300
|
expect(proxy.isAvailable()).toBe(false);
|
|
277
301
|
});
|
|
278
302
|
|
|
279
|
-
test("returns true
|
|
303
|
+
test("returns true when a client with host_file capability is connected", () => {
|
|
280
304
|
setup();
|
|
281
|
-
|
|
305
|
+
mockHasClient = true;
|
|
282
306
|
expect(proxy.isAvailable()).toBe(true);
|
|
283
307
|
});
|
|
284
|
-
|
|
285
|
-
test("returns false after updateSender with clientConnected=false", () => {
|
|
286
|
-
setup();
|
|
287
|
-
proxy.updateSender(sendToClient, true);
|
|
288
|
-
expect(proxy.isAvailable()).toBe(true);
|
|
289
|
-
proxy.updateSender(sendToClient, false);
|
|
290
|
-
expect(proxy.isAvailable()).toBe(false);
|
|
291
|
-
});
|
|
292
308
|
});
|
|
293
309
|
|
|
294
310
|
describe("dispose", () => {
|
|
@@ -377,34 +393,6 @@ describe("HostFileProxy", () => {
|
|
|
377
393
|
});
|
|
378
394
|
});
|
|
379
395
|
|
|
380
|
-
describe("updateSender", () => {
|
|
381
|
-
test("uses updated sender for new requests", async () => {
|
|
382
|
-
setup();
|
|
383
|
-
|
|
384
|
-
const newMessages: unknown[] = [];
|
|
385
|
-
proxy.updateSender((msg) => newMessages.push(msg), true);
|
|
386
|
-
|
|
387
|
-
const resultPromise = proxy.request(
|
|
388
|
-
{
|
|
389
|
-
operation: "read",
|
|
390
|
-
path: "/tmp/test.txt",
|
|
391
|
-
},
|
|
392
|
-
"session-1",
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
expect(sentMessages).toHaveLength(0); // Old sender not used
|
|
396
|
-
expect(newMessages).toHaveLength(1); // New sender used
|
|
397
|
-
|
|
398
|
-
const sent = newMessages[0] as Record<string, unknown>;
|
|
399
|
-
proxy.resolve(sent.requestId as string, {
|
|
400
|
-
content: "updated content",
|
|
401
|
-
isError: false,
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
await resultPromise;
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
|
|
408
396
|
describe("resolve with unknown requestId", () => {
|
|
409
397
|
test("silently ignores unknown requestId", () => {
|
|
410
398
|
setup();
|
|
@@ -522,49 +510,9 @@ describe("HostFileProxy", () => {
|
|
|
522
510
|
});
|
|
523
511
|
});
|
|
524
512
|
|
|
525
|
-
describe("
|
|
526
|
-
test("rejects the promise, clears pending state and timer, invokes onInternalResolve", async () => {
|
|
527
|
-
const resolvedIds: string[] = [];
|
|
528
|
-
sentMessages = [];
|
|
529
|
-
sendToClient = () => {
|
|
530
|
-
throw new Error("transport down");
|
|
531
|
-
};
|
|
532
|
-
proxy = new HostFileProxy(sendToClient, (id) => resolvedIds.push(id));
|
|
533
|
-
|
|
534
|
-
const resultPromise = proxy.request(
|
|
535
|
-
{ operation: "read", path: "/tmp/test.txt" },
|
|
536
|
-
"session-1",
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
await expect(resultPromise).rejects.toThrow("transport down");
|
|
540
|
-
|
|
541
|
-
// The internal resolve should fire exactly once as part of cleanup.
|
|
542
|
-
expect(resolvedIds).toHaveLength(1);
|
|
543
|
-
|
|
544
|
-
// Issue a new request on a fresh (non-throwing) sender and verify
|
|
545
|
-
// the proxy is still functional — no stale timers or bookkeeping
|
|
546
|
-
// from the failed request.
|
|
547
|
-
sentMessages = [];
|
|
548
|
-
proxy.updateSender((msg) => sentMessages.push(msg), true);
|
|
549
|
-
const okPromise = proxy.request(
|
|
550
|
-
{ operation: "read", path: "/tmp/ok.txt" },
|
|
551
|
-
"session-1",
|
|
552
|
-
);
|
|
553
|
-
expect(sentMessages).toHaveLength(1);
|
|
554
|
-
const okRequestId = (sentMessages[0] as Record<string, unknown>)
|
|
555
|
-
.requestId as string;
|
|
556
|
-
expect(proxy.hasPendingRequest(okRequestId)).toBe(true);
|
|
557
|
-
proxy.resolve(okRequestId, { content: "ok", isError: false });
|
|
558
|
-
const okResult = await okPromise;
|
|
559
|
-
expect(okResult.content).toBe("ok");
|
|
560
|
-
expect(okResult.isError).toBe(false);
|
|
561
|
-
});
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
describe("onInternalResolve callback", () => {
|
|
513
|
+
describe("pendingInteractions.resolve callback", () => {
|
|
565
514
|
test("fires on abort", async () => {
|
|
566
|
-
|
|
567
|
-
setup((id) => resolvedIds.push(id));
|
|
515
|
+
setup();
|
|
568
516
|
|
|
569
517
|
const controller = new AbortController();
|
|
570
518
|
const resultPromise = proxy.request(
|
|
@@ -582,12 +530,11 @@ describe("HostFileProxy", () => {
|
|
|
582
530
|
controller.abort();
|
|
583
531
|
await resultPromise;
|
|
584
532
|
|
|
585
|
-
expect(
|
|
533
|
+
expect(resolvedInteractionIds).toContain(requestId);
|
|
586
534
|
});
|
|
587
535
|
|
|
588
536
|
test("fires for each pending request on dispose", () => {
|
|
589
|
-
|
|
590
|
-
setup((id) => resolvedIds.push(id));
|
|
537
|
+
setup();
|
|
591
538
|
|
|
592
539
|
// Create two pending requests and catch rejections from dispose
|
|
593
540
|
const p1 = proxy.request(
|
|
@@ -614,14 +561,13 @@ describe("HostFileProxy", () => {
|
|
|
614
561
|
|
|
615
562
|
proxy.dispose();
|
|
616
563
|
|
|
617
|
-
expect(
|
|
618
|
-
expect(
|
|
619
|
-
expect(
|
|
564
|
+
expect(resolvedInteractionIds).toHaveLength(2);
|
|
565
|
+
expect(resolvedInteractionIds).toContain(ids[0]);
|
|
566
|
+
expect(resolvedInteractionIds).toContain(ids[1]);
|
|
620
567
|
});
|
|
621
568
|
|
|
622
569
|
test("does not fire on normal client-initiated resolve", async () => {
|
|
623
|
-
|
|
624
|
-
setup((id) => resolvedIds.push(id));
|
|
570
|
+
setup();
|
|
625
571
|
|
|
626
572
|
const resultPromise = proxy.request(
|
|
627
573
|
{
|
|
@@ -634,14 +580,14 @@ describe("HostFileProxy", () => {
|
|
|
634
580
|
const sent = sentMessages[0] as Record<string, unknown>;
|
|
635
581
|
const requestId = sent.requestId as string;
|
|
636
582
|
|
|
637
|
-
// Normal resolve from client — should NOT trigger
|
|
583
|
+
// Normal resolve from client — should NOT trigger pendingInteractions.resolve
|
|
638
584
|
proxy.resolve(requestId, {
|
|
639
585
|
content: "file contents",
|
|
640
586
|
isError: false,
|
|
641
587
|
});
|
|
642
588
|
|
|
643
589
|
await resultPromise;
|
|
644
|
-
expect(
|
|
590
|
+
expect(resolvedInteractionIds).toEqual([]);
|
|
645
591
|
});
|
|
646
592
|
});
|
|
647
593
|
});
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import { mkdirSync, mkdtempSync, 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 { HostFileInput } from "../daemon/host-file-proxy.js";
|
|
7
|
+
import type { ToolExecutionResult } from "../tools/types.js";
|
|
8
|
+
|
|
9
|
+
// Mock HostFileProxy singleton so proxy delegation tests can control it.
|
|
10
|
+
let mockFileProxyAvailable = false;
|
|
11
|
+
let mockFileProxyRequestFn: (
|
|
12
|
+
input: HostFileInput,
|
|
13
|
+
conversationId: string,
|
|
14
|
+
signal?: AbortSignal,
|
|
15
|
+
) => Promise<ToolExecutionResult> = () => Promise.resolve({ content: "", isError: false });
|
|
16
|
+
|
|
17
|
+
mock.module("../daemon/host-file-proxy.js", () => ({
|
|
18
|
+
HostFileProxy: {
|
|
19
|
+
get instance() {
|
|
20
|
+
return {
|
|
21
|
+
isAvailable: () => mockFileProxyAvailable,
|
|
22
|
+
request: mockFileProxyRequestFn,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
|
|
7
28
|
import { hostFileReadTool } from "../tools/host-filesystem/read.js";
|
|
8
29
|
import type { ToolContext } from "../tools/types.js";
|
|
9
30
|
|
|
@@ -27,6 +48,8 @@ afterEach(() => {
|
|
|
27
48
|
for (const dir of testDirs.splice(0)) {
|
|
28
49
|
rmSync(dir, { recursive: true, force: true });
|
|
29
50
|
}
|
|
51
|
+
mockFileProxyAvailable = false;
|
|
52
|
+
mockFileProxyRequestFn = () => Promise.resolve({ content: "", isError: false });
|
|
30
53
|
});
|
|
31
54
|
|
|
32
55
|
// Minimal valid JPEG: FF D8 FF E0 header
|
|
@@ -172,28 +195,26 @@ describe("host_file_read image support", () => {
|
|
|
172
195
|
conversationId: string;
|
|
173
196
|
signal?: AbortSignal;
|
|
174
197
|
}> = [];
|
|
198
|
+
mockFileProxyAvailable = true;
|
|
199
|
+
mockFileProxyRequestFn = async (input, conversationId, signal) => {
|
|
200
|
+
requests.push({ input, conversationId, signal });
|
|
201
|
+
return {
|
|
202
|
+
content: "Image loaded: /host/screenshot.png",
|
|
203
|
+
isError: false,
|
|
204
|
+
contentBlocks: [
|
|
205
|
+
{
|
|
206
|
+
type: "image",
|
|
207
|
+
source: {
|
|
208
|
+
type: "base64",
|
|
209
|
+
media_type: "image/png",
|
|
210
|
+
data: PNG_HEADER.toString("base64"),
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
};
|
|
175
216
|
const proxyContext: ToolContext = {
|
|
176
217
|
...makeContext(),
|
|
177
|
-
hostFileProxy: {
|
|
178
|
-
isAvailable: () => true,
|
|
179
|
-
request: async (input, conversationId, signal) => {
|
|
180
|
-
requests.push({ input, conversationId, signal });
|
|
181
|
-
return {
|
|
182
|
-
content: "Image loaded: /host/screenshot.png",
|
|
183
|
-
isError: false,
|
|
184
|
-
contentBlocks: [
|
|
185
|
-
{
|
|
186
|
-
type: "image",
|
|
187
|
-
source: {
|
|
188
|
-
type: "base64",
|
|
189
|
-
media_type: "image/png",
|
|
190
|
-
data: PNG_HEADER.toString("base64"),
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
};
|
|
195
|
-
},
|
|
196
|
-
} as ToolContext["hostFileProxy"],
|
|
197
218
|
};
|
|
198
219
|
|
|
199
220
|
const result = await hostFileReadTool.execute(
|