@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f
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 +94 -91
- package/Dockerfile +5 -16
- package/README.md +7 -10
- package/bun.lock +0 -4
- package/docs/architecture/security.md +20 -20
- package/docs/stt-provider-onboarding.md +4 -5
- package/docs/trusted-contact-access.md +7 -7
- package/eslint-rules/cli-no-daemon-internals.js +4 -0
- package/eslint.config.mjs +7 -1
- package/knip.json +0 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
- package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
- package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
- package/openapi.yaml +1073 -225
- package/package.json +1 -4
- package/scripts/test.sh +35 -13
- package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
- package/src/__tests__/acp-session.test.ts +4 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
- package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
- package/src/__tests__/app-source-watcher.test.ts +11 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
- package/src/__tests__/assistant-attachments.test.ts +62 -4
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
- package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
- package/src/__tests__/attachments-store.test.ts +3 -0
- package/src/__tests__/background-shell-bash.test.ts +34 -0
- package/src/__tests__/background-shell-host-bash.test.ts +12 -0
- package/src/__tests__/background-tool-registry.test.ts +97 -0
- package/src/__tests__/background-tool-routes.test.ts +72 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/btw-routes.test.ts +57 -3
- package/src/__tests__/call-controller.test.ts +474 -84
- package/src/__tests__/call-domain.test.ts +48 -1
- package/src/__tests__/call-pointer-messages.test.ts +57 -19
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +15 -14
- package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
- package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
- package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
- package/src/__tests__/call-setup-flow.test.ts +311 -0
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -7
- package/src/__tests__/channel-readiness-service.test.ts +0 -6
- package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
- package/src/__tests__/channel-retry-sweep.test.ts +76 -64
- package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
- package/src/__tests__/clear-all-lexical.test.ts +90 -0
- package/src/__tests__/compactor-media-strip.test.ts +177 -0
- package/src/__tests__/config-loader-backfill.test.ts +5 -5
- package/src/__tests__/config-schema.test.ts +17 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
- package/src/__tests__/contacts-relay-reads.test.ts +188 -23
- package/src/__tests__/contacts-tools.test.ts +42 -1
- package/src/__tests__/contacts-write.test.ts +181 -0
- package/src/__tests__/context-search-conversations-source.test.ts +220 -81
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +39 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
- package/src/__tests__/conversation-clear-safety.test.ts +0 -1
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -0
- package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
- package/src/__tests__/conversation-error.test.ts +0 -18
- package/src/__tests__/conversation-fork-crud.test.ts +67 -0
- package/src/__tests__/conversation-history-web-search.test.ts +7 -137
- package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
- package/src/__tests__/conversation-process-callsite.test.ts +37 -0
- package/src/__tests__/conversation-queue.test.ts +149 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
- package/src/__tests__/conversation-skill-tools.test.ts +73 -0
- package/src/__tests__/conversation-wipe.test.ts +20 -5
- package/src/__tests__/credential-prompt-route.test.ts +69 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -3
- package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
- package/src/__tests__/edit-propagation.test.ts +56 -2
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
- package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
- package/src/__tests__/guardian-question-mode.test.ts +57 -0
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/guardian-wait-controller.test.ts +619 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
- package/src/__tests__/heic-fixture.ts +55 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
- package/src/__tests__/http-conversation-lineage.test.ts +6 -1
- package/src/__tests__/image-conversion.test.ts +170 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
- package/src/__tests__/introduction-card-resolver.test.ts +354 -0
- package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
- package/src/__tests__/invite-routes-http.test.ts +246 -420
- package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
- package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
- package/src/__tests__/list-messages-attachments.test.ts +159 -0
- package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
- package/src/__tests__/list-messages-queued.test.ts +25 -0
- package/src/__tests__/managed-store.test.ts +129 -1
- package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
- package/src/__tests__/media-stream-output.test.ts +350 -19
- package/src/__tests__/media-stream-server-integration.test.ts +943 -169
- package/src/__tests__/media-stream-stt-session.test.ts +498 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +19 -0
- package/src/__tests__/non-member-access-request.test.ts +349 -3
- package/src/__tests__/notification-decision-fallback.test.ts +104 -8
- package/src/__tests__/notification-decision-strategy.test.ts +57 -8
- package/src/__tests__/onboarding-template-contract.test.ts +27 -43
- package/src/__tests__/openai-provider.test.ts +33 -0
- package/src/__tests__/openai-responses-provider.test.ts +40 -0
- package/src/__tests__/persistence-layering-guard.test.ts +29 -20
- package/src/__tests__/persona-resolver.test.ts +56 -2
- package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
- package/src/__tests__/phone.test.ts +1 -15
- package/src/__tests__/plugin-bootstrap.test.ts +25 -196
- package/src/__tests__/plugin-disabled-state.test.ts +33 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
- package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
- package/src/__tests__/plugin-pipeline.test.ts +63 -1
- package/src/__tests__/plugin-route-contribution.test.ts +62 -115
- package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
- package/src/__tests__/plugin-types.test.ts +0 -1
- package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
- package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
- package/src/__tests__/public-ingress-urls.test.ts +0 -48
- package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
- package/src/__tests__/resolve-trust-class.test.ts +28 -10
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
- package/src/__tests__/schedule-retry.test.ts +38 -14
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
- package/src/__tests__/schedule-routes.test.ts +14 -6
- package/src/__tests__/schedule-store.test.ts +3 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
- package/src/__tests__/scheduler-recurrence.test.ts +57 -107
- package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
- package/src/__tests__/scheduler-wake.test.ts +13 -23
- package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/shell-observability.test.ts +1 -0
- package/src/__tests__/skill-boundary-guard.test.ts +3 -4
- package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
- package/src/__tests__/skill-script-runner-host.test.ts +53 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
- package/src/__tests__/skill-tool-factory.test.ts +73 -1
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
- package/src/__tests__/slack-inbound-verification.test.ts +36 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
- package/src/__tests__/stt-hints.test.ts +2 -256
- package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
- package/src/__tests__/subagent-persistence.test.ts +122 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +99 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
- package/src/__tests__/system-prompt.test.ts +17 -118
- package/src/__tests__/task-scheduler.test.ts +68 -89
- package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
- package/src/__tests__/telephony-tts-guard.test.ts +538 -0
- package/src/__tests__/title-generate-hook.test.ts +16 -0
- package/src/__tests__/tool-approval-handler.test.ts +87 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
- package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
- package/src/__tests__/trust-context-guards.test.ts +21 -10
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
- package/src/__tests__/twilio-provider.test.ts +17 -17
- package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
- package/src/__tests__/twilio-routes.test.ts +257 -387
- package/src/__tests__/twilio-validation.test.ts +1 -1
- package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
- package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
- package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
- package/src/__tests__/voice-quality.test.ts +2 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
- package/src/__tests__/voice-session-bridge.test.ts +1 -10
- package/src/__tests__/workspace-git-service.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
- package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
- package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
- package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
- package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
- package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
- package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
- package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
- package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
- package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
- package/src/acp/__tests__/session-manager.test.ts +6 -0
- package/src/acp/agent-process.test.ts +116 -0
- package/src/acp/agent-process.ts +71 -0
- package/src/acp/auto-install.ts +12 -8
- package/src/acp/failure-error.test.ts +109 -0
- package/src/acp/failure-error.ts +111 -0
- package/src/acp/prepare-agent-env.ts +0 -12
- package/src/acp/resolve-agent.test.ts +6 -45
- package/src/acp/resolve-agent.ts +2 -4
- package/src/acp/session-manager.test.ts +312 -0
- package/src/acp/session-manager.ts +102 -46
- package/src/agent/ax-tree-compaction.test.ts +4 -1
- package/src/agent/image-optimize.ts +17 -127
- package/src/agent/loop.ts +45 -192
- package/src/api/events/background-tool-completed.test.ts +51 -0
- package/src/api/events/background-tool-completed.ts +29 -0
- package/src/api/events/background-tool-started.test.ts +36 -0
- package/src/api/events/background-tool-started.ts +28 -0
- package/src/api/events/conversation-error.ts +0 -1
- package/src/api/events/open-panel.ts +33 -0
- package/src/api/events/subagent-status-changed.ts +4 -1
- package/src/api/index.ts +19 -0
- package/src/api/responses/conversation-message.ts +34 -0
- package/src/approvals/guardian-decision-primitive.ts +74 -24
- package/src/approvals/guardian-request-resolvers.ts +450 -122
- package/src/apps/app-store.ts +1 -0
- package/src/apps/shared-app-links-store.ts +1 -0
- package/src/avatar/identity-avatar.ts +3 -7
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
- package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
- package/src/calls/call-controller.ts +134 -48
- package/src/calls/call-domain.ts +18 -42
- package/src/calls/call-pointer-messages.ts +51 -67
- package/src/calls/call-setup-flow-types.ts +76 -0
- package/src/calls/call-setup-flow.ts +1743 -0
- package/src/calls/call-speech-output.ts +87 -23
- package/src/calls/call-store.ts +4 -0
- package/src/calls/call-transport.ts +22 -36
- package/src/calls/fish-audio-client.ts +3 -0
- package/src/calls/gateway-invite-reader.ts +98 -0
- package/src/calls/guardian-wait-controller.ts +451 -0
- package/src/calls/media-stream-audio-transcode.ts +82 -2
- package/src/calls/media-stream-output.ts +142 -36
- package/src/calls/media-stream-server.ts +297 -178
- package/src/calls/media-stream-stt-session.ts +393 -50
- package/src/calls/media-turn-detector.ts +4 -6
- package/src/calls/relay-access-wait.ts +3 -4
- package/src/calls/relay-setup-router.ts +22 -43
- package/src/calls/relay-verification.ts +17 -24
- package/src/calls/resolve-call-tts-provider.ts +96 -29
- package/src/calls/stt-hints.ts +24 -87
- package/src/calls/telephony-credential-preflight.ts +159 -0
- package/src/calls/telephony-tts-capability.ts +183 -0
- package/src/calls/tts-call-strategy.ts +18 -20
- package/src/calls/twilio-provider.ts +3 -2
- package/src/calls/twilio-routes.ts +47 -351
- package/src/calls/types.ts +5 -3
- package/src/calls/voice-ingress-preflight.ts +9 -0
- package/src/calls/voice-quality.ts +13 -18
- package/src/calls/voice-session-bridge.ts +25 -35
- package/src/channels/__tests__/types.test.ts +28 -0
- package/src/channels/channel-verification-sessions.ts +7 -2
- package/src/channels/config.ts +0 -42
- package/src/channels/slack-thread-store.ts +12 -0
- package/src/channels/types.ts +23 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
- package/src/cli/commands/__tests__/schedules.test.ts +83 -34
- package/src/cli/commands/__tests__/status.test.ts +42 -2
- package/src/cli/commands/contacts.ts +2 -2
- package/src/cli/commands/credentials.ts +17 -0
- package/src/cli/commands/monitoring.ts +191 -0
- package/src/cli/commands/schedules-worker.ts +175 -0
- package/src/cli/commands/schedules.ts +169 -43
- package/src/cli/commands/status.ts +12 -1
- package/src/cli/commands/tools.ts +5 -1
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
- package/src/cli/lib/search-plugins.ts +6 -0
- package/src/cli/lib/toggle-plugin.ts +21 -2
- package/src/cli/program.ts +3 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
- package/src/config/acp-defaults.test.ts +0 -10
- package/src/config/acp-defaults.ts +0 -6
- package/src/config/bundled-skills/acp/SKILL.md +13 -45
- package/src/config/bundled-skills/acp/TOOLS.json +3 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
- package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
- package/src/config/call-site-defaults.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -8
- package/src/config/loader.ts +11 -0
- package/src/config/schema.ts +9 -1
- package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
- package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
- package/src/config/schemas/call-site-catalog.ts +0 -12
- package/src/config/schemas/calls.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +1 -1
- package/src/config/schemas/llm.ts +0 -2
- package/src/config/schemas/memory-v2.ts +1 -1
- package/src/config/schemas/memory-v3.ts +82 -0
- package/src/config/schemas/monitoring.ts +61 -0
- package/src/config/schemas/schedules.ts +35 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills-plugin-filter.test.ts +96 -0
- package/src/config/skills.ts +26 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
- package/src/contacts/canonical-guardian-store.ts +5 -0
- package/src/contacts/contact-store.ts +81 -35
- package/src/contacts/contacts-write.ts +50 -25
- package/src/contacts/member-write-relay.ts +115 -31
- package/src/contacts/types.ts +0 -8
- package/src/context/compactor.ts +29 -15
- package/src/context/outbound-sanitize.ts +202 -0
- package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
- package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
- package/src/daemon/abort-watchdog.ts +7 -0
- package/src/daemon/app-source-watcher.ts +9 -0
- package/src/daemon/assistant-attachments.ts +42 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
- package/src/daemon/conversation-agent-loop.ts +61 -68
- package/src/daemon/conversation-error.ts +1 -15
- package/src/daemon/conversation-history.ts +32 -236
- package/src/daemon/conversation-initial-prompt.ts +77 -0
- package/src/daemon/conversation-lifecycle.ts +25 -1
- package/src/daemon/conversation-messaging.ts +2 -2
- package/src/daemon/conversation-plugin-scope.ts +38 -0
- package/src/daemon/conversation-process.ts +50 -14
- package/src/daemon/conversation-runtime-assembly.ts +36 -6
- package/src/daemon/conversation-skill-tools.ts +19 -3
- package/src/daemon/conversation-store.ts +3 -3
- package/src/daemon/conversation-surfaces.ts +171 -0
- package/src/daemon/conversation-tool-setup.test.ts +95 -0
- package/src/daemon/conversation-tool-setup.ts +116 -1
- package/src/daemon/conversation-turn-finalize.ts +211 -0
- package/src/daemon/conversation.ts +92 -1
- package/src/daemon/disk-pressure-policy.ts +2 -1
- package/src/daemon/event-loop-watchdog.ts +22 -6
- package/src/daemon/external-plugins-bootstrap.ts +47 -134
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
- package/src/daemon/handlers/config-a2a.ts +7 -14
- package/src/daemon/handlers/config-channels.ts +2 -10
- package/src/daemon/handlers/conversation-history.ts +3 -1
- package/src/daemon/handlers/conversations.ts +0 -52
- package/src/daemon/handlers/shared.ts +4 -24
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +59 -472
- package/src/daemon/message-protocol.ts +3 -3
- package/src/daemon/message-provenance.ts +12 -14
- package/src/daemon/message-types/background-tools.ts +28 -0
- package/src/daemon/message-types/contacts.ts +2 -10
- package/src/daemon/message-types/conversations.ts +10 -0
- package/src/daemon/message-types/integrations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pointer-conversation-trust.ts +23 -9
- package/src/daemon/pointer-turn-runner.ts +174 -0
- package/src/daemon/providers-setup.ts +16 -0
- package/src/daemon/shutdown-handlers.ts +139 -47
- package/src/daemon/skill-memory-refresh.ts +2 -2
- package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
- package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
- package/src/daemon/tool-setup-types.ts +8 -0
- package/src/daemon/trust-context.ts +21 -6
- package/src/daemon/turn-latency-tracker.test.ts +93 -0
- package/src/daemon/turn-latency-tracker.ts +38 -0
- package/src/daemon/wake-conversation-ops.ts +10 -8
- package/src/documents/document-comments-store.test.ts +7 -1
- package/src/documents/document-comments-store.ts +8 -0
- package/src/documents/document-store.ts +15 -0
- package/src/export/__tests__/transcript-formatter.test.ts +11 -0
- package/src/export/transcript-formatter.ts +49 -67
- package/src/home/__tests__/feed-writer.test.ts +247 -1
- package/src/home/conversation-starter-checkpoints.ts +1 -0
- package/src/home/feed-writer.ts +61 -0
- package/src/home/job-handlers/conversation-starters.ts +1 -0
- package/src/hooks/hook-loader.ts +12 -0
- package/src/hooks/registry.ts +32 -4
- package/src/inbound/public-ingress-urls.ts +0 -17
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
- package/src/ipc/assistant-server.ts +28 -7
- package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
- package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
- package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
- package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
- package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
- package/src/ipc/routes/db-proxy.ts +5 -2
- package/src/ipc/routes/invite-ipc-routes.ts +53 -39
- package/src/jobs/worker.ts +9 -2
- package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
- package/src/live-voice/live-voice-archive.ts +5 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
- package/src/messaging/providers/channel-transport.ts +6 -0
- package/src/messaging/providers/index.ts +3 -0
- package/src/messaging/providers/slack/api.test.ts +49 -1
- package/src/messaging/providers/slack/api.ts +110 -0
- package/src/messaging/providers/slack/send.test.ts +85 -0
- package/src/messaging/providers/slack/send.ts +100 -28
- package/src/messaging/providers/slack/transport.ts +7 -13
- package/src/messaging/providers/whatsapp/send.ts +29 -9
- package/src/monitoring/__tests__/control.test.ts +235 -0
- package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
- package/src/monitoring/control.ts +105 -0
- package/src/monitoring/resource-sampler.ts +258 -0
- package/src/monitoring/sample-ring-buffer.ts +108 -0
- package/src/monitoring/worker.ts +94 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/access-request-copy.ts +94 -23
- package/src/notifications/adapters/slack.ts +89 -21
- package/src/notifications/approval-card-builder.ts +33 -18
- package/src/notifications/approval-card-data.ts +48 -15
- package/src/notifications/broadcaster.ts +25 -16
- package/src/notifications/decision-engine.ts +131 -32
- package/src/notifications/guardian-question-mode.ts +58 -10
- package/src/permissions/approval-policy.ts +8 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/gateway-threshold-reader.ts +7 -6
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/secret-prompter.ts +11 -3
- package/src/permissions/types.ts +2 -2
- package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
- package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
- package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
- package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
- package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
- package/src/persistence/a2a-invite-store.ts +205 -0
- package/src/persistence/attachments-store.ts +94 -10
- package/src/persistence/checkpoints.ts +45 -0
- package/src/persistence/conversation-crud.ts +453 -260
- package/src/persistence/conversation-display-order-migration.ts +8 -2
- package/src/persistence/conversation-group-migration.test.ts +8 -0
- package/src/persistence/conversation-group-migration.ts +9 -0
- package/src/persistence/conversation-queries.ts +244 -125
- package/src/persistence/conversation-row-batch-delete.ts +9 -5
- package/src/persistence/conversation-search-lexical.ts +49 -0
- package/src/persistence/db-async-query.ts +42 -0
- package/src/persistence/db-connection.ts +13 -0
- package/src/persistence/delivery-channels.ts +0 -82
- package/src/persistence/delivery-crud.ts +27 -6
- package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
- package/src/persistence/embeddings/embedding-identity.ts +17 -5
- package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
- package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
- package/src/persistence/embeddings/qdrant-client.ts +81 -5
- package/src/persistence/group-crud.ts +13 -1
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
- package/src/persistence/job-handlers/cleanup.ts +57 -9
- package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
- package/src/persistence/job-handlers/message-lexical.ts +251 -0
- package/src/persistence/jobs-store.ts +102 -8
- package/src/persistence/jobs-worker.ts +68 -28
- package/src/persistence/llm-request-log-store.ts +35 -19
- package/src/persistence/llm-usage-store.ts +11 -0
- package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
- package/src/persistence/memory-lifecycle-hooks.ts +55 -1
- package/src/persistence/migrations/028-call-session-mode.ts +1 -1
- package/src/persistence/migrations/116-messages-fts.ts +8 -1
- package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
- package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
- package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
- package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
- package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
- package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
- package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
- package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
- package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
- package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
- package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
- package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
- package/src/persistence/raw-query.ts +50 -11
- package/src/persistence/schema/a2a.ts +14 -0
- package/src/persistence/schema/contacts.ts +0 -62
- package/src/persistence/schema/conversation-groups.ts +12 -0
- package/src/persistence/schema/conversations.ts +2 -0
- package/src/persistence/schema/documents.ts +65 -0
- package/src/persistence/schema/guardian.ts +4 -0
- package/src/persistence/schema/index.ts +4 -0
- package/src/persistence/schema/memory-injection.ts +62 -0
- package/src/persistence/schema/workflows.ts +55 -0
- package/src/persistence/slow-query-log.ts +437 -0
- package/src/persistence/slow-sync-log.ts +204 -0
- package/src/persistence/steps.ts +16 -0
- package/src/persistence/subagent-store.ts +125 -0
- package/src/persistence/worker-control.ts +45 -238
- package/src/plugin-api/event-hub-facade.ts +172 -0
- package/src/plugin-api/index.ts +9 -1
- package/src/plugin-api/types.ts +40 -9
- package/src/plugins/defaults/default-plugin-names.ts +60 -0
- package/src/plugins/defaults/index.ts +19 -29
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
- package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
- package/src/plugins/defaults/memory/config.ts +11 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
- package/src/plugins/defaults/memory/embeddings.ts +77 -0
- package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
- package/src/plugins/defaults/memory/frontmatter.ts +50 -0
- package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
- package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
- package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
- package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
- package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
- package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
- package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
- package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
- package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
- package/src/plugins/defaults/memory/graph/tools.ts +1 -1
- package/src/plugins/defaults/memory/hooks/init.ts +31 -5
- package/src/plugins/defaults/memory/indexer.ts +2 -3
- package/src/plugins/defaults/memory/injectors.ts +2 -2
- package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
- package/src/plugins/defaults/memory/job-handlers.ts +13 -12
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
- package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
- package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
- package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
- package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
- package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
- package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
- package/src/plugins/defaults/memory/search/semantic.ts +2 -2
- package/src/plugins/defaults/memory/startup.ts +244 -0
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
- package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
- package/src/plugins/defaults/memory/v2/activation.ts +2 -4
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
- package/src/plugins/defaults/memory/v2/migration.ts +2 -5
- package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
- package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
- package/src/plugins/defaults/memory/v2/router.ts +5 -5
- package/src/plugins/defaults/memory/v2/sim.ts +2 -4
- package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
- package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
- package/src/plugins/defaults/memory/v3/card.ts +1 -4
- package/src/plugins/defaults/memory/v3/dense.ts +60 -25
- package/src/plugins/defaults/memory/v3/edge.ts +1 -1
- package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
- package/src/plugins/defaults/memory/v3/gate.ts +158 -0
- package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
- package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
- package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
- package/src/plugins/defaults/memory/v3/prune.ts +2 -2
- package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
- package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
- package/src/plugins/defaults/turn-context/injectors.ts +1 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
- package/src/plugins/injector-registry.ts +13 -2
- package/src/plugins/mtime-cache.ts +36 -47
- package/src/plugins/pipeline.ts +15 -1
- package/src/plugins/types.ts +14 -23
- package/src/prompts/__tests__/system-prompt.test.ts +170 -32
- package/src/prompts/persona-resolver.ts +13 -9
- package/src/prompts/system-prompt.ts +30 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -119
- package/src/prompts/templates/SOUL.md +43 -13
- package/src/prompts/templates/system-sections.ts +32 -27
- package/src/prompts/templates/users/default.md +19 -0
- package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +14 -1
- package/src/providers/openai/responses-provider.ts +18 -0
- package/src/providers/placeholder-sentinels.ts +18 -8
- package/src/providers/retry.ts +1 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
- package/src/providers/speech-to-text/provider-catalog.ts +0 -89
- package/src/providers/speech-to-text/resolve.ts +55 -0
- package/src/providers/tool-progress-events.test.ts +50 -0
- package/src/providers/tool-progress-events.ts +99 -0
- package/src/providers/types.ts +1 -1
- package/src/providers/vellum-model-routing.test.ts +51 -0
- package/src/providers/vellum-model-routing.ts +84 -0
- package/src/runtime/AGENTS.md +5 -4
- package/src/runtime/__tests__/agent-wake.test.ts +158 -1
- package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
- package/src/runtime/access-request-helper.ts +154 -3
- package/src/runtime/actor-trust-resolver.ts +7 -21
- package/src/runtime/agent-wake.ts +41 -1
- package/src/runtime/assistant-event.ts +86 -12
- package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
- package/src/runtime/channel-approval-types.ts +52 -2
- package/src/runtime/channel-approvals.ts +23 -8
- package/src/runtime/channel-invite-transport.ts +2 -2
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-readiness-service.ts +3 -5
- package/src/runtime/channel-retry-sweep.ts +18 -24
- package/src/runtime/channel-verification-service.ts +9 -11
- package/src/runtime/finalize-event-delivery.ts +30 -16
- package/src/runtime/guardian-action-service.ts +10 -11
- package/src/runtime/guardian-reply-router.ts +122 -21
- package/src/runtime/http-server.ts +44 -101
- package/src/runtime/introduction-policy.test.ts +214 -0
- package/src/runtime/introduction-policy.ts +284 -0
- package/src/runtime/invite-service.ts +104 -361
- package/src/runtime/local-actor-identity.test.ts +38 -0
- package/src/runtime/local-actor-identity.ts +14 -0
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
- package/src/runtime/middleware/rate-limiter.ts +30 -0
- package/src/runtime/middleware/twilio-validation.ts +5 -7
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
- package/src/runtime/migrations/origin-mode.ts +6 -6
- package/src/runtime/pre-first-message-gate.ts +1 -0
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
- package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +15 -3
- package/src/runtime/routes/app-management-routes.ts +4 -7
- package/src/runtime/routes/approval-routes.ts +4 -0
- package/src/runtime/routes/attachment-routes.ts +54 -3
- package/src/runtime/routes/avatar-routes.ts +0 -4
- package/src/runtime/routes/background-tool-routes.ts +34 -5
- package/src/runtime/routes/btw-routes.ts +32 -4
- package/src/runtime/routes/channel-route-shared.ts +18 -14
- package/src/runtime/routes/channel-verification-routes.ts +0 -3
- package/src/runtime/routes/contact-routes.ts +298 -117
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +74 -37
- package/src/runtime/routes/conversation-query-routes.ts +5 -2
- package/src/runtime/routes/conversation-routes.ts +222 -82
- package/src/runtime/routes/conversations-import-routes.ts +8 -1
- package/src/runtime/routes/credential-prompt-routes.ts +20 -5
- package/src/runtime/routes/debug-routes.ts +1 -0
- package/src/runtime/routes/documents-routes.ts +5 -2
- package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
- package/src/runtime/routes/global-search-routes.ts +2 -1
- package/src/runtime/routes/guardian-approval-interception.ts +51 -0
- package/src/runtime/routes/home-feed-routes.ts +60 -1
- package/src/runtime/routes/identity-routes.ts +4 -87
- package/src/runtime/routes/inbound-message-handler.ts +82 -41
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
- package/src/runtime/routes/internal-twilio-routes.ts +0 -15
- package/src/runtime/routes/messages-lexical-routes.ts +75 -0
- package/src/runtime/routes/migration-routes.ts +69 -6
- package/src/runtime/routes/monitoring-routes.ts +237 -0
- package/src/runtime/routes/plugins-routes.ts +329 -8
- package/src/runtime/routes/schedule-routes.ts +49 -8
- package/src/runtime/routes/schedule-worker-routes.ts +210 -0
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
- package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
- package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
- package/src/runtime/services/analyze-conversation.ts +14 -4
- package/src/runtime/services/conversation-serializer.ts +5 -0
- package/src/runtime/slack-no-response.ts +47 -0
- package/src/runtime/slack-reply-session.test.ts +633 -0
- package/src/runtime/slack-reply-session.ts +382 -0
- package/src/runtime/slack-task-progress.ts +95 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/tool-grant-request-helper.ts +17 -1
- package/src/runtime/trust-class.test.ts +141 -0
- package/src/runtime/trust-class.ts +121 -0
- package/src/runtime/trust-verdict-consumer.ts +7 -6
- package/src/schedule/__tests__/run-script.test.ts +21 -0
- package/src/schedule/__tests__/worker-control.test.ts +241 -0
- package/src/schedule/run-script.ts +13 -6
- package/src/schedule/schedule-usage-store.ts +1 -0
- package/src/schedule/scheduler.ts +178 -127
- package/src/schedule/worker-control.ts +118 -0
- package/src/schedule/worker.ts +131 -0
- package/src/skills/__tests__/categories-cache.test.ts +38 -0
- package/src/skills/categories-cache.ts +40 -5
- package/src/skills/managed-store.ts +41 -6
- package/src/skills/validate-input.ts +47 -0
- package/src/stt/types.ts +5 -9
- package/src/subagent/manager.ts +267 -39
- package/src/subagent/types.ts +6 -2
- package/src/subagent/validate-allowlists.ts +65 -0
- package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
- package/src/telemetry/watchdog-direct-emit.ts +89 -0
- package/src/tools/acp/list-agents.test.ts +0 -6
- package/src/tools/background-tool-registry.ts +61 -0
- package/src/tools/document/document-comment-tool.test.ts +4 -0
- package/src/tools/host-terminal/host-shell.test.ts +397 -0
- package/src/tools/host-terminal/host-shell.ts +203 -14
- package/src/tools/skills/find-similar-skills.test.ts +152 -1
- package/src/tools/skills/find-similar-skills.ts +30 -4
- package/src/tools/skills/load.ts +36 -0
- package/src/tools/skills/scaffold-managed.ts +66 -34
- package/src/tools/skills/skill-script-runner.ts +17 -0
- package/src/tools/skills/skill-tool-factory.ts +5 -1
- package/src/tools/terminal/safe-env.ts +3 -0
- package/src/tools/terminal/shell.test.ts +177 -0
- package/src/tools/terminal/shell.ts +98 -4
- package/src/tools/tool-approval-handler.ts +106 -29
- package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
- package/src/tools/types.ts +29 -17
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tts/__tests__/provider-adapters.test.ts +37 -0
- package/src/tts/__tests__/provider-catalog.test.ts +21 -0
- package/src/tts/provider-catalog.ts +40 -9
- package/src/tts/providers/fish-audio-provider.ts +19 -10
- package/src/tts/types.ts +3 -4
- package/src/util/__tests__/process-tree.test.ts +10 -2
- package/src/util/__tests__/text-spacing.test.ts +53 -0
- package/src/util/cgroup-memory.ts +142 -0
- package/src/util/image-conversion.ts +281 -0
- package/src/util/phone.ts +1 -8
- package/src/util/platform.ts +33 -0
- package/src/util/process-tree.ts +10 -2
- package/src/util/text-spacing.ts +53 -0
- package/src/util/worker-process.ts +271 -0
- package/src/workflows/journal-store.ts +16 -1
- package/src/workflows/library.test.ts +35 -20
- package/src/workflows/library.ts +105 -66
- package/src/workspace/git-service.ts +1 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
- package/src/workspace/migrations/118-seed-now-md.ts +64 -0
- package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
- package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
- package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
- package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
- package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
- package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/drizzle/0000_dizzy_maggott.sql +0 -301
- package/drizzle/meta/0000_snapshot.json +0 -1933
- package/drizzle/meta/_journal.json +0 -13
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
- package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
- package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
- package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
- package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
- package/src/__tests__/invite-redemption-service.test.ts +0 -1180
- package/src/__tests__/invite-service-ipc.test.ts +0 -350
- package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
- package/src/__tests__/relay-server.test.ts +0 -6153
- package/src/__tests__/telephony-stt-routing.test.ts +0 -329
- package/src/__tests__/voice-invite-redemption.test.ts +0 -702
- package/src/calls/relay-server.ts +0 -2463
- package/src/calls/telephony-stt-routing.ts +0 -145
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
- package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
- package/src/daemon/daemon-skill-host.ts +0 -262
- package/src/daemon/message-types/meet.ts +0 -143
- package/src/daemon/shutdown-registry.ts +0 -40
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
- package/src/ipc/__tests__/skill-server.test.ts +0 -182
- package/src/ipc/skill-ipc-types.ts +0 -54
- package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
- package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
- package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
- package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
- package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
- package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
- package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
- package/src/ipc/skill-routes/config.ts +0 -47
- package/src/ipc/skill-routes/events.ts +0 -147
- package/src/ipc/skill-routes/identity.ts +0 -21
- package/src/ipc/skill-routes/index.ts +0 -37
- package/src/ipc/skill-routes/log.ts +0 -40
- package/src/ipc/skill-routes/memory.ts +0 -92
- package/src/ipc/skill-routes/platform.ts +0 -39
- package/src/ipc/skill-routes/providers.ts +0 -162
- package/src/ipc/skill-routes/registries.ts +0 -338
- package/src/ipc/skill-server.ts +0 -831
- package/src/ipc/skill-socket-path.ts +0 -20
- package/src/jobs/register-job-handlers.ts +0 -74
- package/src/persistence/invite-store.ts +0 -481
- package/src/plugins/job-handler-registry.ts +0 -94
- package/src/providers/cache-control.ts +0 -26
- package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
- package/src/runtime/invite-redemption-service.ts +0 -828
- package/src/runtime/invite-redemption-templates.ts +0 -46
- package/src/runtime/runtime-mode.ts +0 -40
- package/src/runtime/slack-dm-text-delivery.ts +0 -177
- package/src/util/voice-code.ts +0 -31
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { joinWithSpacing, needsBoundarySpace } from "../text-spacing.js";
|
|
4
|
+
|
|
5
|
+
describe("needsBoundarySpace", () => {
|
|
6
|
+
test("true when both sides fuse two non-whitespace characters", () => {
|
|
7
|
+
expect(needsBoundarySpace("end.", "Next")).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("false when the left side already ends in whitespace", () => {
|
|
11
|
+
expect(needsBoundarySpace("end. ", "Next")).toBe(false);
|
|
12
|
+
expect(needsBoundarySpace("end.\n", "Next")).toBe(false);
|
|
13
|
+
expect(needsBoundarySpace("end.\t", "Next")).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("false when the right side already starts with whitespace", () => {
|
|
17
|
+
expect(needsBoundarySpace("end.", " Next")).toBe(false);
|
|
18
|
+
expect(needsBoundarySpace("end.", "\nNext")).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("false when either side is empty", () => {
|
|
22
|
+
expect(needsBoundarySpace("", "Next")).toBe(false);
|
|
23
|
+
expect(needsBoundarySpace("end.", "")).toBe(false);
|
|
24
|
+
expect(needsBoundarySpace("", "")).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("joinWithSpacing", () => {
|
|
29
|
+
test("inserts a single space between fused segments", () => {
|
|
30
|
+
expect(joinWithSpacing(["Sentence one.", "Sentence two."])).toBe(
|
|
31
|
+
"Sentence one. Sentence two.",
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("preserves whitespace the parts already supply", () => {
|
|
36
|
+
expect(joinWithSpacing(["First half. ", "Second half."])).toBe(
|
|
37
|
+
"First half. Second half.",
|
|
38
|
+
);
|
|
39
|
+
expect(joinWithSpacing(["First.", " Second."])).toBe("First. Second.");
|
|
40
|
+
expect(joinWithSpacing(["Line one\n", "Line two"])).toBe(
|
|
41
|
+
"Line one\nLine two",
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("does not alter intra-part spacing", () => {
|
|
46
|
+
expect(joinWithSpacing(["a b c"])).toBe("a b c");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("skips empty parts without inserting stray spaces", () => {
|
|
50
|
+
expect(joinWithSpacing(["Done.", "", "More."])).toBe("Done. More.");
|
|
51
|
+
expect(joinWithSpacing([])).toBe("");
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container memory accounting read from cgroup files (and the platform
|
|
3
|
+
* `VELLUM_MEMORY_LIMIT` override).
|
|
4
|
+
*
|
|
5
|
+
* Shared by the `/v1/health` identity handler (which reports current + max) and
|
|
6
|
+
* the resource monitor (which additionally samples the peak and the
|
|
7
|
+
* memory.events pressure counters). Keeping the cgroup v2→v1 fallbacks in one
|
|
8
|
+
* place means a single source of truth for how the assistant reads its own
|
|
9
|
+
* memory footprint.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync } from "node:fs";
|
|
13
|
+
import { totalmem } from "node:os";
|
|
14
|
+
|
|
15
|
+
import { parseK8sMemoryBytes } from "./disk-usage.js";
|
|
16
|
+
|
|
17
|
+
function readCgroupInt(path: string): number | null {
|
|
18
|
+
try {
|
|
19
|
+
const raw = readFileSync(path, "utf-8").trim();
|
|
20
|
+
if (raw === "max") return null;
|
|
21
|
+
const bytes = parseInt(raw, 10);
|
|
22
|
+
return Number.isFinite(bytes) && bytes > 0 ? bytes : null;
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Read the memory limit from the VELLUM_MEMORY_LIMIT env var (K8s resource
|
|
30
|
+
* format), then fall back to cgroups, then to os.totalmem() at the call site.
|
|
31
|
+
*
|
|
32
|
+
* In platform mode the container runs under gVisor where cgroup files may report
|
|
33
|
+
* the node's memory rather than the container limit. VELLUM_MEMORY_LIMIT is set
|
|
34
|
+
* by the StatefulSet template to the exact K8s memory limit (e.g. "3Gi").
|
|
35
|
+
*/
|
|
36
|
+
export function getContainerMemoryLimitBytes(): number | null {
|
|
37
|
+
// 1. Prefer the explicit env var set by the platform StatefulSet template.
|
|
38
|
+
try {
|
|
39
|
+
const envLimit = process.env.VELLUM_MEMORY_LIMIT;
|
|
40
|
+
if (envLimit) {
|
|
41
|
+
const parsed = parseK8sMemoryBytes(envLimit);
|
|
42
|
+
if (parsed !== null) return parsed;
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
/* env var parsing failed – fall through to cgroups */
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 2. Try cgroups v2.
|
|
49
|
+
const v2 = readCgroupInt("/sys/fs/cgroup/memory.max");
|
|
50
|
+
if (v2 !== null) return v2;
|
|
51
|
+
|
|
52
|
+
// 3. Try cgroups v1.
|
|
53
|
+
try {
|
|
54
|
+
const raw = readFileSync(
|
|
55
|
+
"/sys/fs/cgroup/memory/memory.limit_in_bytes",
|
|
56
|
+
"utf-8",
|
|
57
|
+
).trim();
|
|
58
|
+
const bytes = parseInt(raw, 10);
|
|
59
|
+
// cgroups v1 uses a near-INT64_MAX sentinel when no limit is set.
|
|
60
|
+
if (!isNaN(bytes) && bytes > 0 && bytes < totalmem() * 1.5) return bytes;
|
|
61
|
+
} catch {
|
|
62
|
+
/* not available */
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Read the container's current memory usage from cgroup files.
|
|
69
|
+
*
|
|
70
|
+
* Tries cgroups v2 (`memory.current`) first, then cgroups v1
|
|
71
|
+
* (`memory/memory.usage_in_bytes`), mirroring the v2-then-v1 fallback used by
|
|
72
|
+
* {@link getContainerMemoryLimitBytes}. Returns null if neither file is
|
|
73
|
+
* available or readable.
|
|
74
|
+
*
|
|
75
|
+
* Unlike the limit lookup, no env-var override is needed: the gVisor issue that
|
|
76
|
+
* motivates VELLUM_MEMORY_LIMIT is specifically about the *limit* files exposing
|
|
77
|
+
* the host node's memory instead of the sandbox limit. The *usage* files
|
|
78
|
+
* (memory.current / memory.usage_in_bytes) reflect the sandbox's own accounting
|
|
79
|
+
* and are accurate under gVisor.
|
|
80
|
+
*/
|
|
81
|
+
export function getContainerMemoryUsageBytes(): number | null {
|
|
82
|
+
return (
|
|
83
|
+
readCgroupInt("/sys/fs/cgroup/memory.current") ??
|
|
84
|
+
readCgroupInt("/sys/fs/cgroup/memory/memory.usage_in_bytes")
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Read the high-water mark of the container's memory usage.
|
|
90
|
+
*
|
|
91
|
+
* cgroups v2 (`memory.peak`) first, then cgroups v1
|
|
92
|
+
* (`memory/memory.max_usage_in_bytes`). Returns null when neither is available
|
|
93
|
+
* — `memory.peak` in particular only exists on newer kernels, so callers must
|
|
94
|
+
* tolerate its absence.
|
|
95
|
+
*/
|
|
96
|
+
export function getContainerMemoryPeakBytes(): number | null {
|
|
97
|
+
return (
|
|
98
|
+
readCgroupInt("/sys/fs/cgroup/memory.peak") ??
|
|
99
|
+
readCgroupInt("/sys/fs/cgroup/memory/memory.max_usage_in_bytes")
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Pressure counters from the cgroup v2 `memory.events` file. Each field counts
|
|
105
|
+
* how many times the cgroup crossed the corresponding boundary since boot; a
|
|
106
|
+
* rising `max` (usage hit the hard limit and allocation was throttled) or
|
|
107
|
+
* `oom_kill` (a process was reaped) is the clearest in-VM signal that the
|
|
108
|
+
* container is being squeezed toward an OOM kill. Returns null on cgroups v1 or
|
|
109
|
+
* when the file is unreadable.
|
|
110
|
+
*/
|
|
111
|
+
export interface ContainerMemoryEvents {
|
|
112
|
+
low: number;
|
|
113
|
+
high: number;
|
|
114
|
+
max: number;
|
|
115
|
+
oom: number;
|
|
116
|
+
oomKill: number;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function getContainerMemoryEvents(): ContainerMemoryEvents | null {
|
|
120
|
+
let raw: string;
|
|
121
|
+
try {
|
|
122
|
+
raw = readFileSync("/sys/fs/cgroup/memory.events", "utf-8");
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const counts: Record<string, number> = {};
|
|
128
|
+
for (const line of raw.split("\n")) {
|
|
129
|
+
const [key, value] = line.trim().split(/\s+/);
|
|
130
|
+
if (!key) continue;
|
|
131
|
+
const parsed = parseInt(value, 10);
|
|
132
|
+
if (Number.isFinite(parsed)) counts[key] = parsed;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
low: counts.low ?? 0,
|
|
137
|
+
high: counts.high ?? 0,
|
|
138
|
+
max: counts.max ?? 0,
|
|
139
|
+
oom: counts.oom ?? 0,
|
|
140
|
+
oomKill: counts.oom_kill ?? 0,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JPEG conversion for images, backed by macOS `sips`.
|
|
3
|
+
*
|
|
4
|
+
* Two consumers share this converter:
|
|
5
|
+
* - transport optimization (`agent/image-optimize.ts`) downscales large
|
|
6
|
+
* images before provider calls;
|
|
7
|
+
* - storage normalization (attachment ingress + history hydration) converts
|
|
8
|
+
* HEIF/HEIC — which Chromium-based clients cannot decode — to JPEG.
|
|
9
|
+
*
|
|
10
|
+
* Conversion runs `sips` (a macOS builtin); on other platforms or on any
|
|
11
|
+
* failure it returns null and callers keep the original bytes. Results are
|
|
12
|
+
* cached on disk keyed by content hash + conversion options, so repeated
|
|
13
|
+
* conversions of the same image (or daemon restarts) skip the sips call.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { execFileSync } from "node:child_process";
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
import {
|
|
19
|
+
existsSync,
|
|
20
|
+
mkdirSync,
|
|
21
|
+
readdirSync,
|
|
22
|
+
readFileSync,
|
|
23
|
+
statSync,
|
|
24
|
+
unlinkSync,
|
|
25
|
+
writeFileSync,
|
|
26
|
+
} from "node:fs";
|
|
27
|
+
import { tmpdir } from "node:os";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
|
|
30
|
+
import { v4 as uuid } from "uuid";
|
|
31
|
+
|
|
32
|
+
const DEFAULT_JPEG_QUALITY = 80;
|
|
33
|
+
|
|
34
|
+
/** Full-resolution quality for stored attachment masters. */
|
|
35
|
+
const STORAGE_JPEG_QUALITY = 90;
|
|
36
|
+
|
|
37
|
+
const CACHE_MAX_ENTRIES = 500;
|
|
38
|
+
|
|
39
|
+
function getCacheDir(): string {
|
|
40
|
+
return join(tmpdir(), "vellum-optimized-images");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readFromCache(key: string): Buffer | null {
|
|
44
|
+
try {
|
|
45
|
+
const cachePath = join(getCacheDir(), `${key}.jpg`);
|
|
46
|
+
if (!existsSync(cachePath)) return null;
|
|
47
|
+
return readFileSync(cachePath) as Buffer;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function writeToCache(key: string, convertedBytes: Buffer): void {
|
|
54
|
+
try {
|
|
55
|
+
const dir = getCacheDir();
|
|
56
|
+
mkdirSync(dir, { recursive: true });
|
|
57
|
+
writeFileSync(join(dir, `${key}.jpg`), convertedBytes);
|
|
58
|
+
evictIfNeeded(dir);
|
|
59
|
+
} catch {
|
|
60
|
+
// Cache write failure is non-fatal.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function evictIfNeeded(dir: string): void {
|
|
65
|
+
try {
|
|
66
|
+
const entries = readdirSync(dir)
|
|
67
|
+
.filter((f) => f.endsWith(".jpg"))
|
|
68
|
+
.map((f) => {
|
|
69
|
+
const full = join(dir, f);
|
|
70
|
+
return { path: full, mtimeMs: statSync(full).mtimeMs };
|
|
71
|
+
})
|
|
72
|
+
.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
73
|
+
const excess = entries.length - CACHE_MAX_ENTRIES;
|
|
74
|
+
for (let i = 0; i < excess; i++) {
|
|
75
|
+
try {
|
|
76
|
+
unlinkSync(entries[i]!.path);
|
|
77
|
+
} catch {
|
|
78
|
+
/* ignore */
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
/* ignore */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface ConvertToJpegOptions {
|
|
87
|
+
/** Downscale so neither side exceeds this; omit to keep full resolution. */
|
|
88
|
+
maxDimensionPx?: number;
|
|
89
|
+
/** JPEG quality 1-100 (default 80). */
|
|
90
|
+
quality?: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function runSips(
|
|
94
|
+
inputBytes: Uint8Array,
|
|
95
|
+
options: ConvertToJpegOptions,
|
|
96
|
+
): Buffer | null {
|
|
97
|
+
const stamp = `${Date.now()}-${uuid().slice(0, 8)}`;
|
|
98
|
+
const srcPath = join(tmpdir(), `vellum-img-opt-${stamp}-src`);
|
|
99
|
+
const outPath = join(tmpdir(), `vellum-img-opt-${stamp}-out.jpg`);
|
|
100
|
+
try {
|
|
101
|
+
writeFileSync(srcPath, inputBytes);
|
|
102
|
+
const args =
|
|
103
|
+
options.maxDimensionPx != null
|
|
104
|
+
? ["--resampleHeightWidthMax", String(options.maxDimensionPx)]
|
|
105
|
+
: [];
|
|
106
|
+
args.push(
|
|
107
|
+
"-s",
|
|
108
|
+
"format",
|
|
109
|
+
"jpeg",
|
|
110
|
+
"-s",
|
|
111
|
+
"formatOptions",
|
|
112
|
+
String(options.quality ?? DEFAULT_JPEG_QUALITY),
|
|
113
|
+
srcPath,
|
|
114
|
+
"--out",
|
|
115
|
+
outPath,
|
|
116
|
+
);
|
|
117
|
+
execFileSync("sips", args, { stdio: "pipe", timeout: 15_000 });
|
|
118
|
+
return readFileSync(outPath) as Buffer;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
} finally {
|
|
122
|
+
try {
|
|
123
|
+
unlinkSync(srcPath);
|
|
124
|
+
} catch {
|
|
125
|
+
/* ignore */
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
unlinkSync(outPath);
|
|
129
|
+
} catch {
|
|
130
|
+
/* ignore */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Convert an image to JPEG, optionally downscaling. Returns null when
|
|
137
|
+
* conversion is unavailable (non-macOS) or fails; callers keep the original.
|
|
138
|
+
*/
|
|
139
|
+
export function convertImageToJpeg(
|
|
140
|
+
bytes: Uint8Array,
|
|
141
|
+
options: ConvertToJpegOptions = {},
|
|
142
|
+
): Buffer | null {
|
|
143
|
+
const hash = createHash("sha256").update(bytes).digest("hex").slice(0, 16);
|
|
144
|
+
// Options qualify the key so full-resolution storage conversions and
|
|
145
|
+
// downscaled transport conversions of the same source never collide.
|
|
146
|
+
const cacheKey = `${hash}-${options.maxDimensionPx ?? "full"}-q${options.quality ?? DEFAULT_JPEG_QUALITY}`;
|
|
147
|
+
|
|
148
|
+
const cached = readFromCache(cacheKey);
|
|
149
|
+
if (cached) return cached;
|
|
150
|
+
|
|
151
|
+
const converted = runSips(bytes, options);
|
|
152
|
+
if (!converted) return null;
|
|
153
|
+
|
|
154
|
+
writeToCache(cacheKey, converted);
|
|
155
|
+
return converted;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// HEIF container brands (ISO BMFF `ftyp` major brand). AVIF brands are
|
|
159
|
+
// deliberately absent: Chromium decodes AVIF natively, so it needs no
|
|
160
|
+
// normalization.
|
|
161
|
+
const HEIF_FTYP_BRANDS = new Set([
|
|
162
|
+
"heic",
|
|
163
|
+
"heix",
|
|
164
|
+
"hevc",
|
|
165
|
+
"hevx",
|
|
166
|
+
"heif",
|
|
167
|
+
"heim",
|
|
168
|
+
"heis",
|
|
169
|
+
"hevm",
|
|
170
|
+
"hevs",
|
|
171
|
+
"mif1",
|
|
172
|
+
"msf1",
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Content-based HEIF/HEIC detection. MIME metadata is unreliable here:
|
|
177
|
+
* Chromium reports an empty `file.type` for `.heic`, which clients coerce to
|
|
178
|
+
* `application/octet-stream`.
|
|
179
|
+
*/
|
|
180
|
+
export function isHeifImage(bytes: Uint8Array): boolean {
|
|
181
|
+
if (bytes.length < 12) return false;
|
|
182
|
+
// ISO BMFF layout: bytes 4-8 are "ftyp", bytes 8-12 the major brand.
|
|
183
|
+
if (
|
|
184
|
+
bytes[4] !== 0x66 || // f
|
|
185
|
+
bytes[5] !== 0x74 || // t
|
|
186
|
+
bytes[6] !== 0x79 || // y
|
|
187
|
+
bytes[7] !== 0x70 // p
|
|
188
|
+
) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
const brand = String.fromCharCode(
|
|
192
|
+
bytes[8]!,
|
|
193
|
+
bytes[9]!,
|
|
194
|
+
bytes[10]!,
|
|
195
|
+
bytes[11]!,
|
|
196
|
+
);
|
|
197
|
+
return HEIF_FTYP_BRANDS.has(brand);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const HEIF_FILENAME_RE = /\.(heic|heif)$/i;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Filename-extension HEIF/HEIC detection, for call sites that only hold
|
|
204
|
+
* attachment metadata (filename + MIME) and want to skip hydrating bytes for
|
|
205
|
+
* non-candidate rows. Complements {@link isHeifImage}: Chromium reports an
|
|
206
|
+
* empty MIME for `.heic`, so legacy rows can carry HEIC bytes under
|
|
207
|
+
* `application/octet-stream` while the extension survives.
|
|
208
|
+
*/
|
|
209
|
+
export function isHeicFilename(filename: string): boolean {
|
|
210
|
+
return HEIF_FILENAME_RE.test(filename.trim());
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Rewrites a filename's extension to `.jpg` (e.g. `IMG_5487.HEIC` → `IMG_5487.jpg`). */
|
|
214
|
+
export function jpegFilenameFor(filename: string): string {
|
|
215
|
+
const fallback = "attachment";
|
|
216
|
+
const trimmed = filename.trim() || fallback;
|
|
217
|
+
if (/\.jpe?g$/i.test(trimmed)) return trimmed;
|
|
218
|
+
const withoutExtension = trimmed.replace(/\.[^./\\]+$/, "") || fallback;
|
|
219
|
+
return `${withoutExtension}.jpg`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface NormalizedImageBytes {
|
|
223
|
+
mimeType: string;
|
|
224
|
+
bytes: Uint8Array;
|
|
225
|
+
converted: boolean;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Normalize image bytes for storage: HEIF/HEIC becomes a full-resolution JPEG
|
|
230
|
+
* master; everything else (and any conversion failure) passes through
|
|
231
|
+
* unchanged. Callers that persist a filename should rewrite it with
|
|
232
|
+
* {@link jpegFilenameFor} when `converted` is true.
|
|
233
|
+
*/
|
|
234
|
+
export function normalizeImageBytes(
|
|
235
|
+
mimeType: string,
|
|
236
|
+
bytes: Uint8Array,
|
|
237
|
+
): NormalizedImageBytes {
|
|
238
|
+
if (!isHeifImage(bytes)) {
|
|
239
|
+
return { mimeType, bytes, converted: false };
|
|
240
|
+
}
|
|
241
|
+
const converted = convertImageToJpeg(bytes, {
|
|
242
|
+
quality: STORAGE_JPEG_QUALITY,
|
|
243
|
+
});
|
|
244
|
+
if (!converted) {
|
|
245
|
+
return { mimeType, bytes, converted: false };
|
|
246
|
+
}
|
|
247
|
+
return { mimeType: "image/jpeg", bytes: converted, converted: true };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface NormalizedImageBase64 {
|
|
251
|
+
mimeType: string;
|
|
252
|
+
dataBase64: string;
|
|
253
|
+
converted: boolean;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Base64 variant of {@link normalizeImageBytes}. Sniffs the decoded head
|
|
258
|
+
* first so non-HEIF payloads skip the full decode.
|
|
259
|
+
*/
|
|
260
|
+
export function normalizeImageBase64(
|
|
261
|
+
mimeType: string,
|
|
262
|
+
dataBase64: string,
|
|
263
|
+
): NormalizedImageBase64 {
|
|
264
|
+
// 16 base64 chars decode to the 12 bytes the ftyp sniff needs.
|
|
265
|
+
const head = Buffer.from(dataBase64.slice(0, 16), "base64");
|
|
266
|
+
if (!isHeifImage(head)) {
|
|
267
|
+
return { mimeType, dataBase64, converted: false };
|
|
268
|
+
}
|
|
269
|
+
const normalized = normalizeImageBytes(
|
|
270
|
+
mimeType,
|
|
271
|
+
Buffer.from(dataBase64, "base64"),
|
|
272
|
+
);
|
|
273
|
+
if (!normalized.converted) {
|
|
274
|
+
return { mimeType, dataBase64, converted: false };
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
mimeType: normalized.mimeType,
|
|
278
|
+
dataBase64: Buffer.from(normalized.bytes).toString("base64"),
|
|
279
|
+
converted: true,
|
|
280
|
+
};
|
|
281
|
+
}
|
package/src/util/phone.ts
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Phone number normalization
|
|
2
|
+
* Phone number normalization utilities.
|
|
3
3
|
*
|
|
4
4
|
* Accepts common US and international phone number formats and normalizes
|
|
5
5
|
* them to E.164 before validation, rate-limit lookups, or storage.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Basic E.164 phone number validation: starts with +, followed by 10-15 digits.
|
|
10
|
-
*/
|
|
11
|
-
export function isValidE164(phone: string): boolean {
|
|
12
|
-
return /^\+\d{10,15}$/.test(phone);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
8
|
/**
|
|
16
9
|
* Normalize a phone number string to E.164 format.
|
|
17
10
|
*
|
package/src/util/platform.ts
CHANGED
|
@@ -247,6 +247,28 @@ export function getMemoryWorkerPidPath(): string {
|
|
|
247
247
|
return join(getWorkspaceDir(), "memory-worker.pid");
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
/** Returns the path to the schedule-worker PID file ($VELLUM_WORKSPACE_DIR/schedule-worker.pid). */
|
|
251
|
+
export function getScheduleWorkerPidPath(): string {
|
|
252
|
+
return join(getWorkspaceDir(), "schedule-worker.pid");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Returns the directory where the resource monitor persists its forensics
|
|
257
|
+
* ($VELLUM_WORKSPACE_DIR/data/monitoring). Lives on the workspace volume (the
|
|
258
|
+
* PVC) so the sample ring buffer and high-memory snapshots survive an OOM
|
|
259
|
+
* SIGKILL that resets all in-process state. Git-ignored from the workspace
|
|
260
|
+
* tree (see `data/monitoring/` in git-service.ts) so the assistant's own
|
|
261
|
+
* telemetry is not auto-committed as user changes.
|
|
262
|
+
*/
|
|
263
|
+
export function getMonitoringDataDir(): string {
|
|
264
|
+
return join(getDataDir(), "monitoring");
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Returns the path to the monitoring PID file, under the monitor data dir. */
|
|
268
|
+
export function getMonitoringPidPath(): string {
|
|
269
|
+
return join(getMonitoringDataDir(), "monitoring.pid");
|
|
270
|
+
}
|
|
271
|
+
|
|
250
272
|
/**
|
|
251
273
|
* Returns the workspace root for user-facing state.
|
|
252
274
|
*
|
|
@@ -331,6 +353,17 @@ export function getWorkspaceRoutesDir(): string {
|
|
|
331
353
|
return join(getWorkspaceDir(), "routes");
|
|
332
354
|
}
|
|
333
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Returns $VELLUM_WORKSPACE_DIR/workflows — saved (named) workflow scripts.
|
|
358
|
+
*
|
|
359
|
+
* A file here becomes a saved workflow whose source is executed (in the sandbox,
|
|
360
|
+
* and unattended when triggered by a schedule), so the file risk classifier
|
|
361
|
+
* escalates writes under this path to High like `tools/` and `routes/`.
|
|
362
|
+
*/
|
|
363
|
+
export function getWorkspaceWorkflowsDir(): string {
|
|
364
|
+
return join(getWorkspaceDir(), "workflows");
|
|
365
|
+
}
|
|
366
|
+
|
|
334
367
|
/** Returns $VELLUM_WORKSPACE_DIR/deprecated — transitional files slated for removal. */
|
|
335
368
|
export function getDeprecatedDir(): string {
|
|
336
369
|
return join(getWorkspaceDir(), "deprecated");
|
package/src/util/process-tree.ts
CHANGED
|
@@ -64,7 +64,10 @@ function scriptName(scriptPath: string): string {
|
|
|
64
64
|
* Derive a readable name from a command line. For interpreter invocations
|
|
65
65
|
* (`bun run /…/jobs/worker.ts`) the script path is far more useful than the
|
|
66
66
|
* interpreter name, so prefer the first script-looking argument and summarize it
|
|
67
|
-
* as `<parent-dir>-<filename>` (e.g. `jobs-worker`).
|
|
67
|
+
* as `<parent-dir>-<filename>` (e.g. `jobs-worker`). When an interpreter is run
|
|
68
|
+
* without a script file (`bun run dev`, `bun x prettier`, `bun repl`) the bare
|
|
69
|
+
* interpreter name says nothing about what is running, so surface the arguments
|
|
70
|
+
* — what was actually run — alongside it (e.g. `bun run dev`). Plain binaries
|
|
68
71
|
* (`/…/vellum-qdrant`) keep their bare executable name.
|
|
69
72
|
*/
|
|
70
73
|
export function deriveName(command: string): string {
|
|
@@ -73,8 +76,13 @@ export function deriveName(command: string): string {
|
|
|
73
76
|
|
|
74
77
|
const argv0 = basename(tokens[0]);
|
|
75
78
|
if (RUNTIMES.has(argv0)) {
|
|
76
|
-
const
|
|
79
|
+
const args = tokens.slice(1);
|
|
80
|
+
const script = args.find((t) => SCRIPT_EXT_RE.test(t));
|
|
77
81
|
if (script) return scriptName(script);
|
|
82
|
+
// No script to summarize: show the non-flag arguments so the entry reads as
|
|
83
|
+
// "what was run" rather than an opaque `bun`. Flags are dropped as noise.
|
|
84
|
+
const meaningful = args.filter((t) => !t.startsWith("-"));
|
|
85
|
+
if (meaningful.length > 0) return `${argv0} ${meaningful.join(" ")}`;
|
|
78
86
|
}
|
|
79
87
|
return argv0;
|
|
80
88
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boundary-aware text joining.
|
|
3
|
+
*
|
|
4
|
+
* A single assistant turn is emitted as a sequence of text blocks split by
|
|
5
|
+
* tool-call and message boundaries. The model frequently ends one block with a
|
|
6
|
+
* sentence-final period and no trailing whitespace, then opens the next block
|
|
7
|
+
* with a capital letter and no leading whitespace — because from the model's
|
|
8
|
+
* point of view each block is its own response. Concatenating those blocks raw
|
|
9
|
+
* fuses the boundary into `...end.Next...` with the space missing.
|
|
10
|
+
*
|
|
11
|
+
* These helpers insert a single separating space at such a boundary, and only
|
|
12
|
+
* there: when both sides carry a character at the join and neither is already
|
|
13
|
+
* whitespace. Blocks that already supply a boundary space (or are empty) join
|
|
14
|
+
* verbatim, so intra-block token streams — where the model's own spacing is
|
|
15
|
+
* authoritative — are never altered.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** Whitespace characters that count as an existing join boundary. */
|
|
19
|
+
function isJoinWhitespace(ch: string | undefined): boolean {
|
|
20
|
+
return ch === " " || ch === "\n" || ch === "\t";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether concatenating `left` + `right` needs a single separating space:
|
|
25
|
+
* true only when both sides have a character at the join and neither of those
|
|
26
|
+
* characters is already whitespace. Returns `false` when either side is empty.
|
|
27
|
+
*/
|
|
28
|
+
export function needsBoundarySpace(left: string, right: string): boolean {
|
|
29
|
+
const prev = left[left.length - 1];
|
|
30
|
+
const next = right[0];
|
|
31
|
+
return (
|
|
32
|
+
prev !== undefined &&
|
|
33
|
+
next !== undefined &&
|
|
34
|
+
!isJoinWhitespace(prev) &&
|
|
35
|
+
!isJoinWhitespace(next)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Join text parts, inserting a single space between adjacent parts only when
|
|
41
|
+
* the boundary would otherwise fuse two non-whitespace characters. Parts that
|
|
42
|
+
* already carry a boundary space (or are empty) are joined verbatim.
|
|
43
|
+
*/
|
|
44
|
+
export function joinWithSpacing(parts: string[]): string {
|
|
45
|
+
let result = parts[0] ?? "";
|
|
46
|
+
for (let i = 1; i < parts.length; i++) {
|
|
47
|
+
if (needsBoundarySpace(result, parts[i])) {
|
|
48
|
+
result += " ";
|
|
49
|
+
}
|
|
50
|
+
result += parts[i];
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|