@vellumai/assistant 0.4.46 → 0.4.49
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 +7 -7
- package/README.md +2 -23
- package/docs/architecture/integrations.md +45 -41
- package/docs/architecture/keychain-broker.md +3 -3
- package/docs/architecture/security.md +5 -5
- package/docs/runbook-trusted-contacts.md +3 -8
- package/hook-templates/debug-prompt-logger/hook.json +1 -1
- package/hook-templates/debug-prompt-logger/run.sh +1 -3
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +0 -1
- package/src/__tests__/anthropic-provider.test.ts +156 -0
- package/src/__tests__/approval-cascade.test.ts +810 -0
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-attachments.test.ts +12 -34
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
- package/src/__tests__/browser-fill-credential.test.ts +5 -2
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -1
- package/src/__tests__/channel-guardian.test.ts +0 -2
- package/src/__tests__/channel-readiness-routes.test.ts +35 -25
- package/src/__tests__/channel-readiness-service.test.ts +10 -9
- package/src/__tests__/checker.test.ts +9 -29
- package/src/__tests__/cli.test.ts +23 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-tools.test.ts +2 -19
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-image-dimensions.test.ts +332 -0
- package/src/__tests__/context-token-estimator.test.ts +196 -13
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +144 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +23 -22
- package/src/__tests__/credential-broker-server-use.test.ts +22 -21
- package/src/__tests__/credential-broker.test.ts +2 -1
- package/src/__tests__/credential-metadata-store.test.ts +239 -26
- package/src/__tests__/credential-resolve.test.ts +5 -4
- package/src/__tests__/credential-security-e2e.test.ts +8 -8
- package/src/__tests__/credential-security-invariants.test.ts +111 -7
- package/src/__tests__/credential-vault-unit.test.ts +287 -54
- package/src/__tests__/credential-vault.test.ts +406 -12
- package/src/__tests__/credentials-cli.test.ts +82 -6
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +4 -2
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-image-service.test.ts +75 -45
- package/src/__tests__/gemini-provider.test.ts +9 -6
- package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -33
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -20
- package/src/__tests__/guardian-action-followup-executor.test.ts +1 -28
- package/src/__tests__/guardian-action-followup-store.test.ts +1 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-grant-minting.test.ts +35 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- package/src/__tests__/host-cu-proxy.test.ts +629 -0
- package/src/__tests__/host-shell-tool.test.ts +27 -15
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/ingress-url-consistency.test.ts +14 -21
- package/src/__tests__/integration-status.test.ts +38 -25
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +10 -9
- package/src/__tests__/keychain-broker-client.test.ts +11 -43
- package/src/__tests__/managed-proxy-context.test.ts +5 -3
- package/src/__tests__/media-generate-image.test.ts +63 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +7 -3
- package/src/__tests__/messaging-send-tool.test.ts +4 -6
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/oauth-cli.test.ts +373 -14
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/oauth-store.test.ts +756 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +0 -1
- package/src/__tests__/provider-fail-open-selection.test.ts +3 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +70 -6
- package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +15 -21
- package/src/__tests__/recording-handler.test.ts +3 -4
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/runtime-events-sse.test.ts +55 -7
- package/src/__tests__/schedule-store.test.ts +0 -1
- package/src/__tests__/scheduler-recurrence.test.ts +0 -1
- package/src/__tests__/schema-transforms.test.ts +226 -0
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/script-proxy-injection-runtime.test.ts +23 -13
- package/src/__tests__/script-proxy-policy-runtime.test.ts +1 -1
- package/src/__tests__/script-proxy-session-manager.test.ts +1 -1
- package/src/__tests__/secret-ingress-handler.test.ts +0 -1
- package/src/__tests__/secret-onetime-send.test.ts +5 -3
- package/src/__tests__/send-endpoint-busy.test.ts +21 -6
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/session-init.benchmark.test.ts +4 -5
- package/src/__tests__/session-messaging-secret-redirect.test.ts +5 -4
- package/src/__tests__/skill-include-graph.test.ts +66 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-load-tool.test.ts +149 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skills-uninstall.test.ts +3 -3
- package/src/__tests__/skills.test.ts +3 -12
- package/src/__tests__/slack-channel-config.test.ts +76 -11
- package/src/__tests__/slack-share-routes.test.ts +17 -14
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -0
- package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
- package/src/__tests__/terminal-tools.test.ts +4 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
- package/src/__tests__/trust-store.test.ts +1 -22
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +2 -1
- package/src/__tests__/twilio-provider.test.ts +4 -2
- package/src/__tests__/twilio-routes.test.ts +5 -20
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/agent/ax-tree-compaction.test.ts +235 -0
- package/src/agent/loop.ts +76 -130
- package/src/calls/call-domain.ts +8 -10
- package/src/calls/relay-server.ts +9 -13
- package/src/calls/twilio-config.ts +4 -8
- package/src/calls/twilio-provider.ts +2 -1
- package/src/calls/twilio-rest.ts +2 -1
- package/src/calls/twilio-routes.ts +1 -2
- package/src/calls/voice-ingress-preflight.ts +1 -1
- package/src/cli/commands/browser-relay.ts +46 -15
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/credentials.ts +110 -23
- package/src/cli/commands/oauth/apps.ts +255 -0
- package/src/cli/commands/oauth/connections.ts +299 -0
- package/src/cli/commands/oauth/index.ts +52 -0
- package/src/cli/commands/oauth/providers.ts +242 -0
- package/src/cli/commands/skills.ts +4 -338
- package/src/cli/program.ts +1 -5
- package/src/cli/reference.ts +1 -3
- package/src/cli.ts +3 -2
- package/src/config/assistant-feature-flags.ts +0 -3
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -4
- package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +22 -4
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +29 -32
- package/src/config/bundled-skills/gmail/SKILL.md +4 -4
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +54 -61
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +25 -28
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +14 -17
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +39 -44
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +61 -58
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +50 -49
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +11 -13
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +148 -146
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +175 -173
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +71 -76
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +32 -38
- package/src/config/bundled-skills/google-calendar/SKILL.md +2 -2
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +90 -44
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +9 -10
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +5 -6
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +4 -5
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +14 -15
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +37 -37
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +4 -9
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +24 -3
- package/src/config/bundled-skills/messaging/SKILL.md +6 -6
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +62 -63
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +15 -16
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +6 -7
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +14 -15
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +128 -128
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +33 -34
- package/src/config/bundled-skills/messaging/tools/shared.ts +12 -15
- package/src/config/bundled-skills/settings/SKILL.md +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +2 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
- package/src/config/bundled-skills/slack/tools/shared.ts +4 -10
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +15 -16
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +95 -92
- package/src/config/env-registry.ts +14 -83
- package/src/config/env.ts +11 -50
- package/src/config/feature-flag-registry.json +16 -16
- package/src/config/schema.ts +3 -1
- package/src/config/skills.ts +21 -2
- package/src/context/image-dimensions.ts +229 -0
- package/src/context/token-estimator.ts +75 -12
- package/src/context/window-manager.ts +49 -10
- package/src/daemon/assistant-attachments.ts +1 -13
- package/src/daemon/guardian-action-generators.ts +4 -5
- package/src/daemon/handlers/config-ingress.ts +8 -33
- package/src/daemon/handlers/config-slack-channel.ts +76 -56
- package/src/daemon/handlers/config-telegram.ts +53 -24
- package/src/daemon/handlers/sessions.ts +10 -24
- package/src/daemon/handlers/shared.ts +0 -130
- package/src/daemon/host-cu-proxy.ts +401 -0
- package/src/daemon/lifecycle.ts +39 -63
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/computer-use.ts +2 -119
- package/src/daemon/message-types/host-cu.ts +19 -0
- package/src/daemon/message-types/integrations.ts +1 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/server.ts +14 -21
- package/src/daemon/session-agent-loop-handlers.ts +2 -0
- package/src/daemon/session-attachments.ts +1 -2
- package/src/daemon/session-messaging.ts +3 -1
- package/src/daemon/session-slash.ts +1 -1
- package/src/daemon/session-surfaces.ts +40 -28
- package/src/daemon/session-tool-setup.ts +20 -11
- package/src/daemon/session.ts +139 -16
- package/src/daemon/tool-side-effects.ts +2 -8
- package/src/daemon/watch-handler.ts +2 -2
- package/src/email/providers/index.ts +2 -1
- package/src/events/tool-metrics-listener.ts +2 -2
- package/src/hooks/manager.ts +1 -4
- package/src/inbound/public-ingress-urls.ts +7 -7
- package/src/instrument.ts +15 -1
- package/src/logfire.ts +16 -5
- package/src/media/app-icon-generator.ts +30 -4
- package/src/media/avatar-router.ts +26 -3
- package/src/media/gemini-image-service.ts +28 -2
- package/src/memory/conversation-key-store.ts +21 -0
- package/src/memory/db-init.ts +4 -0
- package/src/memory/guardian-action-store.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +60 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/schema/guardian.ts +1 -1
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/oauth.ts +65 -0
- package/src/messaging/provider.ts +19 -13
- package/src/messaging/providers/gmail/adapter.ts +40 -23
- package/src/messaging/providers/gmail/client.ts +283 -122
- package/src/messaging/providers/gmail/people-client.ts +32 -24
- package/src/messaging/providers/slack/adapter.ts +29 -19
- package/src/messaging/providers/slack/client.ts +265 -78
- package/src/messaging/providers/telegram-bot/adapter.ts +19 -18
- package/src/messaging/providers/whatsapp/adapter.ts +17 -11
- package/src/messaging/registry.ts +2 -31
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/signal.ts +4 -5
- package/src/oauth/byo-connection.test.ts +537 -0
- package/src/oauth/byo-connection.ts +128 -0
- package/src/oauth/connect-orchestrator.ts +139 -56
- package/src/oauth/connect-types.ts +17 -23
- package/src/oauth/connection-resolver.ts +58 -0
- package/src/oauth/connection.ts +38 -0
- package/src/oauth/manual-token-connection.ts +104 -0
- package/src/oauth/oauth-store.ts +496 -0
- package/src/oauth/platform-connection.test.ts +192 -0
- package/src/oauth/platform-connection.ts +111 -0
- package/src/oauth/provider-behaviors.ts +124 -0
- package/src/oauth/scope-policy.ts +9 -2
- package/src/oauth/seed-providers.ts +161 -0
- package/src/oauth/token-persistence.ts +74 -78
- package/src/permissions/checker.ts +8 -4
- package/src/permissions/defaults.ts +0 -1
- package/src/permissions/prompter.ts +10 -1
- package/src/permissions/trust-store.ts +13 -0
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
- package/src/prompts/system-prompt.ts +70 -45
- package/src/providers/anthropic/client.ts +133 -24
- package/src/providers/gemini/client.ts +15 -6
- package/src/providers/managed-proxy/constants.ts +2 -2
- package/src/providers/managed-proxy/context.ts +5 -1
- package/src/providers/ratelimit.ts +17 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +1 -27
- package/src/runtime/AGENTS.md +17 -0
- package/src/runtime/auth/route-policy.ts +0 -3
- package/src/runtime/channel-invite-transports/telegram.ts +2 -1
- package/src/runtime/channel-readiness-service.ts +168 -195
- package/src/runtime/channel-readiness-types.ts +4 -0
- package/src/runtime/channel-reply-delivery.ts +0 -40
- package/src/runtime/gateway-client.ts +0 -7
- package/src/runtime/guardian-action-conversation-turn.ts +1 -3
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-action-message-composer.ts +3 -23
- package/src/runtime/http-server.ts +17 -10
- package/src/runtime/http-types.ts +2 -3
- package/src/runtime/middleware/rate-limiter.ts +74 -20
- package/src/runtime/middleware/twilio-validation.ts +1 -11
- package/src/runtime/pending-interactions.ts +14 -12
- package/src/runtime/routes/channel-delivery-routes.ts +0 -1
- package/src/runtime/routes/channel-readiness-routes.ts +2 -0
- package/src/runtime/routes/conversation-routes.ts +73 -19
- package/src/runtime/routes/diagnostics-routes.ts +11 -9
- package/src/runtime/routes/events-routes.ts +21 -11
- package/src/runtime/routes/guardian-approval-interception.ts +20 -5
- package/src/runtime/routes/host-cu-routes.ts +97 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
- package/src/runtime/routes/integrations/slack/share.ts +6 -6
- package/src/runtime/routes/integrations/twilio.ts +6 -5
- package/src/runtime/routes/log-export-routes.ts +126 -8
- package/src/runtime/routes/secret-routes.ts +3 -2
- package/src/runtime/routes/settings-routes.ts +113 -48
- package/src/runtime/routes/surface-action-routes.ts +1 -1
- package/src/runtime/routes/watch-routes.ts +128 -0
- package/src/schedule/integration-status.ts +10 -8
- package/src/security/credential-key.ts +14 -0
- package/src/security/keychain-broker-client.ts +5 -6
- package/src/security/oauth2.ts +1 -1
- package/src/security/token-manager.ts +145 -43
- package/src/skills/catalog-install.ts +358 -0
- package/src/skills/include-graph.ts +32 -0
- package/src/telegram/bot-username.ts +2 -3
- package/src/tools/apps/definitions.ts +0 -5
- package/src/tools/assets/materialize.ts +0 -5
- package/src/tools/assets/search.ts +0 -5
- package/src/tools/browser/headless-browser.ts +1 -67
- package/src/tools/browser/network-recorder.ts +1 -1
- package/src/tools/browser/network-recording-types.ts +1 -1
- package/src/tools/claude-code/claude-code.ts +0 -5
- package/src/tools/computer-use/definitions.ts +46 -11
- package/src/tools/computer-use/registry.ts +4 -5
- package/src/tools/credentials/broker.ts +5 -4
- package/src/tools/credentials/metadata-store.ts +22 -74
- package/src/tools/credentials/resolve.ts +2 -1
- package/src/tools/credentials/vault.ts +139 -151
- package/src/tools/filesystem/edit.ts +1 -6
- package/src/tools/filesystem/read.ts +0 -5
- package/src/tools/filesystem/write.ts +1 -6
- package/src/tools/host-filesystem/edit.ts +1 -6
- package/src/tools/host-filesystem/read.ts +1 -6
- package/src/tools/host-filesystem/write.ts +1 -6
- package/src/tools/mcp/mcp-tool-factory.ts +18 -1
- package/src/tools/memory/definitions.ts +0 -5
- package/src/tools/network/web-fetch.ts +0 -5
- package/src/tools/network/web-search.ts +0 -5
- package/src/tools/registry.ts +2 -7
- package/src/tools/schema-transforms.ts +99 -0
- package/src/tools/skills/load.ts +62 -8
- package/src/tools/swarm/delegate.ts +0 -5
- package/src/tools/system/avatar-generator.ts +0 -5
- package/src/tools/ui-surface/definitions.ts +0 -15
- package/src/tools/watch/screen-watch.ts +0 -5
- package/src/tools/watch/watch-state.ts +0 -12
- package/src/util/logger.ts +7 -41
- package/src/util/platform.ts +9 -28
- package/src/version.ts +10 -0
- package/src/watcher/providers/github.ts +51 -52
- package/src/watcher/providers/gmail.ts +88 -80
- package/src/watcher/providers/google-calendar.ts +94 -86
- package/src/watcher/providers/linear.ts +87 -93
- package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
- package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
- package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
- package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
- package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
- package/src/cli/commands/dev.ts +0 -129
- package/src/cli/commands/map.ts +0 -391
- package/src/cli/commands/oauth.ts +0 -77
- package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -16
- package/src/daemon/computer-use-session.ts +0 -1020
- package/src/daemon/ride-shotgun-handler.ts +0 -567
- package/src/oauth/provider-profiles.ts +0 -192
- package/src/prompts/computer-use-prompt.ts +0 -98
- package/src/runtime/routes/computer-use-routes.ts +0 -641
- package/src/runtime/telegram-streaming-delivery.test.ts +0 -597
- package/src/runtime/telegram-streaming-delivery.ts +0 -383
- package/src/tools/computer-use/request-computer-control.ts +0 -61
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host computer-use proxy.
|
|
3
|
+
*
|
|
4
|
+
* Proxies computer-use actions to the desktop client when running as a
|
|
5
|
+
* managed assistant, following the same request/resolve pattern as
|
|
6
|
+
* HostBashProxy. Also owns CU-specific state tracking (step counting,
|
|
7
|
+
* loop detection, observation formatting) for the unified agent loop.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { v4 as uuid } from "uuid";
|
|
11
|
+
|
|
12
|
+
import type { ContentBlock } from "../providers/types.js";
|
|
13
|
+
import type { ToolExecutionResult } from "../tools/types.js";
|
|
14
|
+
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
15
|
+
import { getLogger } from "../util/logger.js";
|
|
16
|
+
import type { ServerMessage } from "./message-protocol.js";
|
|
17
|
+
|
|
18
|
+
const log = getLogger("host-cu-proxy");
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Constants
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
const REQUEST_TIMEOUT_SEC = 60;
|
|
25
|
+
const MAX_STEPS = 50;
|
|
26
|
+
const MAX_HISTORY_ENTRIES = 10;
|
|
27
|
+
const LOOP_DETECTION_WINDOW = 3;
|
|
28
|
+
const CONSECUTIVE_UNCHANGED_WARNING_THRESHOLD = 2;
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Types
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
export interface CuObservationResult {
|
|
35
|
+
axTree?: string;
|
|
36
|
+
axDiff?: string;
|
|
37
|
+
secondaryWindows?: string;
|
|
38
|
+
screenshot?: string; // base64 JPEG
|
|
39
|
+
screenshotWidthPx?: number;
|
|
40
|
+
screenshotHeightPx?: number;
|
|
41
|
+
screenWidthPt?: number;
|
|
42
|
+
screenHeightPt?: number;
|
|
43
|
+
executionResult?: string;
|
|
44
|
+
executionError?: string;
|
|
45
|
+
userGuidance?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ActionRecord {
|
|
49
|
+
step: number;
|
|
50
|
+
toolName: string;
|
|
51
|
+
input: Record<string, unknown>;
|
|
52
|
+
reasoning?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface PendingRequest {
|
|
56
|
+
resolve: (result: ToolExecutionResult) => void;
|
|
57
|
+
reject: (err: Error) => void;
|
|
58
|
+
timer: ReturnType<typeof setTimeout>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// HostCuProxy
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
export class HostCuProxy {
|
|
66
|
+
private pending = new Map<string, PendingRequest>();
|
|
67
|
+
private sendToClient: (msg: ServerMessage) => void;
|
|
68
|
+
private clientConnected = false;
|
|
69
|
+
|
|
70
|
+
// CU state tracking (per-conversation)
|
|
71
|
+
private _stepCount = 0;
|
|
72
|
+
private _maxSteps: number;
|
|
73
|
+
private _previousAXTree: string | undefined;
|
|
74
|
+
private _consecutiveUnchangedSteps = 0;
|
|
75
|
+
private _actionHistory: ActionRecord[] = [];
|
|
76
|
+
|
|
77
|
+
constructor(
|
|
78
|
+
sendToClient: (msg: ServerMessage) => void,
|
|
79
|
+
maxSteps = MAX_STEPS,
|
|
80
|
+
) {
|
|
81
|
+
this.sendToClient = sendToClient;
|
|
82
|
+
this._maxSteps = maxSteps;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// CU state accessors (for testing / external inspection)
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
get stepCount(): number {
|
|
90
|
+
return this._stepCount;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get maxSteps(): number {
|
|
94
|
+
return this._maxSteps;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get previousAXTree(): string | undefined {
|
|
98
|
+
return this._previousAXTree;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get consecutiveUnchangedSteps(): number {
|
|
102
|
+
return this._consecutiveUnchangedSteps;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get actionHistory(): readonly ActionRecord[] {
|
|
106
|
+
return this._actionHistory;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Sender management
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
updateSender(
|
|
114
|
+
sendToClient: (msg: ServerMessage) => void,
|
|
115
|
+
clientConnected: boolean,
|
|
116
|
+
): void {
|
|
117
|
+
this.sendToClient = sendToClient;
|
|
118
|
+
this.clientConnected = clientConnected;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Request / resolve lifecycle
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
request(
|
|
126
|
+
toolName: string,
|
|
127
|
+
input: Record<string, unknown>,
|
|
128
|
+
sessionId: string,
|
|
129
|
+
stepNumber: number,
|
|
130
|
+
reasoning?: string,
|
|
131
|
+
signal?: AbortSignal,
|
|
132
|
+
): Promise<ToolExecutionResult> {
|
|
133
|
+
if (signal?.aborted) {
|
|
134
|
+
return Promise.resolve({
|
|
135
|
+
content: "Aborted",
|
|
136
|
+
isError: true,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Enforce step limit before sending to client
|
|
141
|
+
if (this._stepCount > this._maxSteps) {
|
|
142
|
+
return Promise.resolve({
|
|
143
|
+
content: `Step limit (${this._maxSteps}) exceeded. Call computer_use_done to finish.`,
|
|
144
|
+
isError: true,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const requestId = uuid();
|
|
149
|
+
|
|
150
|
+
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
151
|
+
const timer = setTimeout(() => {
|
|
152
|
+
this.pending.delete(requestId);
|
|
153
|
+
log.warn({ requestId, toolName }, "Host CU proxy request timed out");
|
|
154
|
+
resolve({
|
|
155
|
+
content: "Host CU proxy timed out waiting for client response",
|
|
156
|
+
isError: true,
|
|
157
|
+
});
|
|
158
|
+
}, REQUEST_TIMEOUT_SEC * 1000);
|
|
159
|
+
|
|
160
|
+
this.pending.set(requestId, { resolve, reject, timer });
|
|
161
|
+
|
|
162
|
+
if (signal) {
|
|
163
|
+
const onAbort = () => {
|
|
164
|
+
if (this.pending.has(requestId)) {
|
|
165
|
+
clearTimeout(timer);
|
|
166
|
+
this.pending.delete(requestId);
|
|
167
|
+
resolve({ content: "Aborted", isError: true });
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
this.sendToClient({
|
|
174
|
+
type: "host_cu_request",
|
|
175
|
+
requestId,
|
|
176
|
+
sessionId,
|
|
177
|
+
toolName,
|
|
178
|
+
input,
|
|
179
|
+
stepNumber,
|
|
180
|
+
reasoning,
|
|
181
|
+
} as ServerMessage);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
resolve(requestId: string, observation: CuObservationResult): void {
|
|
186
|
+
const entry = this.pending.get(requestId);
|
|
187
|
+
if (!entry) {
|
|
188
|
+
log.warn({ requestId }, "No pending host CU request for response");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
clearTimeout(entry.timer);
|
|
192
|
+
this.pending.delete(requestId);
|
|
193
|
+
|
|
194
|
+
// Update CU state from observation
|
|
195
|
+
this.updateStateFromObservation(observation);
|
|
196
|
+
|
|
197
|
+
const result = this.formatObservation(observation);
|
|
198
|
+
entry.resolve(result);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
hasPendingRequest(requestId: string): boolean {
|
|
202
|
+
return this.pending.has(requestId);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// CU state management
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Increment step count and record an action. Call this before sending
|
|
211
|
+
* each non-terminal tool request.
|
|
212
|
+
*/
|
|
213
|
+
recordAction(
|
|
214
|
+
toolName: string,
|
|
215
|
+
input: Record<string, unknown>,
|
|
216
|
+
reasoning?: string,
|
|
217
|
+
): void {
|
|
218
|
+
this._stepCount++;
|
|
219
|
+
this._actionHistory.push({
|
|
220
|
+
step: this._stepCount,
|
|
221
|
+
toolName,
|
|
222
|
+
input,
|
|
223
|
+
reasoning,
|
|
224
|
+
});
|
|
225
|
+
// Keep history bounded
|
|
226
|
+
if (this._actionHistory.length > MAX_HISTORY_ENTRIES) {
|
|
227
|
+
this._actionHistory = this._actionHistory.slice(-MAX_HISTORY_ENTRIES);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Reset all CU state. Called on terminal tools (computer_use_done, etc.). */
|
|
232
|
+
reset(): void {
|
|
233
|
+
this._stepCount = 0;
|
|
234
|
+
this._previousAXTree = undefined;
|
|
235
|
+
this._consecutiveUnchangedSteps = 0;
|
|
236
|
+
this._actionHistory = [];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
// Observation formatting
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Formats a CU observation into a ToolExecutionResult with text content
|
|
245
|
+
* (AX tree wrapped in markers, diff, warnings) and optional screenshot
|
|
246
|
+
* as an image content block.
|
|
247
|
+
*/
|
|
248
|
+
formatObservation(obs: CuObservationResult): ToolExecutionResult {
|
|
249
|
+
const parts: string[] = [];
|
|
250
|
+
|
|
251
|
+
// Surface user guidance prominently so the model sees it first
|
|
252
|
+
if (obs.userGuidance) {
|
|
253
|
+
parts.push(`USER GUIDANCE: ${obs.userGuidance}`);
|
|
254
|
+
parts.push("");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (obs.executionResult) {
|
|
258
|
+
parts.push(obs.executionResult);
|
|
259
|
+
parts.push("");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// AX tree diff / unchanged warning
|
|
263
|
+
if (obs.axDiff) {
|
|
264
|
+
parts.push(obs.axDiff);
|
|
265
|
+
parts.push("");
|
|
266
|
+
} else if (this._previousAXTree != null && obs.axTree != null) {
|
|
267
|
+
// No diff means the screen didn't change
|
|
268
|
+
if (
|
|
269
|
+
this._consecutiveUnchangedSteps >=
|
|
270
|
+
CONSECUTIVE_UNCHANGED_WARNING_THRESHOLD
|
|
271
|
+
) {
|
|
272
|
+
parts.push(
|
|
273
|
+
`WARNING: ${this._consecutiveUnchangedSteps} consecutive actions had NO VISIBLE EFFECT on the UI. You MUST try a completely different approach.`,
|
|
274
|
+
);
|
|
275
|
+
} else {
|
|
276
|
+
parts.push(
|
|
277
|
+
"Your last action had NO VISIBLE EFFECT on the UI. Try something different.",
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
parts.push("");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Loop detection: identical actions repeated
|
|
284
|
+
if (this._actionHistory.length >= LOOP_DETECTION_WINDOW) {
|
|
285
|
+
const recent = this._actionHistory.slice(-LOOP_DETECTION_WINDOW);
|
|
286
|
+
const allIdentical = recent.every(
|
|
287
|
+
(r) =>
|
|
288
|
+
r.toolName === recent[0].toolName &&
|
|
289
|
+
JSON.stringify(r.input) === JSON.stringify(recent[0].input),
|
|
290
|
+
);
|
|
291
|
+
if (allIdentical) {
|
|
292
|
+
parts.push(
|
|
293
|
+
`WARNING: You've repeated the same action (${recent[0].toolName}) ${LOOP_DETECTION_WINDOW} times. Try something different.`,
|
|
294
|
+
);
|
|
295
|
+
parts.push("");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Current screen state wrapped in markers for history compaction
|
|
300
|
+
if (obs.axTree) {
|
|
301
|
+
parts.push("<ax-tree>");
|
|
302
|
+
parts.push("CURRENT SCREEN STATE:");
|
|
303
|
+
parts.push(HostCuProxy.escapeAxTreeContent(obs.axTree));
|
|
304
|
+
parts.push("</ax-tree>");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Screenshot metadata
|
|
308
|
+
const screenshotMeta = this.formatScreenshotMetadata(obs);
|
|
309
|
+
if (screenshotMeta.length > 0) {
|
|
310
|
+
parts.push("");
|
|
311
|
+
parts.push(...screenshotMeta);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const content = parts.join("\n").trim() || "Action executed";
|
|
315
|
+
|
|
316
|
+
// Build content blocks for screenshot
|
|
317
|
+
const contentBlocks: ContentBlock[] = [];
|
|
318
|
+
if (obs.screenshot) {
|
|
319
|
+
contentBlocks.push({
|
|
320
|
+
type: "image",
|
|
321
|
+
source: {
|
|
322
|
+
type: "base64",
|
|
323
|
+
media_type: "image/jpeg",
|
|
324
|
+
data: obs.screenshot,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const isError = obs.executionError != null;
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
content: isError
|
|
333
|
+
? `Action failed: ${obs.executionError}\n\n${content}`
|
|
334
|
+
: content,
|
|
335
|
+
isError,
|
|
336
|
+
...(contentBlocks.length > 0 ? { contentBlocks } : {}),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// ---------------------------------------------------------------------------
|
|
341
|
+
// Dispose
|
|
342
|
+
// ---------------------------------------------------------------------------
|
|
343
|
+
|
|
344
|
+
dispose(): void {
|
|
345
|
+
for (const [_requestId, entry] of this.pending) {
|
|
346
|
+
clearTimeout(entry.timer);
|
|
347
|
+
entry.reject(
|
|
348
|
+
new AssistantError("Host CU proxy disposed", ErrorCode.INTERNAL_ERROR),
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
this.pending.clear();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Private helpers
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
|
|
358
|
+
/** Update consecutive-unchanged tracking from an incoming observation. */
|
|
359
|
+
private updateStateFromObservation(obs: CuObservationResult): void {
|
|
360
|
+
if (this._stepCount > 0) {
|
|
361
|
+
if (
|
|
362
|
+
obs.axDiff == null &&
|
|
363
|
+
this._previousAXTree != null &&
|
|
364
|
+
obs.axTree != null
|
|
365
|
+
) {
|
|
366
|
+
this._consecutiveUnchangedSteps++;
|
|
367
|
+
} else if (obs.axDiff != null) {
|
|
368
|
+
this._consecutiveUnchangedSteps = 0;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (obs.axTree != null) {
|
|
373
|
+
this._previousAXTree = obs.axTree;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
private formatScreenshotMetadata(obs: CuObservationResult): string[] {
|
|
378
|
+
if (!obs.screenshot) return [];
|
|
379
|
+
|
|
380
|
+
const lines: string[] = [];
|
|
381
|
+
if (obs.screenshotWidthPx != null && obs.screenshotHeightPx != null) {
|
|
382
|
+
lines.push(
|
|
383
|
+
`Screenshot metadata: ${obs.screenshotWidthPx}x${obs.screenshotHeightPx} px`,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
if (obs.screenWidthPt != null && obs.screenHeightPt != null) {
|
|
387
|
+
lines.push(
|
|
388
|
+
`Screen metadata: ${obs.screenWidthPt}x${obs.screenHeightPt} pt`,
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return lines;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Escapes literal `</ax-tree>` inside AX tree content so compaction
|
|
396
|
+
* regex does not stop prematurely.
|
|
397
|
+
*/
|
|
398
|
+
static escapeAxTreeContent(content: string): string {
|
|
399
|
+
return content.replace(/<\/ax-tree>/gi, "</ax-tree>");
|
|
400
|
+
}
|
|
401
|
+
}
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
getQdrantUrlEnv,
|
|
16
16
|
getRuntimeHttpHost,
|
|
17
17
|
getRuntimeHttpPort,
|
|
18
|
+
setIngressPublicBaseUrl,
|
|
18
19
|
validateEnv,
|
|
19
20
|
} from "../config/env.js";
|
|
20
21
|
import { loadConfig } from "../config/loader.js";
|
|
@@ -22,7 +23,7 @@ import { HeartbeatService } from "../heartbeat/heartbeat-service.js";
|
|
|
22
23
|
import { getHookManager } from "../hooks/manager.js";
|
|
23
24
|
import { installTemplates } from "../hooks/templates.js";
|
|
24
25
|
import { closeSentry, initSentry } from "../instrument.js";
|
|
25
|
-
import { initLogfire } from "../logfire.js";
|
|
26
|
+
import { disableLogfire, initLogfire } from "../logfire.js";
|
|
26
27
|
import { getMcpServerManager } from "../mcp/manager.js";
|
|
27
28
|
import * as attachmentsStore from "../memory/attachments-store.js";
|
|
28
29
|
import {
|
|
@@ -40,6 +41,8 @@ import {
|
|
|
40
41
|
emitNotificationSignal,
|
|
41
42
|
registerBroadcastFn,
|
|
42
43
|
} from "../notifications/emit-signal.js";
|
|
44
|
+
import { backfillManualTokenConnections } from "../oauth/manual-token-connection.js";
|
|
45
|
+
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
43
46
|
import { ensurePromptFiles } from "../prompts/system-prompt.js";
|
|
44
47
|
import { syncUpdateBulletinOnStartup } from "../prompts/update-bulletin.js";
|
|
45
48
|
import { buildAssistantEvent } from "../runtime/assistant-event.js";
|
|
@@ -54,7 +57,6 @@ import {
|
|
|
54
57
|
import { ensureVellumGuardianBinding } from "../runtime/guardian-vellum-migration.js";
|
|
55
58
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
56
59
|
import { startScheduler } from "../schedule/scheduler.js";
|
|
57
|
-
import { watchSessions } from "../tools/watch/watch-state.js";
|
|
58
60
|
import { getLogger, initLogger } from "../util/logger.js";
|
|
59
61
|
import {
|
|
60
62
|
ensureDataDir,
|
|
@@ -94,10 +96,6 @@ import {
|
|
|
94
96
|
registerMessagingProviders,
|
|
95
97
|
registerWatcherProviders,
|
|
96
98
|
} from "./providers-setup.js";
|
|
97
|
-
import {
|
|
98
|
-
handleRideShotgunStart,
|
|
99
|
-
handleRideShotgunStop,
|
|
100
|
-
} from "./ride-shotgun-handler.js";
|
|
101
99
|
import { seedInterfaceFiles } from "./seed-files.js";
|
|
102
100
|
import { DaemonServer } from "./server.js";
|
|
103
101
|
import { initSlashPairingContext } from "./session-slash.js";
|
|
@@ -159,6 +157,12 @@ export async function runDaemon(): Promise<void> {
|
|
|
159
157
|
);
|
|
160
158
|
}
|
|
161
159
|
initializeDb();
|
|
160
|
+
// Seed well-known OAuth provider configurations (insert-if-not-exists)
|
|
161
|
+
seedOAuthProviders();
|
|
162
|
+
// Backfill oauth_connection rows for manual-token providers (Telegram,
|
|
163
|
+
// Slack channel) that already have keychain credentials from before the
|
|
164
|
+
// oauth_connection migration. Safe to call on every startup.
|
|
165
|
+
await backfillManualTokenConnections();
|
|
162
166
|
log.info("Daemon startup: DB initialized");
|
|
163
167
|
|
|
164
168
|
// Ensure a vellum guardian binding exists and mint the CLI edge token
|
|
@@ -193,7 +197,9 @@ export async function runDaemon(): Promise<void> {
|
|
|
193
197
|
const httpTokenPath = join(getRootDir(), "http-token");
|
|
194
198
|
writeFileSync(httpTokenPath, credentials.accessToken, { mode: 0o600 });
|
|
195
199
|
chmodSync(httpTokenPath, 0o600);
|
|
196
|
-
log.info(
|
|
200
|
+
log.info(
|
|
201
|
+
"Daemon startup: CLI edge token written to credential store and http-token",
|
|
202
|
+
);
|
|
197
203
|
} else {
|
|
198
204
|
log.warn("No guardian principal available — CLI edge token not written");
|
|
199
205
|
}
|
|
@@ -234,6 +240,19 @@ export async function runDaemon(): Promise<void> {
|
|
|
234
240
|
log.info("Daemon startup: loading config");
|
|
235
241
|
const config = loadConfig();
|
|
236
242
|
|
|
243
|
+
// Seed module-level ingress state from the workspace config so that
|
|
244
|
+
// getIngressPublicBaseUrl() returns the correct value immediately after
|
|
245
|
+
// startup (before any handleIngressConfig("set") call). Without this,
|
|
246
|
+
// code paths that read the module-level state directly (e.g. session-slash
|
|
247
|
+
// pairing info) would see undefined until an explicit set.
|
|
248
|
+
if (config.ingress.enabled && config.ingress.publicBaseUrl) {
|
|
249
|
+
setIngressPublicBaseUrl(config.ingress.publicBaseUrl);
|
|
250
|
+
log.info(
|
|
251
|
+
{ url: config.ingress.publicBaseUrl },
|
|
252
|
+
"Daemon startup: seeded ingress URL from workspace config",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
237
256
|
if (config.logFile.dir) {
|
|
238
257
|
initLogger({
|
|
239
258
|
dir: config.logFile.dir,
|
|
@@ -251,6 +270,18 @@ export async function runDaemon(): Promise<void> {
|
|
|
251
270
|
await closeSentry();
|
|
252
271
|
}
|
|
253
272
|
|
|
273
|
+
// If Logfire observability is not explicitly enabled, disable it so
|
|
274
|
+
// wrapWithLogfire() calls during provider setup become no-ops. Logfire
|
|
275
|
+
// is initialized eagerly (before config loads) for the same reason as
|
|
276
|
+
// Sentry — but the feature flag gates whether it actually traces.
|
|
277
|
+
const logfireEnabled = isAssistantFeatureFlagEnabled(
|
|
278
|
+
"feature_flags.logfire.enabled",
|
|
279
|
+
config,
|
|
280
|
+
);
|
|
281
|
+
if (!logfireEnabled) {
|
|
282
|
+
disableLogfire();
|
|
283
|
+
}
|
|
284
|
+
|
|
254
285
|
await initializeProvidersAndTools(config);
|
|
255
286
|
|
|
256
287
|
// Start the DaemonServer (session manager) before Qdrant so HTTP
|
|
@@ -493,64 +524,9 @@ export async function runDaemon(): Promise<void> {
|
|
|
493
524
|
);
|
|
494
525
|
},
|
|
495
526
|
},
|
|
496
|
-
|
|
527
|
+
getWatchDeps: () => {
|
|
497
528
|
const ctx = server.getHandlerContext();
|
|
498
529
|
return {
|
|
499
|
-
cuSessions: ctx.cuSessions,
|
|
500
|
-
sharedRequestTimestamps: ctx.sharedRequestTimestamps,
|
|
501
|
-
cuObservationParseSequence: ctx.cuObservationParseSequence,
|
|
502
|
-
handleRideShotgunStart: async (params) => {
|
|
503
|
-
// The handler generates its own watchId/sessionId and
|
|
504
|
-
// sends them via ctx.send as a watch_started message.
|
|
505
|
-
// We intercept send to capture the IDs before they broadcast.
|
|
506
|
-
let capturedWatchId = "";
|
|
507
|
-
let capturedSessionId = "";
|
|
508
|
-
const interceptCtx = {
|
|
509
|
-
...ctx,
|
|
510
|
-
send: (msg: ServerMessage) => {
|
|
511
|
-
if (
|
|
512
|
-
"type" in msg &&
|
|
513
|
-
msg.type === "watch_started" &&
|
|
514
|
-
"watchId" in msg &&
|
|
515
|
-
"sessionId" in msg
|
|
516
|
-
) {
|
|
517
|
-
capturedWatchId = (msg as { watchId: string }).watchId;
|
|
518
|
-
capturedSessionId = (msg as { sessionId: string }).sessionId;
|
|
519
|
-
}
|
|
520
|
-
ctx.send(msg);
|
|
521
|
-
},
|
|
522
|
-
};
|
|
523
|
-
await handleRideShotgunStart(
|
|
524
|
-
{
|
|
525
|
-
type: "ride_shotgun_start",
|
|
526
|
-
durationSeconds: params.durationSeconds,
|
|
527
|
-
intervalSeconds: params.intervalSeconds,
|
|
528
|
-
mode: params.mode,
|
|
529
|
-
targetDomain: params.targetDomain,
|
|
530
|
-
navigateDomain: params.navigateDomain,
|
|
531
|
-
autoNavigate: params.autoNavigate,
|
|
532
|
-
},
|
|
533
|
-
interceptCtx,
|
|
534
|
-
);
|
|
535
|
-
return { watchId: capturedWatchId, sessionId: capturedSessionId };
|
|
536
|
-
},
|
|
537
|
-
handleRideShotgunStop: async (watchId) => {
|
|
538
|
-
await handleRideShotgunStop(
|
|
539
|
-
{ type: "ride_shotgun_stop", watchId },
|
|
540
|
-
ctx,
|
|
541
|
-
);
|
|
542
|
-
},
|
|
543
|
-
getRideShotgunStatus: (watchId) => {
|
|
544
|
-
const session = watchSessions.get(watchId);
|
|
545
|
-
if (!session) return undefined;
|
|
546
|
-
return {
|
|
547
|
-
status: session.status,
|
|
548
|
-
sessionId: session.sessionId,
|
|
549
|
-
recordingId: session.recordingId,
|
|
550
|
-
savedRecordingPath: session.savedRecordingPath,
|
|
551
|
-
bootstrapFailureReason: session.bootstrapFailureReason,
|
|
552
|
-
};
|
|
553
|
-
},
|
|
554
530
|
handleWatchObservation: async (params) => {
|
|
555
531
|
await handleWatchObservation(
|
|
556
532
|
{
|
|
@@ -21,6 +21,7 @@ export * from "./message-types/diagnostics.js";
|
|
|
21
21
|
export * from "./message-types/documents.js";
|
|
22
22
|
export * from "./message-types/guardian-actions.js";
|
|
23
23
|
export * from "./message-types/host-bash.js";
|
|
24
|
+
export * from "./message-types/host-cu.js";
|
|
24
25
|
export * from "./message-types/host-file.js";
|
|
25
26
|
export * from "./message-types/inbox.js";
|
|
26
27
|
export * from "./message-types/integrations.js";
|
|
@@ -69,6 +70,7 @@ import type {
|
|
|
69
70
|
_GuardianActionsServerMessages,
|
|
70
71
|
} from "./message-types/guardian-actions.js";
|
|
71
72
|
import type { _HostBashServerMessages } from "./message-types/host-bash.js";
|
|
73
|
+
import type { _HostCuServerMessages } from "./message-types/host-cu.js";
|
|
72
74
|
import type { _HostFileServerMessages } from "./message-types/host-file.js";
|
|
73
75
|
import type {
|
|
74
76
|
_InboxClientMessages,
|
|
@@ -180,6 +182,7 @@ export type ServerMessage =
|
|
|
180
182
|
| _DocumentsServerMessages
|
|
181
183
|
| _GuardianActionsServerMessages
|
|
182
184
|
| _HostBashServerMessages
|
|
185
|
+
| _HostCuServerMessages
|
|
183
186
|
| _HostFileServerMessages
|
|
184
187
|
| _MemoryServerMessages
|
|
185
188
|
| _WorkspaceServerMessages
|