@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
|
@@ -63,6 +63,13 @@ import {
|
|
|
63
63
|
PluginCatalogUnavailableError,
|
|
64
64
|
type PluginSearchMatch,
|
|
65
65
|
} from "../../cli/lib/search-plugins.js";
|
|
66
|
+
import {
|
|
67
|
+
disablePlugin,
|
|
68
|
+
enablePlugin,
|
|
69
|
+
InvalidPluginNameError as InvalidTogglePluginNameError,
|
|
70
|
+
PluginAlreadyInStateException,
|
|
71
|
+
PluginDirectoryNotFoundError,
|
|
72
|
+
} from "../../cli/lib/toggle-plugin.js";
|
|
66
73
|
import {
|
|
67
74
|
PluginNotInstalledError,
|
|
68
75
|
uninstallPlugin,
|
|
@@ -73,7 +80,13 @@ import {
|
|
|
73
80
|
type PluginUpgradeStrategy,
|
|
74
81
|
upgradePlugin,
|
|
75
82
|
} from "../../cli/lib/upgrade-plugin.js";
|
|
83
|
+
import { isPluginDisabled } from "../../plugins/disabled-state.js";
|
|
84
|
+
import { getLocalCategorySlugs } from "../../skills/categories-cache.js";
|
|
76
85
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
86
|
+
import {
|
|
87
|
+
getOriginClientId,
|
|
88
|
+
publishPluginsChanged,
|
|
89
|
+
} from "../sync/resource-sync-events.js";
|
|
77
90
|
import {
|
|
78
91
|
BadRequestError,
|
|
79
92
|
ConflictError,
|
|
@@ -95,6 +108,11 @@ const pluginInfoSchema = z.object({
|
|
|
95
108
|
"Plugin's directory name (kebab-case). Matches `assistant plugins install <id>`.",
|
|
96
109
|
),
|
|
97
110
|
name: z.string().describe("Display name. Equal to `id` today."),
|
|
111
|
+
enabled: z
|
|
112
|
+
.boolean()
|
|
113
|
+
.describe(
|
|
114
|
+
"Whether the plugin is active in this workspace. `false` when a `.disabled` sentinel is present under its directory; `true` otherwise.",
|
|
115
|
+
),
|
|
98
116
|
description: z
|
|
99
117
|
.string()
|
|
100
118
|
.nullable()
|
|
@@ -113,10 +131,27 @@ const pluginInfoSchema = z.object({
|
|
|
113
131
|
.describe(
|
|
114
132
|
"Non-fatal issues with this entry (missing `package.json`, malformed JSON, ...). Omitted when clean.",
|
|
115
133
|
),
|
|
134
|
+
category: z
|
|
135
|
+
.string()
|
|
136
|
+
.nullable()
|
|
137
|
+
.optional()
|
|
138
|
+
.describe(
|
|
139
|
+
"Marketplace category slug (Skills taxonomy); null when origin/category is unknown, e.g. non-marketplace installs.",
|
|
140
|
+
),
|
|
116
141
|
});
|
|
117
142
|
|
|
118
143
|
const pluginsListResponseSchema = z.object({
|
|
119
144
|
plugins: z.array(pluginInfoSchema),
|
|
145
|
+
categoryCounts: z
|
|
146
|
+
.record(z.string(), z.number())
|
|
147
|
+
.optional()
|
|
148
|
+
.describe(
|
|
149
|
+
"Installed plugins per category (before the category filter is applied).",
|
|
150
|
+
),
|
|
151
|
+
totalCount: z
|
|
152
|
+
.number()
|
|
153
|
+
.optional()
|
|
154
|
+
.describe("Total installed plugins matching non-category filters."),
|
|
120
155
|
});
|
|
121
156
|
|
|
122
157
|
const pluginMatchSourceSchema = z
|
|
@@ -148,6 +183,12 @@ const pluginSearchMatchSchema = z.object({
|
|
|
148
183
|
.string()
|
|
149
184
|
.optional()
|
|
150
185
|
.describe("Short description, when known (external entries only today)."),
|
|
186
|
+
category: z
|
|
187
|
+
.string()
|
|
188
|
+
.nullable()
|
|
189
|
+
.describe(
|
|
190
|
+
"Marketplace category slug (Skills taxonomy); null when the entry declares none.",
|
|
191
|
+
),
|
|
151
192
|
source: pluginMatchSourceSchema,
|
|
152
193
|
});
|
|
153
194
|
|
|
@@ -611,10 +652,12 @@ const pluginDiffResponseSchema = z.object({
|
|
|
611
652
|
interface PluginView {
|
|
612
653
|
id: string;
|
|
613
654
|
name: string;
|
|
655
|
+
enabled: boolean;
|
|
614
656
|
description: string | null;
|
|
615
657
|
version: string | null;
|
|
616
658
|
path: string;
|
|
617
659
|
issues?: string[];
|
|
660
|
+
category?: string | null;
|
|
618
661
|
}
|
|
619
662
|
|
|
620
663
|
function projectPlugin(entry: InstalledPluginInfo): PluginView {
|
|
@@ -624,6 +667,8 @@ function projectPlugin(entry: InstalledPluginInfo): PluginView {
|
|
|
624
667
|
const view: PluginView = {
|
|
625
668
|
id: entry.name,
|
|
626
669
|
name: entry.name,
|
|
670
|
+
// `entry.name` is the plugin directory name, which is the sentinel key.
|
|
671
|
+
enabled: !isPluginDisabled(entry.name),
|
|
627
672
|
description: entry.packageJson?.description ?? null,
|
|
628
673
|
version: entry.packageJson?.version ?? null,
|
|
629
674
|
path: entry.target,
|
|
@@ -634,11 +679,56 @@ function projectPlugin(entry: InstalledPluginInfo): PluginView {
|
|
|
634
679
|
return view;
|
|
635
680
|
}
|
|
636
681
|
|
|
682
|
+
/**
|
|
683
|
+
* Marketplace → Skills category slug aliases for known, unambiguous mismatches.
|
|
684
|
+
* Keep this tiny: only add a mapping when it is obviously correct. Marketplace
|
|
685
|
+
* slugs with no clean Skills equivalent are intentionally absent so they fall
|
|
686
|
+
* through to `null` → the "system" bucket.
|
|
687
|
+
*/
|
|
688
|
+
const MARKETPLACE_CATEGORY_ALIASES: Record<string, string> = {
|
|
689
|
+
developer: "development",
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Normalize a raw marketplace category slug to the shared Skills taxonomy so
|
|
694
|
+
* the rail never carries an invisible bucket. Lowercases + trims, applies the
|
|
695
|
+
* alias map, then returns the slug only when it is a valid Skills slug —
|
|
696
|
+
* otherwise `null`, which buckets under "system" so the plugin stays both
|
|
697
|
+
* counted and reachable. `validSlugs` is resolved once per request by the
|
|
698
|
+
* caller (never per item).
|
|
699
|
+
*/
|
|
700
|
+
export function normalizeMarketplaceCategory(
|
|
701
|
+
raw: string | null | undefined,
|
|
702
|
+
validSlugs: Set<string>,
|
|
703
|
+
): string | null {
|
|
704
|
+
if (!raw) return null;
|
|
705
|
+
const slug = raw.trim().toLowerCase();
|
|
706
|
+
if (!slug) return null;
|
|
707
|
+
const aliased = MARKETPLACE_CATEGORY_ALIASES[slug] ?? slug;
|
|
708
|
+
return validSlugs.has(aliased) ? aliased : null;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Valid Skills category slugs the marketplace categories normalize against.
|
|
713
|
+
* Sync + local (bundled YAML via the Skills categories-cache) so the plugins
|
|
714
|
+
* list never takes on remote latency; a read failure degrades to an empty set,
|
|
715
|
+
* normalizing every category to `null` → "system" rather than throwing —
|
|
716
|
+
* mirroring the bounded posture of the catalog lookup.
|
|
717
|
+
*/
|
|
718
|
+
function getValidCategorySlugs(): Set<string> {
|
|
719
|
+
try {
|
|
720
|
+
return getLocalCategorySlugs();
|
|
721
|
+
} catch {
|
|
722
|
+
return new Set();
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
637
726
|
/** Wire shape for a catalog match. Mirrors {@link pluginSearchMatchSchema}. */
|
|
638
727
|
interface PluginMatchView {
|
|
639
728
|
name: string;
|
|
640
729
|
path: string;
|
|
641
730
|
description?: string;
|
|
731
|
+
category: string | null;
|
|
642
732
|
source: { kind: "github"; repo: string; path?: string; ref: string };
|
|
643
733
|
}
|
|
644
734
|
|
|
@@ -647,10 +737,14 @@ interface PluginMatchView {
|
|
|
647
737
|
* serializer's `Record<string, unknown>` contract holds. The wire shape is
|
|
648
738
|
* identical to {@link PluginSearchMatch}.
|
|
649
739
|
*/
|
|
650
|
-
function projectMatch(
|
|
740
|
+
function projectMatch(
|
|
741
|
+
m: PluginSearchMatch,
|
|
742
|
+
validSlugs: Set<string>,
|
|
743
|
+
): PluginMatchView {
|
|
651
744
|
const view: PluginMatchView = {
|
|
652
745
|
name: m.name,
|
|
653
746
|
path: m.path,
|
|
747
|
+
category: normalizeMarketplaceCategory(m.category, validSlugs),
|
|
654
748
|
source: {
|
|
655
749
|
kind: "github",
|
|
656
750
|
repo: m.source.repo,
|
|
@@ -678,14 +772,103 @@ function matchesQuery(plugin: PluginView, needle: string): boolean {
|
|
|
678
772
|
// Handler — list installed
|
|
679
773
|
// ---------------------------------------------------------------------------
|
|
680
774
|
|
|
681
|
-
|
|
775
|
+
/** Uncategorized fallback bucket — matches the Skills taxonomy default. */
|
|
776
|
+
const UNCATEGORIZED = "system";
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Time budget for the marketplace category lookup on the installed list.
|
|
780
|
+
* The installed list is a fast local read; the catalog is a remote GitHub
|
|
781
|
+
* fetch that can hang on a cold cache. Bounding the lookup keeps `GET
|
|
782
|
+
* /v1/plugins` responsive during a marketplace slowdown.
|
|
783
|
+
*/
|
|
784
|
+
const CATEGORY_LOOKUP_TIMEOUT_MS = 1500;
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Resolve the marketplace category map, racing the catalog fetch against a
|
|
788
|
+
* timer so a slow/hanging GitHub fetch can't block the installed list: on a
|
|
789
|
+
* rejection or a timeout past {@link CATEGORY_LOOKUP_TIMEOUT_MS} it degrades to
|
|
790
|
+
* an empty map (every `category` resolves to `null`). `timeoutMs` is injectable
|
|
791
|
+
* so tests can exercise the bound without the full production budget.
|
|
792
|
+
*/
|
|
793
|
+
export async function loadCategoryMapBounded(
|
|
794
|
+
timeoutMs: number = CATEGORY_LOOKUP_TIMEOUT_MS,
|
|
795
|
+
): Promise<Map<string, string | null>> {
|
|
796
|
+
// Clear the timer once the race settles so a catalog-wins path doesn't leave
|
|
797
|
+
// the timer pending per request (matters for shutdown / test handles).
|
|
798
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
799
|
+
try {
|
|
800
|
+
const catalog = await Promise.race([
|
|
801
|
+
getPluginCatalog(DEFAULT_PLUGIN_REF, {
|
|
802
|
+
fetch: globalThis.fetch.bind(globalThis),
|
|
803
|
+
}),
|
|
804
|
+
new Promise<null>((resolve) => {
|
|
805
|
+
timer = setTimeout(() => resolve(null), timeoutMs);
|
|
806
|
+
}),
|
|
807
|
+
]);
|
|
808
|
+
if (!catalog) return new Map();
|
|
809
|
+
return new Map(catalog.matches.map((m) => [m.name, m.category]));
|
|
810
|
+
} catch {
|
|
811
|
+
return new Map();
|
|
812
|
+
} finally {
|
|
813
|
+
if (timer) clearTimeout(timer);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
async function handleListPlugins({
|
|
818
|
+
queryParams = {},
|
|
819
|
+
}: RouteHandlerArgs): Promise<{
|
|
682
820
|
plugins: PluginView[];
|
|
683
|
-
|
|
821
|
+
categoryCounts: Record<string, number>;
|
|
822
|
+
totalCount: number;
|
|
823
|
+
}> {
|
|
684
824
|
const q = queryParams.q?.trim();
|
|
825
|
+
const category = queryParams.category?.trim();
|
|
826
|
+
|
|
685
827
|
const installed = listInstalledPlugins();
|
|
686
828
|
const projected = installed.map(projectPlugin);
|
|
687
|
-
|
|
688
|
-
|
|
829
|
+
|
|
830
|
+
// Nothing installed → `categoryCounts`/`totalCount` are deterministically
|
|
831
|
+
// empty and there is nothing to categorize, so skip the network-bound catalog
|
|
832
|
+
// lookup entirely (no wasted GitHub request or bounded stall wait).
|
|
833
|
+
if (projected.length === 0) {
|
|
834
|
+
return { plugins: [], categoryCounts: {}, totalCount: 0 };
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// Categories live only in the catalog. A marketplace outage OR slowdown must
|
|
838
|
+
// never block the installed list, so the lookup is bounded: it degrades to an
|
|
839
|
+
// empty map (every category becomes `null`) on a rejection or a stall.
|
|
840
|
+
const categoryMap = await loadCategoryMapBounded();
|
|
841
|
+
|
|
842
|
+
// Normalize raw marketplace slugs to the shared Skills taxonomy once per
|
|
843
|
+
// request: a raw slug with no Skills row (e.g. `developer`, `memory`) would
|
|
844
|
+
// otherwise be counted in "All" yet unreachable by any rail row. Normalizing
|
|
845
|
+
// maps the unambiguous ones (`developer` → `development`) and folds the rest
|
|
846
|
+
// to `null` → "system", so counts always match visible rows.
|
|
847
|
+
const validSlugs = getValidCategorySlugs();
|
|
848
|
+
|
|
849
|
+
// An installed plugin's `id` is its directory name, which is the catalog
|
|
850
|
+
// match's `name` — so it's the lookup key.
|
|
851
|
+
const withCategory = projected.map((p) => ({
|
|
852
|
+
...p,
|
|
853
|
+
category: normalizeMarketplaceCategory(categoryMap.get(p.id), validSlugs),
|
|
854
|
+
}));
|
|
855
|
+
|
|
856
|
+
let list = q ? withCategory.filter((p) => matchesQuery(p, q)) : withCategory;
|
|
857
|
+
|
|
858
|
+
// Counts are taken BEFORE the category filter so the rail badges stay stable
|
|
859
|
+
// while a single category is selected.
|
|
860
|
+
const categoryCounts: Record<string, number> = {};
|
|
861
|
+
for (const p of list) {
|
|
862
|
+
const bucket = p.category ?? UNCATEGORIZED;
|
|
863
|
+
categoryCounts[bucket] = (categoryCounts[bucket] ?? 0) + 1;
|
|
864
|
+
}
|
|
865
|
+
const totalCount = list.length;
|
|
866
|
+
|
|
867
|
+
if (category) {
|
|
868
|
+
list = list.filter((p) => (p.category ?? UNCATEGORIZED) === category);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return { plugins: list, categoryCounts, totalCount };
|
|
689
872
|
}
|
|
690
873
|
|
|
691
874
|
// ---------------------------------------------------------------------------
|
|
@@ -718,13 +901,17 @@ async function handleSearchPlugins({
|
|
|
718
901
|
fetch: globalThis.fetch.bind(globalThis),
|
|
719
902
|
});
|
|
720
903
|
const matches = filterPluginCatalog(catalog, query);
|
|
904
|
+
// Resolve the valid Skills slugs once per request, then normalize each
|
|
905
|
+
// match's marketplace category against them so "Available" filters
|
|
906
|
+
// consistently against the same taxonomy as the installed rail.
|
|
907
|
+
const validSlugs = getValidCategorySlugs();
|
|
721
908
|
// Re-pack `readonly` lib types into mutable copies so the route
|
|
722
909
|
// serializer's `Record<string, unknown>` contract holds. The wire
|
|
723
910
|
// shape is identical.
|
|
724
911
|
return {
|
|
725
912
|
query,
|
|
726
913
|
ref: catalog.ref,
|
|
727
|
-
matches: matches.map(projectMatch),
|
|
914
|
+
matches: matches.map((m) => projectMatch(m, validSlugs)),
|
|
728
915
|
};
|
|
729
916
|
} catch (err) {
|
|
730
917
|
if (err instanceof InvalidSearchPatternError) {
|
|
@@ -754,6 +941,7 @@ interface PluginUninstallResponse {
|
|
|
754
941
|
|
|
755
942
|
function handleUninstallPlugin({
|
|
756
943
|
pathParams = {},
|
|
944
|
+
headers,
|
|
757
945
|
}: RouteHandlerArgs): PluginUninstallResponse {
|
|
758
946
|
// The HTTP router has already URL-decoded `:name` for us; pass it
|
|
759
947
|
// through verbatim — `uninstallPlugin` runs the same
|
|
@@ -763,6 +951,7 @@ function handleUninstallPlugin({
|
|
|
763
951
|
|
|
764
952
|
try {
|
|
765
953
|
const result = uninstallPlugin({ name: rawName });
|
|
954
|
+
publishPluginsChanged(getOriginClientId(headers));
|
|
766
955
|
return { name: result.name, target: result.target };
|
|
767
956
|
} catch (err) {
|
|
768
957
|
if (err instanceof InvalidPluginNameError) {
|
|
@@ -834,7 +1023,7 @@ async function resolveInstallMarketplaceRef(
|
|
|
834
1023
|
return entry.marketplaceCommit;
|
|
835
1024
|
}
|
|
836
1025
|
|
|
837
|
-
async function handleInstallPlugin({ body = {} }: RouteHandlerArgs) {
|
|
1026
|
+
async function handleInstallPlugin({ body = {}, headers }: RouteHandlerArgs) {
|
|
838
1027
|
const name = typeof body.name === "string" ? body.name : "";
|
|
839
1028
|
if (!name) {
|
|
840
1029
|
throw new BadRequestError("`name` is required");
|
|
@@ -858,6 +1047,7 @@ async function handleInstallPlugin({ body = {} }: RouteHandlerArgs) {
|
|
|
858
1047
|
{ name, ref: marketplaceRef, force },
|
|
859
1048
|
{ fetch: globalThis.fetch.bind(globalThis) },
|
|
860
1049
|
);
|
|
1050
|
+
publishPluginsChanged(getOriginClientId(headers));
|
|
861
1051
|
return {
|
|
862
1052
|
ok: true as const,
|
|
863
1053
|
name: result.name,
|
|
@@ -1008,6 +1198,7 @@ async function handleDiffPlugin({ pathParams = {} }: RouteHandlerArgs) {
|
|
|
1008
1198
|
async function handleUpgradePlugin({
|
|
1009
1199
|
pathParams = {},
|
|
1010
1200
|
body = {},
|
|
1201
|
+
headers,
|
|
1011
1202
|
}: RouteHandlerArgs) {
|
|
1012
1203
|
const rawName = pathParams.name ?? "";
|
|
1013
1204
|
const dryRun = typeof body.dryRun === "boolean" ? body.dryRun : undefined;
|
|
@@ -1025,6 +1216,7 @@ async function handleUpgradePlugin({
|
|
|
1025
1216
|
{ name: rawName, dryRun, strategy },
|
|
1026
1217
|
{ fetch: globalThis.fetch.bind(globalThis) },
|
|
1027
1218
|
);
|
|
1219
|
+
publishPluginsChanged(getOriginClientId(headers));
|
|
1028
1220
|
return {
|
|
1029
1221
|
name: result.name,
|
|
1030
1222
|
outcome: result.outcome,
|
|
@@ -1073,6 +1265,58 @@ async function handleUpgradePlugin({
|
|
|
1073
1265
|
}
|
|
1074
1266
|
}
|
|
1075
1267
|
|
|
1268
|
+
// ---------------------------------------------------------------------------
|
|
1269
|
+
// Handler — enable / disable
|
|
1270
|
+
// ---------------------------------------------------------------------------
|
|
1271
|
+
|
|
1272
|
+
/**
|
|
1273
|
+
* Map a `toggle-plugin` lib error onto the transport-agnostic route error.
|
|
1274
|
+
* `enablePlugin` / `disablePlugin` throw their own taxonomy (distinct from the
|
|
1275
|
+
* install/uninstall libs), which the branches below narrow to 400 / 404 / 409;
|
|
1276
|
+
* anything unrecognized surfaces as an unexpected 500.
|
|
1277
|
+
*/
|
|
1278
|
+
function mapTogglePluginError(err: unknown): RouteError {
|
|
1279
|
+
if (err instanceof InvalidTogglePluginNameError) {
|
|
1280
|
+
return new BadRequestError(err.message);
|
|
1281
|
+
}
|
|
1282
|
+
if (err instanceof PluginDirectoryNotFoundError) {
|
|
1283
|
+
return new NotFoundError(err.message);
|
|
1284
|
+
}
|
|
1285
|
+
if (err instanceof PluginAlreadyInStateException) {
|
|
1286
|
+
return new ConflictError(err.message);
|
|
1287
|
+
}
|
|
1288
|
+
return new InternalError(
|
|
1289
|
+
err instanceof Error ? err.message : "plugin toggle failed",
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/**
|
|
1294
|
+
* Toggle a plugin's `.disabled` sentinel through the shared toggle-plugin lib,
|
|
1295
|
+
* then publish a generic `sync_changed(plugins:list)` so every client refetches
|
|
1296
|
+
* `GET /v1/plugins`. Enable and disable emit the SAME invalidation — the tag
|
|
1297
|
+
* names WHICH resource is stale, not the new value. The origin client id is
|
|
1298
|
+
* threaded through for self-echo suppression.
|
|
1299
|
+
*/
|
|
1300
|
+
function handleEnablePlugin({ pathParams = {}, headers }: RouteHandlerArgs) {
|
|
1301
|
+
try {
|
|
1302
|
+
enablePlugin(pathParams.name ?? "");
|
|
1303
|
+
publishPluginsChanged(getOriginClientId(headers));
|
|
1304
|
+
return { ok: true };
|
|
1305
|
+
} catch (err) {
|
|
1306
|
+
throw mapTogglePluginError(err);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
function handleDisablePlugin({ pathParams = {}, headers }: RouteHandlerArgs) {
|
|
1311
|
+
try {
|
|
1312
|
+
disablePlugin(pathParams.name ?? "");
|
|
1313
|
+
publishPluginsChanged(getOriginClientId(headers));
|
|
1314
|
+
return { ok: true };
|
|
1315
|
+
} catch (err) {
|
|
1316
|
+
throw mapTogglePluginError(err);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1076
1320
|
// ---------------------------------------------------------------------------
|
|
1077
1321
|
// Route definitions
|
|
1078
1322
|
// ---------------------------------------------------------------------------
|
|
@@ -1088,7 +1332,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
1088
1332
|
},
|
|
1089
1333
|
summary: "List installed plugins",
|
|
1090
1334
|
description:
|
|
1091
|
-
"Return one entry per directory under `<workspaceDir>/plugins/`, sorted alphabetically. Matches the CLI's `assistant plugins list`. Supports `?q=<text>` for case-insensitive substring matching across plugin id, name, and description.",
|
|
1335
|
+
"Return one entry per directory under `<workspaceDir>/plugins/`, sorted alphabetically. Matches the CLI's `assistant plugins list`. Supports `?q=<text>` for case-insensitive substring matching across plugin id, name, and description. Each entry carries a `category` (marketplace slug from the Skills taxonomy, or `null` for non-marketplace installs); the response also reports `categoryCounts` (per-category totals, computed before the category filter) and `totalCount`. `?category=<slug>` filters the returned plugins by category server-side while leaving the counts unfiltered. A marketplace outage degrades `category` to `null` without failing the list.",
|
|
1092
1336
|
tags: ["plugins"],
|
|
1093
1337
|
queryParams: [
|
|
1094
1338
|
{
|
|
@@ -1097,6 +1341,12 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
1097
1341
|
description:
|
|
1098
1342
|
"Optional substring filter applied to plugin id, name, and description.",
|
|
1099
1343
|
},
|
|
1344
|
+
{
|
|
1345
|
+
name: "category",
|
|
1346
|
+
schema: { type: "string" },
|
|
1347
|
+
description:
|
|
1348
|
+
"Filter installed plugins by category slug (Skills taxonomy).",
|
|
1349
|
+
},
|
|
1100
1350
|
],
|
|
1101
1351
|
responseBody: pluginsListResponseSchema,
|
|
1102
1352
|
handler: handleListPlugins,
|
|
@@ -1389,4 +1639,75 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
1389
1639
|
},
|
|
1390
1640
|
handler: handleUpgradePlugin,
|
|
1391
1641
|
},
|
|
1642
|
+
{
|
|
1643
|
+
operationId: "plugins_enable",
|
|
1644
|
+
endpoint: "plugins/:name/enable",
|
|
1645
|
+
method: "POST",
|
|
1646
|
+
policy: {
|
|
1647
|
+
requiredScopes: ["settings.write"],
|
|
1648
|
+
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
1649
|
+
},
|
|
1650
|
+
summary: "Enable a plugin",
|
|
1651
|
+
description:
|
|
1652
|
+
"Enable a plugin in this workspace by removing its `.disabled` sentinel, mirroring the CLI's `assistant plugins enable <name>`. The change is honored live at read time by every tool / injector / hook gate — no restart required. Broadcasts a `sync_changed` invalidation carrying the `plugins:list` tag so other clients refetch `GET /v1/plugins`. An already-enabled plugin returns 409; a name with no plugin directory returns 404 (prefix a default plugin with `default-`); a malformed name returns 400.",
|
|
1653
|
+
tags: ["plugins"],
|
|
1654
|
+
pathParams: [
|
|
1655
|
+
{
|
|
1656
|
+
name: "name",
|
|
1657
|
+
type: "string",
|
|
1658
|
+
description:
|
|
1659
|
+
"Directory name under `<workspaceDir>/plugins/`. Prefix a default plugin with `default-`. Must be kebab-case alphanumerics.",
|
|
1660
|
+
},
|
|
1661
|
+
],
|
|
1662
|
+
responseBody: z.object({ ok: z.boolean() }),
|
|
1663
|
+
additionalResponses: {
|
|
1664
|
+
"400": {
|
|
1665
|
+
description:
|
|
1666
|
+
"The plugin name failed validation (not kebab-case alphanumerics).",
|
|
1667
|
+
},
|
|
1668
|
+
"404": {
|
|
1669
|
+
description: "No plugin directory exists with the given name.",
|
|
1670
|
+
},
|
|
1671
|
+
"409": {
|
|
1672
|
+
description: "The plugin is already enabled.",
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
handler: handleEnablePlugin,
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
operationId: "plugins_disable",
|
|
1679
|
+
endpoint: "plugins/:name/disable",
|
|
1680
|
+
method: "POST",
|
|
1681
|
+
policy: {
|
|
1682
|
+
requiredScopes: ["settings.write"],
|
|
1683
|
+
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
1684
|
+
},
|
|
1685
|
+
summary: "Disable a plugin",
|
|
1686
|
+
description:
|
|
1687
|
+
"Disable a plugin in this workspace by dropping a `.disabled` sentinel, mirroring the CLI's `assistant plugins disable <name>`. The change is honored live at read time by every tool / injector / hook gate — no restart required. Broadcasts a `sync_changed` invalidation carrying the `plugins:list` tag so other clients refetch `GET /v1/plugins`. An already-disabled plugin returns 409; a user plugin with no directory returns 404 (default plugins are stubbed on demand via the `default-` prefix); a malformed name returns 400.",
|
|
1688
|
+
tags: ["plugins"],
|
|
1689
|
+
pathParams: [
|
|
1690
|
+
{
|
|
1691
|
+
name: "name",
|
|
1692
|
+
type: "string",
|
|
1693
|
+
description:
|
|
1694
|
+
"Directory name under `<workspaceDir>/plugins/`. Prefix a default plugin with `default-`. Must be kebab-case alphanumerics.",
|
|
1695
|
+
},
|
|
1696
|
+
],
|
|
1697
|
+
responseBody: z.object({ ok: z.boolean() }),
|
|
1698
|
+
additionalResponses: {
|
|
1699
|
+
"400": {
|
|
1700
|
+
description:
|
|
1701
|
+
"The plugin name failed validation (not kebab-case alphanumerics).",
|
|
1702
|
+
},
|
|
1703
|
+
"404": {
|
|
1704
|
+
description:
|
|
1705
|
+
"No plugin directory exists with the given name (user plugins must already be installed).",
|
|
1706
|
+
},
|
|
1707
|
+
"409": {
|
|
1708
|
+
description: "The plugin is already disabled.",
|
|
1709
|
+
},
|
|
1710
|
+
},
|
|
1711
|
+
handler: handleDisablePlugin,
|
|
1712
|
+
},
|
|
1392
1713
|
];
|
|
@@ -273,7 +273,7 @@ async function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
273
273
|
// entirely (see the workflow branch below), so only require a message for the
|
|
274
274
|
// execute path. Requiring it for workflow mode would force API/UI callers to
|
|
275
275
|
// pass an unused dummy string.
|
|
276
|
-
if (mode !== "workflow" && !message) {
|
|
276
|
+
if (mode !== "workflow" && mode !== "script" && !message) {
|
|
277
277
|
throw new BadRequestError("message is required");
|
|
278
278
|
}
|
|
279
279
|
if (description === "") {
|
|
@@ -283,9 +283,9 @@ async function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
283
283
|
// The settings UI only exposes execute mode; `workflow` mode is reachable
|
|
284
284
|
// here (flag-gated) and via the schedule_create LLM tool. All other modes
|
|
285
285
|
// remain tool-only.
|
|
286
|
-
if (mode !== "execute" && mode !== "workflow") {
|
|
286
|
+
if (mode !== "execute" && mode !== "workflow" && mode !== "script") {
|
|
287
287
|
throw new BadRequestError(
|
|
288
|
-
"Only 'execute' and 'workflow' modes are supported by this endpoint",
|
|
288
|
+
"Only 'execute', 'script', and 'workflow' modes are supported by this endpoint",
|
|
289
289
|
);
|
|
290
290
|
}
|
|
291
291
|
|
|
@@ -321,11 +321,42 @@ async function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
321
321
|
{ id: job.id, name: job.name, workflowName },
|
|
322
322
|
"Workflow schedule created",
|
|
323
323
|
);
|
|
324
|
+
return { schedule: serializeSchedule(job, new Map()) };
|
|
325
|
+
} catch (err) {
|
|
326
|
+
if (err instanceof Error) throw new BadRequestError(err.message);
|
|
327
|
+
throw err;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (mode === "script") {
|
|
332
|
+
const script = typeof body.script === "string" ? body.script.trim() : "";
|
|
333
|
+
if (!script) {
|
|
334
|
+
throw new BadRequestError("script is required for script-mode schedules");
|
|
335
|
+
}
|
|
336
|
+
const timeoutMs = body.timeoutMs == null ? null : Number(body.timeoutMs);
|
|
337
|
+
if (timeoutMs !== null) {
|
|
338
|
+
const timeoutError = validateScriptTimeoutMs(timeoutMs);
|
|
339
|
+
if (timeoutError) throw new BadRequestError(timeoutError);
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
const job = await createSchedule({
|
|
343
|
+
name,
|
|
344
|
+
description,
|
|
345
|
+
message,
|
|
346
|
+
mode: "script",
|
|
347
|
+
script,
|
|
348
|
+
enabled,
|
|
349
|
+
timezone,
|
|
350
|
+
expression: normalized.expression,
|
|
351
|
+
syntax: normalized.syntax,
|
|
352
|
+
timeoutMs,
|
|
353
|
+
});
|
|
354
|
+
log.info({ id: job.id, name: job.name }, "Script schedule created");
|
|
355
|
+
return { schedule: serializeSchedule(job, new Map()) };
|
|
324
356
|
} catch (err) {
|
|
325
357
|
if (err instanceof Error) throw new BadRequestError(err.message);
|
|
326
358
|
throw err;
|
|
327
359
|
}
|
|
328
|
-
return handleListSchedules({});
|
|
329
360
|
}
|
|
330
361
|
|
|
331
362
|
try {
|
|
@@ -341,11 +372,11 @@ async function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
341
372
|
inferenceProfile,
|
|
342
373
|
});
|
|
343
374
|
log.info({ id: job.id, name: job.name }, "Schedule created");
|
|
375
|
+
return { schedule: serializeSchedule(job, new Map()) };
|
|
344
376
|
} catch (err) {
|
|
345
377
|
if (err instanceof Error) throw new BadRequestError(err.message);
|
|
346
378
|
throw err;
|
|
347
379
|
}
|
|
348
|
-
return handleListSchedules({});
|
|
349
380
|
}
|
|
350
381
|
|
|
351
382
|
async function handleToggleSchedule(id: string, body: Record<string, unknown>) {
|
|
@@ -675,7 +706,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
675
706
|
},
|
|
676
707
|
summary: "Create schedule",
|
|
677
708
|
description:
|
|
678
|
-
"Create a new recurring schedule
|
|
709
|
+
"Create a new recurring schedule (execute, script, or workflow mode).",
|
|
679
710
|
tags: ["schedules"],
|
|
680
711
|
requestBody: z.object({
|
|
681
712
|
name: z.string().describe("Display name"),
|
|
@@ -703,7 +734,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
703
734
|
.optional(),
|
|
704
735
|
mode: z
|
|
705
736
|
.string()
|
|
706
|
-
.describe("'execute' (default) or 'workflow' (flag-gated)")
|
|
737
|
+
.describe("'execute' (default), 'script', or 'workflow' (flag-gated)")
|
|
707
738
|
.optional(),
|
|
708
739
|
workflowName: z
|
|
709
740
|
.string()
|
|
@@ -713,6 +744,15 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
713
744
|
.unknown()
|
|
714
745
|
.describe("Args passed to the workflow run (workflow mode)")
|
|
715
746
|
.optional(),
|
|
747
|
+
script: z
|
|
748
|
+
.string()
|
|
749
|
+
.describe("Shell command run on each fire (required for script mode)")
|
|
750
|
+
.optional(),
|
|
751
|
+
timeoutMs: z
|
|
752
|
+
.number()
|
|
753
|
+
.nullable()
|
|
754
|
+
.describe("Script execution timeout override in ms (script mode)")
|
|
755
|
+
.optional(),
|
|
716
756
|
inferenceProfile: z
|
|
717
757
|
.string()
|
|
718
758
|
.nullable()
|
|
@@ -722,7 +762,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
722
762
|
.optional(),
|
|
723
763
|
}),
|
|
724
764
|
responseBody: z.object({
|
|
725
|
-
|
|
765
|
+
schedule: scheduleSchema.describe("The created schedule"),
|
|
726
766
|
}),
|
|
727
767
|
handler: ({ body }: RouteHandlerArgs) => handleCreateSchedule(body ?? {}),
|
|
728
768
|
},
|
|
@@ -903,6 +943,7 @@ async function handleRunScheduleNow(id: string) {
|
|
|
903
943
|
const result = await runScript(schedule.script, {
|
|
904
944
|
timeoutMs: schedule.timeoutMs ?? undefined,
|
|
905
945
|
scheduleRunId: runId,
|
|
946
|
+
scheduleId: schedule.id,
|
|
906
947
|
});
|
|
907
948
|
await completeScheduleRun(runId, {
|
|
908
949
|
status: result.exitCode === 0 ? "ok" : "error",
|