@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,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistence for subagent lifecycle records (the `subagents` table, created by
|
|
3
|
+
* migration 311).
|
|
4
|
+
*
|
|
5
|
+
* This module owns only the durable row shape and raw SQL. The mapping to and
|
|
6
|
+
* from the manager's `SubagentState` lives in `SubagentManager`, keeping this
|
|
7
|
+
* layer decoupled from the subagent domain types.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { rawAll, rawRun } from "./raw-query.js";
|
|
11
|
+
|
|
12
|
+
/** A durable subagent lifecycle record (camelCase mirror of the row). */
|
|
13
|
+
export interface SubagentRecord {
|
|
14
|
+
id: string;
|
|
15
|
+
parentConversationId: string;
|
|
16
|
+
conversationId: string;
|
|
17
|
+
label: string;
|
|
18
|
+
objective: string;
|
|
19
|
+
role: string;
|
|
20
|
+
isFork: boolean;
|
|
21
|
+
/** Tri-state: null when the spawner left it unset. */
|
|
22
|
+
sendResultToUser: boolean | null;
|
|
23
|
+
status: string;
|
|
24
|
+
error: string | null;
|
|
25
|
+
createdAt: number;
|
|
26
|
+
startedAt: number | null;
|
|
27
|
+
completedAt: number | null;
|
|
28
|
+
inputTokens: number;
|
|
29
|
+
outputTokens: number;
|
|
30
|
+
estimatedCost: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Raw row shape (snake_case, SQLite stores booleans as 0/1). */
|
|
34
|
+
interface SubagentRow {
|
|
35
|
+
id: string;
|
|
36
|
+
parent_conversation_id: string;
|
|
37
|
+
conversation_id: string;
|
|
38
|
+
label: string;
|
|
39
|
+
objective: string;
|
|
40
|
+
role: string;
|
|
41
|
+
is_fork: number;
|
|
42
|
+
send_result_to_user: number | null;
|
|
43
|
+
status: string;
|
|
44
|
+
error: string | null;
|
|
45
|
+
created_at: number;
|
|
46
|
+
started_at: number | null;
|
|
47
|
+
completed_at: number | null;
|
|
48
|
+
input_tokens: number;
|
|
49
|
+
output_tokens: number;
|
|
50
|
+
estimated_cost: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function rowToRecord(r: SubagentRow): SubagentRecord {
|
|
54
|
+
return {
|
|
55
|
+
id: r.id,
|
|
56
|
+
parentConversationId: r.parent_conversation_id,
|
|
57
|
+
conversationId: r.conversation_id,
|
|
58
|
+
label: r.label,
|
|
59
|
+
objective: r.objective,
|
|
60
|
+
role: r.role,
|
|
61
|
+
isFork: r.is_fork === 1,
|
|
62
|
+
sendResultToUser:
|
|
63
|
+
r.send_result_to_user == null ? null : r.send_result_to_user === 1,
|
|
64
|
+
status: r.status,
|
|
65
|
+
error: r.error,
|
|
66
|
+
createdAt: r.created_at,
|
|
67
|
+
startedAt: r.started_at,
|
|
68
|
+
completedAt: r.completed_at,
|
|
69
|
+
inputTokens: r.input_tokens,
|
|
70
|
+
outputTokens: r.output_tokens,
|
|
71
|
+
estimatedCost: r.estimated_cost,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Insert or update a subagent record. Called on spawn and on every status
|
|
77
|
+
* transition; the conflict clause refreshes the mutable lifecycle fields while
|
|
78
|
+
* the immutable identity/config columns stay as first written.
|
|
79
|
+
*/
|
|
80
|
+
export function upsertSubagentRecord(rec: SubagentRecord): void {
|
|
81
|
+
rawRun(
|
|
82
|
+
"subagent:upsertRecord",
|
|
83
|
+
`INSERT INTO subagents (
|
|
84
|
+
id, parent_conversation_id, conversation_id, label, objective, role,
|
|
85
|
+
is_fork, send_result_to_user, status, error, created_at, started_at,
|
|
86
|
+
completed_at, input_tokens, output_tokens, estimated_cost
|
|
87
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
88
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
89
|
+
status = excluded.status,
|
|
90
|
+
error = excluded.error,
|
|
91
|
+
started_at = excluded.started_at,
|
|
92
|
+
completed_at = excluded.completed_at,
|
|
93
|
+
input_tokens = excluded.input_tokens,
|
|
94
|
+
output_tokens = excluded.output_tokens,
|
|
95
|
+
estimated_cost = excluded.estimated_cost`,
|
|
96
|
+
rec.id,
|
|
97
|
+
rec.parentConversationId,
|
|
98
|
+
rec.conversationId,
|
|
99
|
+
rec.label,
|
|
100
|
+
rec.objective,
|
|
101
|
+
rec.role,
|
|
102
|
+
rec.isFork ? 1 : 0,
|
|
103
|
+
rec.sendResultToUser == null ? null : rec.sendResultToUser ? 1 : 0,
|
|
104
|
+
rec.status,
|
|
105
|
+
rec.error,
|
|
106
|
+
rec.createdAt,
|
|
107
|
+
rec.startedAt,
|
|
108
|
+
rec.completedAt,
|
|
109
|
+
rec.inputTokens,
|
|
110
|
+
rec.outputTokens,
|
|
111
|
+
rec.estimatedCost,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Load every persisted subagent record. Used once at startup to rehydrate. */
|
|
116
|
+
export function loadAllSubagentRecords(): SubagentRecord[] {
|
|
117
|
+
return rawAll<SubagentRow>("subagent:loadAll", `SELECT * FROM subagents`).map(
|
|
118
|
+
rowToRecord,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Delete a subagent record once the manager is fully done with it. */
|
|
123
|
+
export function deleteSubagentRecord(id: string): void {
|
|
124
|
+
rawRun("subagent:deleteRecord", `DELETE FROM subagents WHERE id = ?`, id);
|
|
125
|
+
}
|
|
@@ -3,262 +3,73 @@
|
|
|
3
3
|
* OS process whose entry point is `worker.ts`.
|
|
4
4
|
*
|
|
5
5
|
* Both the `assistant memory worker` CLI and the daemon lifecycle (when
|
|
6
|
-
* `memory.worker.enabled` is set) need to probe, spawn, and stop this process
|
|
7
|
-
*
|
|
6
|
+
* `memory.worker.enabled` is set) need to probe, spawn, and stop this process.
|
|
7
|
+
* The generic PID-file mechanics live in `util/worker-process.ts`; this module
|
|
8
|
+
* binds them to the memory worker's PID path and entry point.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
-
closeSync,
|
|
12
|
-
existsSync,
|
|
13
|
-
mkdirSync,
|
|
14
|
-
openSync,
|
|
15
|
-
readFileSync,
|
|
16
|
-
unlinkSync,
|
|
17
|
-
} from "node:fs";
|
|
18
|
-
import { dirname } from "node:path";
|
|
19
|
-
|
|
20
|
-
import { getCurrentLogFilePath } from "../util/logger.js";
|
|
21
11
|
import { getMemoryWorkerPidPath } from "../util/platform.js";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
!!err &&
|
|
32
|
-
typeof err === "object" &&
|
|
33
|
-
"code" in err &&
|
|
34
|
-
(err as { code?: unknown }).code === "ESRCH"
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Read a PID file and report liveness. A missing or malformed file reports
|
|
40
|
-
* not_running; a file pointing at a dead process is cleaned up and reported as
|
|
41
|
-
* not_running. Used for the worker-process PID file, whose PID is a normal
|
|
42
|
-
* spawned child (never PID 1), so `process.kill(pid, 0)` liveness is reliable.
|
|
43
|
-
*/
|
|
44
|
-
function probePidFile(path: string): MemoryWorkerStatus {
|
|
45
|
-
if (!existsSync(path)) return { status: "not_running" };
|
|
46
|
-
|
|
47
|
-
const raw = readFileSync(path, "utf-8").trim();
|
|
48
|
-
const pid = parseInt(raw, 10);
|
|
49
|
-
if (!Number.isFinite(pid) || pid <= 0) return { status: "not_running" };
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
process.kill(pid, 0);
|
|
53
|
-
return { status: "running", pid };
|
|
54
|
-
} catch (err: unknown) {
|
|
55
|
-
if (isEsrchError(err)) {
|
|
56
|
-
// Stale file — clean it up.
|
|
57
|
-
try {
|
|
58
|
-
unlinkSync(path);
|
|
59
|
-
} catch {
|
|
60
|
-
// best-effort
|
|
61
|
-
}
|
|
62
|
-
return { status: "not_running" };
|
|
63
|
-
}
|
|
64
|
-
// Any other error (e.g. EPERM: the process exists but this caller may not
|
|
65
|
-
// signal it) means the process is alive. Report it running rather than
|
|
66
|
-
// letting the error escape a status probe.
|
|
67
|
-
return { status: "running", pid };
|
|
68
|
-
}
|
|
69
|
-
}
|
|
12
|
+
import {
|
|
13
|
+
probeWorkerPidFile,
|
|
14
|
+
spawnWorkerProcess,
|
|
15
|
+
type SpawnWorkerProcessOptions,
|
|
16
|
+
stopWorkerProcess,
|
|
17
|
+
WorkerProcessSpawnError,
|
|
18
|
+
type WorkerProcessStatus,
|
|
19
|
+
} from "../util/worker-process.js";
|
|
70
20
|
|
|
71
21
|
/**
|
|
72
22
|
* Inspect the PID file to determine whether the worker process is alive.
|
|
73
23
|
* A stale PID file (pointing at a dead process) is cleaned up and reported
|
|
74
24
|
* as not_running.
|
|
75
25
|
*/
|
|
76
|
-
export function probeMemoryWorker():
|
|
77
|
-
return
|
|
26
|
+
export function probeMemoryWorker(): WorkerProcessStatus {
|
|
27
|
+
return probeWorkerPidFile(getMemoryWorkerPidPath());
|
|
78
28
|
}
|
|
79
29
|
|
|
80
|
-
export class MemoryWorkerSpawnError extends
|
|
30
|
+
export class MemoryWorkerSpawnError extends WorkerProcessSpawnError {}
|
|
81
31
|
|
|
82
32
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* is merely slow, and (because the CLI failure path leaves
|
|
89
|
-
* `memory.worker.enabled` off) leaves that detached worker draining the queue
|
|
90
|
-
* alongside the daemon's synchronous in-process runner — two drainers racing on
|
|
91
|
-
* the same jobs.
|
|
92
|
-
*/
|
|
93
|
-
const PID_FILE_WAIT_TIMEOUT_MS = 15_000;
|
|
94
|
-
|
|
95
|
-
/** Poll interval while waiting for the worker's PID file to appear. */
|
|
96
|
-
const PID_FILE_POLL_INTERVAL_MS = 100;
|
|
97
|
-
|
|
98
|
-
export interface SpawnMemoryWorkerOptions {
|
|
99
|
-
/**
|
|
100
|
-
* Override how long to wait for the worker's PID file, in ms. Defaults to
|
|
101
|
-
* {@link PID_FILE_WAIT_TIMEOUT_MS}. Primarily a testing seam.
|
|
102
|
-
*/
|
|
103
|
-
pidWaitTimeoutMs?: number;
|
|
104
|
-
/**
|
|
105
|
-
* Override the PID-file poll interval, in ms. Defaults to
|
|
106
|
-
* {@link PID_FILE_POLL_INTERVAL_MS}. Primarily a testing seam.
|
|
107
|
-
*/
|
|
108
|
-
pidPollIntervalMs?: number;
|
|
109
|
-
/**
|
|
110
|
-
* When the wait times out while the child is still alive (a hung or very slow
|
|
111
|
-
* start), terminate that child before throwing. Callers that leave
|
|
112
|
-
* `memory.worker.enabled` off on failure — the CLI `memory worker start` —
|
|
113
|
-
* MUST set this: otherwise the detached worker keeps coming up and drains the
|
|
114
|
-
* queue behind the daemon's still-active synchronous runner. The daemon's own
|
|
115
|
-
* startup spawn leaves the flag on, so a late worker there becomes the sole
|
|
116
|
-
* drainer; it passes `false` to let that worker live.
|
|
117
|
-
*/
|
|
118
|
-
terminateOnTimeout?: boolean;
|
|
119
|
-
/**
|
|
120
|
-
* Process parentage (default `true`):
|
|
121
|
-
* - `true` — the worker is its own session leader and outlives the spawning
|
|
122
|
-
* process. The short-lived `assistant memory worker` CLI needs this so the
|
|
123
|
-
* worker keeps running after the command returns.
|
|
124
|
-
* - `false` — the worker is a direct child of the spawning process. The
|
|
125
|
-
* daemon passes this so the worker it owns appears in its process tree
|
|
126
|
-
* (`assistant ps`) and is torn down with the daemon. It does not need to
|
|
127
|
-
* survive daemon restarts; the daemon re-spawns it on boot.
|
|
128
|
-
* Either way the child is `unref`'d, so the spawning process never blocks on
|
|
129
|
-
* it and the worker is tracked via its PID file rather than the handle.
|
|
130
|
-
*/
|
|
131
|
-
detached?: boolean;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
type WorkerReadyOutcome = "ready" | "exited" | "timeout";
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Wait for the worker to signal readiness by writing its PID file.
|
|
33
|
+
* Spawn the memory worker as a background process. If a worker is already
|
|
34
|
+
* running, returns its PID with `alreadyRunning: true` rather than spawning a
|
|
35
|
+
* second one. Throws {@link MemoryWorkerSpawnError} if the child crashes
|
|
36
|
+
* during startup or never writes its PID file within the wait window (i.e.
|
|
37
|
+
* failed to start).
|
|
138
38
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
39
|
+
* Beyond the generic option semantics documented on
|
|
40
|
+
* {@link SpawnWorkerProcessOptions}, two flags carry queue-ownership
|
|
41
|
+
* consequences specific to the memory worker:
|
|
142
42
|
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
const markExited = () => {
|
|
154
|
-
childExited = true;
|
|
155
|
-
};
|
|
156
|
-
// A pending `exited` promise does not keep the event loop alive once the child
|
|
157
|
-
// is unref'd, so this floating wait won't hang the process.
|
|
158
|
-
void exited?.then(markExited, markExited);
|
|
159
|
-
|
|
160
|
-
const deadline = Date.now() + timeoutMs;
|
|
161
|
-
while (Date.now() < deadline) {
|
|
162
|
-
if (existsSync(pidPath)) return "ready";
|
|
163
|
-
if (childExited) {
|
|
164
|
-
// The worker could write the PID file and exit in the same tick — re-check
|
|
165
|
-
// before declaring it dead.
|
|
166
|
-
return existsSync(pidPath) ? "ready" : "exited";
|
|
167
|
-
}
|
|
168
|
-
await Bun.sleep(pollIntervalMs);
|
|
169
|
-
}
|
|
170
|
-
return existsSync(pidPath) ? "ready" : "timeout";
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Spawn the memory worker as a background process. `opts.detached` (default
|
|
175
|
-
* `true`) controls process parentage — see {@link SpawnMemoryWorkerOptions}.
|
|
176
|
-
*
|
|
177
|
-
* If a worker is already running, returns its PID with `alreadyRunning: true`
|
|
178
|
-
* rather than spawning a second one. Throws {@link MemoryWorkerSpawnError} if
|
|
179
|
-
* the child crashes during startup or never writes its PID file within the
|
|
180
|
-
* wait window (i.e. failed to start).
|
|
43
|
+
* - `terminateOnTimeout` — callers that leave `memory.worker.enabled` off
|
|
44
|
+
* on failure (the CLI `memory worker start`) MUST set this: otherwise the
|
|
45
|
+
* detached worker keeps coming up and drains the queue behind the
|
|
46
|
+
* daemon's still-active synchronous runner — two drainers racing on the
|
|
47
|
+
* same jobs. The daemon's own startup spawn leaves the flag on, so a late
|
|
48
|
+
* worker there becomes the sole drainer; it passes `false` to let that
|
|
49
|
+
* worker live.
|
|
50
|
+
* - `detached` — `true` for the short-lived CLI (the worker outlives the
|
|
51
|
+
* command); `false` for the daemon (the worker appears in `assistant ps`
|
|
52
|
+
* and is torn down with the daemon).
|
|
181
53
|
*/
|
|
182
54
|
export async function spawnMemoryWorkerProcess(
|
|
183
|
-
opts:
|
|
55
|
+
opts: SpawnWorkerProcessOptions = {},
|
|
184
56
|
): Promise<{
|
|
185
57
|
pid: number;
|
|
186
58
|
alreadyRunning: boolean;
|
|
187
59
|
}> {
|
|
188
|
-
const pidWaitTimeoutMs = opts.pidWaitTimeoutMs ?? PID_FILE_WAIT_TIMEOUT_MS;
|
|
189
|
-
const pidPollIntervalMs = opts.pidPollIntervalMs ?? PID_FILE_POLL_INTERVAL_MS;
|
|
190
|
-
const detached = opts.detached ?? true;
|
|
191
|
-
const current = probeMemoryWorker();
|
|
192
|
-
if (current.status === "running" && current.pid != null) {
|
|
193
|
-
return { pid: current.pid, alreadyRunning: true };
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const pidPath = getMemoryWorkerPidPath();
|
|
197
|
-
const entry = new URL("../jobs/worker.ts", import.meta.url);
|
|
198
|
-
|
|
199
|
-
// Pipe the worker's stderr into the same daily log file the daemon
|
|
200
|
-
// writes to. The worker's pino logger already writes there directly,
|
|
201
|
-
// but stderr captures crash traces (uncaught exceptions that bypass
|
|
202
|
-
// the catch handler) and pino's fallback output if the file logger
|
|
203
|
-
// fails to initialize. Without this, any such output is lost to
|
|
204
|
-
// /dev/null and the worker dies silently.
|
|
205
|
-
let stderrFd: number | "inherit" = "inherit";
|
|
206
60
|
try {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
cmd: ["bun", "run", entry.pathname],
|
|
217
|
-
stdio: ["ignore", "ignore", stderrFd],
|
|
218
|
-
detached,
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// Close our copy of the log fd — the child has its own.
|
|
222
|
-
if (typeof stderrFd === "number") {
|
|
223
|
-
closeSync(stderrFd);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Unreference so the spawning process doesn't wait for the child.
|
|
227
|
-
child.unref();
|
|
228
|
-
|
|
229
|
-
// Wait for the worker to report readiness by writing its PID file (the worker
|
|
230
|
-
// writes it on startup). The child is `unref`'d, so a worker that is merely
|
|
231
|
-
// slow keeps coming up after we stop waiting.
|
|
232
|
-
const outcome = await waitForWorkerPidFile(
|
|
233
|
-
pidPath,
|
|
234
|
-
child.exited,
|
|
235
|
-
pidWaitTimeoutMs,
|
|
236
|
-
pidPollIntervalMs,
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
if (outcome !== "ready") {
|
|
240
|
-
// On a plain timeout the child may still be alive (hung or very slow start).
|
|
241
|
-
// Terminate it when asked so a worker we are reporting as failed cannot come
|
|
242
|
-
// up later and drain the queue behind the daemon's synchronous runner. On an
|
|
243
|
-
// early exit the child is already gone, so there is nothing to kill.
|
|
244
|
-
if (outcome === "timeout" && opts.terminateOnTimeout) {
|
|
245
|
-
try {
|
|
246
|
-
child.kill();
|
|
247
|
-
} catch {
|
|
248
|
-
// best-effort — the child may already be gone
|
|
249
|
-
}
|
|
61
|
+
return await spawnWorkerProcess({
|
|
62
|
+
pidPath: getMemoryWorkerPidPath(),
|
|
63
|
+
entry: new URL("../jobs/worker.ts", import.meta.url),
|
|
64
|
+
workerLabel: "Memory worker",
|
|
65
|
+
options: opts,
|
|
66
|
+
});
|
|
67
|
+
} catch (err) {
|
|
68
|
+
if (err instanceof WorkerProcessSpawnError) {
|
|
69
|
+
throw new MemoryWorkerSpawnError(err.message);
|
|
250
70
|
}
|
|
251
|
-
throw
|
|
252
|
-
outcome === "exited"
|
|
253
|
-
? "Memory worker exited during startup before writing its PID file"
|
|
254
|
-
: `Memory worker was spawned but did not write its PID file within ${Math.round(
|
|
255
|
-
pidWaitTimeoutMs / 1000,
|
|
256
|
-
)}s`,
|
|
257
|
-
);
|
|
71
|
+
throw err;
|
|
258
72
|
}
|
|
259
|
-
|
|
260
|
-
const pid = parseInt(readFileSync(pidPath, "utf-8").trim(), 10);
|
|
261
|
-
return { pid, alreadyRunning: false };
|
|
262
73
|
}
|
|
263
74
|
|
|
264
75
|
/**
|
|
@@ -268,10 +79,6 @@ export async function spawnMemoryWorkerProcess(
|
|
|
268
79
|
* whether anything was stopped. Only throws if `process.kill` itself fails
|
|
269
80
|
* (e.g. EPERM) — a not-running worker is a no-op.
|
|
270
81
|
*/
|
|
271
|
-
export function stopMemoryWorkerProcess():
|
|
272
|
-
|
|
273
|
-
if (current.status === "running" && current.pid != null) {
|
|
274
|
-
process.kill(current.pid, "SIGTERM");
|
|
275
|
-
}
|
|
276
|
-
return current;
|
|
82
|
+
export function stopMemoryWorkerProcess(): WorkerProcessStatus {
|
|
83
|
+
return stopWorkerProcess(getMemoryWorkerPidPath());
|
|
277
84
|
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability-restricted view of the assistant event hub handed to workspace
|
|
3
|
+
* plugins through `@vellumai/plugin-api`.
|
|
4
|
+
*
|
|
5
|
+
* Plugins receive this facade instead of the raw {@link AssistantEventHub}
|
|
6
|
+
* singleton. It exposes only the operations a plugin legitimately needs —
|
|
7
|
+
* subscribing to runtime events, publishing non-host events, and checking for
|
|
8
|
+
* subscribers — each delegated to the one daemon hub instance so subscriptions
|
|
9
|
+
* and reads observe the same shared state.
|
|
10
|
+
*
|
|
11
|
+
* Two classes of hub method are withheld:
|
|
12
|
+
*
|
|
13
|
+
* - **`publish` of host-proxy control events** (`host_bash_*`, `host_file_*`,
|
|
14
|
+
* `host_transfer_*`, `host_browser_*`, `host_cu_*`, `host_app_control_*`).
|
|
15
|
+
* These drive privileged shell / file / input / browser execution on the
|
|
16
|
+
* desktop client; the host proxies gate that execution (risk classification,
|
|
17
|
+
* user approval, same-actor binding, pending-interaction registration) before
|
|
18
|
+
* publishing. The facade's `publish` rejects them so an in-process plugin
|
|
19
|
+
* cannot reach the host machine outside the sandbox.
|
|
20
|
+
*
|
|
21
|
+
* - **Methods returning live subscriber entries or mutating hub state**
|
|
22
|
+
* (`listClients*`, `getClientById`, `disposeClient`, …). A `ClientEntry`
|
|
23
|
+
* carries the subscriber's `callback` — a direct event-delivery primitive — so
|
|
24
|
+
* handing one to a plugin would let it deliver a forged host event without
|
|
25
|
+
* going through the guarded `publish` at all.
|
|
26
|
+
*
|
|
27
|
+
* `subscribe` registers the plugin as an in-process consumer only (never a
|
|
28
|
+
* device "client"), so it cannot impersonate a real client by id or receive
|
|
29
|
+
* host-capability-targeted events; its callback is handed an isolated, frozen
|
|
30
|
+
* snapshot so it cannot mutate an in-flight event a real client receives later
|
|
31
|
+
* in the same fanout.
|
|
32
|
+
*
|
|
33
|
+
* `publish` canonicalizes the caller's event (and options) to their JSON wire
|
|
34
|
+
* form — the exact representation the client receives — then deep-freezes that
|
|
35
|
+
* snapshot before checking the type and forwards it. JSON canonicalization
|
|
36
|
+
* collapses getters / Proxies to inert values and coerces boxed values (e.g.
|
|
37
|
+
* `new String("host_bash_request")`) to primitives, so the guard cannot be
|
|
38
|
+
* shown a benign type while the client acts on a host one (time-of-check vs.
|
|
39
|
+
* time-of-use). Freezing stops a subscriber from mutating the in-flight event
|
|
40
|
+
* mid-fanout (the hub delivers one object to every subscriber in turn).
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
44
|
+
import {
|
|
45
|
+
type AssistantEventFilter,
|
|
46
|
+
type AssistantEventHub,
|
|
47
|
+
assistantEventHub,
|
|
48
|
+
} from "../runtime/assistant-event-hub.js";
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The subset of {@link AssistantEventHub} workspace plugins may use. Picking
|
|
52
|
+
* method signatures off the class keeps the facade in sync with the hub while
|
|
53
|
+
* statically withholding everything else.
|
|
54
|
+
*/
|
|
55
|
+
export type PluginEventHub = Pick<
|
|
56
|
+
AssistantEventHub,
|
|
57
|
+
"subscribe" | "publish" | "hasSubscribersForEvent"
|
|
58
|
+
>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Type prefix shared by every daemon-to-client host-proxy control event. Each
|
|
62
|
+
* host-proxy message type (`host_bash_request`, `host_file_cancel`, …) begins
|
|
63
|
+
* with it, so a prefix test covers all current and future host-proxy kinds.
|
|
64
|
+
*/
|
|
65
|
+
const HOST_CONTROL_EVENT_TYPE_PREFIX = "host_";
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* JSON primitives pinned at module-load time — before any user plugin loads and
|
|
69
|
+
* could swap the globals. A JSON round-trip canonicalizes a published event to
|
|
70
|
+
* exactly the wire form the client receives, so the guard checks the same
|
|
71
|
+
* representation the client will act on.
|
|
72
|
+
*/
|
|
73
|
+
const jsonStringify: typeof JSON.stringify = JSON.stringify;
|
|
74
|
+
const jsonParse: typeof JSON.parse = JSON.parse;
|
|
75
|
+
|
|
76
|
+
/** Canonicalize a value to its JSON wire form. Throws if it is not serializable. */
|
|
77
|
+
function wireSnapshot<T>(value: T): T {
|
|
78
|
+
return jsonParse(jsonStringify(value)) as T;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Recursively freeze a value (cycle-safe). The hub fans the same event object
|
|
83
|
+
* out to every subscriber in turn; freezing the snapshot stops a malicious
|
|
84
|
+
* subscriber — e.g. a plugin that subscribed and then calls `publish` — from
|
|
85
|
+
* mutating the in-flight event into a host request before a later host-capable
|
|
86
|
+
* client receives it.
|
|
87
|
+
*/
|
|
88
|
+
function deepFreeze<T>(value: T, seen: WeakSet<object> = new WeakSet()): T {
|
|
89
|
+
if (value === null || typeof value !== "object") return value;
|
|
90
|
+
if (seen.has(value)) return value;
|
|
91
|
+
seen.add(value);
|
|
92
|
+
for (const key of Object.keys(value)) {
|
|
93
|
+
deepFreeze((value as Record<string, unknown>)[key], seen);
|
|
94
|
+
}
|
|
95
|
+
return Object.freeze(value);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* `String.prototype.startsWith` bound at module-load time — before any user
|
|
100
|
+
* plugin loads and could monkey-patch the prototype — so the host-prefix check
|
|
101
|
+
* cannot be neutralized by a patched method.
|
|
102
|
+
*/
|
|
103
|
+
const startsWith = Function.prototype.call.bind(
|
|
104
|
+
String.prototype.startsWith,
|
|
105
|
+
) as (str: string, search: string) => boolean;
|
|
106
|
+
|
|
107
|
+
/** The blocked event type if `event` is a host-proxy control event, else `undefined`. */
|
|
108
|
+
function hostControlEventType(event: AssistantEvent): string | undefined {
|
|
109
|
+
const type: unknown = event.message?.type;
|
|
110
|
+
return typeof type === "string" &&
|
|
111
|
+
startsWith(type, HOST_CONTROL_EVENT_TYPE_PREFIX)
|
|
112
|
+
? type
|
|
113
|
+
: undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** The plugin-facing event hub. See module docs. */
|
|
117
|
+
export const pluginAssistantEventHub: PluginEventHub = Object.freeze({
|
|
118
|
+
subscribe: (subscriber) => {
|
|
119
|
+
// Plugins subscribe as in-process consumers only — never as device
|
|
120
|
+
// "clients" — so a plugin cannot impersonate/evict a real client by id or
|
|
121
|
+
// receive host-capability-targeted events meant for the desktop app. The
|
|
122
|
+
// filter is canonicalized to inert data so the hub never invokes a
|
|
123
|
+
// plugin-defined getter while reading `entry.filter` during fanout, and the
|
|
124
|
+
// callback is handed an isolated, frozen snapshot so it cannot mutate an
|
|
125
|
+
// in-flight event a real client receives later in the same fanout (the hub
|
|
126
|
+
// delivers one shared object to every subscriber in turn).
|
|
127
|
+
let filter: AssistantEventFilter | undefined;
|
|
128
|
+
try {
|
|
129
|
+
filter = subscriber.filter ? wireSnapshot(subscriber.filter) : undefined;
|
|
130
|
+
} catch {
|
|
131
|
+
filter = undefined;
|
|
132
|
+
}
|
|
133
|
+
return assistantEventHub.subscribe({
|
|
134
|
+
type: "process",
|
|
135
|
+
filter,
|
|
136
|
+
callback: (event) => {
|
|
137
|
+
let isolated: AssistantEvent;
|
|
138
|
+
try {
|
|
139
|
+
isolated = deepFreeze(wireSnapshot(event));
|
|
140
|
+
} catch {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
return subscriber.callback(isolated);
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
publish: async (event, options) => {
|
|
149
|
+
let snapshot: AssistantEvent;
|
|
150
|
+
let snapshotOptions: Parameters<AssistantEventHub["publish"]>[1];
|
|
151
|
+
try {
|
|
152
|
+
snapshot = deepFreeze(wireSnapshot(event));
|
|
153
|
+
snapshotOptions = options ? wireSnapshot(options) : undefined;
|
|
154
|
+
} catch {
|
|
155
|
+
throw new Error("Plugins may not publish a non-serializable event.");
|
|
156
|
+
}
|
|
157
|
+
const blockedType = hostControlEventType(snapshot);
|
|
158
|
+
if (blockedType !== undefined) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Plugins may not publish daemon-to-client host-proxy control events (type "${blockedType}").`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return assistantEventHub.publish(snapshot, snapshotOptions);
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
hasSubscribersForEvent: (event) =>
|
|
167
|
+
// Read the caller's `conversationId` once and pass an inert object, so the
|
|
168
|
+
// hub never reads a plugin-defined getter.
|
|
169
|
+
assistantEventHub.hasSubscribersForEvent({
|
|
170
|
+
conversationId: event?.conversationId,
|
|
171
|
+
}),
|
|
172
|
+
});
|
package/src/plugin-api/index.ts
CHANGED
|
@@ -128,7 +128,15 @@ export type {
|
|
|
128
128
|
AssistantEventHub,
|
|
129
129
|
AssistantEventSubscription,
|
|
130
130
|
} from "../runtime/assistant-event-hub.js";
|
|
131
|
-
|
|
131
|
+
// The hub plugins receive is a capability-restricted facade over the daemon
|
|
132
|
+
// singleton (see `event-hub-facade.ts`): plugins may `subscribe` to runtime
|
|
133
|
+
// events (shared subscriber state), `publish` non-host events, and check
|
|
134
|
+
// `hasSubscribersForEvent`. `publish` refuses daemon-to-client host-proxy
|
|
135
|
+
// control events (`host_*`), and methods that return live subscriber callbacks
|
|
136
|
+
// or mutate hub state are withheld — both would let a plugin drive privileged
|
|
137
|
+
// host execution without the host proxies' approval gate.
|
|
138
|
+
export type { PluginEventHub } from "./event-hub-facade.js";
|
|
139
|
+
export { pluginAssistantEventHub as assistantEventHub } from "./event-hub-facade.js";
|
|
132
140
|
export { getModelProfiles } from "./model-profiles.js";
|
|
133
141
|
// Check whether a model or profile can process image input. Accepts a concrete
|
|
134
142
|
// model id, a profile key, or a `ModelProfileInfo`; a bare string is resolved
|