@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
|
@@ -70,21 +70,38 @@ export type ApprovalCardBlock = z.infer<typeof ApprovalCardBlockSchema>;
|
|
|
70
70
|
|
|
71
71
|
// ── Public types ────────────────────────────────────────────────────────────
|
|
72
72
|
|
|
73
|
+
/** A card action option resolved from the request's domain (id + label + style). */
|
|
74
|
+
export interface ApprovalCardActionOption {
|
|
75
|
+
/** Canonical action id — becomes the `apr:<requestId>:<id>` callback. */
|
|
76
|
+
id: string;
|
|
77
|
+
label: string;
|
|
78
|
+
style?: SurfaceAction["style"];
|
|
79
|
+
}
|
|
80
|
+
|
|
73
81
|
export interface ApprovalCardParams {
|
|
74
82
|
/** Prefix for `surfaceId` — combined with `requestId` to form e.g. "access-request-abc123". */
|
|
75
83
|
surfaceIdPrefix: string;
|
|
76
84
|
/** Top-level card title shown in the surface header (e.g. "Access Request", "Tool approval"). */
|
|
77
85
|
cardTitle: string;
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Primary line inside the card — the subject of the decision: the
|
|
88
|
+
* requester's display name for access requests, the tool name for tool
|
|
89
|
+
* approvals.
|
|
90
|
+
*/
|
|
91
|
+
primaryLine: string;
|
|
92
|
+
/** Secondary line below the primary line (e.g. "Requesting access to the assistant"). */
|
|
81
93
|
subtitle: string;
|
|
82
94
|
/** Markdown body — blockquotes, warnings, links, etc. */
|
|
83
95
|
body: string;
|
|
84
96
|
/** Key-value metadata grid rendered below the body. */
|
|
85
97
|
metadata: Array<{ label: string; value: string }>;
|
|
86
|
-
/** When present,
|
|
98
|
+
/** When present, action buttons are wired with `apr:<requestId>:*` action IDs. */
|
|
87
99
|
requestId?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Domain-specific action set (e.g. the signal-driven introduction-card
|
|
102
|
+
* actions). When absent, the generic Approve/Reject pair is rendered.
|
|
103
|
+
*/
|
|
104
|
+
actions?: ApprovalCardActionOption[];
|
|
88
105
|
/** Plain-text content for the fallback `text` block. */
|
|
89
106
|
fallbackText: string;
|
|
90
107
|
}
|
|
@@ -105,7 +122,7 @@ export function buildApprovalCardBlocks(
|
|
|
105
122
|
const {
|
|
106
123
|
surfaceIdPrefix,
|
|
107
124
|
cardTitle,
|
|
108
|
-
|
|
125
|
+
primaryLine,
|
|
109
126
|
subtitle,
|
|
110
127
|
body,
|
|
111
128
|
metadata,
|
|
@@ -113,23 +130,21 @@ export function buildApprovalCardBlocks(
|
|
|
113
130
|
fallbackText,
|
|
114
131
|
} = params;
|
|
115
132
|
|
|
133
|
+
const actionOptions: ApprovalCardActionOption[] = params.actions ?? [
|
|
134
|
+
{ id: "approve_once", label: "Approve", style: "primary" },
|
|
135
|
+
{ id: "reject", label: "Reject", style: "destructive" },
|
|
136
|
+
];
|
|
137
|
+
|
|
116
138
|
const actions: SurfaceAction[] | undefined = requestId
|
|
117
|
-
?
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
id: `apr:${requestId}:reject`,
|
|
125
|
-
label: "Reject",
|
|
126
|
-
style: "destructive",
|
|
127
|
-
},
|
|
128
|
-
]
|
|
139
|
+
? actionOptions.map((option) => ({
|
|
140
|
+
id: `apr:${requestId}:${option.id}`,
|
|
141
|
+
label: option.label,
|
|
142
|
+
...(option.style ? { style: option.style } : {}),
|
|
143
|
+
}))
|
|
129
144
|
: undefined;
|
|
130
145
|
|
|
131
146
|
const data: CardSurfaceData = {
|
|
132
|
-
title:
|
|
147
|
+
title: primaryLine,
|
|
133
148
|
subtitle,
|
|
134
149
|
body,
|
|
135
150
|
metadata,
|
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
import {
|
|
17
17
|
buildAccessRequestCardView,
|
|
18
18
|
buildAccessRequestContractText,
|
|
19
|
+
buildIntroductionActionsForPayload,
|
|
19
20
|
parseAccessRequestPayload,
|
|
20
21
|
} from "./access-request-copy.js";
|
|
21
22
|
import {
|
|
23
|
+
type ApprovalCardActionOption,
|
|
22
24
|
type ApprovalCardBlock,
|
|
23
25
|
type ApprovalCardParams,
|
|
24
26
|
buildApprovalCardBlocks,
|
|
@@ -97,7 +99,18 @@ export type ApprovalCardData = AccessRequestCardData | ToolApprovalCardData;
|
|
|
97
99
|
function resolveAccessRequestCard(
|
|
98
100
|
payload: Record<string, unknown>,
|
|
99
101
|
): ApprovalCardParams {
|
|
100
|
-
const
|
|
102
|
+
const parsed = parseAccessRequestPayload(payload);
|
|
103
|
+
const view = buildAccessRequestCardView(parsed);
|
|
104
|
+
|
|
105
|
+
// Signal-driven introduction actions; the emphasis (primary lead,
|
|
106
|
+
// destructive Block) is resolved by introduction-policy and maps 1:1 onto
|
|
107
|
+
// the Surface style vocabulary.
|
|
108
|
+
const actions: ApprovalCardActionOption[] =
|
|
109
|
+
buildIntroductionActionsForPayload(parsed).map((action) => ({
|
|
110
|
+
id: action.id,
|
|
111
|
+
label: action.label,
|
|
112
|
+
style: action.emphasis,
|
|
113
|
+
}));
|
|
101
114
|
|
|
102
115
|
const metadata: Array<{ label: string; value: string }> = [];
|
|
103
116
|
|
|
@@ -139,11 +152,12 @@ function resolveAccessRequestCard(
|
|
|
139
152
|
return {
|
|
140
153
|
surfaceIdPrefix: ACCESS_REQUEST_SURFACE_PREFIX,
|
|
141
154
|
cardTitle: "Access Request",
|
|
142
|
-
|
|
155
|
+
primaryLine: view.displayName,
|
|
143
156
|
subtitle: "Requesting access to the assistant",
|
|
144
157
|
body,
|
|
145
158
|
metadata,
|
|
146
159
|
requestId: view.requestId,
|
|
160
|
+
actions,
|
|
147
161
|
fallbackText: buildAccessRequestContractText(payload),
|
|
148
162
|
};
|
|
149
163
|
}
|
|
@@ -170,14 +184,22 @@ function isLenientToolApproval(payload: LenientToolApprovalPayload): boolean {
|
|
|
170
184
|
payload.requestKind,
|
|
171
185
|
payload.toolName,
|
|
172
186
|
);
|
|
173
|
-
if (!modeResolution)
|
|
187
|
+
if (!modeResolution) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
174
190
|
return (
|
|
175
191
|
modeResolution.mode === "approval" &&
|
|
176
192
|
payload.requestKind !== "access_request"
|
|
177
193
|
);
|
|
178
194
|
}
|
|
179
195
|
|
|
180
|
-
/**
|
|
196
|
+
/**
|
|
197
|
+
* Shape a tool-approval/grant payload (strict or lenient) into card params.
|
|
198
|
+
*
|
|
199
|
+
* The card is about the tool: the primary line names the tool awaiting
|
|
200
|
+
* approval. The requester appears only as metadata context, never as the
|
|
201
|
+
* subject of the decision.
|
|
202
|
+
*/
|
|
181
203
|
function extractToolApprovalCard(
|
|
182
204
|
p: GuardianQuestionPayload | LenientToolApprovalPayload,
|
|
183
205
|
): ApprovalCardParams {
|
|
@@ -186,12 +208,16 @@ function extractToolApprovalCard(
|
|
|
186
208
|
const rawRequester = nonEmpty(p.requesterIdentifier);
|
|
187
209
|
const requester = rawRequester
|
|
188
210
|
? sanitizeIdentityField(rawRequester)
|
|
189
|
-
:
|
|
211
|
+
: undefined;
|
|
190
212
|
|
|
191
213
|
const isGrant = p.requestKind === "tool_grant_request";
|
|
192
214
|
|
|
215
|
+
// Who is asking is a fact the guardian weighs, so the row always renders:
|
|
216
|
+
// an unresolvable requester surfaces as "Unknown" rather than a silently
|
|
217
|
+
// missing row. In practice the producers always carry at least the raw
|
|
218
|
+
// channel user ID — this placeholder covers defensive/lenient parses.
|
|
193
219
|
const metadata: Array<{ label: string; value: string }> = [];
|
|
194
|
-
metadata.push({ label: "
|
|
220
|
+
metadata.push({ label: "Requested by", value: requester ?? "Unknown" });
|
|
195
221
|
const sourceChannel = nonEmpty(p.sourceChannel);
|
|
196
222
|
if (sourceChannel) {
|
|
197
223
|
metadata.push({ label: "Source", value: sourceChannel });
|
|
@@ -203,7 +229,8 @@ function extractToolApprovalCard(
|
|
|
203
229
|
|
|
204
230
|
// Fallback text with request-code instructions for older clients.
|
|
205
231
|
const baseFallback =
|
|
206
|
-
p.questionText ??
|
|
232
|
+
p.questionText ??
|
|
233
|
+
`Approve tool: ${toolName} (requested by ${requester ?? "Unknown"})`;
|
|
207
234
|
let fallbackText = baseFallback;
|
|
208
235
|
const requestCode = nonEmpty(p.requestCode);
|
|
209
236
|
if (requestCode) {
|
|
@@ -222,10 +249,8 @@ function extractToolApprovalCard(
|
|
|
222
249
|
return {
|
|
223
250
|
surfaceIdPrefix: TOOL_APPROVAL_SURFACE_PREFIX,
|
|
224
251
|
cardTitle: isGrant ? "Tool Grant Request" : "Tool Approval",
|
|
225
|
-
|
|
226
|
-
subtitle:
|
|
227
|
-
? "Requesting permission to use this tool"
|
|
228
|
-
: "Requesting approval to run this tool",
|
|
252
|
+
primaryLine: toolName,
|
|
253
|
+
subtitle: "Requires your approval to run",
|
|
229
254
|
body,
|
|
230
255
|
metadata,
|
|
231
256
|
requestId: nonEmpty(p.requestId),
|
|
@@ -246,13 +271,19 @@ function resolveToolApprovalCard(
|
|
|
246
271
|
): ApprovalCardParams | null {
|
|
247
272
|
const strict = parseGuardianQuestionPayload(payload);
|
|
248
273
|
if (strict) {
|
|
249
|
-
if (!isToolApprovalPayload(strict))
|
|
274
|
+
if (!isToolApprovalPayload(strict)) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
250
277
|
return extractToolApprovalCard(strict);
|
|
251
278
|
}
|
|
252
279
|
|
|
253
280
|
const lenient = LenientToolApprovalPayloadSchema.safeParse(payload);
|
|
254
|
-
if (!lenient.success)
|
|
255
|
-
|
|
281
|
+
if (!lenient.success) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
if (!isLenientToolApproval(lenient.data)) {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
256
287
|
return extractToolApprovalCard(lenient.data);
|
|
257
288
|
}
|
|
258
289
|
|
|
@@ -268,7 +299,9 @@ export function resolveApprovalCardData(
|
|
|
268
299
|
sourceEventName: string,
|
|
269
300
|
contextPayload: Record<string, unknown> | undefined,
|
|
270
301
|
): ApprovalCardData | null {
|
|
271
|
-
if (!contextPayload)
|
|
302
|
+
if (!contextPayload) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
272
305
|
|
|
273
306
|
if (sourceEventName === "ingress.access_request") {
|
|
274
307
|
return {
|
|
@@ -17,6 +17,7 @@ import type { ApprovalUIMetadata } from "../runtime/channel-approval-types.js";
|
|
|
17
17
|
import { getLogger } from "../util/logger.js";
|
|
18
18
|
import {
|
|
19
19
|
buildAccessRequestContractText,
|
|
20
|
+
buildIntroductionActionsForPayload,
|
|
20
21
|
parseAccessRequestPayload,
|
|
21
22
|
} from "./access-request-copy.js";
|
|
22
23
|
import { isGuardianSensitiveEvent } from "./adapters/macos.js";
|
|
@@ -28,10 +29,7 @@ import {
|
|
|
28
29
|
updateDeliveryStatus,
|
|
29
30
|
} from "./deliveries-store.js";
|
|
30
31
|
import { resolveDestinations } from "./destination-resolver.js";
|
|
31
|
-
import {
|
|
32
|
-
parseGuardianQuestionPayload,
|
|
33
|
-
resolveGuardianInstructionModeFromPayload,
|
|
34
|
-
} from "./guardian-question-mode.js";
|
|
32
|
+
import { parseInteractiveApprovalPayload } from "./guardian-question-mode.js";
|
|
35
33
|
import { nonEmpty } from "./notification-utils.js";
|
|
36
34
|
import type { NotificationSignal } from "./signal.js";
|
|
37
35
|
import type {
|
|
@@ -59,27 +57,32 @@ function resolveApprovalContext(
|
|
|
59
57
|
signal: NotificationSignal,
|
|
60
58
|
): ApprovalUIMetadata | undefined {
|
|
61
59
|
const payload = signal.contextPayload;
|
|
62
|
-
if (!payload)
|
|
60
|
+
if (!payload) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
63
|
|
|
64
64
|
if (signal.sourceEventName === "ingress.access_request") {
|
|
65
65
|
const requestId = nonEmpty(
|
|
66
66
|
typeof payload.requestId === "string" ? payload.requestId : undefined,
|
|
67
67
|
);
|
|
68
|
-
if (!requestId)
|
|
68
|
+
if (!requestId) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
69
71
|
return {
|
|
70
72
|
requestId,
|
|
71
|
-
actions:
|
|
73
|
+
actions: buildIntroductionActionsForPayload(
|
|
74
|
+
parseAccessRequestPayload(payload),
|
|
75
|
+
),
|
|
72
76
|
plainTextFallback: buildAccessRequestContractText(payload),
|
|
73
77
|
};
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
if (signal.sourceEventName === "guardian.question") {
|
|
77
|
-
const parsed =
|
|
78
|
-
if (!parsed)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const requestId =
|
|
82
|
-
if (!requestId) return undefined;
|
|
81
|
+
const parsed = parseInteractiveApprovalPayload(payload);
|
|
82
|
+
if (!parsed) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const requestId = parsed.requestId;
|
|
83
86
|
|
|
84
87
|
// Extract tool context so channel adapters can render structured
|
|
85
88
|
// approval cards without re-parsing contextPayload.
|
|
@@ -184,8 +187,12 @@ export class NotificationBroadcaster {
|
|
|
184
187
|
// event fires immediately, before slower channel sends (e.g. Telegram 30s
|
|
185
188
|
// timeout) can delay it past the macOS deep-link retry window.
|
|
186
189
|
const orderedChannels = [...decision.selectedChannels].sort((a, b) => {
|
|
187
|
-
if (a === "vellum")
|
|
188
|
-
|
|
190
|
+
if (a === "vellum") {
|
|
191
|
+
return -1;
|
|
192
|
+
}
|
|
193
|
+
if (b === "vellum") {
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
189
196
|
return 0;
|
|
190
197
|
});
|
|
191
198
|
|
|
@@ -552,7 +559,9 @@ export class NotificationBroadcaster {
|
|
|
552
559
|
function resolveSourceConversationId(
|
|
553
560
|
sourceContextId: string | undefined,
|
|
554
561
|
): string | undefined {
|
|
555
|
-
if (!sourceContextId)
|
|
562
|
+
if (!sourceContextId) {
|
|
563
|
+
return undefined;
|
|
564
|
+
}
|
|
556
565
|
try {
|
|
557
566
|
return getConversation(sourceContextId) ? sourceContextId : undefined;
|
|
558
567
|
} catch {
|
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
buildAccessRequestInviteDirective,
|
|
33
33
|
hasAccessRequestInstructions,
|
|
34
34
|
hasInviteFlowDirective,
|
|
35
|
+
isHandshakeOfferedForPayload,
|
|
36
|
+
parseAccessRequestPayload,
|
|
35
37
|
} from "./access-request-copy.js";
|
|
36
38
|
import {
|
|
37
39
|
buildAccessRequestSeedContentBlocks,
|
|
@@ -47,8 +49,10 @@ import { createDecision } from "./decisions-store.js";
|
|
|
47
49
|
import {
|
|
48
50
|
buildGuardianRequestCodeInstruction,
|
|
49
51
|
hasGuardianRequestCodeInstruction,
|
|
52
|
+
parseInteractiveApprovalPayload,
|
|
50
53
|
resolveGuardianQuestionInstructionMode,
|
|
51
54
|
stripConflictingGuardianRequestInstructions,
|
|
55
|
+
stripGuardianRequestCodeInstructions,
|
|
52
56
|
} from "./guardian-question-mode.js";
|
|
53
57
|
import { nonEmpty, readPayloadString } from "./notification-utils.js";
|
|
54
58
|
import { getPreferenceSummary } from "./preference-summary.js";
|
|
@@ -143,6 +147,7 @@ function buildSystemPrompt(
|
|
|
143
147
|
` - Avoid meta-send phrasing (e.g. "I'd like to send a notification", "May I go ahead with that?"). Write the recipient-facing message directly.`,
|
|
144
148
|
` - Avoid intermediary-instruction phrasing like "consider telling the guardian", "ask the recipient to", or "the assistant should remind them". Rewrite it as final copy the recipient can act on directly.`,
|
|
145
149
|
` - For telegram: 1-2 concise sentences.`,
|
|
150
|
+
` - For slack approval requests: the message renders inside an interactive card with Approve/Reject buttons. Describe only what needs approval — never include approval/reference codes, code-reply instructions, or directions to respond in another app.`,
|
|
146
151
|
`- \`conversationSeedMessage\` is the opening message in the internal notification conversation and also the expanded detail shown in the home feed. It should be richer and more contextual than the popup body.`,
|
|
147
152
|
` - For vellum (desktop): use structured markdown for readability. Break content into bullet points, numbered lists, or short sections with **bold** labels. Avoid long unbroken paragraphs — scan-friendly formatting is preferred.`,
|
|
148
153
|
` - Never dump raw JSON. Include only human-readable context.`,
|
|
@@ -382,11 +387,19 @@ function validateDecisionOutput(
|
|
|
382
387
|
availableChannels: NotificationChannel[],
|
|
383
388
|
candidateSet?: ConversationCandidateSet,
|
|
384
389
|
): NotificationDecision | null {
|
|
385
|
-
if (typeof input.shouldNotify !== "boolean")
|
|
386
|
-
|
|
387
|
-
|
|
390
|
+
if (typeof input.shouldNotify !== "boolean") {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
if (typeof input.reasoningSummary !== "string") {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
if (typeof input.dedupeKey !== "string") {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
388
399
|
|
|
389
|
-
if (!Array.isArray(input.selectedChannels))
|
|
400
|
+
if (!Array.isArray(input.selectedChannels)) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
390
403
|
const validatedChannels = (input.selectedChannels as unknown[]).filter(
|
|
391
404
|
(ch): ch is NotificationChannel =>
|
|
392
405
|
typeof ch === "string" &&
|
|
@@ -482,7 +495,9 @@ export function validateConversationActions(
|
|
|
482
495
|
): Partial<Record<NotificationChannel, ConversationAction>> {
|
|
483
496
|
const result: Partial<Record<NotificationChannel, ConversationAction>> = {};
|
|
484
497
|
|
|
485
|
-
if (!raw || typeof raw !== "object")
|
|
498
|
+
if (!raw || typeof raw !== "object") {
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
486
501
|
|
|
487
502
|
const actionsObj = raw as Record<string, unknown>;
|
|
488
503
|
const channelSet = new Set(validChannels);
|
|
@@ -502,8 +517,12 @@ export function validateConversationActions(
|
|
|
502
517
|
}
|
|
503
518
|
|
|
504
519
|
for (const [ch, actionRaw] of Object.entries(actionsObj)) {
|
|
505
|
-
if (!channelSet.has(ch as NotificationChannel))
|
|
506
|
-
|
|
520
|
+
if (!channelSet.has(ch as NotificationChannel)) {
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
if (!actionRaw || typeof actionRaw !== "object") {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
507
526
|
|
|
508
527
|
const channel = ch as NotificationChannel;
|
|
509
528
|
const action = actionRaw as Record<string, unknown>;
|
|
@@ -558,8 +577,9 @@ function ensureGuardianRequestCodeInCopy(
|
|
|
558
577
|
requestCode,
|
|
559
578
|
mode,
|
|
560
579
|
);
|
|
561
|
-
if (hasGuardianRequestCodeInstruction(sanitized, requestCode, mode))
|
|
580
|
+
if (hasGuardianRequestCodeInstruction(sanitized, requestCode, mode)) {
|
|
562
581
|
return sanitized;
|
|
582
|
+
}
|
|
563
583
|
return sanitized.length > 0
|
|
564
584
|
? `${sanitized}\n\n${instruction}`
|
|
565
585
|
: instruction;
|
|
@@ -577,36 +597,79 @@ function ensureGuardianRequestCodeInCopy(
|
|
|
577
597
|
};
|
|
578
598
|
}
|
|
579
599
|
|
|
600
|
+
/**
|
|
601
|
+
* Remove request-code reply instructions from copy for a channel whose
|
|
602
|
+
* approval UI makes them redundant. Instruction-only fields keep their
|
|
603
|
+
* original text rather than becoming empty — downstream treats an empty
|
|
604
|
+
* body as missing copy.
|
|
605
|
+
*/
|
|
606
|
+
function stripGuardianRequestCodeInCopy(
|
|
607
|
+
copy: RenderedChannelCopy,
|
|
608
|
+
requestCode: string,
|
|
609
|
+
): RenderedChannelCopy {
|
|
610
|
+
const strip = (text: string): string => {
|
|
611
|
+
const stripped = stripGuardianRequestCodeInstructions(text, requestCode);
|
|
612
|
+
return stripped.length > 0 ? stripped : text;
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
return {
|
|
616
|
+
...copy,
|
|
617
|
+
body: strip(copy.body),
|
|
618
|
+
deliveryText: copy.deliveryText
|
|
619
|
+
? strip(copy.deliveryText)
|
|
620
|
+
: copy.deliveryText,
|
|
621
|
+
conversationSeedMessage: copy.conversationSeedMessage
|
|
622
|
+
? strip(copy.conversationSeedMessage)
|
|
623
|
+
: copy.conversationSeedMessage,
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
580
627
|
/**
|
|
581
628
|
* Guardian questions that share a conversation require explicit request-code
|
|
582
629
|
* targeting. Enforce request-code instructions in rendered copy so guardians
|
|
583
630
|
* can always disambiguate replies even when model copy omits them.
|
|
631
|
+
*
|
|
632
|
+
* Slack is the exception for approval-mode questions: the Slack adapter
|
|
633
|
+
* renders those as an interactive card with Approve/Reject buttons (see
|
|
634
|
+
* `resolveApprovalContext` in broadcaster.ts, gated on the same
|
|
635
|
+
* `parseInteractiveApprovalPayload`), so code-reply instructions are
|
|
636
|
+
* redundant noise there and are stripped instead of enforced in.
|
|
584
637
|
*/
|
|
585
638
|
function enforceGuardianRequestCode(
|
|
586
639
|
decision: NotificationDecision,
|
|
587
640
|
signal: NotificationSignal,
|
|
588
641
|
): NotificationDecision {
|
|
589
|
-
if (signal.sourceEventName !== "guardian.question")
|
|
642
|
+
if (signal.sourceEventName !== "guardian.question") {
|
|
643
|
+
return decision;
|
|
644
|
+
}
|
|
590
645
|
const rawCode = signal.contextPayload.requestCode;
|
|
591
|
-
if (typeof rawCode !== "string" || rawCode.trim().length === 0)
|
|
646
|
+
if (typeof rawCode !== "string" || rawCode.trim().length === 0) {
|
|
592
647
|
return decision;
|
|
648
|
+
}
|
|
593
649
|
|
|
594
650
|
const requestCode = rawCode.trim().toUpperCase();
|
|
595
651
|
const modeResolution = resolveGuardianQuestionInstructionMode(
|
|
596
652
|
signal.contextPayload,
|
|
597
653
|
);
|
|
654
|
+
const slackRendersApprovalButtons =
|
|
655
|
+
parseInteractiveApprovalPayload(signal.contextPayload) != null;
|
|
598
656
|
const nextCopy: Partial<Record<NotificationChannel, RenderedChannelCopy>> = {
|
|
599
657
|
...decision.renderedCopy,
|
|
600
658
|
};
|
|
601
659
|
|
|
602
660
|
for (const channel of Object.keys(nextCopy) as NotificationChannel[]) {
|
|
603
661
|
const copy = nextCopy[channel];
|
|
604
|
-
if (!copy)
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
662
|
+
if (!copy) {
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
nextCopy[channel] =
|
|
666
|
+
channel === "slack" && slackRendersApprovalButtons
|
|
667
|
+
? stripGuardianRequestCodeInCopy(copy, requestCode)
|
|
668
|
+
: ensureGuardianRequestCodeInCopy(
|
|
669
|
+
copy,
|
|
670
|
+
requestCode,
|
|
671
|
+
modeResolution.mode,
|
|
672
|
+
);
|
|
610
673
|
}
|
|
611
674
|
|
|
612
675
|
return {
|
|
@@ -624,14 +687,18 @@ function ensureSeedContentBlocks(
|
|
|
624
687
|
decision: NotificationDecision,
|
|
625
688
|
blocks: unknown[] | null | undefined,
|
|
626
689
|
): NotificationDecision {
|
|
627
|
-
if (!blocks)
|
|
690
|
+
if (!blocks) {
|
|
691
|
+
return decision;
|
|
692
|
+
}
|
|
628
693
|
|
|
629
694
|
const nextCopy: Partial<Record<NotificationChannel, RenderedChannelCopy>> = {
|
|
630
695
|
...decision.renderedCopy,
|
|
631
696
|
};
|
|
632
697
|
for (const channel of Object.keys(nextCopy) as NotificationChannel[]) {
|
|
633
698
|
const copy = nextCopy[channel];
|
|
634
|
-
if (!copy)
|
|
699
|
+
if (!copy) {
|
|
700
|
+
continue;
|
|
701
|
+
}
|
|
635
702
|
if (!copy.seedContentBlocks) {
|
|
636
703
|
nextCopy[channel] = { ...copy, seedContentBlocks: blocks };
|
|
637
704
|
}
|
|
@@ -651,7 +718,9 @@ function enforceToolApprovalSeedBlocks(
|
|
|
651
718
|
decision: NotificationDecision,
|
|
652
719
|
signal: NotificationSignal,
|
|
653
720
|
): NotificationDecision {
|
|
654
|
-
if (signal.sourceEventName !== "guardian.question")
|
|
721
|
+
if (signal.sourceEventName !== "guardian.question") {
|
|
722
|
+
return decision;
|
|
723
|
+
}
|
|
655
724
|
return ensureSeedContentBlocks(
|
|
656
725
|
decision,
|
|
657
726
|
buildToolApprovalSeedContentBlocks(signal.contextPayload),
|
|
@@ -675,7 +744,9 @@ function enforceAccessRequestInstructions(
|
|
|
675
744
|
decision: NotificationDecision,
|
|
676
745
|
signal: NotificationSignal,
|
|
677
746
|
): NotificationDecision {
|
|
678
|
-
if (signal.sourceEventName !== "ingress.access_request")
|
|
747
|
+
if (signal.sourceEventName !== "ingress.access_request") {
|
|
748
|
+
return decision;
|
|
749
|
+
}
|
|
679
750
|
|
|
680
751
|
const rawCode = signal.contextPayload.requestCode;
|
|
681
752
|
const hasRequestCode =
|
|
@@ -688,14 +759,20 @@ function enforceAccessRequestInstructions(
|
|
|
688
759
|
if (hasRequestCode) {
|
|
689
760
|
const requestCode = rawCode.trim().toUpperCase();
|
|
690
761
|
const contractText = buildAccessRequestContractText(signal.contextPayload);
|
|
762
|
+
const handshakeOffered = isHandshakeOfferedForPayload(
|
|
763
|
+
parseAccessRequestPayload(signal.contextPayload),
|
|
764
|
+
);
|
|
691
765
|
|
|
692
766
|
for (const channel of Object.keys(nextCopy) as NotificationChannel[]) {
|
|
693
767
|
const copy = nextCopy[channel];
|
|
694
|
-
if (!copy)
|
|
768
|
+
if (!copy) {
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
695
771
|
nextCopy[channel] = ensureAccessRequestInstructionsInCopy(
|
|
696
772
|
copy,
|
|
697
773
|
requestCode,
|
|
698
774
|
contractText,
|
|
775
|
+
handshakeOffered,
|
|
699
776
|
);
|
|
700
777
|
}
|
|
701
778
|
} else {
|
|
@@ -704,7 +781,9 @@ function enforceAccessRequestInstructions(
|
|
|
704
781
|
|
|
705
782
|
for (const channel of Object.keys(nextCopy) as NotificationChannel[]) {
|
|
706
783
|
const copy = nextCopy[channel];
|
|
707
|
-
if (!copy)
|
|
784
|
+
if (!copy) {
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
708
787
|
nextCopy[channel] = ensureInviteFlowDirectiveInCopy(
|
|
709
788
|
copy,
|
|
710
789
|
inviteDirective,
|
|
@@ -730,10 +809,13 @@ function ensureAccessRequestInstructionsInCopy(
|
|
|
730
809
|
copy: RenderedChannelCopy,
|
|
731
810
|
requestCode: string,
|
|
732
811
|
contractText: string,
|
|
812
|
+
handshakeOffered: boolean,
|
|
733
813
|
): RenderedChannelCopy {
|
|
734
814
|
const ensureText = (text: string | undefined): string => {
|
|
735
815
|
const base = typeof text === "string" ? text.trim() : "";
|
|
736
|
-
if (hasAccessRequestInstructions(base, requestCode))
|
|
816
|
+
if (hasAccessRequestInstructions(base, requestCode, { handshakeOffered })) {
|
|
817
|
+
return base;
|
|
818
|
+
}
|
|
737
819
|
return base.length > 0 ? `${base}\n\n${contractText}` : contractText;
|
|
738
820
|
};
|
|
739
821
|
|
|
@@ -755,7 +837,9 @@ function ensureInviteFlowDirectiveInCopy(
|
|
|
755
837
|
): RenderedChannelCopy {
|
|
756
838
|
const ensureText = (text: string | undefined): string => {
|
|
757
839
|
const base = typeof text === "string" ? text.trim() : "";
|
|
758
|
-
if (hasInviteFlowDirective(base))
|
|
840
|
+
if (hasInviteFlowDirective(base)) {
|
|
841
|
+
return base;
|
|
842
|
+
}
|
|
759
843
|
return base.length > 0 ? `${base}\n\n${inviteDirective}` : inviteDirective;
|
|
760
844
|
};
|
|
761
845
|
|
|
@@ -1138,15 +1222,21 @@ export function enforceRoutingIntent(
|
|
|
1138
1222
|
// Preserve the decision's selected channels first, then add connected
|
|
1139
1223
|
// channels until we reach two channels total.
|
|
1140
1224
|
for (const ch of selectedConnected) {
|
|
1141
|
-
if (seen.has(ch))
|
|
1225
|
+
if (seen.has(ch)) {
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1142
1228
|
expanded.push(ch);
|
|
1143
1229
|
seen.add(ch);
|
|
1144
1230
|
}
|
|
1145
1231
|
for (const ch of connectedChannels) {
|
|
1146
|
-
if (seen.has(ch))
|
|
1232
|
+
if (seen.has(ch)) {
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1147
1235
|
expanded.push(ch);
|
|
1148
1236
|
seen.add(ch);
|
|
1149
|
-
if (expanded.length >= 2)
|
|
1237
|
+
if (expanded.length >= 2) {
|
|
1238
|
+
break;
|
|
1239
|
+
}
|
|
1150
1240
|
}
|
|
1151
1241
|
|
|
1152
1242
|
const enforced = { ...decision };
|
|
@@ -1184,15 +1274,20 @@ export function enforceGuardianCallConversationAffinity(
|
|
|
1184
1274
|
decision: NotificationDecision,
|
|
1185
1275
|
signal: NotificationSignal,
|
|
1186
1276
|
): NotificationDecision {
|
|
1187
|
-
if (signal.sourceEventName !== "guardian.question")
|
|
1277
|
+
if (signal.sourceEventName !== "guardian.question") {
|
|
1278
|
+
return decision;
|
|
1279
|
+
}
|
|
1188
1280
|
|
|
1189
1281
|
const callSessionId = signal.contextPayload?.callSessionId;
|
|
1190
|
-
if (typeof callSessionId !== "string" || callSessionId.trim().length === 0)
|
|
1282
|
+
if (typeof callSessionId !== "string" || callSessionId.trim().length === 0) {
|
|
1191
1283
|
return decision;
|
|
1284
|
+
}
|
|
1192
1285
|
|
|
1193
1286
|
// If an affinity hint already exists for vellum, the second+ dispatch
|
|
1194
1287
|
// will be handled by enforceConversationAffinity — nothing to do here.
|
|
1195
|
-
if (signal.conversationAffinityHint?.vellum)
|
|
1288
|
+
if (signal.conversationAffinityHint?.vellum) {
|
|
1289
|
+
return decision;
|
|
1290
|
+
}
|
|
1196
1291
|
|
|
1197
1292
|
const enforced = { ...decision };
|
|
1198
1293
|
const conversationActions: Partial<
|
|
@@ -1226,13 +1321,17 @@ function enforceConversationAffinity(
|
|
|
1226
1321
|
decision: NotificationDecision,
|
|
1227
1322
|
affinityHint: Partial<Record<string, string>> | undefined,
|
|
1228
1323
|
): NotificationDecision {
|
|
1229
|
-
if (!affinityHint)
|
|
1324
|
+
if (!affinityHint) {
|
|
1325
|
+
return decision;
|
|
1326
|
+
}
|
|
1230
1327
|
|
|
1231
1328
|
const entries = Object.entries(affinityHint).filter(
|
|
1232
1329
|
([, conversationId]) =>
|
|
1233
1330
|
typeof conversationId === "string" && conversationId.length > 0,
|
|
1234
1331
|
);
|
|
1235
|
-
if (entries.length === 0)
|
|
1332
|
+
if (entries.length === 0) {
|
|
1333
|
+
return decision;
|
|
1334
|
+
}
|
|
1236
1335
|
|
|
1237
1336
|
const enforced = { ...decision };
|
|
1238
1337
|
const conversationActions: Partial<
|