@vellumai/assistant 0.7.1 → 0.7.2
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 +32 -49
- package/Dockerfile +1 -0
- package/README.md +1 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
- package/bun.lock +26 -26
- package/docs/architecture/security.md +20 -0
- package/docs/plugins.md +7 -9
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +9 -0
- package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
- package/node_modules/@vellumai/twilio-client/package.json +18 -0
- package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
- package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
- package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
- package/openapi.yaml +565 -12
- package/package.json +6 -3
- package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
- package/src/__tests__/app-bundler.test.ts +170 -1
- package/src/__tests__/app-control-flow.test.ts +374 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-routes-http.test.ts +23 -6
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
- package/src/__tests__/assistant-event-hub.test.ts +109 -2
- package/src/__tests__/assistant-event.test.ts +10 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -7
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
- package/src/__tests__/btw-routes.test.ts +13 -4
- package/src/__tests__/call-controller.test.ts +49 -1
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-readiness-service.test.ts +59 -1
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +90 -155
- package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +36 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
- package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
- package/src/__tests__/credentials-cli.test.ts +5 -12
- package/src/__tests__/cu-unified-flow.test.ts +185 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
- package/src/__tests__/heartbeat-service.test.ts +718 -1
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +602 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +246 -47
- package/src/__tests__/host-bash-routes.test.ts +294 -0
- package/src/__tests__/host-browser-proxy.test.ts +24 -22
- package/src/__tests__/host-browser-routes.test.ts +39 -13
- package/src/__tests__/host-cu-proxy.test.ts +41 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
- package/src/__tests__/host-file-proxy.test.ts +37 -43
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +262 -0
- package/src/__tests__/host-file-write-tool.test.ts +42 -1
- package/src/__tests__/host-proxy-base.test.ts +312 -0
- package/src/__tests__/host-shell-tool.test.ts +22 -4
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- package/src/__tests__/inline-command-runner.test.ts +0 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
- package/src/__tests__/integration-status.test.ts +85 -5
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/prechat-onboarding-contract.test.ts +3 -1
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/require-fresh-approval.test.ts +0 -1
- package/src/__tests__/retry-backoff.test.ts +87 -0
- package/src/__tests__/runtime-events-sse.test.ts +10 -6
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
- package/src/__tests__/skill-feature-flags.test.ts +43 -41
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
- package/src/__tests__/skill-load-inline-command.test.ts +0 -51
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +9 -14
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +3 -5
- package/src/__tests__/twilio-validation.test.ts +93 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/backup/__tests__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +51 -151
- package/src/backup/paths.ts +2 -18
- package/src/backup/restore.ts +107 -231
- package/src/bundler/app-bundler.ts +51 -3
- package/src/calls/relay-server.ts +4 -44
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +33 -105
- package/src/calls/twilio-routes.ts +11 -12
- package/src/channels/types.ts +8 -7
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +73 -0
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +15 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +9 -6
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +296 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +0 -18
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +67 -10
- package/src/config/bundled-skills/acp/SKILL.md +6 -0
- package/src/config/bundled-skills/acp/TOOLS.json +1 -22
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
- package/src/config/bundled-skills/app-control/SKILL.md +75 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
- package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
- package/src/config/bundled-skills/document/TOOLS.json +0 -8
- package/src/config/bundled-skills/followups/TOOLS.json +0 -12
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
- package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
- package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
- package/src/config/bundled-skills/settings/SKILL.md +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +0 -12
- package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
- package/src/config/bundled-skills/subagent/SKILL.md +6 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
- package/src/config/bundled-tool-registry.ts +21 -0
- package/src/config/env-registry.ts +0 -2
- package/src/config/env.ts +19 -12
- package/src/config/feature-flag-registry.json +21 -133
- package/src/config/loader.ts +73 -99
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -4
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/heartbeat.ts +63 -0
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +5 -10
- package/src/config/schemas/memory-lifecycle.ts +77 -24
- package/src/config/schemas/memory-v2.ts +48 -4
- package/src/config/schemas/platform.ts +6 -0
- package/src/config/schemas/services.ts +1 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/contacts/contact-store.ts +0 -30
- package/src/contacts/contacts-write.ts +0 -27
- package/src/context/window-manager.ts +1 -2
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +12 -41
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +126 -5
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +4 -3
- package/src/daemon/conversation-agent-loop-handlers.ts +21 -3
- package/src/daemon/conversation-agent-loop.ts +32 -28
- package/src/daemon/conversation-lifecycle.ts +8 -1
- package/src/daemon/conversation-process.ts +16 -11
- package/src/daemon/conversation-runtime-assembly.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +125 -4
- package/src/daemon/conversation-tool-setup.ts +16 -55
- package/src/daemon/conversation.ts +21 -2
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +293 -0
- package/src/daemon/host-bash-proxy.ts +84 -74
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +81 -86
- package/src/daemon/host-file-proxy.ts +93 -69
- package/src/daemon/host-proxy-base.ts +294 -0
- package/src/daemon/host-proxy-preactivation.ts +82 -0
- package/src/daemon/host-transfer-proxy.ts +247 -129
- package/src/daemon/lifecycle.ts +115 -117
- package/src/daemon/message-protocol.ts +3 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +11 -8
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +4 -0
- package/src/daemon/message-types/host-cu.ts +2 -0
- package/src/daemon/message-types/host-file.ts +4 -0
- package/src/daemon/message-types/host-transfer.ts +3 -0
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/process-message.ts +18 -1
- package/src/daemon/shutdown-handlers.ts +0 -3
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +15 -7
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
- package/src/heartbeat/heartbeat-run-store.ts +236 -0
- package/src/heartbeat/heartbeat-service.ts +280 -49
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +17 -92
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +14 -1
- package/src/ipc/cli-client.ts +32 -1
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/mcp-auth-orchestrator.ts +213 -0
- package/src/mcp/mcp-auth-state.ts +133 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
- package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
- package/src/memory/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -0
- package/src/memory/auto-analysis-constants.ts +17 -0
- package/src/memory/auto-analysis-guard.ts +5 -15
- package/src/memory/canonical-guardian-store.ts +7 -7
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
- package/src/memory/context-search/agent-protocol.ts +6 -6
- package/src/memory/context-search/agent-runner.ts +32 -7
- package/src/memory/context-search/sources/memory-v2.ts +17 -5
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +4 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -4
- package/src/memory/graph/conversation-graph-memory.ts +1 -24
- package/src/memory/graph/graph-search.ts +8 -0
- package/src/memory/graph/retriever.ts +28 -0
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
- package/src/memory/jobs/embed-concept-page.ts +28 -2
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
- package/src/memory/jobs-store.ts +66 -22
- package/src/memory/jobs-worker.ts +112 -63
- package/src/memory/memory-v2-activation-log-store.ts +1 -1
- package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
- package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +50 -20
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +7 -0
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/v2/__tests__/activation.test.ts +77 -95
- package/src/memory/v2/__tests__/injection.test.ts +43 -21
- package/src/memory/v2/__tests__/sim.test.ts +166 -6
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +0 -1
- package/src/memory/v2/activation.ts +69 -88
- package/src/memory/v2/consolidation-job.ts +3 -5
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +86 -53
- package/src/memory/v2/prompts/consolidation.ts +312 -91
- package/src/memory/v2/qdrant.ts +99 -1
- package/src/memory/v2/sim.ts +126 -16
- package/src/memory/v2/skill-qdrant.ts +12 -3
- package/src/memory/v2/skill-store.ts +16 -1
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +6 -5
- package/src/messaging/providers/gmail/types.ts +0 -49
- package/src/messaging/providers/slack/adapter.ts +1 -31
- package/src/messaging/providers/slack/types.ts +0 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/oauth/connect-orchestrator.ts +4 -0
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/outbound-proxy/index.ts +1 -37
- package/src/outbound-proxy/logging.ts +1 -1
- package/src/outbound-proxy/policy.ts +6 -5
- package/src/outbound-proxy/router.ts +2 -1
- package/src/permissions/approval-policy.test.ts +6 -275
- package/src/permissions/approval-policy.ts +0 -51
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +3 -17
- package/src/permissions/gateway-threshold-reader.ts +2 -0
- package/src/permissions/prompter.ts +34 -1
- package/src/permissions/secret-prompter.ts +6 -2
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/system-prompt.ts +3 -18
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/runtime/assistant-event-hub.ts +118 -96
- package/src/runtime/assistant-event.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +19 -0
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-invite-transport.ts +2 -48
- package/src/runtime/channel-invite-transports/email.ts +1 -1
- package/src/runtime/channel-invite-transports/slack.ts +1 -1
- package/src/runtime/channel-invite-transports/telegram.ts +1 -1
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
- package/src/runtime/channel-invite-types.ts +54 -0
- package/src/runtime/channel-readiness-service.ts +32 -13
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
- package/src/runtime/migrations/migration-transport.ts +7 -7
- package/src/runtime/migrations/vbundle-builder.ts +327 -60
- package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +245 -68
- package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
- package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +114 -0
- package/src/runtime/pending-interactions.ts +35 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
- package/src/runtime/routes/approval-interception-types.ts +13 -0
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/btw-routes.ts +14 -37
- package/src/runtime/routes/client-routes.ts +1 -0
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +30 -13
- package/src/runtime/routes/document-pdf-renderer.ts +165 -0
- package/src/runtime/routes/documents-routes.ts +30 -0
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +12 -6
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-approval-interception.ts +2 -8
- package/src/runtime/routes/heartbeat-routes.ts +103 -38
- package/src/runtime/routes/host-app-control-routes.ts +134 -0
- package/src/runtime/routes/host-bash-routes.ts +36 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +44 -14
- package/src/runtime/routes/host-file-routes.ts +33 -10
- package/src/runtime/routes/host-transfer-routes.ts +64 -24
- package/src/runtime/routes/http-adapter.ts +1 -0
- package/src/runtime/routes/identity-intro-cache.ts +30 -0
- package/src/runtime/routes/identity-routes.ts +15 -43
- package/src/runtime/routes/inbound-message-handler.ts +1 -9
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +441 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-templates.ts +4 -7
- package/src/schedule/integration-status.ts +66 -2
- package/src/schedule/recurrence-engine.ts +4 -1
- package/src/schedule/retry-backoff.ts +18 -0
- package/src/schedule/retry-policy.ts +82 -0
- package/src/schedule/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -2
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +63 -38
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- package/src/skills/catalog-files.ts +2 -8
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/remote-skill-policy.ts +5 -5
- package/src/skills/skill-file-provider.ts +1 -1
- package/src/skills/skill-file-types.ts +13 -0
- package/src/skills/skillssh-audit-types.ts +28 -0
- package/src/skills/skillssh-registry.ts +8 -21
- package/src/telemetry/types.ts +2 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +23 -24
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +2 -0
- package/src/tools/host-filesystem/edit.ts +26 -0
- package/src/tools/host-filesystem/read.ts +26 -0
- package/src/tools/host-filesystem/transfer.ts +31 -1
- package/src/tools/host-filesystem/write.ts +26 -0
- package/src/tools/host-terminal/host-shell.ts +58 -0
- package/src/tools/schedule/create.ts +6 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/schedule/update.ts +10 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
- package/src/tools/shared/filesystem/path-policy.ts +25 -1
- package/src/tools/skills/load.ts +0 -32
- package/src/tools/tool-approval-handler.ts +1 -5
- package/src/tools/types.ts +4 -0
- package/src/usage/pricing.ts +1 -1
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/migrations/003-seed-device-id.ts +1 -1
- package/src/workspace/migrations/006-services-config.ts +8 -5
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
- package/src/__tests__/twilio-rest.test.ts +0 -34
- package/src/backup/__tests__/backup-key.test.ts +0 -152
- package/src/backup/__tests__/backup-worker.test.ts +0 -782
- package/src/backup/__tests__/offsite-writer.test.ts +0 -641
- package/src/backup/__tests__/stream-crypt.test.ts +0 -228
- package/src/backup/backup-key.ts +0 -137
- package/src/backup/backup-worker.ts +0 -472
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- package/src/daemon/message-types/pairing.ts +0 -58
- package/src/outbound-proxy/config.ts +0 -20
- package/src/outbound-proxy/health.ts +0 -18
- package/src/outbound-proxy/types.ts +0 -150
- package/src/runtime/capability-tokens.ts +0 -190
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPC route for the `contacts/prompt` CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. CLI calls `contacts/prompt` IPC route with optional channel/role hints.
|
|
6
|
+
* 2. Daemon broadcasts a `contact_request` to all connected clients.
|
|
7
|
+
* 3. Client shows a contact address input form.
|
|
8
|
+
* 4. User enters an address; client POSTs to the gateway's
|
|
9
|
+
* `POST /v1/contacts/prompt` HTTP route.
|
|
10
|
+
* 5. Gateway upserts the contact + channel (gateway owns all contact writes).
|
|
11
|
+
* 6. Gateway calls daemon IPC `resolve_contact_prompt` with the new contact info.
|
|
12
|
+
* 7. Daemon resolves the pending promise; `contacts/prompt` IPC returns to CLI.
|
|
13
|
+
*
|
|
14
|
+
* The daemon only broadcasts the prompt and waits. It never writes contacts.
|
|
15
|
+
* All writes go through the gateway.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { v4 as uuid } from "uuid";
|
|
19
|
+
import { z } from "zod";
|
|
20
|
+
|
|
21
|
+
import { getLogger } from "../../util/logger.js";
|
|
22
|
+
import { broadcastMessage } from "../assistant-event-hub.js";
|
|
23
|
+
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
24
|
+
|
|
25
|
+
const log = getLogger("contact-prompt-routes");
|
|
26
|
+
|
|
27
|
+
/** Timeout for waiting on the user to submit the contact form (5 min). */
|
|
28
|
+
const CONTACT_PROMPT_TIMEOUT_MS = 300_000;
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Pending contact prompts
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
export interface ContactPromptResult {
|
|
35
|
+
ok: boolean;
|
|
36
|
+
error?: string;
|
|
37
|
+
contactId?: string;
|
|
38
|
+
channelId?: string;
|
|
39
|
+
channelType?: string;
|
|
40
|
+
address?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface PendingContactPrompt {
|
|
44
|
+
resolve: (result: ContactPromptResult) => void;
|
|
45
|
+
timer: ReturnType<typeof setTimeout>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const pendingContactPrompts = new Map<string, PendingContactPrompt>();
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Called by the gateway after it writes the contact and channel.
|
|
52
|
+
* Resolves the pending promise so the CLI's `contacts/prompt` IPC call returns.
|
|
53
|
+
*/
|
|
54
|
+
function resolveContactPrompt({
|
|
55
|
+
body = {},
|
|
56
|
+
}: RouteHandlerArgs): { resolved: boolean } {
|
|
57
|
+
const { requestId, contactId, channelId, channelType, address, error } =
|
|
58
|
+
body as {
|
|
59
|
+
requestId: string;
|
|
60
|
+
contactId?: string;
|
|
61
|
+
channelId?: string;
|
|
62
|
+
channelType?: string;
|
|
63
|
+
address?: string;
|
|
64
|
+
error?: string;
|
|
65
|
+
};
|
|
66
|
+
const pending = pendingContactPrompts.get(requestId);
|
|
67
|
+
if (!pending) {
|
|
68
|
+
log.warn({ requestId }, "resolve_contact_prompt: no pending prompt found");
|
|
69
|
+
return { resolved: false };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
clearTimeout(pending.timer);
|
|
73
|
+
pendingContactPrompts.delete(requestId);
|
|
74
|
+
|
|
75
|
+
if (error) {
|
|
76
|
+
pending.resolve({ ok: false, error });
|
|
77
|
+
} else {
|
|
78
|
+
pending.resolve({
|
|
79
|
+
ok: true,
|
|
80
|
+
contactId,
|
|
81
|
+
channelId,
|
|
82
|
+
channelType,
|
|
83
|
+
address,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
log.info({ requestId, contactId }, "Contact prompt resolved");
|
|
88
|
+
return { resolved: true };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Schema
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
const ContactPromptParams = z.object({
|
|
96
|
+
channel: z
|
|
97
|
+
.string()
|
|
98
|
+
.optional()
|
|
99
|
+
.describe(
|
|
100
|
+
"Suggested channel type hint (e.g. phone, email, telegram). Free text — not enforced.",
|
|
101
|
+
),
|
|
102
|
+
placeholder: z
|
|
103
|
+
.string()
|
|
104
|
+
.optional()
|
|
105
|
+
.describe("Placeholder text for the address input field."),
|
|
106
|
+
label: z.string().optional().describe("Display label shown in the prompt UI."),
|
|
107
|
+
description: z.string().optional().describe("Longer description for the prompt UI."),
|
|
108
|
+
role: z
|
|
109
|
+
.enum(["guardian", "trusted-contact", "unknown"])
|
|
110
|
+
.default("unknown")
|
|
111
|
+
.describe("Intended role of the contact being registered."),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Handler
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
async function handleContactPrompt({
|
|
119
|
+
body = {},
|
|
120
|
+
}: RouteHandlerArgs): Promise<ContactPromptResult> {
|
|
121
|
+
const { channel, placeholder, label, description, role } =
|
|
122
|
+
ContactPromptParams.parse(body);
|
|
123
|
+
|
|
124
|
+
const requestId = uuid();
|
|
125
|
+
|
|
126
|
+
return new Promise((resolve) => {
|
|
127
|
+
const timer = setTimeout(() => {
|
|
128
|
+
pendingContactPrompts.delete(requestId);
|
|
129
|
+
log.warn({ requestId }, "Contact prompt timed out");
|
|
130
|
+
resolve({ ok: false, error: "Prompt timed out" });
|
|
131
|
+
}, CONTACT_PROMPT_TIMEOUT_MS);
|
|
132
|
+
|
|
133
|
+
pendingContactPrompts.set(requestId, { resolve, timer });
|
|
134
|
+
|
|
135
|
+
broadcastMessage({
|
|
136
|
+
type: "contact_request",
|
|
137
|
+
requestId,
|
|
138
|
+
channel,
|
|
139
|
+
placeholder,
|
|
140
|
+
label,
|
|
141
|
+
description,
|
|
142
|
+
role,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
log.info({ requestId, channel, role }, "Contact prompt broadcast");
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
// Routes
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
export const CONTACT_PROMPT_ROUTES: RouteDefinition[] = [
|
|
154
|
+
{
|
|
155
|
+
operationId: "contacts_prompt",
|
|
156
|
+
endpoint: "contacts/prompt",
|
|
157
|
+
method: "POST",
|
|
158
|
+
handler: handleContactPrompt,
|
|
159
|
+
summary: "Prompt user to register a contact channel",
|
|
160
|
+
description:
|
|
161
|
+
"Broadcasts a contact_request to connected clients, waits for the user to submit an address via the gateway. The gateway owns the contact write and notifies the daemon via resolve_contact_prompt IPC.",
|
|
162
|
+
tags: ["contacts"],
|
|
163
|
+
requestBody: ContactPromptParams,
|
|
164
|
+
responseBody: z.object({
|
|
165
|
+
ok: z.boolean(),
|
|
166
|
+
error: z.string().optional(),
|
|
167
|
+
contactId: z.string().optional(),
|
|
168
|
+
channelId: z.string().optional(),
|
|
169
|
+
channelType: z.string().optional(),
|
|
170
|
+
address: z.string().optional(),
|
|
171
|
+
}),
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
operationId: "resolve_contact_prompt",
|
|
175
|
+
endpoint: "resolve_contact_prompt",
|
|
176
|
+
method: "POST",
|
|
177
|
+
handler: resolveContactPrompt,
|
|
178
|
+
summary: "Gateway callback: resolve a pending contact prompt",
|
|
179
|
+
description:
|
|
180
|
+
"Called by the gateway after it writes the contact and channel. Unblocks the waiting contacts/prompt IPC call.",
|
|
181
|
+
tags: ["contacts"],
|
|
182
|
+
},
|
|
183
|
+
];
|
|
@@ -50,7 +50,11 @@ import {
|
|
|
50
50
|
CONFIG_RELOAD_DEBOUNCE_MS,
|
|
51
51
|
log,
|
|
52
52
|
} from "../../daemon/handlers/shared.js";
|
|
53
|
-
import {
|
|
53
|
+
import {
|
|
54
|
+
getAssistantMessageIdsInTurn,
|
|
55
|
+
getConversation,
|
|
56
|
+
getMessageById,
|
|
57
|
+
} from "../../memory/conversation-crud.js";
|
|
54
58
|
import { clearEmbeddingBackendCache } from "../../memory/embedding-backend.js";
|
|
55
59
|
import {
|
|
56
60
|
getRequestLogById,
|
|
@@ -58,6 +62,7 @@ import {
|
|
|
58
62
|
} from "../../memory/llm-request-log-store.js";
|
|
59
63
|
import { getMemoryRecallLogByMessageIds } from "../../memory/memory-recall-log-store.js";
|
|
60
64
|
import { getMemoryV2ActivationLogByMessageIds } from "../../memory/memory-v2-activation-log-store.js";
|
|
65
|
+
import { MEMORY_V2_CONSOLIDATION_SOURCE } from "../../memory/v2/constants.js";
|
|
61
66
|
import { initializeProviders } from "../../providers/registry.js";
|
|
62
67
|
import { resolvePricingForUsage } from "../../util/pricing.js";
|
|
63
68
|
import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
|
|
@@ -459,6 +464,26 @@ function handleGetMessageContent({
|
|
|
459
464
|
return result;
|
|
460
465
|
}
|
|
461
466
|
|
|
467
|
+
const CONVERSATION_KINDS = [
|
|
468
|
+
"user",
|
|
469
|
+
"background",
|
|
470
|
+
"background_memory_consolidation",
|
|
471
|
+
"scheduled",
|
|
472
|
+
] as const;
|
|
473
|
+
type ConversationKind = (typeof CONVERSATION_KINDS)[number];
|
|
474
|
+
|
|
475
|
+
function resolveConversationKind(
|
|
476
|
+
source: string,
|
|
477
|
+
conversationType: string,
|
|
478
|
+
): ConversationKind {
|
|
479
|
+
if (source === MEMORY_V2_CONSOLIDATION_SOURCE) {
|
|
480
|
+
return "background_memory_consolidation";
|
|
481
|
+
}
|
|
482
|
+
if (conversationType === "background") return "background";
|
|
483
|
+
if (conversationType === "scheduled") return "scheduled";
|
|
484
|
+
return "user";
|
|
485
|
+
}
|
|
486
|
+
|
|
462
487
|
function handleGetLlmContext({ pathParams = {} }: RouteHandlerArgs) {
|
|
463
488
|
const messageId = pathParams.id;
|
|
464
489
|
if (!messageId) {
|
|
@@ -469,8 +494,17 @@ function handleGetLlmContext({ pathParams = {} }: RouteHandlerArgs) {
|
|
|
469
494
|
const memoryRecallLog = getMemoryRecallLogByMessageIds(turnMessageIds);
|
|
470
495
|
const memoryV2Activation =
|
|
471
496
|
getMemoryV2ActivationLogByMessageIds(turnMessageIds);
|
|
497
|
+
const message = getMessageById(messageId);
|
|
498
|
+
const conversation = message ? getConversation(message.conversationId) : null;
|
|
499
|
+
const conversationKind: ConversationKind = conversation
|
|
500
|
+
? resolveConversationKind(
|
|
501
|
+
conversation.source,
|
|
502
|
+
conversation.conversationType,
|
|
503
|
+
)
|
|
504
|
+
: "user";
|
|
472
505
|
return {
|
|
473
506
|
messageId,
|
|
507
|
+
conversationKind,
|
|
474
508
|
logs: logs.map((log) => {
|
|
475
509
|
let requestPayload: unknown;
|
|
476
510
|
try {
|
|
@@ -709,6 +743,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
709
743
|
tags: ["messages"],
|
|
710
744
|
responseBody: z.object({
|
|
711
745
|
messageId: z.string(),
|
|
746
|
+
conversationKind: z.enum(CONVERSATION_KINDS),
|
|
712
747
|
logs: z.array(z.unknown()),
|
|
713
748
|
memoryRecall: z.object({}).passthrough().nullable(),
|
|
714
749
|
memoryV2Activation: z.object({}).passthrough().nullable(),
|
|
@@ -44,7 +44,9 @@ import {
|
|
|
44
44
|
isWakeUpGreeting,
|
|
45
45
|
} from "../../daemon/first-greeting.js";
|
|
46
46
|
import { renderHistoryContent } from "../../daemon/handlers/shared.js";
|
|
47
|
+
import { HostAppControlProxy } from "../../daemon/host-app-control-proxy.js";
|
|
47
48
|
import { HostCuProxy } from "../../daemon/host-cu-proxy.js";
|
|
49
|
+
import { preactivateHostProxySkills } from "../../daemon/host-proxy-preactivation.js";
|
|
48
50
|
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
49
51
|
import type {
|
|
50
52
|
HostProxyTransportMetadata,
|
|
@@ -1320,10 +1322,9 @@ export async function handleSendMessage(
|
|
|
1320
1322
|
|
|
1321
1323
|
// Store pre-chat onboarding context on the conversation when this is the
|
|
1322
1324
|
// very first message (no prior messages loaded). Artifact persistence
|
|
1323
|
-
// (IDENTITY.md, USER.md, sidecar)
|
|
1324
|
-
//
|
|
1325
|
-
// the
|
|
1326
|
-
// path it runs immediately before inference starts.
|
|
1325
|
+
// (IDENTITY.md, USER.md, sidecar) runs before either the canned greeting
|
|
1326
|
+
// broadcast or normal LLM inference so client-side identity reads observe
|
|
1327
|
+
// the selected assistant name.
|
|
1327
1328
|
const isFirstOnboarding =
|
|
1328
1329
|
!!body.onboarding && conversation.messages.length === 0;
|
|
1329
1330
|
if (isFirstOnboarding) {
|
|
@@ -1395,15 +1396,30 @@ export async function handleSendMessage(
|
|
|
1395
1396
|
if (!conversation.isProcessing() || !conversation.hostCuProxy) {
|
|
1396
1397
|
conversation.setHostCuProxy(new HostCuProxy());
|
|
1397
1398
|
}
|
|
1398
|
-
// Only preactivate CU when the conversation is idle — if the conversation is
|
|
1399
|
-
// processing, this message will be queued and preactivation is deferred
|
|
1400
|
-
// to dequeue time in drainQueueImpl to avoid mutating in-flight turn state.
|
|
1401
|
-
if (!conversation.isProcessing()) {
|
|
1402
|
-
conversation.addPreactivatedSkillId("computer-use");
|
|
1403
|
-
}
|
|
1404
1399
|
} else if (!conversation.isProcessing()) {
|
|
1405
1400
|
conversation.setHostCuProxy(undefined);
|
|
1406
1401
|
}
|
|
1402
|
+
// App-control mirrors CU's per-conversation lifecycle: the proxy owns a
|
|
1403
|
+
// singleton lock plus per-session loop tracking. Instantiation is
|
|
1404
|
+
// unconditional when the client supports the capability — feature-flag
|
|
1405
|
+
// gating lives in the skill-projection layer (which reads the
|
|
1406
|
+
// `feature-flag: app-control` declaration in SKILL.md frontmatter), so
|
|
1407
|
+
// an attached proxy is harmless when the flag resolves to off.
|
|
1408
|
+
if (supportsHostProxy(sourceInterface, "host_app_control")) {
|
|
1409
|
+
if (!conversation.isProcessing() || !conversation.hostAppControlProxy) {
|
|
1410
|
+
conversation.setHostAppControlProxy(
|
|
1411
|
+
new HostAppControlProxy(mapping.conversationId),
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
} else if (!conversation.isProcessing()) {
|
|
1415
|
+
conversation.setHostAppControlProxy(undefined);
|
|
1416
|
+
}
|
|
1417
|
+
// Only preactivate when the conversation is idle — if it's processing,
|
|
1418
|
+
// this message will be queued and preactivation is deferred to dequeue
|
|
1419
|
+
// time in drainQueueImpl to avoid mutating in-flight turn state.
|
|
1420
|
+
if (!conversation.isProcessing()) {
|
|
1421
|
+
preactivateHostProxySkills(conversation, sourceInterface);
|
|
1422
|
+
}
|
|
1407
1423
|
// Wire sendToClient to the SSE hub so all subsystems can reach the HTTP client.
|
|
1408
1424
|
// hasNoClient must remain `!isInteractive` so downstream tool gating
|
|
1409
1425
|
// (`isToolActiveForContext` for HOST_TOOL_NAMES, `createToolExecutor`'s
|
|
@@ -1473,6 +1489,10 @@ export async function handleSendMessage(
|
|
|
1473
1489
|
conversationId,
|
|
1474
1490
|
};
|
|
1475
1491
|
|
|
1492
|
+
if (isFirstOnboarding) {
|
|
1493
|
+
persistOnboardingArtifacts(body.onboarding!);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1476
1496
|
setTimeout(() => {
|
|
1477
1497
|
broadcastMessage({
|
|
1478
1498
|
type: "user_message_echo",
|
|
@@ -1493,9 +1513,6 @@ export async function handleSendMessage(
|
|
|
1493
1513
|
"canned-greeting queue drain",
|
|
1494
1514
|
);
|
|
1495
1515
|
|
|
1496
|
-
if (isFirstOnboarding) {
|
|
1497
|
-
persistOnboardingArtifacts(body.onboarding!);
|
|
1498
|
-
}
|
|
1499
1516
|
conversation.warmPromptCache();
|
|
1500
1517
|
}, 0);
|
|
1501
1518
|
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown to PDF renderer for document export.
|
|
3
|
+
*
|
|
4
|
+
* Converts markdown content to styled HTML via `marked`, then renders
|
|
5
|
+
* the HTML to a PDF buffer using Playwright headless Chromium.
|
|
6
|
+
* The HTML template uses print-friendly styling that matches the
|
|
7
|
+
* document editor typography.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { marked } from "marked";
|
|
11
|
+
|
|
12
|
+
import { importPlaywright } from "../../tools/browser/runtime-check.js";
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Print template
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
const FONT_STACK = `"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`;
|
|
19
|
+
|
|
20
|
+
function wrapInPrintTemplate(innerHtml: string): string {
|
|
21
|
+
return `<!DOCTYPE html>
|
|
22
|
+
<html>
|
|
23
|
+
<head>
|
|
24
|
+
<meta charset="utf-8">
|
|
25
|
+
<style>
|
|
26
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
27
|
+
|
|
28
|
+
body {
|
|
29
|
+
font-family: ${FONT_STACK};
|
|
30
|
+
font-size: 14px;
|
|
31
|
+
line-height: 1.7;
|
|
32
|
+
color: #1a1a1a;
|
|
33
|
+
background: #ffffff;
|
|
34
|
+
padding: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
h1 { font-size: 28px; font-weight: 600; margin-top: 32px; margin-bottom: 12px; }
|
|
38
|
+
h2 { font-size: 22px; font-weight: 600; margin-top: 28px; margin-bottom: 10px; }
|
|
39
|
+
h3 { font-size: 18px; font-weight: 600; margin-top: 24px; margin-bottom: 8px; }
|
|
40
|
+
h4, h5, h6 { font-size: 16px; font-weight: 600; margin-top: 20px; margin-bottom: 8px; }
|
|
41
|
+
|
|
42
|
+
p {
|
|
43
|
+
margin-bottom: 12px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
pre {
|
|
47
|
+
background: #f5f5f5;
|
|
48
|
+
border-radius: 8px;
|
|
49
|
+
padding: 12px 16px;
|
|
50
|
+
overflow-x: auto;
|
|
51
|
+
margin-bottom: 12px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
code {
|
|
55
|
+
font-family: "DM Mono", "SF Mono", monospace;
|
|
56
|
+
font-size: 13px;
|
|
57
|
+
background: #f5f5f5;
|
|
58
|
+
border-radius: 4px;
|
|
59
|
+
padding: 2px 5px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
pre code {
|
|
63
|
+
background: none;
|
|
64
|
+
padding: 0;
|
|
65
|
+
border-radius: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
blockquote {
|
|
69
|
+
border-left: 3px solid #6366f1;
|
|
70
|
+
padding-left: 16px;
|
|
71
|
+
margin: 12px 0;
|
|
72
|
+
color: #555555;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
table {
|
|
76
|
+
width: 100%;
|
|
77
|
+
border-collapse: collapse;
|
|
78
|
+
margin: 12px 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
th, td {
|
|
82
|
+
border: 1px solid #e0e0e0;
|
|
83
|
+
padding: 8px 12px;
|
|
84
|
+
text-align: left;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
th {
|
|
88
|
+
background: #f5f5f5;
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
ul, ol {
|
|
93
|
+
margin: 12px 0;
|
|
94
|
+
padding-left: 24px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
li {
|
|
98
|
+
margin-bottom: 4px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
a {
|
|
102
|
+
color: #6366f1;
|
|
103
|
+
text-decoration: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
hr {
|
|
107
|
+
border: none;
|
|
108
|
+
border-top: 1px solid #e0e0e0;
|
|
109
|
+
margin: 24px 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
img {
|
|
113
|
+
max-width: 100%;
|
|
114
|
+
height: auto;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
</style>
|
|
118
|
+
</head>
|
|
119
|
+
<body>
|
|
120
|
+
${innerHtml}
|
|
121
|
+
</body>
|
|
122
|
+
</html>`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Public API
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Convert a markdown string to a PDF buffer.
|
|
131
|
+
*
|
|
132
|
+
* Parses markdown to HTML via `marked`, wraps it in a print-friendly
|
|
133
|
+
* template, then renders to PDF using Playwright headless Chromium.
|
|
134
|
+
* The browser is always closed in a `finally` block.
|
|
135
|
+
*/
|
|
136
|
+
export async function renderMarkdownToPDF(
|
|
137
|
+
title: string,
|
|
138
|
+
markdown: string,
|
|
139
|
+
): Promise<Buffer> {
|
|
140
|
+
const innerHtml = marked.parse(markdown, {
|
|
141
|
+
gfm: true,
|
|
142
|
+
breaks: true,
|
|
143
|
+
}) as string;
|
|
144
|
+
const fullHtml = wrapInPrintTemplate(innerHtml);
|
|
145
|
+
|
|
146
|
+
const pw = await importPlaywright();
|
|
147
|
+
const browser = await pw.chromium.launch({ headless: true });
|
|
148
|
+
try {
|
|
149
|
+
const page = await browser.newPage();
|
|
150
|
+
await page.setContent(fullHtml, { waitUntil: "networkidle" });
|
|
151
|
+
const pdfBuffer = await page.pdf({
|
|
152
|
+
format: "A4",
|
|
153
|
+
margin: {
|
|
154
|
+
top: "0.75in",
|
|
155
|
+
bottom: "0.75in",
|
|
156
|
+
left: "0.75in",
|
|
157
|
+
right: "0.75in",
|
|
158
|
+
},
|
|
159
|
+
printBackground: true,
|
|
160
|
+
});
|
|
161
|
+
return Buffer.from(pdfBuffer);
|
|
162
|
+
} finally {
|
|
163
|
+
await browser.close();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -8,8 +8,10 @@ import { z } from "zod";
|
|
|
8
8
|
|
|
9
9
|
import { rawAll, rawGet, rawRun } from "../../memory/raw-query.js";
|
|
10
10
|
import { getLogger } from "../../util/logger.js";
|
|
11
|
+
import { renderMarkdownToPDF } from "./document-pdf-renderer.js";
|
|
11
12
|
import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
|
|
12
13
|
import type { RouteDefinition } from "./types.js";
|
|
14
|
+
import { RouteResponse } from "./types.js";
|
|
13
15
|
|
|
14
16
|
const log = getLogger("documents-routes");
|
|
15
17
|
|
|
@@ -312,4 +314,32 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
312
314
|
return result;
|
|
313
315
|
},
|
|
314
316
|
},
|
|
317
|
+
|
|
318
|
+
{
|
|
319
|
+
operationId: "exportDocumentPDF",
|
|
320
|
+
endpoint: "documents/:id/pdf",
|
|
321
|
+
method: "GET",
|
|
322
|
+
policyKey: "documents",
|
|
323
|
+
requirePolicyEnforcement: true,
|
|
324
|
+
summary: "Export a document as PDF",
|
|
325
|
+
description: "Render a document to PDF and return the binary content.",
|
|
326
|
+
tags: ["documents"],
|
|
327
|
+
handler: async ({ pathParams }) => {
|
|
328
|
+
const result = loadDocument(pathParams!.id);
|
|
329
|
+
if (!result.success) {
|
|
330
|
+
throw new NotFoundError(result.error);
|
|
331
|
+
}
|
|
332
|
+
const pdfBuffer = await renderMarkdownToPDF(result.title, result.content);
|
|
333
|
+
const filename =
|
|
334
|
+
result.title
|
|
335
|
+
.replace(/[^a-zA-Z0-9_-]/g, "-")
|
|
336
|
+
.replace(/-+/g, "-")
|
|
337
|
+
.replace(/^-|-$/g, "") || "document";
|
|
338
|
+
return new RouteResponse(new Uint8Array(pdfBuffer), {
|
|
339
|
+
"Content-Type": "application/pdf",
|
|
340
|
+
"Content-Disposition": `attachment; filename="${filename}.pdf"`,
|
|
341
|
+
"Content-Length": String(pdfBuffer.length),
|
|
342
|
+
});
|
|
343
|
+
},
|
|
344
|
+
},
|
|
315
345
|
];
|
|
@@ -10,12 +10,27 @@
|
|
|
10
10
|
export class RouteError extends Error {
|
|
11
11
|
readonly code: string;
|
|
12
12
|
readonly statusCode: number;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Optional structured payload surfaced to clients in the standard
|
|
15
|
+
* error envelope as `error.details`. Use sparingly — only when the
|
|
16
|
+
* client genuinely needs machine-readable context beyond `code` and
|
|
17
|
+
* `message` (e.g. mirroring a platform-side response shape).
|
|
18
|
+
*/
|
|
19
|
+
readonly details?: unknown;
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
message: string,
|
|
23
|
+
code: string,
|
|
24
|
+
statusCode: number,
|
|
25
|
+
details?: unknown,
|
|
26
|
+
) {
|
|
15
27
|
super(message);
|
|
16
28
|
this.name = "RouteError";
|
|
17
29
|
this.code = code;
|
|
18
30
|
this.statusCode = statusCode;
|
|
31
|
+
if (details !== undefined) {
|
|
32
|
+
this.details = details;
|
|
33
|
+
}
|
|
19
34
|
}
|
|
20
35
|
}
|
|
21
36
|
|
|
@@ -55,8 +70,8 @@ export class NotFoundError extends RouteError {
|
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
export class UnprocessableEntityError extends RouteError {
|
|
58
|
-
constructor(message: string) {
|
|
59
|
-
super(message, "UNPROCESSABLE_ENTITY", 422);
|
|
73
|
+
constructor(message: string, details?: unknown) {
|
|
74
|
+
super(message, "UNPROCESSABLE_ENTITY", 422, details);
|
|
60
75
|
this.name = "UnprocessableEntityError";
|
|
61
76
|
}
|
|
62
77
|
}
|
|
@@ -22,7 +22,10 @@ import type { HostProxyCapability } from "../../channels/types.js";
|
|
|
22
22
|
import { parseInterfaceId, supportsHostProxy } from "../../channels/types.js";
|
|
23
23
|
import { getOrCreateConversation } from "../../memory/conversation-key-store.js";
|
|
24
24
|
import { getLogger } from "../../util/logger.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
formatSseFrame,
|
|
27
|
+
formatSseHeartbeatWithData,
|
|
28
|
+
} from "../assistant-event.js";
|
|
26
29
|
import type {
|
|
27
30
|
AssistantEventCallback,
|
|
28
31
|
AssistantEventFilter,
|
|
@@ -37,8 +40,8 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
37
40
|
|
|
38
41
|
const log = getLogger("events-routes");
|
|
39
42
|
|
|
40
|
-
/** Keep-alive comment sent to idle clients every
|
|
41
|
-
const DEFAULT_HEARTBEAT_INTERVAL_MS =
|
|
43
|
+
/** Keep-alive comment sent to idle clients every 5 s by default. */
|
|
44
|
+
const DEFAULT_HEARTBEAT_INTERVAL_MS = 5_000;
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
47
|
* Stream assistant events as Server-Sent Events.
|
|
@@ -58,7 +61,7 @@ const DEFAULT_HEARTBEAT_INTERVAL_MS = 7_000;
|
|
|
58
61
|
*
|
|
59
62
|
* Options (for testing):
|
|
60
63
|
* hub -- override the event hub (defaults to process singleton).
|
|
61
|
-
* heartbeatIntervalMs -- how often to emit keep-alive comments (default
|
|
64
|
+
* heartbeatIntervalMs -- how often to emit keep-alive comments (default 5 s).
|
|
62
65
|
*/
|
|
63
66
|
export function handleSubscribeAssistantEvents(
|
|
64
67
|
args: RouteHandlerArgs,
|
|
@@ -77,6 +80,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
77
80
|
// ── Client identity from headers ──────────────────────────────────────
|
|
78
81
|
const rawClientId = headers?.["x-vellum-client-id"];
|
|
79
82
|
const rawInterfaceId = headers?.["x-vellum-interface-id"];
|
|
83
|
+
const rawMachineName = headers?.["x-vellum-machine-name"];
|
|
80
84
|
const clientId = rawClientId?.trim() || null;
|
|
81
85
|
const interfaceId = clientId
|
|
82
86
|
? parseInterfaceId(rawInterfaceId?.trim())
|
|
@@ -100,6 +104,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
100
104
|
"host_bash",
|
|
101
105
|
"host_file",
|
|
102
106
|
"host_cu",
|
|
107
|
+
"host_app_control",
|
|
103
108
|
"host_browser",
|
|
104
109
|
];
|
|
105
110
|
|
|
@@ -165,6 +170,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
165
170
|
capabilities: ALL_CAPABILITIES.filter((cap) =>
|
|
166
171
|
supportsHostProxy(interfaceId, cap),
|
|
167
172
|
),
|
|
173
|
+
machineName: rawMachineName?.trim() || undefined,
|
|
168
174
|
})
|
|
169
175
|
: hub.subscribe({
|
|
170
176
|
...subscriberBase,
|
|
@@ -188,7 +194,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
188
194
|
return;
|
|
189
195
|
}
|
|
190
196
|
|
|
191
|
-
controller.enqueue(encoder.encode(
|
|
197
|
+
controller.enqueue(encoder.encode(formatSseHeartbeatWithData()));
|
|
192
198
|
|
|
193
199
|
heartbeatTimer = setInterval(() => {
|
|
194
200
|
try {
|
|
@@ -200,7 +206,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
200
206
|
if (clientId) {
|
|
201
207
|
hub.touchClient(clientId);
|
|
202
208
|
}
|
|
203
|
-
controller.enqueue(encoder.encode(
|
|
209
|
+
controller.enqueue(encoder.encode(formatSseHeartbeatWithData()));
|
|
204
210
|
} catch {
|
|
205
211
|
sub.dispose();
|
|
206
212
|
cleanup();
|