@vellumai/assistant 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +48 -50
- 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/memory.md +5 -2
- 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 +52 -5
- 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/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- 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 +1020 -40
- 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 +384 -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 +157 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
- package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- 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-conversation-messages.test.ts +8 -2
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +62 -2
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +461 -147
- 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-schema.test.ts +1 -0
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
- package/src/__tests__/config-watcher.test.ts +142 -71
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +3 -7
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop.test.ts +454 -5
- 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-error.test.ts +150 -3
- 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-process-callsite.test.ts +43 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -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-runtime-assembly.test.ts +65 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -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 +12 -12
- package/src/__tests__/cu-unified-flow.test.ts +351 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +3 -4
- 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-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +968 -2
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +772 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +439 -47
- package/src/__tests__/host-bash-routes.test.ts +459 -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 +248 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
- package/src/__tests__/host-file-proxy.test.ts +301 -45
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +420 -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 +932 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
- package/src/__tests__/http-user-message-parity.test.ts +108 -1
- 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__/injector-chain.test.ts +18 -6
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- 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-profile-guard.test.ts +18 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
- 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__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/relay-server.test.ts +15 -4
- 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 +2 -2
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- 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__/suggestion-routes.test.ts +46 -0
- 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-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- 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-safe-storage-limits-release.test.ts +90 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/approvals/guardian-decision-primitive.ts +13 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -17
- 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/backup/snapshot-lock.ts +2 -27
- package/src/bundler/app-bundler.ts +51 -3
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-conversation-messages.ts +46 -10
- 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 -5
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +137 -25
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +71 -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 +303 -7
- package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
- package/src/cli/commands/oauth/connect.ts +127 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +16 -25
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +6 -2
- package/src/config/assistant-feature-flags.ts +79 -12
- 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/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- 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 -20
- package/src/config/feature-flag-registry.json +47 -135
- package/src/config/loader.ts +197 -104
- 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 +17 -9
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +64 -1
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +7 -10
- package/src/config/schemas/memory-lifecycle.ts +90 -24
- package/src/config/schemas/memory-v2.ts +121 -13
- package/src/config/schemas/platform.ts +49 -3
- package/src/config/schemas/services.ts +29 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -55
- 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 +187 -5
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +89 -60
- package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
- package/src/daemon/conversation-agent-loop.ts +202 -61
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +9 -4
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-runtime-assembly.ts +28 -2
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +305 -4
- package/src/daemon/conversation-tool-setup.ts +66 -62
- package/src/daemon/conversation.ts +38 -24
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -2
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +389 -0
- package/src/daemon/host-bash-proxy.ts +117 -82
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +127 -86
- package/src/daemon/host-file-proxy.ts +129 -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 +338 -129
- package/src/daemon/lifecycle.ts +194 -145
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +14 -4
- package/src/daemon/message-protocol.ts +6 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +15 -8
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- 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/messages.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/profiler-run-store.ts +5 -5
- 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/documents/document-store.ts +85 -0
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/filing/filing-service.ts +30 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
- package/src/heartbeat/heartbeat-run-store.ts +249 -0
- package/src/heartbeat/heartbeat-service.ts +459 -54
- 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/feed-scheduler.ts +18 -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/platform-callback-registration.ts +8 -15
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +70 -3
- package/src/ipc/cli-client.ts +32 -1
- package/src/ipc/gateway-client.ts +37 -3
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/live-voice/protocol.ts +5 -7
- 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/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -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/admin.ts +5 -9
- 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 +51 -9
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +22 -9
- package/src/memory/context-search/sources/memory.ts +0 -1
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +5 -13
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +6 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
- package/src/memory/graph/conversation-graph-memory.ts +43 -78
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +10 -67
- package/src/memory/graph/graph-search.ts +9 -20
- package/src/memory/graph/retriever.test.ts +6 -0
- package/src/memory/graph/retriever.ts +34 -10
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/indexer.ts +54 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- 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 +114 -22
- package/src/memory/jobs-worker.ts +193 -106
- package/src/memory/memory-v2-activation-log-store.ts +33 -15
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- 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/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +49 -32
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +13 -67
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +387 -344
- package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
- package/src/memory/v2/__tests__/injection.test.ts +181 -169
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +154 -188
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +76 -2
- package/src/memory/v2/activation.ts +213 -239
- package/src/memory/v2/consolidation-job.ts +65 -17
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +123 -103
- package/src/memory/v2/prompts/consolidation.ts +348 -92
- package/src/memory/v2/qdrant.ts +198 -1
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +113 -77
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +91 -53
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +28 -5
- package/src/memory/v2/types.ts +10 -10
- 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/copy-composer.ts +13 -0
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +6 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- 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/plugins/defaults/injectors.ts +35 -2
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +867 -0
- package/src/proactive-artifact/job.ts +352 -0
- package/src/proactive-artifact/message-copy.ts +41 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +23 -24
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +151 -99
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +32 -0
- package/src/runtime/auth/same-actor.ts +216 -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/channel-retry-sweep.ts +65 -1
- package/src/runtime/guardian-reply-router.ts +10 -0
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/local-actor-identity.ts +52 -11
- 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 +43 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
- 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 +21 -2
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +65 -39
- package/src/runtime/routes/debug-bash-routes.ts +163 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +169 -0
- package/src/runtime/routes/documents-routes.ts +32 -75
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +38 -0
- 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 +56 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +66 -9
- package/src/runtime/routes/host-file-routes.ts +54 -5
- package/src/runtime/routes/host-transfer-routes.ts +122 -19
- 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 +21 -180
- package/src/runtime/routes/inbound-message-handler.ts +78 -21
- 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/guardian-reply-intercept.ts +3 -0
- 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 +14 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.test.ts +41 -15
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +474 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- 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/run-script.ts +37 -5
- 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 +83 -39
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/security/secure-keys.ts +55 -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 +10 -16
- 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/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- 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/background-tool-registry.ts +17 -3
- 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.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +68 -0
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +68 -0
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +78 -3
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +68 -0
- package/src/tools/host-terminal/host-shell.ts +66 -1
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +12 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- 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/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +32 -11
- package/src/tools/types.ts +28 -2
- package/src/tts/provider-catalog.ts +3 -5
- package/src/usage/pricing.ts +1 -1
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/heartbeat-service.ts +19 -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/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- 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/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -395
- 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/bash.ts +0 -198
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -8,10 +8,16 @@
|
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
|
|
10
10
|
import { HostTransferProxy } from "../../daemon/host-transfer-proxy.js";
|
|
11
|
+
import {
|
|
12
|
+
enforceSameActorOrThrow,
|
|
13
|
+
SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
14
|
+
} from "../auth/same-actor.js";
|
|
15
|
+
import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
|
|
11
16
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
12
17
|
import {
|
|
13
18
|
BadRequestError,
|
|
14
19
|
ConflictError,
|
|
20
|
+
ForbiddenError,
|
|
15
21
|
NotFoundError,
|
|
16
22
|
} from "./errors.js";
|
|
17
23
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
@@ -34,6 +40,7 @@ function findProxyByTransferId(transferId: string) {
|
|
|
34
40
|
|
|
35
41
|
function handleTransferContentGet({
|
|
36
42
|
pathParams = {},
|
|
43
|
+
headers = {},
|
|
37
44
|
}: RouteHandlerArgs): Uint8Array {
|
|
38
45
|
const transferId = pathParams.transferId;
|
|
39
46
|
if (!transferId) {
|
|
@@ -45,6 +52,35 @@ function handleTransferContentGet({
|
|
|
45
52
|
throw new NotFoundError("Unknown or consumed transfer");
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
const targetClientId = match.proxy.getTargetClientIdForTransfer(transferId);
|
|
56
|
+
if (targetClientId != null) {
|
|
57
|
+
const headerMap = headers as Record<string, string | undefined>;
|
|
58
|
+
const submittingClientId =
|
|
59
|
+
headerMap["x-vellum-client-id"]?.trim() || undefined;
|
|
60
|
+
if (!submittingClientId)
|
|
61
|
+
throw new BadRequestError(
|
|
62
|
+
"x-vellum-client-id header required for targeted transfer",
|
|
63
|
+
);
|
|
64
|
+
if (submittingClientId !== targetClientId)
|
|
65
|
+
throw new ForbiddenError(
|
|
66
|
+
`Client "${submittingClientId}" is not the owner of this transfer`,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Defense-in-depth: the submitting actor's principal must match the
|
|
70
|
+
// actor that opened the target client's SSE stream. Compare against
|
|
71
|
+
// the value persisted at registration time so a brief reconnect does
|
|
72
|
+
// not 403 a legitimate fetch.
|
|
73
|
+
enforceSameActorOrThrow({
|
|
74
|
+
sourceActorPrincipalId: resolveActorPrincipalIdForLocalGuardian(
|
|
75
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
76
|
+
),
|
|
77
|
+
targetActorPrincipalId:
|
|
78
|
+
match.proxy.getTargetActorPrincipalIdForTransfer(transferId),
|
|
79
|
+
targetClientId,
|
|
80
|
+
op: "host_transfer",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
48
84
|
const content = match.proxy.getTransferContent(transferId);
|
|
49
85
|
if (!content) {
|
|
50
86
|
throw new NotFoundError("Unknown or consumed transfer");
|
|
@@ -55,8 +91,11 @@ function handleTransferContentGet({
|
|
|
55
91
|
|
|
56
92
|
/**
|
|
57
93
|
* Resolve Content-Length and X-Transfer-SHA256 response headers for the
|
|
58
|
-
* GET transfer content endpoint. Called by the HTTP adapter
|
|
59
|
-
*
|
|
94
|
+
* GET transfer content endpoint. Called by the HTTP adapter AFTER the handler
|
|
95
|
+
* runs (`http-adapter.ts:107-125`), so the entry has already been consumed by
|
|
96
|
+
* `getTransferContent`. We read the size/sha256 from
|
|
97
|
+
* `takeJustConsumedTransferMetadata`, which the proxy populates synchronously
|
|
98
|
+
* during the handler's `getTransferContent` call.
|
|
60
99
|
*/
|
|
61
100
|
function resolveTransferContentGetHeaders({
|
|
62
101
|
pathParams = {},
|
|
@@ -66,16 +105,14 @@ function resolveTransferContentGetHeaders({
|
|
|
66
105
|
const transferId = pathParams?.transferId;
|
|
67
106
|
if (!transferId) return { "Content-Type": "application/octet-stream" };
|
|
68
107
|
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const content = match.proxy.getTransferContent(transferId);
|
|
73
|
-
if (!content) return { "Content-Type": "application/octet-stream" };
|
|
108
|
+
const meta =
|
|
109
|
+
HostTransferProxy.instance.takeJustConsumedTransferMetadata(transferId);
|
|
110
|
+
if (!meta) return { "Content-Type": "application/octet-stream" };
|
|
74
111
|
|
|
75
112
|
return {
|
|
76
113
|
"Content-Type": "application/octet-stream",
|
|
77
|
-
"Content-Length":
|
|
78
|
-
"X-Transfer-SHA256":
|
|
114
|
+
"Content-Length": meta.sizeBytes.toString(),
|
|
115
|
+
"X-Transfer-SHA256": meta.sha256,
|
|
79
116
|
};
|
|
80
117
|
}
|
|
81
118
|
|
|
@@ -98,6 +135,31 @@ async function handleTransferContentPut({
|
|
|
98
135
|
throw new NotFoundError("Unknown or consumed transfer");
|
|
99
136
|
}
|
|
100
137
|
|
|
138
|
+
const targetClientId = match.proxy.getTargetClientIdForTransfer(transferId);
|
|
139
|
+
if (targetClientId != null) {
|
|
140
|
+
const headerMap = headers as Record<string, string | undefined>;
|
|
141
|
+
const submittingClientId =
|
|
142
|
+
headerMap["x-vellum-client-id"]?.trim() || undefined;
|
|
143
|
+
if (!submittingClientId)
|
|
144
|
+
throw new BadRequestError(
|
|
145
|
+
"x-vellum-client-id header required for targeted transfer",
|
|
146
|
+
);
|
|
147
|
+
if (submittingClientId !== targetClientId)
|
|
148
|
+
throw new ForbiddenError(
|
|
149
|
+
`Client "${submittingClientId}" is not the owner of this transfer`,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
enforceSameActorOrThrow({
|
|
153
|
+
sourceActorPrincipalId: resolveActorPrincipalIdForLocalGuardian(
|
|
154
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
155
|
+
),
|
|
156
|
+
targetActorPrincipalId:
|
|
157
|
+
match.proxy.getTargetActorPrincipalIdForTransfer(transferId),
|
|
158
|
+
targetClientId,
|
|
159
|
+
op: "host_transfer",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
101
163
|
const data = rawBody ? Buffer.from(rawBody) : Buffer.alloc(0);
|
|
102
164
|
const sha256 = headers["x-transfer-sha256"] ?? "";
|
|
103
165
|
|
|
@@ -107,11 +169,6 @@ async function handleTransferContentPut({
|
|
|
107
169
|
sha256,
|
|
108
170
|
);
|
|
109
171
|
|
|
110
|
-
// For to_sandbox transfers there is no separate /v1/host-transfer-result
|
|
111
|
-
// callback — the PUT handler is the terminal event. Always clean up the
|
|
112
|
-
// pending interaction so it doesn't leak.
|
|
113
|
-
pendingInteractions.resolve(match.requestId);
|
|
114
|
-
|
|
115
172
|
if (!result.accepted) {
|
|
116
173
|
throw new BadRequestError(result.error ?? "Transfer content rejected");
|
|
117
174
|
}
|
|
@@ -123,7 +180,7 @@ async function handleTransferContentPut({
|
|
|
123
180
|
// POST /v1/host-transfer-result
|
|
124
181
|
// ---------------------------------------------------------------------------
|
|
125
182
|
|
|
126
|
-
function handleTransferResult({ body }: RouteHandlerArgs) {
|
|
183
|
+
function handleTransferResult({ body, headers }: RouteHandlerArgs) {
|
|
127
184
|
if (!body || typeof body !== "object") {
|
|
128
185
|
throw new BadRequestError("Request body is required");
|
|
129
186
|
}
|
|
@@ -141,9 +198,7 @@ function handleTransferResult({ body }: RouteHandlerArgs) {
|
|
|
141
198
|
|
|
142
199
|
const peeked = pendingInteractions.get(requestId);
|
|
143
200
|
if (!peeked) {
|
|
144
|
-
throw new NotFoundError(
|
|
145
|
-
"No pending interaction found for this requestId",
|
|
146
|
-
);
|
|
201
|
+
throw new NotFoundError("No pending interaction found for this requestId");
|
|
147
202
|
}
|
|
148
203
|
|
|
149
204
|
if (peeked.kind !== "host_transfer") {
|
|
@@ -152,7 +207,28 @@ function handleTransferResult({ body }: RouteHandlerArgs) {
|
|
|
152
207
|
);
|
|
153
208
|
}
|
|
154
209
|
|
|
155
|
-
|
|
210
|
+
if (peeked.targetClientId != null) {
|
|
211
|
+
const headerMap = (headers as Record<string, string | undefined>) ?? {};
|
|
212
|
+
const rawClientId = headerMap["x-vellum-client-id"];
|
|
213
|
+
const submittingClientId = rawClientId?.trim() || undefined;
|
|
214
|
+
if (!submittingClientId)
|
|
215
|
+
throw new BadRequestError(
|
|
216
|
+
"x-vellum-client-id header is missing for a targeted host transfer request.",
|
|
217
|
+
);
|
|
218
|
+
if (submittingClientId !== peeked.targetClientId)
|
|
219
|
+
throw new ForbiddenError(
|
|
220
|
+
`Client "${submittingClientId}" is not the target for this request (expected "${peeked.targetClientId}").`,
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
enforceSameActorOrThrow({
|
|
224
|
+
sourceActorPrincipalId: resolveActorPrincipalIdForLocalGuardian(
|
|
225
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
226
|
+
),
|
|
227
|
+
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
228
|
+
targetClientId: peeked.targetClientId,
|
|
229
|
+
op: "host_transfer",
|
|
230
|
+
});
|
|
231
|
+
}
|
|
156
232
|
|
|
157
233
|
HostTransferProxy.instance.resolveTransferResult(requestId, {
|
|
158
234
|
isError: isError ?? false,
|
|
@@ -179,6 +255,15 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
179
255
|
"Serve raw file bytes for a to_host transfer. Single-use: returns 404 after first consumption.",
|
|
180
256
|
tags: ["host-transfer"],
|
|
181
257
|
responseHeaders: resolveTransferContentGetHeaders,
|
|
258
|
+
additionalResponses: {
|
|
259
|
+
"400": {
|
|
260
|
+
description:
|
|
261
|
+
"x-vellum-client-id header is missing for a targeted transfer.",
|
|
262
|
+
},
|
|
263
|
+
"403": {
|
|
264
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
182
267
|
handler: handleTransferContentGet,
|
|
183
268
|
},
|
|
184
269
|
{
|
|
@@ -191,6 +276,15 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
191
276
|
description:
|
|
192
277
|
"Receive raw file bytes for a to_sandbox transfer. Verifies SHA-256 integrity via the X-Transfer-SHA256 header.",
|
|
193
278
|
tags: ["host-transfer"],
|
|
279
|
+
additionalResponses: {
|
|
280
|
+
"400": {
|
|
281
|
+
description:
|
|
282
|
+
"x-vellum-client-id header is missing for a targeted transfer.",
|
|
283
|
+
},
|
|
284
|
+
"403": {
|
|
285
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
286
|
+
},
|
|
287
|
+
},
|
|
194
288
|
handler: handleTransferContentPut,
|
|
195
289
|
},
|
|
196
290
|
{
|
|
@@ -211,6 +305,15 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
211
305
|
responseBody: z.object({
|
|
212
306
|
accepted: z.boolean(),
|
|
213
307
|
}),
|
|
308
|
+
additionalResponses: {
|
|
309
|
+
"400": {
|
|
310
|
+
description:
|
|
311
|
+
"x-vellum-client-id header is missing for a targeted host transfer request.",
|
|
312
|
+
},
|
|
313
|
+
"403": {
|
|
314
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
315
|
+
},
|
|
316
|
+
},
|
|
214
317
|
handler: handleTransferResult,
|
|
215
318
|
},
|
|
216
319
|
];
|
|
@@ -48,6 +48,36 @@ function readWorkspaceFile(name: string): string {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function parseIdentityIntroSection(content: string): string | null {
|
|
52
|
+
let inSection = false;
|
|
53
|
+
|
|
54
|
+
for (const line of content.split("\n")) {
|
|
55
|
+
const trimmed = line.trim();
|
|
56
|
+
if (/^#+\s/.test(trimmed)) {
|
|
57
|
+
inSection = trimmed.toLowerCase().includes("identity intro");
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (inSection && trimmed.length > 0) {
|
|
61
|
+
return trimmed;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Read the explicit `## Identity Intro` section from workspace prompt files.
|
|
70
|
+
*
|
|
71
|
+
* BOOTSTRAP.md instructs the assistant to write this section in IDENTITY.md.
|
|
72
|
+
* SOUL.md remains a fallback for older workspaces that stored the intro there.
|
|
73
|
+
*/
|
|
74
|
+
export function readWorkspaceIdentityIntro(): string | null {
|
|
75
|
+
return (
|
|
76
|
+
parseIdentityIntroSection(readWorkspaceFile("IDENTITY.md")) ??
|
|
77
|
+
parseIdentityIntroSection(readWorkspaceFile("SOUL.md"))
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
51
81
|
/** Compute a SHA-256 hex hash of the concatenated identity file contents. */
|
|
52
82
|
export function computeIdentityContentHash(): string {
|
|
53
83
|
const staticFiles = IDENTITY_FILES.map(readWorkspaceFile).join("\n---\n");
|
|
@@ -2,163 +2,33 @@
|
|
|
2
2
|
* Identity and health endpoint handlers.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { existsSync, readFileSync, statfsSync, statSync } from "node:fs";
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
6
|
import { availableParallelism, cpus, totalmem } from "node:os";
|
|
8
7
|
|
|
9
8
|
import { z } from "zod";
|
|
10
9
|
|
|
11
|
-
import {
|
|
12
|
-
getCpuLimit,
|
|
13
|
-
getIsPlatform,
|
|
14
|
-
getMinikubeStorageSize,
|
|
15
|
-
} from "../../config/env-registry.js";
|
|
10
|
+
import { getCpuLimit, getIsPlatform } from "../../config/env-registry.js";
|
|
16
11
|
import { parseIdentityFields } from "../../daemon/handlers/identity.js";
|
|
17
12
|
import { getProfilerRuntimeStatus } from "../../daemon/profiler-run-store.js";
|
|
18
13
|
import { getMaxMigrationVersion } from "../../memory/migrations/registry.js";
|
|
19
14
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from "../../util/
|
|
15
|
+
getDiskUsageInfo,
|
|
16
|
+
parseK8sMemoryBytes,
|
|
17
|
+
} from "../../util/disk-usage.js";
|
|
18
|
+
import { getWorkspacePromptPath } from "../../util/platform.js";
|
|
23
19
|
import { APP_VERSION } from "../../version.js";
|
|
20
|
+
import { resolveHatchedAtReadOnly } from "../../workspace/hatched-date.js";
|
|
24
21
|
import { WORKSPACE_MIGRATIONS } from "../../workspace/migrations/registry.js";
|
|
25
22
|
import { getLastWorkspaceMigrationId } from "../../workspace/migrations/runner.js";
|
|
26
23
|
import { NotFoundError } from "./errors.js";
|
|
27
24
|
import { getCachedIntro } from "./identity-intro-cache.js";
|
|
28
25
|
import type { RouteDefinition } from "./types.js";
|
|
29
26
|
|
|
30
|
-
interface DiskSpaceInfo {
|
|
31
|
-
path: string;
|
|
32
|
-
totalMb: number;
|
|
33
|
-
usedMb: number;
|
|
34
|
-
freeMb: number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Measure the on-disk usage of one or more directory paths using `du -sb`.
|
|
39
|
-
* Returns the sum of all paths in bytes, or null on failure.
|
|
40
|
-
*/
|
|
41
|
-
function getDirectorySizeBytes(paths: string[]): number | null {
|
|
42
|
-
try {
|
|
43
|
-
const existing = paths.filter((p) => existsSync(p));
|
|
44
|
-
if (existing.length === 0) return null;
|
|
45
|
-
const result = spawnSync("du", ["-sb", ...existing], {
|
|
46
|
-
encoding: "utf-8",
|
|
47
|
-
timeout: 30_000,
|
|
48
|
-
});
|
|
49
|
-
if (result.status !== 0) return null;
|
|
50
|
-
let total = 0;
|
|
51
|
-
for (const line of result.stdout.trim().split("\n")) {
|
|
52
|
-
const size = parseInt(line.split("\t")[0], 10);
|
|
53
|
-
if (!isNaN(size) && size > 0) total += size;
|
|
54
|
-
}
|
|
55
|
-
return total > 0 ? total : null;
|
|
56
|
-
} catch {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const DU_CACHE_TTL_MS = 60_000;
|
|
62
|
-
let duCacheValue: number | null = null;
|
|
63
|
-
let duCacheTime = 0;
|
|
64
|
-
let duCachePaths: string | null = null;
|
|
65
|
-
|
|
66
|
-
function getCachedDirectorySizeBytes(paths: string[]): number | null {
|
|
67
|
-
const key = paths.join("\0");
|
|
68
|
-
const now = Date.now();
|
|
69
|
-
if (duCachePaths === key && now - duCacheTime < DU_CACHE_TTL_MS) {
|
|
70
|
-
return duCacheValue;
|
|
71
|
-
}
|
|
72
|
-
duCacheValue = getDirectorySizeBytes(paths);
|
|
73
|
-
duCacheTime = now;
|
|
74
|
-
duCachePaths = key;
|
|
75
|
-
return duCacheValue;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getDiskSpaceInfo(): DiskSpaceInfo | null {
|
|
79
|
-
try {
|
|
80
|
-
const wsDir = getWorkspaceDir();
|
|
81
|
-
const diskPath = existsSync(wsDir) ? wsDir : "/";
|
|
82
|
-
const stats = statfsSync(diskPath);
|
|
83
|
-
const fsTotalBytes = stats.bsize * stats.blocks;
|
|
84
|
-
const fsFreeBytes = stats.bsize * stats.bavail;
|
|
85
|
-
const bytesToMb = (b: number) =>
|
|
86
|
-
Math.round((b / (1024 * 1024)) * 100) / 100;
|
|
87
|
-
|
|
88
|
-
// Minikube mode: the platform passes the PVC storage size so we can
|
|
89
|
-
// report accurate capacity. On hostPath-backed PVCs statfsSync reports
|
|
90
|
-
// the host's entire filesystem rather than the PVC. Detect this by
|
|
91
|
-
// comparing filesystem size against PVC size — if the filesystem is
|
|
92
|
-
// larger, measure actual directory usage with `du` instead.
|
|
93
|
-
const storageSizeRaw = getMinikubeStorageSize();
|
|
94
|
-
if (storageSizeRaw) {
|
|
95
|
-
const pvcTotalBytes = parseK8sMemoryBytes(storageSizeRaw);
|
|
96
|
-
if (pvcTotalBytes !== null && fsTotalBytes > pvcTotalBytes * 1.1) {
|
|
97
|
-
const volumePaths = [diskPath];
|
|
98
|
-
if (diskPath !== "/data" && existsSync("/data")) {
|
|
99
|
-
volumePaths.push("/data");
|
|
100
|
-
}
|
|
101
|
-
const usedBytes = getCachedDirectorySizeBytes(volumePaths);
|
|
102
|
-
if (usedBytes !== null) {
|
|
103
|
-
return {
|
|
104
|
-
path: diskPath,
|
|
105
|
-
totalMb: bytesToMb(pvcTotalBytes),
|
|
106
|
-
usedMb: bytesToMb(usedBytes),
|
|
107
|
-
freeMb: bytesToMb(Math.max(0, pvcTotalBytes - usedBytes)),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
path: diskPath,
|
|
115
|
-
totalMb: bytesToMb(fsTotalBytes),
|
|
116
|
-
usedMb: bytesToMb(fsTotalBytes - fsFreeBytes),
|
|
117
|
-
freeMb: bytesToMb(fsFreeBytes),
|
|
118
|
-
};
|
|
119
|
-
} catch {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
27
|
interface MemoryInfo {
|
|
125
28
|
currentMb: number;
|
|
126
29
|
maxMb: number;
|
|
127
30
|
}
|
|
128
31
|
|
|
129
|
-
/**
|
|
130
|
-
* Parse a Kubernetes-style memory string (e.g. "3Gi", "512Mi", "1G") into bytes.
|
|
131
|
-
* Returns null if the value is not a recognized format.
|
|
132
|
-
*/
|
|
133
|
-
function parseK8sMemoryBytes(value: string): number | null {
|
|
134
|
-
const match = value
|
|
135
|
-
.trim()
|
|
136
|
-
.match(/^(\d+(?:\.\d+)?)\s*(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E|m)?$/);
|
|
137
|
-
if (!match) return null;
|
|
138
|
-
const num = parseFloat(match[1]);
|
|
139
|
-
const unit = match[2] ?? "";
|
|
140
|
-
const multipliers: Record<string, number> = {
|
|
141
|
-
"": 1,
|
|
142
|
-
m: 1e-3,
|
|
143
|
-
k: 1e3,
|
|
144
|
-
M: 1e6,
|
|
145
|
-
G: 1e9,
|
|
146
|
-
T: 1e12,
|
|
147
|
-
P: 1e15,
|
|
148
|
-
E: 1e18,
|
|
149
|
-
Ki: 1024,
|
|
150
|
-
Mi: 1024 ** 2,
|
|
151
|
-
Gi: 1024 ** 3,
|
|
152
|
-
Ti: 1024 ** 4,
|
|
153
|
-
Pi: 1024 ** 5,
|
|
154
|
-
Ei: 1024 ** 6,
|
|
155
|
-
};
|
|
156
|
-
const mult = multipliers[unit];
|
|
157
|
-
if (mult === undefined) return null;
|
|
158
|
-
const bytes = Math.round(num * mult);
|
|
159
|
-
return bytes > 0 ? bytes : null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
32
|
/**
|
|
163
33
|
* Read the memory limit from the VELLUM_MEMORY_LIMIT env var (K8s resource format),
|
|
164
34
|
* then fall back to cgroups, then to os.totalmem().
|
|
@@ -457,7 +327,7 @@ function getDetailedHealth() {
|
|
|
457
327
|
status: "healthy",
|
|
458
328
|
timestamp: new Date().toISOString(),
|
|
459
329
|
version: APP_VERSION,
|
|
460
|
-
disk:
|
|
330
|
+
disk: getDiskUsageInfo(),
|
|
461
331
|
memory: getMemoryInfo(),
|
|
462
332
|
cpu: getCpuInfo(),
|
|
463
333
|
migrations: {
|
|
@@ -488,13 +358,7 @@ function getIdentity() {
|
|
|
488
358
|
|
|
489
359
|
const version = APP_VERSION;
|
|
490
360
|
|
|
491
|
-
|
|
492
|
-
try {
|
|
493
|
-
const stats = statSync(identityPath);
|
|
494
|
-
createdAt = stats.birthtime.toISOString();
|
|
495
|
-
} catch {
|
|
496
|
-
// ignore
|
|
497
|
-
}
|
|
361
|
+
const createdAt = resolveIdentityCreatedAt(identityPath);
|
|
498
362
|
|
|
499
363
|
return {
|
|
500
364
|
name: fields.name ?? "",
|
|
@@ -507,10 +371,18 @@ function getIdentity() {
|
|
|
507
371
|
};
|
|
508
372
|
}
|
|
509
373
|
|
|
374
|
+
function resolveIdentityCreatedAt(identityPath: string): string | undefined {
|
|
375
|
+
return resolveHatchedAtReadOnly(identityPath);
|
|
376
|
+
}
|
|
377
|
+
|
|
510
378
|
function getIdentityIntro() {
|
|
511
|
-
const
|
|
512
|
-
if (
|
|
513
|
-
|
|
379
|
+
const identityPath = getWorkspacePromptPath("IDENTITY.md");
|
|
380
|
+
if (existsSync(identityPath)) {
|
|
381
|
+
const content = readFileSync(identityPath, "utf-8");
|
|
382
|
+
const fields = parseIdentityFields(content);
|
|
383
|
+
if (fields.name) {
|
|
384
|
+
return { text: `Hi, I'm ${fields.name}!` };
|
|
385
|
+
}
|
|
514
386
|
}
|
|
515
387
|
|
|
516
388
|
const cached = getCachedIntro();
|
|
@@ -520,37 +392,6 @@ function getIdentityIntro() {
|
|
|
520
392
|
return { text: cached.text };
|
|
521
393
|
}
|
|
522
394
|
|
|
523
|
-
// ---------------------------------------------------------------------------
|
|
524
|
-
// Identity intro cache
|
|
525
|
-
// ---------------------------------------------------------------------------
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* Parse the `## Identity Intro` section from SOUL.md.
|
|
529
|
-
* Returns the first non-empty line under that heading, or null.
|
|
530
|
-
*/
|
|
531
|
-
function readSoulIdentityIntro(): string | null {
|
|
532
|
-
try {
|
|
533
|
-
const soulPath = getWorkspacePromptPath("SOUL.md");
|
|
534
|
-
if (!existsSync(soulPath)) return null;
|
|
535
|
-
const content = readFileSync(soulPath, "utf-8");
|
|
536
|
-
|
|
537
|
-
let inSection = false;
|
|
538
|
-
for (const line of content.split("\n")) {
|
|
539
|
-
const trimmed = line.trim();
|
|
540
|
-
if (/^#+\s/.test(trimmed)) {
|
|
541
|
-
inSection = trimmed.toLowerCase().includes("identity intro");
|
|
542
|
-
continue;
|
|
543
|
-
}
|
|
544
|
-
if (inSection && trimmed.length > 0) {
|
|
545
|
-
return trimmed;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
} catch {
|
|
549
|
-
// Fall through to cache/fallback
|
|
550
|
-
}
|
|
551
|
-
return null;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
395
|
// ---------------------------------------------------------------------------
|
|
555
396
|
// Zod schemas for profiler health metadata
|
|
556
397
|
// ---------------------------------------------------------------------------
|
|
@@ -647,7 +488,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
647
488
|
handler: getIdentityIntro,
|
|
648
489
|
summary: "Get identity intro text",
|
|
649
490
|
description:
|
|
650
|
-
"Returns
|
|
491
|
+
"Returns a deterministic greeting derived from the assistant name in IDENTITY.md, falling back to LLM-generated cache.",
|
|
651
492
|
tags: ["identity"],
|
|
652
493
|
responseBody: z.object({
|
|
653
494
|
text: z.string(),
|
|
@@ -11,11 +11,12 @@ import {
|
|
|
11
11
|
isChannelId,
|
|
12
12
|
parseInterfaceId,
|
|
13
13
|
} from "../../channels/types.js";
|
|
14
|
-
import { touchContactInteraction } from "../../contacts/contacts-write.js";
|
|
15
14
|
import {
|
|
16
15
|
createApprovalConversationGenerator,
|
|
17
16
|
createApprovalCopyGenerator,
|
|
18
17
|
} from "../../daemon/approval-generators.js";
|
|
18
|
+
import { getDiskPressureStatus } from "../../daemon/disk-pressure-guard.js";
|
|
19
|
+
import { classifyDiskPressureTurnPolicy } from "../../daemon/disk-pressure-policy.js";
|
|
19
20
|
import { processMessage } from "../../daemon/process-message.js";
|
|
20
21
|
import type { TrustContext } from "../../daemon/trust-context.js";
|
|
21
22
|
import { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
getPendingVerificationReply,
|
|
37
38
|
} from "../../memory/delivery-channels.js";
|
|
38
39
|
import {
|
|
40
|
+
clearPayload,
|
|
39
41
|
findMessageBySourceId,
|
|
40
42
|
linkMessage,
|
|
41
43
|
recordInbound,
|
|
@@ -76,6 +78,8 @@ import { tryTranscribeAudioAttachments } from "./inbound-stages/transcribe-audio
|
|
|
76
78
|
import type { RouteHandlerArgs } from "./types.js";
|
|
77
79
|
|
|
78
80
|
const log = getLogger("runtime-http");
|
|
81
|
+
const DISK_PRESSURE_REMOTE_BLOCK_REPLY =
|
|
82
|
+
"Storage is critically low, so remote messages are ignored until the guardian frees enough space. Please try again later.";
|
|
79
83
|
|
|
80
84
|
// Delete-lookup retry configuration. Delete webhooks can race ahead of
|
|
81
85
|
// the inbound handler's `linkMessage` call when the original message's
|
|
@@ -442,7 +446,7 @@ export async function handleChannelInbound({
|
|
|
442
446
|
`[Voice message received — ${transcribeResult.reason}]` +
|
|
443
447
|
(trimmedContent ? `\n\n${trimmedContent}` : "");
|
|
444
448
|
break;
|
|
445
|
-
// "no_audio"
|
|
449
|
+
// "no_audio" — no action needed
|
|
446
450
|
}
|
|
447
451
|
}
|
|
448
452
|
|
|
@@ -511,13 +515,6 @@ export async function handleChannelInbound({
|
|
|
511
515
|
}
|
|
512
516
|
}
|
|
513
517
|
|
|
514
|
-
// Track contact interaction only for genuinely new messages (not webhook
|
|
515
|
-
// retries). This was previously in ACL enforcement which runs before dedup,
|
|
516
|
-
// causing retries to inflate interaction counts.
|
|
517
|
-
if (!result.duplicate && resolvedMember) {
|
|
518
|
-
touchContactInteraction(resolvedMember.channel.id);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
518
|
// external_conversation_bindings is assistant-agnostic. Restrict writes to
|
|
522
519
|
// self so assistant-scoped legacy routes do not overwrite each other's
|
|
523
520
|
// channel binding metadata for the same chat.
|
|
@@ -532,6 +529,78 @@ export async function handleChannelInbound({
|
|
|
532
529
|
});
|
|
533
530
|
}
|
|
534
531
|
|
|
532
|
+
// ── Actor role resolution ──
|
|
533
|
+
// Uses shared channel-agnostic resolution so all ingress paths classify
|
|
534
|
+
// guardian vs non-guardian actors the same way.
|
|
535
|
+
const trustCtx: TrustContext = resolveTrustContext({
|
|
536
|
+
assistantId: canonicalAssistantId,
|
|
537
|
+
sourceChannel,
|
|
538
|
+
conversationExternalId,
|
|
539
|
+
actorExternalId: rawSenderId,
|
|
540
|
+
actorUsername: body.actorUsername,
|
|
541
|
+
actorDisplayName: body.actorDisplayName,
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
const diskPressureDecision = classifyDiskPressureTurnPolicy(
|
|
545
|
+
getDiskPressureStatus(),
|
|
546
|
+
{
|
|
547
|
+
sourceChannel,
|
|
548
|
+
sourceInterface,
|
|
549
|
+
trustContext: {
|
|
550
|
+
sourceChannel: trustCtx.sourceChannel,
|
|
551
|
+
trustClass: trustCtx.trustClass,
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
);
|
|
555
|
+
if (diskPressureDecision.action === "block") {
|
|
556
|
+
if (!result.duplicate) {
|
|
557
|
+
clearPayload(result.eventId);
|
|
558
|
+
markProcessed(result.eventId);
|
|
559
|
+
}
|
|
560
|
+
log.info(
|
|
561
|
+
{
|
|
562
|
+
conversationId: result.conversationId,
|
|
563
|
+
eventId: result.eventId,
|
|
564
|
+
duplicate: result.duplicate,
|
|
565
|
+
reason: diskPressureDecision.reason,
|
|
566
|
+
trustClass: trustCtx.trustClass,
|
|
567
|
+
},
|
|
568
|
+
"Channel inbound blocked during disk pressure cleanup mode",
|
|
569
|
+
);
|
|
570
|
+
|
|
571
|
+
if (replyCallbackUrl && !result.duplicate) {
|
|
572
|
+
const replyPayload: Parameters<typeof deliverChannelReply>[1] = {
|
|
573
|
+
chatId: conversationExternalId,
|
|
574
|
+
text: DISK_PRESSURE_REMOTE_BLOCK_REPLY,
|
|
575
|
+
assistantId: canonicalAssistantId,
|
|
576
|
+
};
|
|
577
|
+
if (sourceChannel === "slack" && (canonicalSenderId ?? rawSenderId)) {
|
|
578
|
+
replyPayload.ephemeral = true;
|
|
579
|
+
replyPayload.user = (canonicalSenderId ?? rawSenderId)!;
|
|
580
|
+
}
|
|
581
|
+
try {
|
|
582
|
+
await deliverChannelReply(replyCallbackUrl, replyPayload);
|
|
583
|
+
} catch (err) {
|
|
584
|
+
log.warn(
|
|
585
|
+
{
|
|
586
|
+
err,
|
|
587
|
+
conversationId: result.conversationId,
|
|
588
|
+
eventId: result.eventId,
|
|
589
|
+
},
|
|
590
|
+
"Failed to deliver disk pressure block reply",
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return {
|
|
596
|
+
accepted: true,
|
|
597
|
+
duplicate: result.duplicate,
|
|
598
|
+
eventId: result.eventId,
|
|
599
|
+
diskPressure: "blocked",
|
|
600
|
+
reason: diskPressureDecision.reason,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
535
604
|
// ── Slack reaction handling ──
|
|
536
605
|
// Reactions arrive as regular `SlackInboundEvent`s with `callbackData`
|
|
537
606
|
// prefixed `reaction:` (added) or `reaction_removed:` (removed).
|
|
@@ -743,18 +812,6 @@ export async function handleChannelInbound({
|
|
|
743
812
|
// which handles request code matching, callback parsing, and NL classification
|
|
744
813
|
// against canonical_guardian_requests.
|
|
745
814
|
|
|
746
|
-
// ── Actor role resolution ──
|
|
747
|
-
// Uses shared channel-agnostic resolution so all ingress paths classify
|
|
748
|
-
// guardian vs non-guardian actors the same way.
|
|
749
|
-
const trustCtx: TrustContext = resolveTrustContext({
|
|
750
|
-
assistantId: canonicalAssistantId,
|
|
751
|
-
sourceChannel,
|
|
752
|
-
conversationExternalId,
|
|
753
|
-
actorExternalId: rawSenderId,
|
|
754
|
-
actorUsername: body.actorUsername,
|
|
755
|
-
actorDisplayName: body.actorDisplayName,
|
|
756
|
-
});
|
|
757
|
-
|
|
758
815
|
// ── Canonical guardian reply router ──
|
|
759
816
|
const guardianReplyResult = await handleGuardianReplyIntercept({
|
|
760
817
|
isDuplicate: result.duplicate,
|