@vellumai/assistant 0.11.2 → 0.11.3-dev.202608080427.92f668a
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 +69 -9
- package/docs/flux-turn-detection-spike.md +243 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/docs/trusted-contact-access.md +9 -5
- package/docs/vellum-doctor.md +195 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
- package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
- package/node_modules/@vellumai/environments/src/index.ts +17 -6
- package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
- package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
- package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
- package/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
- package/openapi.yaml +619 -47
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/src/__tests__/agent-image-optimize.test.ts +4 -4
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
- package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
- package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/answered-question-persistence.test.ts +240 -0
- package/src/__tests__/anthropic-provider.test.ts +165 -30
- package/src/__tests__/app-control-flow.test.ts +9 -8
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
- package/src/__tests__/attachments-store.test.ts +130 -68
- package/src/__tests__/attachments.test.ts +36 -36
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/call-controller.test.ts +120 -0
- package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
- package/src/__tests__/canned-reply-release.test.ts +86 -0
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-guardian.test.ts +59 -29
- package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
- package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
- package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +19 -0
- package/src/__tests__/config-schema.test.ts +150 -7
- package/src/__tests__/consult-deadline.test.ts +65 -0
- package/src/__tests__/conversation-agent-loop.test.ts +438 -2
- package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
- package/src/__tests__/conversation-disk-view.test.ts +4 -4
- package/src/__tests__/conversation-error.test.ts +22 -3
- package/src/__tests__/conversation-fork-crud.test.ts +5 -1
- package/src/__tests__/conversation-fork-referential.test.ts +352 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
- package/src/__tests__/conversation-group-tools.test.ts +32 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
- package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
- package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
- package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
- package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
- package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
- package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
- package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
- package/src/__tests__/conversation-queue.test.ts +433 -1
- package/src/__tests__/conversation-retry-route.test.ts +3 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
- package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
- package/src/__tests__/conversation-store.test.ts +26 -10
- package/src/__tests__/conversation-summarize-route.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
- package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
- package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
- package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
- package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
- package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
- package/src/__tests__/credential-prompt-route.test.ts +54 -7
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +89 -28
- package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
- package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
- package/src/__tests__/disk-pressure-guard.test.ts +55 -55
- package/src/__tests__/disk-pressure-routes.test.ts +10 -10
- package/src/__tests__/disk-pressure-tools.test.ts +2 -2
- package/src/__tests__/disk-usage.test.ts +35 -20
- package/src/__tests__/document-sync-tags.test.ts +379 -0
- package/src/__tests__/document-update-default-surface.test.ts +28 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
- package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
- package/src/__tests__/events-dev-bypass-actor.test.ts +294 -1
- package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
- package/src/__tests__/file-list-tool.test.ts +12 -10
- package/src/__tests__/file-ops-service.test.ts +151 -44
- package/src/__tests__/file-read-container-boundary.test.ts +137 -0
- package/src/__tests__/file-read-tool.test.ts +21 -9
- package/src/__tests__/file-url-path-guard.test.ts +83 -0
- package/src/__tests__/filesystem-tools.test.ts +82 -66
- package/src/__tests__/guardian-outbound-http.test.ts +8 -8
- package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
- package/src/__tests__/helpers/hub-clients.ts +42 -0
- package/src/__tests__/helpers/mock-conversation.ts +46 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
- package/src/__tests__/history-repair.test.ts +112 -12
- package/src/__tests__/host-bash-proxy.test.ts +10 -5
- package/src/__tests__/host-bash-routes.test.ts +67 -0
- package/src/__tests__/host-browser-proxy.test.ts +2 -2
- package/src/__tests__/host-cu-proxy.test.ts +3 -7
- package/src/__tests__/host-file-proxy.test.ts +3 -7
- package/src/__tests__/host-file-read-tool.test.ts +5 -1
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
- package/src/__tests__/http-conversation-lineage.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +44 -0
- package/src/__tests__/identity-routes.test.ts +13 -13
- package/src/__tests__/image-conversion.test.ts +29 -26
- package/src/__tests__/image-source-path-reinject.test.ts +2 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
- package/src/__tests__/introduction-card-resolver.test.ts +6 -1
- package/src/__tests__/list-messages-attachments.test.ts +56 -32
- package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
- package/src/__tests__/list-messages-page-latest.test.ts +61 -61
- package/src/__tests__/list-messages-provider-error.test.ts +6 -6
- package/src/__tests__/list-messages-queued.test.ts +49 -6
- package/src/__tests__/list-messages-system-card.test.ts +4 -4
- package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
- package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
- package/src/__tests__/llm-usage-store.test.ts +55 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
- package/src/__tests__/media-stream-output.test.ts +175 -0
- package/src/__tests__/media-stream-server-integration.test.ts +36 -0
- package/src/__tests__/media-stream-stt-session.test.ts +67 -0
- package/src/__tests__/migration-export-http.test.ts +1 -1
- package/src/__tests__/migration-import-commit-http.test.ts +1 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
- package/src/__tests__/migration-validate-http.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +65 -3
- package/src/__tests__/notification-platform-adapter.test.ts +104 -0
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
- package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
- package/src/__tests__/path-policy.test.ts +164 -1
- package/src/__tests__/persist-media-references.test.ts +2 -2
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
- package/src/__tests__/persist-unsendable-image.test.ts +23 -23
- package/src/__tests__/persona-resolver.test.ts +154 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
- package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
- package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
- package/src/__tests__/profiler-routes.test.ts +13 -13
- package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
- package/src/__tests__/proxy-approval-callback.test.ts +3 -3
- package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
- package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
- package/src/__tests__/resolve-trust-class.test.ts +20 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
- package/src/__tests__/run-due-schedules.test.ts +174 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
- package/src/__tests__/schedule-routes.test.ts +730 -8
- package/src/__tests__/schedule-store.test.ts +540 -0
- package/src/__tests__/schedule-tools.test.ts +103 -0
- package/src/__tests__/scheduler-wake.test.ts +5 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
- package/src/__tests__/secure-keys.test.ts +91 -0
- package/src/__tests__/server-history-render.test.ts +97 -7
- package/src/__tests__/size-guard.test.ts +8 -8
- package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
- package/src/__tests__/skill-tool-factory.test.ts +247 -0
- package/src/__tests__/skills-install-staging.test.ts +15 -6
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
- package/src/__tests__/slack-inbound-verification.test.ts +4 -1
- package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
- package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
- package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
- package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
- package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
- package/src/__tests__/subagent-disposal.test.ts +10 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
- package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
- package/src/__tests__/subagent-manager-notify.test.ts +148 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/subagent-persistence.test.ts +141 -0
- package/src/__tests__/subagent-role-registry.test.ts +172 -63
- package/src/__tests__/subagent-role-resolution.test.ts +88 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
- package/src/__tests__/subagent-terminal-message.test.ts +88 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
- package/src/__tests__/subagent-tools.test.ts +1901 -108
- package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
- package/src/__tests__/system-prompt.test.ts +82 -7
- package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
- package/src/__tests__/tool-result-spool.test.ts +74 -18
- package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
- package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
- package/src/__tests__/tools-audio-read.test.ts +10 -10
- package/src/__tests__/tools-get-route.test.ts +85 -12
- package/src/__tests__/tools-list-cli.test.ts +171 -0
- package/src/__tests__/top-level-renderer.test.ts +54 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
- package/src/__tests__/turn-tail-chain.test.ts +135 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
- package/src/__tests__/ui-visual-surface.test.ts +5 -4
- package/src/__tests__/ui-work-result-surface.test.ts +5 -4
- package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
- package/src/__tests__/usage-routes.test.ts +62 -0
- package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
- package/src/__tests__/visible-app-context.test.ts +20 -4
- package/src/__tests__/web-search-history.test.ts +96 -0
- package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
- package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +150 -0
- package/src/acp/failure-error.ts +3 -5
- package/src/agent/attachments.ts +26 -24
- package/src/agent/history-repair/history-repair.ts +27 -26
- package/src/agent/image-optimize.ts +6 -6
- package/src/agent/loop.ts +40 -22
- package/src/agent/message-types.ts +3 -3
- package/src/api/constants/document-tools.ts +55 -0
- package/src/api/events/question-answered.ts +53 -0
- package/src/api/events/tool-result.ts +7 -0
- package/src/api/index.ts +13 -0
- package/src/api/responses/conversation-message.ts +11 -0
- package/src/api/surfaces-oauth-connect.test.ts +96 -0
- package/src/api/surfaces.ts +36 -8
- package/src/approvals/guardian-channel-delivery.ts +83 -0
- package/src/approvals/guardian-expiry-notifier.ts +13 -11
- package/src/approvals/guardian-request-resolvers.ts +222 -135
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +13 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +131 -12
- package/src/calls/__tests__/voice-triage-escalate.test.ts +106 -0
- package/src/calls/call-controller.ts +30 -2
- package/src/calls/call-speech-output.ts +12 -4
- package/src/calls/call-transport.ts +18 -1
- package/src/calls/media-stream-output.ts +53 -5
- package/src/calls/media-stream-server.ts +21 -1
- package/src/calls/media-stream-stt-session.ts +49 -0
- package/src/calls/telephony-synthesis-language.ts +84 -0
- package/src/calls/tts-text-sanitizer.ts +12 -5
- package/src/calls/voice-session-bridge.ts +86 -17
- package/src/calls/voice-triage-escalate.ts +54 -7
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +20 -2
- package/src/channels/gateway-verification-sessions.ts +7 -2
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +37 -1
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/commands/__tests__/cache.test.ts +7 -4
- package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
- package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
- package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
- package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
- package/src/cli/commands/__tests__/plugins.test.ts +692 -0
- package/src/cli/commands/__tests__/schedules.test.ts +136 -37
- package/src/cli/commands/conversations.ts +7 -3
- package/src/cli/commands/credentials.help.ts +7 -0
- package/src/cli/commands/inference-profiles.ts +9 -3
- package/src/cli/commands/inference.help.ts +16 -2
- package/src/cli/commands/mcp.help.ts +17 -6
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/memory-retrospective.ts +18 -0
- package/src/cli/commands/notifications.ts +3 -6
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
- package/src/cli/commands/oauth/connect.test.ts +26 -1
- package/src/cli/commands/oauth/connect.ts +4 -1
- package/src/cli/commands/oauth/index.help.ts +3 -1
- package/src/cli/commands/oauth/providers.ts +3 -0
- package/src/cli/commands/plugins.help.ts +25 -2
- package/src/cli/commands/plugins.ts +289 -10
- package/src/cli/commands/schedules.help.ts +14 -12
- package/src/cli/commands/schedules.ts +19 -5
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/tools.help.ts +4 -2
- package/src/cli/commands/tools.ts +38 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
- package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +161 -0
- package/src/cli/lib/install-from-github.ts +61 -0
- package/src/cli/lib/install-from-platform.ts +13 -2
- package/src/cli/lib/plugin-surfaces.ts +124 -4
- package/src/cli/lib/upgrade-plugin.ts +60 -0
- package/src/cli.ts +1 -1
- package/src/config/__tests__/default-profile-catalog.test.ts +11 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
- package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
- package/src/config/__tests__/profile-tool-support.test.ts +131 -0
- package/src/config/bundled-skills/AGENTS.md +1 -1
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +15 -15
- package/src/config/bundled-skills/schedule/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +53 -22
- package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/bundled-skills/visualize/SKILL.md +1 -1
- package/src/config/call-site-defaults.ts +4 -5
- package/src/config/default-profile-catalog.ts +9 -5
- package/src/config/feature-flag-registry.json +25 -17
- package/src/config/llm-resolver.ts +45 -15
- package/src/config/loader.ts +75 -1
- package/src/config/profile-tool-support.ts +110 -0
- package/src/config/sanitize-for-transfer.ts +11 -0
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/live-voice.test.ts +142 -4
- package/src/config/schemas/__tests__/stt.test.ts +20 -5
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/channels.ts +13 -0
- package/src/config/schemas/live-voice.ts +82 -23
- package/src/config/schemas/llm.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +25 -0
- package/src/config/schemas/plugin-updates.ts +59 -0
- package/src/config/schemas/services.ts +8 -4
- package/src/config/schemas/stt.ts +18 -5
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/schemas/tts.ts +63 -0
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
- package/src/contacts/guardian-delivery-reader.ts +29 -2
- package/src/context/compactor.ts +4 -4
- package/src/context/post-turn-tool-result-truncation.ts +32 -16
- package/src/context/strip-injections.ts +42 -0
- package/src/context/tool-result-spool.ts +32 -18
- package/src/credential-execution/ces-runtime.ts +3 -0
- package/src/credential-execution/client.ts +22 -1
- package/src/credential-execution/process-manager.test.ts +99 -0
- package/src/credential-execution/process-manager.ts +62 -16
- package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
- package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
- package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
- package/src/daemon/channel-ui-capability.ts +4 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
- package/src/daemon/conversation-agent-loop.ts +318 -148
- package/src/daemon/conversation-attachments.ts +1 -1
- package/src/daemon/conversation-error.ts +8 -1
- package/src/daemon/conversation-initial-prompt.ts +16 -38
- package/src/daemon/conversation-lifecycle.ts +154 -32
- package/src/daemon/conversation-messaging.ts +106 -43
- package/src/daemon/conversation-process.ts +131 -33
- package/src/daemon/conversation-queue-manager.ts +10 -0
- package/src/daemon/conversation-runtime-assembly.ts +9 -4
- package/src/daemon/conversation-store.ts +52 -3
- package/src/daemon/conversation-surface-state.ts +9 -0
- package/src/daemon/conversation-surfaces.ts +403 -210
- package/src/daemon/conversation-tool-setup.ts +56 -7
- package/src/daemon/conversation-turn-finalize.ts +134 -89
- package/src/daemon/conversation.ts +111 -27
- package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
- package/src/daemon/disk-pressure-guard.ts +3 -3
- package/src/daemon/doordash-steps.ts +5 -5
- package/src/daemon/external-plugins-bootstrap.ts +7 -1
- package/src/daemon/handlers/config-channels.ts +48 -5
- package/src/daemon/handlers/conversation-history.ts +1 -1
- package/src/daemon/handlers/conversations.ts +62 -17
- package/src/daemon/handlers/shared.ts +12 -0
- package/src/daemon/handlers/skills.ts +11 -1
- package/src/daemon/identity-helpers.ts +38 -10
- package/src/daemon/install-assistant-command.ts +322 -0
- package/src/daemon/lifecycle.ts +14 -3
- package/src/daemon/message-types/conversations.ts +6 -7
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/persist-media-references.ts +23 -14
- package/src/daemon/process-message.ts +6 -6
- package/src/daemon/tool-setup-types.ts +19 -122
- package/src/daemon/tool-side-effects.ts +17 -94
- package/src/daemon/trust-context-types.ts +39 -0
- package/src/daemon/trust-context.ts +14 -6
- package/src/daemon/turn-tail-chain.ts +73 -0
- package/src/daemon/web-search-history.ts +47 -33
- package/src/heartbeat/heartbeat-service.ts +6 -6
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/__tests__/socket-path.test.ts +21 -0
- package/src/ipc/assistant-server.ts +17 -10
- package/src/ipc/cli-client.ts +10 -1
- package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
- package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
- package/src/ipc/socket-cleanup.ts +9 -7
- package/src/ipc/socket-path.ts +4 -96
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
- package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
- package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +932 -0
- package/src/live-voice/__tests__/live-voice-integration.test.ts +12 -5
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +179 -146
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +324 -2
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +131 -2
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-tts.test.ts +148 -2
- package/src/live-voice/__tests__/live-voice-vad.test.ts +313 -32
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/__tests__/progress-phrases.test.ts +167 -0
- package/src/live-voice/__tests__/protocol.test.ts +52 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
- package/src/live-voice/live-voice-archive.ts +13 -13
- package/src/live-voice/live-voice-connection.ts +7 -1
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +168 -0
- package/src/live-voice/live-voice-session.ts +1137 -351
- package/src/live-voice/live-voice-tts.ts +18 -2
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/progress-phrases.ts +105 -2
- package/src/live-voice/protocol.ts +110 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +196 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/client.ts +14 -7
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +195 -240
- package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
- package/src/messaging/providers/callback-routing.ts +1 -0
- package/src/messaging/providers/discord/api.ts +312 -0
- package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
- package/src/messaging/providers/discord/render.test.ts +204 -0
- package/src/messaging/providers/discord/render.ts +195 -0
- package/src/messaging/providers/discord/send.test.ts +179 -0
- package/src/messaging/providers/discord/send.ts +212 -0
- package/src/messaging/providers/discord/transport.ts +81 -0
- package/src/messaging/providers/index.ts +3 -1
- package/src/messaging/providers/retry-policy.test.ts +247 -0
- package/src/messaging/providers/retry-policy.ts +206 -0
- package/src/messaging/providers/slack/mention-source.test.ts +285 -0
- package/src/messaging/providers/slack/mention-source.ts +287 -0
- package/src/messaging/providers/telegram-bot/api.ts +47 -130
- package/src/messaging/providers/whatsapp/api.ts +47 -136
- package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +495 -0
- package/src/monitoring/db-integrity-sample.ts +6 -1
- package/src/monitoring/plugin-auto-update.ts +463 -0
- package/src/monitoring/resource-sampler.ts +21 -5
- package/src/monitoring/worker.ts +13 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
- package/src/notifications/__tests__/broadcaster.test.ts +37 -1
- package/src/notifications/__tests__/copy-composer.test.ts +165 -0
- package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
- package/src/notifications/__tests__/notification-utils.test.ts +249 -0
- package/src/notifications/adapters/platform.ts +31 -2
- package/src/notifications/assistant-reply-producer.ts +79 -32
- package/src/notifications/broadcaster.ts +30 -10
- package/src/notifications/copy-composer.ts +69 -0
- package/src/notifications/emit-signal.ts +82 -15
- package/src/notifications/events-store.ts +10 -2
- package/src/notifications/home-feed-side-effect.ts +6 -3
- package/src/notifications/notification-utils.ts +173 -5
- package/src/notifications/signal.ts +13 -0
- package/src/oauth/AGENTS.md +4 -2
- package/src/oauth/byo-connection.ts +6 -1
- package/src/oauth/credential-token-resolver.ts +3 -10
- package/src/oauth/manual-token-connection.ts +29 -64
- package/src/oauth/manual-token-providers.ts +62 -0
- package/src/oauth/provider-serializer.ts +13 -0
- package/src/oauth/seed-providers.ts +62 -11
- package/src/onboarding/onboarding-events-store.ts +91 -1
- package/src/permissions/question-prompter.test.ts +4 -0
- package/src/permissions/question-prompter.ts +21 -4
- package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
- package/src/persistence/attachments-store.ts +15 -15
- package/src/persistence/conversation-attention-store.ts +30 -10
- package/src/persistence/conversation-bootstrap.ts +17 -0
- package/src/persistence/conversation-crud.ts +363 -97
- package/src/persistence/conversation-group-migration.ts +1 -1
- package/src/persistence/conversation-key-store.ts +38 -10
- package/src/persistence/conversation-lineage.ts +226 -0
- package/src/persistence/conversation-plugin-facade.ts +28 -3
- package/src/persistence/conversation-queries.ts +207 -33
- package/src/persistence/conversation-types.ts +107 -1
- package/src/persistence/jobs-store.ts +32 -8
- package/src/persistence/llm-usage-store.ts +22 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
- package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
- package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
- package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
- package/src/persistence/schema/conversations.ts +32 -0
- package/src/persistence/schema/infrastructure.ts +3 -0
- package/src/persistence/steps.ts +30 -0
- package/src/persistence/subagent-store.ts +148 -6
- package/src/platform/managed-speech.test.ts +20 -0
- package/src/platform/managed-speech.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/index.ts +28 -5
- package/src/plugin-api/webhook-url.ts +151 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
- package/src/plugins/__tests__/mcp-servers.test.ts +370 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
- package/src/plugins/collect-source-versions.ts +4 -27
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
- package/src/plugins/defaults/exploration-drift/package.json +1 -1
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
- package/src/plugins/defaults/image-recovery/recover.ts +67 -57
- package/src/plugins/defaults/index.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
- package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
- package/src/plugins/defaults/memory/job-handlers.ts +87 -5
- package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
- package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
- package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
- package/src/plugins/defaults/memory/v2/router.ts +8 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
- package/src/plugins/external-plugin-loader.ts +64 -8
- package/src/plugins/installed-plugin-dirs.ts +101 -0
- package/src/plugins/mcp-servers.ts +343 -0
- package/src/plugins/mtime-cache.ts +34 -22
- package/src/plugins/types.ts +69 -8
- package/src/prompts/persona-resolver.ts +6 -2
- package/src/prompts/system-prompt.ts +72 -17
- package/src/providers/__tests__/inference.test.ts +40 -0
- package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
- package/src/providers/__tests__/retry-callsite.test.ts +72 -2
- package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
- package/src/providers/anthropic/client.ts +112 -95
- package/src/providers/connection-resolution.ts +35 -1
- package/src/providers/gemini/client.ts +5 -5
- package/src/providers/inference/adapter-factory.ts +16 -10
- package/src/providers/inference/auth.ts +16 -0
- package/src/providers/inference/connection-availability.ts +164 -12
- package/src/providers/inference/connections.ts +25 -1
- package/src/providers/media-resolve.ts +21 -11
- package/src/providers/model-catalog.ts +15 -0
- package/src/providers/openai/chat-completions-provider.ts +4 -4
- package/src/providers/openai/responses-provider.ts +12 -25
- package/src/providers/registry.ts +9 -4
- package/src/providers/retry.ts +25 -0
- package/src/providers/server-tool-pairing.ts +134 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +620 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +472 -12
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +719 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +283 -1
- package/src/providers/speech-to-text/deepgram-realtime.ts +117 -3
- package/src/providers/speech-to-text/deepgram.ts +1 -0
- package/src/providers/speech-to-text/provider-catalog.ts +137 -8
- package/src/providers/speech-to-text/resolve.ts +105 -12
- package/src/providers/speech-to-text/vellum-managed.ts +7 -1
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
- package/src/providers/types.ts +26 -6
- package/src/providers/vellum-model-routing.ts +6 -7
- package/src/runtime/AGENTS.md +2 -0
- package/src/runtime/__tests__/agent-wake.test.ts +16 -16
- package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
- package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
- package/src/runtime/__tests__/local-actor-identity-force-refresh.test.ts +104 -0
- package/src/runtime/agent-wake.ts +63 -24
- package/src/runtime/assistant-event-hub.ts +110 -12
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
- package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
- package/src/runtime/auth/same-actor.ts +56 -8
- package/src/runtime/auth/scopes.ts +12 -0
- package/src/runtime/auth/types.ts +2 -0
- package/src/runtime/background-job-runner.ts +5 -27
- package/src/runtime/channel-readiness-service.ts +59 -3
- package/src/runtime/channel-readiness-types.ts +18 -0
- package/src/runtime/desktop-presence.ts +69 -0
- package/src/runtime/http-server.ts +12 -0
- package/src/runtime/local-actor-identity.ts +29 -14
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +217 -1
- package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
- package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
- package/src/runtime/routes/__tests__/sse-actor-principal-heal.test.ts +165 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +2 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
- package/src/runtime/routes/archive-utils.ts +16 -12
- package/src/runtime/routes/attachment-routes.ts +13 -6
- package/src/runtime/routes/canned-reply-release.ts +54 -0
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-verification-routes.ts +2 -27
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
- package/src/runtime/routes/client-routes.ts +114 -2
- package/src/runtime/routes/conversation-cli-routes.ts +10 -12
- package/src/runtime/routes/conversation-list-routes.ts +59 -10
- package/src/runtime/routes/conversation-management-routes.ts +47 -18
- package/src/runtime/routes/conversation-query-routes.ts +32 -53
- package/src/runtime/routes/conversation-routes.ts +360 -293
- package/src/runtime/routes/credential-prompt-routes.ts +20 -2
- package/src/runtime/routes/debug-routes.ts +4 -1
- package/src/runtime/routes/default-provider-routes.ts +7 -11
- package/src/runtime/routes/documents-routes.ts +44 -1
- package/src/runtime/routes/events-routes.ts +29 -1
- package/src/runtime/routes/host-app-control-routes.ts +2 -0
- package/src/runtime/routes/host-bash-routes.ts +2 -0
- package/src/runtime/routes/host-browser-routes.ts +2 -0
- package/src/runtime/routes/host-cu-routes.ts +2 -0
- package/src/runtime/routes/host-file-routes.ts +2 -0
- package/src/runtime/routes/host-transfer-routes.ts +4 -0
- package/src/runtime/routes/identity-routes.ts +6 -6
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
- package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
- package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
- package/src/runtime/routes/inference-profiles-routes.ts +152 -73
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
- package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
- package/src/runtime/routes/log-export-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +141 -57
- package/src/runtime/routes/notification-routes.ts +0 -14
- package/src/runtime/routes/oauth-providers.ts +1 -0
- package/src/runtime/routes/plugins-routes.ts +127 -4
- package/src/runtime/routes/profiler-routes.ts +4 -2
- package/src/runtime/routes/question-routes.ts +28 -10
- package/src/runtime/routes/retrospective-routes.ts +9 -3
- package/src/runtime/routes/schedule-routes.ts +210 -12
- package/src/runtime/routes/secret-routes.ts +40 -23
- package/src/runtime/routes/settings-routes.ts +41 -13
- package/src/runtime/routes/skills-routes.ts +79 -0
- package/src/runtime/routes/sse-actor-principal-heal.ts +113 -0
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
- package/src/runtime/routes/wake-conversation-routes.ts +23 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +24 -9
- package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
- package/src/runtime/sync/resource-sync-events.ts +79 -1
- package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
- package/src/runtime/sync/worker-daemon-notify.ts +44 -6
- package/src/runtime/verification-outbound-actions.ts +250 -222
- package/src/runtime/verification-templates.ts +41 -30
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
- package/src/schedule/inference-profile.ts +64 -3
- package/src/schedule/plugin-schedule-declarations.ts +518 -0
- package/src/schedule/plugin-schedule-reconciler.ts +605 -0
- package/src/schedule/plugin-schedules-gate.ts +23 -0
- package/src/schedule/schedule-store.ts +520 -26
- package/src/schedule/scheduler.ts +38 -0
- package/src/security/credential-backend.ts +51 -4
- package/src/security/encrypted-store.ts +64 -42
- package/src/security/oauth2.ts +6 -22
- package/src/security/secure-keys.ts +55 -7
- package/src/skills/catalog-install.ts +20 -7
- package/src/skills/inline-command-runner.ts +2 -7
- package/src/skills/skill-history.test.ts +269 -0
- package/src/skills/skill-history.ts +250 -0
- package/src/skills/skillssh-registry.ts +1 -1
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/language-metadata.test.ts +85 -0
- package/src/stt/__tests__/speech-energy.test.ts +79 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +18 -6
- package/src/stt/language-metadata.ts +65 -0
- package/src/stt/speech-energy.ts +115 -12
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +119 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
- package/src/subagent/consult-prompt.ts +3 -1
- package/src/subagent/consult-transcript.ts +1 -1
- package/src/subagent/manager.ts +304 -44
- package/src/subagent/progress-events.ts +35 -0
- package/src/subagent/role-resolution.ts +88 -0
- package/src/subagent/types.ts +303 -67
- package/src/subagent/validate-allowlists.ts +3 -4
- package/src/telegram/__tests__/webhook-health.test.ts +73 -1
- package/src/telegram/webhook-health.ts +101 -3
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
- package/src/telemetry/activation-funnel.ts +6 -1
- package/src/telemetry/live-voice-funnel.ts +75 -0
- package/src/telemetry/telemetry-event-sources.ts +6 -0
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire.generated.ts +2 -0
- package/src/telemetry/types.ts +23 -4
- package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
- package/src/tools/ask-question/ask-question-tool.ts +56 -2
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/calls/call-start.ts +8 -5
- package/src/tools/conversation-groups/move_to_group.ts +10 -12
- package/src/tools/document/document-tool.ts +11 -4
- package/src/tools/execution-timeout.ts +9 -2
- package/src/tools/executor.ts +7 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +7 -13
- package/src/tools/filesystem/search.ts +23 -21
- package/src/tools/filesystem/write.ts +4 -1
- package/src/tools/host-filesystem/edit.ts +7 -2
- package/src/tools/host-filesystem/read.ts +21 -8
- package/src/tools/host-filesystem/write.ts +10 -2
- package/src/tools/host-terminal/host-shell.ts +2 -2
- package/src/tools/mcp/mcp-tool-factory.ts +25 -1
- package/src/tools/permission-checker.ts +8 -3
- package/src/tools/schedule/delete.ts +13 -1
- package/src/tools/schedule/list.ts +14 -3
- package/src/tools/schedule/update.ts +56 -33
- package/src/tools/shared/filesystem/audio-read.ts +6 -4
- package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
- package/src/tools/shared/filesystem/image-read.ts +12 -12
- package/src/tools/shared/filesystem/path-policy.ts +70 -5
- package/src/tools/shared/filesystem/size-guard.ts +6 -6
- package/src/tools/shared/input-misuse.ts +72 -0
- package/src/tools/skills/scaffold-managed.ts +82 -0
- package/src/tools/skills/skill-tool-factory.ts +14 -1
- package/src/tools/subagent/consult-deadline.ts +12 -7
- package/src/tools/subagent/message.ts +3 -1
- package/src/tools/subagent/read.ts +66 -4
- package/src/tools/subagent/spawn.ts +500 -78
- package/src/tools/tool-approval-handler.ts +45 -4
- package/src/tools/types.ts +22 -3
- package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
- package/src/tools/ui-surface/visual-validation.ts +2 -0
- package/src/tts/__tests__/provider-adapters.test.ts +147 -0
- package/src/tts/__tests__/speakable-segments.test.ts +470 -0
- package/src/tts/language-voices.ts +23 -0
- package/src/tts/providers/deepgram-provider.ts +3 -1
- package/src/tts/providers/elevenlabs-provider.ts +73 -1
- package/src/tts/providers/xai-provider.ts +28 -2
- package/src/tts/speakable-segments.ts +293 -23
- package/src/tts/synthesis-stream.ts +7 -0
- package/src/tts/types.ts +7 -0
- package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
- package/src/usage/subagent-attribution.ts +108 -0
- package/src/util/__tests__/language-subtag.test.ts +54 -0
- package/src/util/__tests__/sqlite-retry.test.ts +112 -0
- package/src/util/abort-reasons.ts +16 -0
- package/src/util/ansi.ts +44 -0
- package/src/util/disk-usage.ts +17 -13
- package/src/util/image-conversion.ts +20 -13
- package/src/util/language-subtag.ts +43 -0
- package/src/util/schedule-source-key.ts +23 -0
- package/src/util/unicode.ts +1 -1
- package/src/util/worker-process.ts +7 -1
- package/src/workspace/git-service.ts +33 -9
- package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
- package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +116 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/top-level-renderer.ts +15 -2
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
- package/src/daemon/install-symlink.ts +0 -207
- package/src/live-voice/__tests__/front-decision.test.ts +0 -525
- package/src/live-voice/front-decision.ts +0 -429
- package/src/notifications/deferred-emit.ts +0 -147
|
@@ -4,14 +4,18 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This module owns only the durable row shape and raw SQL. The mapping to and
|
|
6
6
|
* from the manager's `SubagentState` lives in `SubagentManager`, keeping this
|
|
7
|
-
* layer decoupled from the subagent domain types.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* layer decoupled from the subagent domain types. It reaches into that domain
|
|
8
|
+
* for exactly two things, both to keep a SQL predicate from drifting away from
|
|
9
|
+
* the definition the manager uses: `normalizeSubagentLabel`, because label
|
|
10
|
+
* lookups have to fold the way the in-memory index folds and SQLite has no
|
|
11
|
+
* equivalent (`lower()` is ASCII-only), and `TERMINAL_STATUSES`, which decides
|
|
12
|
+
* which statuses a similarity scan reads as finished.
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
normalizeSubagentLabel,
|
|
17
|
+
TERMINAL_STATUSES,
|
|
18
|
+
} from "../subagent/types.js";
|
|
15
19
|
import { rawAll, rawGet, rawRun } from "./raw-query.js";
|
|
16
20
|
|
|
17
21
|
/** A durable subagent lifecycle record (camelCase mirror of the row). */
|
|
@@ -299,6 +303,144 @@ export function getSubagentRecordsByParent(
|
|
|
299
303
|
).map(rowToRecord);
|
|
300
304
|
}
|
|
301
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Rows the similarity scan reads before it stops. The scan is bounded so a
|
|
308
|
+
* long-lived assistant cannot turn every spawn into a full-table read; a
|
|
309
|
+
* truncated window can only under-count, which is the safe direction for a
|
|
310
|
+
* caller that rate-limits on the count.
|
|
311
|
+
*/
|
|
312
|
+
const RECENT_SPAWN_SCAN_LIMIT = 500;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* The status a run has to hold to count as a repeat of already-done work. A
|
|
316
|
+
* failed, aborted, or interrupted run left no answer behind, so spawning its
|
|
317
|
+
* objective again is recovery rather than repetition, and counting those runs
|
|
318
|
+
* would hold the retry that is exactly the right move.
|
|
319
|
+
*/
|
|
320
|
+
const REUSABLE_SPAWN_STATUS = "completed";
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Statuses the scan skips: the run ended without an answer, so it is neither
|
|
324
|
+
* work already done nor work still under way. Derived from the terminal set so
|
|
325
|
+
* a new terminal status cannot silently read as in flight.
|
|
326
|
+
*/
|
|
327
|
+
const DEAD_END_SPAWN_STATUSES: readonly string[] = [
|
|
328
|
+
...TERMINAL_STATUSES,
|
|
329
|
+
].filter((status) => status !== REUSABLE_SPAWN_STATUS);
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Fold an objective to the form two spawns are compared in: lowercased and
|
|
333
|
+
* whitespace-collapsed. Callers normalize the incoming objective with this same
|
|
334
|
+
* function, so both sides of the comparison are folded by one implementation.
|
|
335
|
+
*
|
|
336
|
+
* The whole objective is compared, never a prefix. Batch work routinely shares
|
|
337
|
+
* a long instruction preamble and diverges only in its tail (the file,
|
|
338
|
+
* component, or ticket each run targets), and comparing prefixes reads that
|
|
339
|
+
* batch as one objective repeated. Comparing in full costs only the re-run
|
|
340
|
+
* whose wording changed, which is a missed catch by an advisory guard, while a
|
|
341
|
+
* batch folded together holds work the caller genuinely meant to run. The
|
|
342
|
+
* runaway shape this guard exists for is a burst of the SAME objective, which
|
|
343
|
+
* folds identically either way, so full comparison gives up nothing on the
|
|
344
|
+
* case that matters and keeps a legitimate fan-out running.
|
|
345
|
+
*
|
|
346
|
+
* The separate `context` spawn argument is not part of the key: a subagent row
|
|
347
|
+
* does not carry it (context, prompts, and trust are deliberately left off the
|
|
348
|
+
* durable record), so two spawns with one objective and different contexts
|
|
349
|
+
* still fold together. That residue is bounded by the guard being advisory:
|
|
350
|
+
* the caller is told what already ran and spawns anyway if it meant to.
|
|
351
|
+
*/
|
|
352
|
+
export function normalizeSpawnObjective(objective: string): string {
|
|
353
|
+
return objective.toLowerCase().replace(/\s+/gu, " ").trim();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** How runs matching one normalized objective are distributed in a scope. */
|
|
357
|
+
export interface SimilarSpawnTally {
|
|
358
|
+
/** Runs that completed, so their answer exists and can be read. */
|
|
359
|
+
count: number;
|
|
360
|
+
/** Summed `estimated_cost` of the completed rows. */
|
|
361
|
+
estimatedCost: number;
|
|
362
|
+
/**
|
|
363
|
+
* Runs still under way (pending, running, or awaiting input). Kept apart
|
|
364
|
+
* from `count` because they have produced nothing to read yet: they are
|
|
365
|
+
* evidence of duplicated work in progress, not of an available answer.
|
|
366
|
+
*/
|
|
367
|
+
inFlight: number;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** The two scopes a repeat spawn is judged against. */
|
|
371
|
+
export interface RecentSimilarSpawns {
|
|
372
|
+
/** Matches spawned under the same parent conversation. */
|
|
373
|
+
conversation: SimilarSpawnTally;
|
|
374
|
+
/** Matches anywhere in this assistant; the table holds one assistant's rows. */
|
|
375
|
+
assistant: SimilarSpawnTally;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Tally the runs since `sinceMs` (an epoch cutoff) whose objective folds to
|
|
380
|
+
* `normalizedObjective`, both under `parentConversationId` and assistant-wide,
|
|
381
|
+
* split by whether each run finished with an answer or is still under way.
|
|
382
|
+
*
|
|
383
|
+
* Runs that ended without an answer are left out entirely: spawning their
|
|
384
|
+
* objective again is recovery rather than repetition. Advisor rows are left out
|
|
385
|
+
* too: an advisor consult blocks its caller and is not rate-limited, so its
|
|
386
|
+
* history must not count against a background spawn.
|
|
387
|
+
*
|
|
388
|
+
* Both scopes come from one bounded scan because the assistant-wide set
|
|
389
|
+
* contains the conversation's, so a second query would read the same rows
|
|
390
|
+
* twice.
|
|
391
|
+
*
|
|
392
|
+
* Rows hold the raw objective, so the fold has to happen on the column too.
|
|
393
|
+
* It runs in JS rather than SQL: SQLite's `lower()` folds ASCII only and has no
|
|
394
|
+
* whitespace-collapsing function, so a SQL predicate would disagree with
|
|
395
|
+
* {@link normalizeSpawnObjective} on exactly the objectives (accented, oddly
|
|
396
|
+
* spaced) a re-run is most likely to differ by.
|
|
397
|
+
*/
|
|
398
|
+
export function countRecentSimilarSpawns(args: {
|
|
399
|
+
parentConversationId: string;
|
|
400
|
+
normalizedObjective: string;
|
|
401
|
+
sinceMs: number;
|
|
402
|
+
}): RecentSimilarSpawns {
|
|
403
|
+
const rows = rawAll<{
|
|
404
|
+
parent_conversation_id: string;
|
|
405
|
+
objective: string;
|
|
406
|
+
status: string;
|
|
407
|
+
estimated_cost: number;
|
|
408
|
+
}>(
|
|
409
|
+
"subagent:countRecentSimilar",
|
|
410
|
+
`SELECT parent_conversation_id, objective, status, estimated_cost FROM subagents
|
|
411
|
+
WHERE created_at >= ? AND role <> 'advisor'
|
|
412
|
+
AND status NOT IN (${DEAD_END_SPAWN_STATUSES.map(() => "?").join(", ")})
|
|
413
|
+
ORDER BY created_at DESC
|
|
414
|
+
LIMIT ?`,
|
|
415
|
+
args.sinceMs,
|
|
416
|
+
...DEAD_END_SPAWN_STATUSES,
|
|
417
|
+
RECENT_SPAWN_SCAN_LIMIT,
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
const tally: RecentSimilarSpawns = {
|
|
421
|
+
conversation: { count: 0, estimatedCost: 0, inFlight: 0 },
|
|
422
|
+
assistant: { count: 0, estimatedCost: 0, inFlight: 0 },
|
|
423
|
+
};
|
|
424
|
+
const add = (scope: SimilarSpawnTally, row: (typeof rows)[number]): void => {
|
|
425
|
+
if (row.status === REUSABLE_SPAWN_STATUS) {
|
|
426
|
+
scope.count += 1;
|
|
427
|
+
scope.estimatedCost += row.estimated_cost;
|
|
428
|
+
} else {
|
|
429
|
+
scope.inFlight += 1;
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
for (const row of rows) {
|
|
433
|
+
if (normalizeSpawnObjective(row.objective) !== args.normalizedObjective) {
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
add(tally.assistant, row);
|
|
437
|
+
if (row.parent_conversation_id === args.parentConversationId) {
|
|
438
|
+
add(tally.conversation, row);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return tally;
|
|
442
|
+
}
|
|
443
|
+
|
|
302
444
|
/**
|
|
303
445
|
* Delete every subagent record spawned under `parentConversationId`. A row
|
|
304
446
|
* lives as long as its parent conversation, and the TTL sweep drops a child's
|
|
@@ -75,6 +75,26 @@ describe("managedSpeechTranscribe", () => {
|
|
|
75
75
|
expect(JSON.parse(init.body as string)).not.toHaveProperty("source");
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
test("sends the spoken language when one is given", async () => {
|
|
79
|
+
// The platform forwards this to Deepgram, which otherwise decodes the
|
|
80
|
+
// audio as English rather than detecting its language.
|
|
81
|
+
await managedSpeechTranscribe({
|
|
82
|
+
audio: AUDIO,
|
|
83
|
+
mimeType: "audio/wav",
|
|
84
|
+
language: "multi",
|
|
85
|
+
});
|
|
86
|
+
const [, init] = mockClient!.fetch.mock.calls[0] as [string, RequestInit];
|
|
87
|
+
expect(JSON.parse(init.body as string).language).toBe("multi");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("omits language when not provided", async () => {
|
|
91
|
+
// An absent field and an empty one are different requests upstream, and
|
|
92
|
+
// the empty one fails the platform serializer.
|
|
93
|
+
await managedSpeechTranscribe({ audio: AUDIO, mimeType: "audio/wav" });
|
|
94
|
+
const [, init] = mockClient!.fetch.mock.calls[0] as [string, RequestInit];
|
|
95
|
+
expect(JSON.parse(init.body as string)).not.toHaveProperty("language");
|
|
96
|
+
});
|
|
97
|
+
|
|
78
98
|
test("returns unavailable when no platform client resolves", async () => {
|
|
79
99
|
mockClient = null;
|
|
80
100
|
const result = await managedSpeechTranscribe({
|
|
@@ -90,6 +90,14 @@ export async function managedSpeechTranscribe(input: {
|
|
|
90
90
|
audio: Buffer;
|
|
91
91
|
mimeType: string;
|
|
92
92
|
source?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Spoken language to decode: a BCP-47 code, or `"multi"` for nova-3
|
|
95
|
+
* code-switching. Omitted means the platform sends none, which Deepgram
|
|
96
|
+
* decodes as English rather than detecting the language. Older platform
|
|
97
|
+
* builds that predate the field ignore it, so sending one is safe before
|
|
98
|
+
* the platform side deploys.
|
|
99
|
+
*/
|
|
100
|
+
language?: string;
|
|
93
101
|
signal?: AbortSignal;
|
|
94
102
|
}): Promise<ManagedSpeechResult<ManagedSpeechTranscription>> {
|
|
95
103
|
const resolved = await resolveClient();
|
|
@@ -107,6 +115,7 @@ export async function managedSpeechTranscribe(input: {
|
|
|
107
115
|
audioBase64: input.audio.toString("base64"),
|
|
108
116
|
mimeType: input.mimeType,
|
|
109
117
|
...(input.source !== undefined ? { source: input.source } : {}),
|
|
118
|
+
...(input.language ? { language: input.language } : {}),
|
|
110
119
|
}),
|
|
111
120
|
signal: input.signal,
|
|
112
121
|
},
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards that `resolveOauthCallbackUrl` reaches plugins.
|
|
3
|
+
*
|
|
4
|
+
* The shim written into `<workspaceDir>/node_modules/@vellumai/plugin-api`
|
|
5
|
+
* re-binds whatever `Object.keys()` finds on the plugin-api namespace, so an
|
|
6
|
+
* export missing from `index.ts` is missing from every installed plugin with
|
|
7
|
+
* no other signal than a plugin failing to import it.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
import { PLUGIN_API_EXPORTS } from "../../embedded/plugin-api.js";
|
|
13
|
+
import * as pluginApi from "../index.js";
|
|
14
|
+
|
|
15
|
+
describe("plugin-api OAuth callback export", () => {
|
|
16
|
+
test("is exported from the plugin-api surface", () => {
|
|
17
|
+
expect(typeof pluginApi.resolveOauthCallbackUrl).toEqual("function");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("is carried into the generated shim's binding list", () => {
|
|
21
|
+
expect(PLUGIN_API_EXPORTS).toContain("resolveOauthCallbackUrl");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("takes no arguments, so a plugin cannot vary the URI", () => {
|
|
25
|
+
// The value a Client ID Metadata Document publishes and the value the
|
|
26
|
+
// host later authorizes with have to be the same string.
|
|
27
|
+
expect(pluginApi.resolveOauthCallbackUrl.length).toEqual(0);
|
|
28
|
+
});
|
|
29
|
+
});
|
package/src/plugin-api/index.ts
CHANGED
|
@@ -173,6 +173,23 @@ export {
|
|
|
173
173
|
CredentialResolutionError,
|
|
174
174
|
resolveCredential,
|
|
175
175
|
} from "./resolve-credential.js";
|
|
176
|
+
// Resolve the public URL a third party should deliver to for one of the
|
|
177
|
+
// plugin's own ingress routes. Which URL is correct depends on how the
|
|
178
|
+
// assistant is reachable (a managed platform callback route, or a configured
|
|
179
|
+
// public ingress), and `ingress.publicBaseUrl` alone does not decide it. Uses
|
|
180
|
+
// the same resolution as `webhooks register`, and registers the callback route
|
|
181
|
+
// on the managed branches. The plugin defaults to the one in context.
|
|
182
|
+
export { resolveWebhookUrl, type WebhookUrlOptions } from "./webhook-url.js";
|
|
183
|
+
// Resolve the redirect URI an authorization server should send a user back
|
|
184
|
+
// to after consent. One shared route serves every OAuth flow in the
|
|
185
|
+
// assistant, demultiplexed by OAuth `state`, so this takes no arguments and
|
|
186
|
+
// returns the same URL for every caller and every attempt. A plugin needs it
|
|
187
|
+
// when it publishes something that has to name the redirect URI ahead of the
|
|
188
|
+
// flow, such as a Client ID Metadata Document, whose `redirect_uris` an
|
|
189
|
+
// authorization server matches exactly. Throws when no public ingress is
|
|
190
|
+
// configured and the assistant is not connected to the platform, which is the
|
|
191
|
+
// case where no URL would work.
|
|
192
|
+
export { resolveOauthCallbackUrl } from "../inbound/oauth-callback-url.js";
|
|
176
193
|
// Resolve a provider for a call site (optionally overriding the profile) so a
|
|
177
194
|
// plugin can run inference through the workspace's configured profiles and
|
|
178
195
|
// credentials — managed-proxy or BYOK — without supplying its own API key.
|
|
@@ -317,6 +334,7 @@ export {
|
|
|
317
334
|
deleteConversation,
|
|
318
335
|
getConversation,
|
|
319
336
|
getConversationDirPath,
|
|
337
|
+
getConversationProcessingStartedAt,
|
|
320
338
|
getMessages,
|
|
321
339
|
hasLexicalTokens,
|
|
322
340
|
isConversationProcessing,
|
|
@@ -337,21 +355,26 @@ export { synthesizeText, TtsSynthesisError } from "../tts/synthesize-text.js";
|
|
|
337
355
|
export type { TtsSynthesisResult } from "../tts/types.js";
|
|
338
356
|
// Streaming speech-to-text — open a live transcription session against the
|
|
339
357
|
// assistant's globally configured STT provider stack. The plugin feeds audio
|
|
340
|
-
// chunks via `sendAudio` and receives
|
|
341
|
-
// the `start(onEvent)` callback, closing with `stop`.
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
//
|
|
358
|
+
// chunks via `sendAudio` and receives transcript and turn-boundary events
|
|
359
|
+
// through the `start(onEvent)` callback, closing with `stop`.
|
|
360
|
+
// `SttStreamServerEvent` types the events handed to `onEvent`; every member of
|
|
361
|
+
// that union is exported alongside it so a plugin can name each variant in an
|
|
362
|
+
// exhaustive switch. `SttErrorCategory` classifies `error` events;
|
|
363
|
+
// `SttProviderId` names the resolved session's provider.
|
|
345
364
|
export type {
|
|
346
365
|
StreamingTranscriber,
|
|
347
366
|
SttErrorCategory,
|
|
348
367
|
SttProviderId,
|
|
349
368
|
SttStreamServerClosedEvent,
|
|
369
|
+
SttStreamServerEagerTurnEndEvent,
|
|
350
370
|
SttStreamServerErrorEvent,
|
|
351
371
|
SttStreamServerEvent,
|
|
352
372
|
SttStreamServerFinalEvent,
|
|
353
373
|
SttStreamServerFinalizedEvent,
|
|
354
374
|
SttStreamServerPartialEvent,
|
|
375
|
+
SttStreamServerTurnEndEvent,
|
|
376
|
+
SttStreamServerTurnResumedEvent,
|
|
377
|
+
SttStreamServerTurnStartEvent,
|
|
355
378
|
} from "../stt/types.js";
|
|
356
379
|
export { openTranscriptionSession } from "./transcription-session.js";
|
|
357
380
|
// Conversation agent-loop turn — run a full conversation turn (persist user
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public URL resolution for a plugin's own ingress route.
|
|
3
|
+
*
|
|
4
|
+
* A plugin that receives third-party webhooks has to tell the vendor where to
|
|
5
|
+
* deliver. Which URL is correct depends on how the assistant is reachable:
|
|
6
|
+
* a platform pod and a platform-connected assistant are served through a
|
|
7
|
+
* managed callback route, while a self-hosted deployment is served through its
|
|
8
|
+
* configured public ingress. `ingress.publicBaseUrl` alone does not decide it,
|
|
9
|
+
* because on a platform-connected assistant that value holds the Velay tunnel
|
|
10
|
+
* address, which is not where plugin routes are served.
|
|
11
|
+
*
|
|
12
|
+
* `resolveCallbackUrl` owns that decision for every caller in the codebase
|
|
13
|
+
* (`webhooks register`, the Telegram webhook manager). This exposes it to
|
|
14
|
+
* plugins so there is one implementation rather than one per plugin.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
|
|
19
|
+
import { getConfig } from "../config/loader.js";
|
|
20
|
+
import { resolveCallbackUrl } from "../inbound/platform-callback-registration.js";
|
|
21
|
+
import { getPublicBaseUrl } from "../inbound/public-ingress-urls.js";
|
|
22
|
+
import { getCurrentPluginName } from "../plugins/plugin-execution-context.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The namespace the gateway serves plugin ingress under. Fixed here rather
|
|
26
|
+
* than supplied by the caller, so a plugin cannot claim another's routes.
|
|
27
|
+
*/
|
|
28
|
+
const PLUGIN_WEBHOOK_PREFIX = "webhooks/plugins";
|
|
29
|
+
|
|
30
|
+
/** Plugin directory names usable as a URL path segment. */
|
|
31
|
+
const SAFE_PLUGIN_NAME = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Route paths the gateway serves, matching `IngressRouteSchema` in
|
|
35
|
+
* `gateway/src/channels/plugin-ingress.ts`: relative, free of query, fragment
|
|
36
|
+
* and whitespace, canonical under percent-decoding, and carrying no `.` or
|
|
37
|
+
* `..` segment.
|
|
38
|
+
*
|
|
39
|
+
* The two must agree. A path this rejects but the gateway serves is a route a
|
|
40
|
+
* plugin can install and then never resolve a URL for.
|
|
41
|
+
*/
|
|
42
|
+
function isServableRoutePath(value: string): boolean {
|
|
43
|
+
if (value.length === 0 || value.endsWith("/")) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (!/^[^/?#\s][^?#\s]*$/.test(value)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
let decoded: string;
|
|
50
|
+
try {
|
|
51
|
+
decoded = decodeURIComponent(value);
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (decoded !== value) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return !value.split("/").some((seg) => seg === "." || seg === "..");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface WebhookUrlOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Route path within the plugin's namespace, such as `"events-photon"`.
|
|
64
|
+
* Relative, with no leading slash.
|
|
65
|
+
*/
|
|
66
|
+
path: string;
|
|
67
|
+
/**
|
|
68
|
+
* Plugin whose namespace the route belongs to.
|
|
69
|
+
*
|
|
70
|
+
* Defaults to the plugin in context, which covers hooks and tools. Supply it
|
|
71
|
+
* explicitly from a plugin route handler, where no context is established.
|
|
72
|
+
*/
|
|
73
|
+
plugin?: string;
|
|
74
|
+
/** Human-readable label for the platform's admin display. */
|
|
75
|
+
sourceIdentifier?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Registration type for one route.
|
|
80
|
+
*
|
|
81
|
+
* The platform keys a callback route by type, so two routes of one plugin need
|
|
82
|
+
* two types or the second registration replaces the first. The slug keeps the
|
|
83
|
+
* type legible in the platform's admin display and the digest keeps it unique:
|
|
84
|
+
* `events-v1` and `events_v1` share a slug and differ here.
|
|
85
|
+
*/
|
|
86
|
+
function registrationType(plugin: string, route: string): string {
|
|
87
|
+
const slug = route.replace(/[^a-z0-9]+/gi, "_");
|
|
88
|
+
const digest = createHash("sha256").update(route).digest("hex").slice(0, 8);
|
|
89
|
+
return `plugin_${plugin}_${slug}_${digest}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Drop a trailing slash from a resolved callback URL.
|
|
94
|
+
*
|
|
95
|
+
* The platform appends one to the callback URLs it hands back, and a provider
|
|
96
|
+
* given `.../events-comms/` delivers to that spelling verbatim. The gateway
|
|
97
|
+
* matches a plugin route against its declared path, which may never end in a
|
|
98
|
+
* slash (see `IngressRouteSchema`), so the slash comes off once here rather
|
|
99
|
+
* than at each plugin that registers a URL.
|
|
100
|
+
*
|
|
101
|
+
* Only the path is ever trimmed: this resolver passes no query parameters, and
|
|
102
|
+
* a URL carrying one is left alone rather than truncated.
|
|
103
|
+
*/
|
|
104
|
+
function withoutTrailingSlash(url: string): string {
|
|
105
|
+
if (url.includes("?") || url.includes("#")) {
|
|
106
|
+
return url;
|
|
107
|
+
}
|
|
108
|
+
return url.replace(/\/+$/, "");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Resolve the public URL a third party should deliver to for `path`.
|
|
113
|
+
*
|
|
114
|
+
* On the managed branches this registers a callback route with the platform,
|
|
115
|
+
* which is idempotent and matches what `assistant webhooks register` does.
|
|
116
|
+
*
|
|
117
|
+
* @throws when the plugin cannot be determined, when `path` is not one the
|
|
118
|
+
* gateway would serve, or when no ingress is configured and the assistant is
|
|
119
|
+
* not connected to the platform. That last case has no URL that would work,
|
|
120
|
+
* and a plausible one would produce a vendor registration that silently
|
|
121
|
+
* receives nothing.
|
|
122
|
+
*/
|
|
123
|
+
export async function resolveWebhookUrl(
|
|
124
|
+
options: WebhookUrlOptions,
|
|
125
|
+
): Promise<string> {
|
|
126
|
+
const { path, sourceIdentifier } = options;
|
|
127
|
+
const plugin = options.plugin ?? getCurrentPluginName();
|
|
128
|
+
|
|
129
|
+
if (plugin === undefined) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
"No plugin is in context; pass `plugin` to resolve a webhook URL.",
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (!SAFE_PLUGIN_NAME.test(plugin)) {
|
|
135
|
+
throw new Error(`Invalid plugin name for a webhook URL: "${plugin}"`);
|
|
136
|
+
}
|
|
137
|
+
if (!isServableRoutePath(path)) {
|
|
138
|
+
throw new Error(`Invalid plugin webhook path: "${path}"`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const callbackPath = `${PLUGIN_WEBHOOK_PREFIX}/${plugin}/${path}`;
|
|
142
|
+
|
|
143
|
+
const resolved = await resolveCallbackUrl(
|
|
144
|
+
() => `${getPublicBaseUrl(getConfig())}/${callbackPath}`,
|
|
145
|
+
callbackPath,
|
|
146
|
+
registrationType(plugin, path),
|
|
147
|
+
undefined,
|
|
148
|
+
sourceIdentifier,
|
|
149
|
+
);
|
|
150
|
+
return withoutTrailingSlash(resolved);
|
|
151
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of installed plugin directories, including the realpath
|
|
3
|
+
* containment boundary that keeps a symlinked root pointing outside the
|
|
4
|
+
* plugins directory out of the list.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
mkdirSync,
|
|
9
|
+
mkdtempSync,
|
|
10
|
+
rmSync,
|
|
11
|
+
symlinkSync,
|
|
12
|
+
writeFileSync,
|
|
13
|
+
} from "node:fs";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { afterAll, beforeEach, describe, expect, test } from "bun:test";
|
|
17
|
+
|
|
18
|
+
import { getWorkspacePluginsDir } from "../../util/platform.js";
|
|
19
|
+
import { listInstalledPluginDirs } from "../installed-plugin-dirs.js";
|
|
20
|
+
|
|
21
|
+
const pluginsDir = getWorkspacePluginsDir();
|
|
22
|
+
const outsideRoot = mkdtempSync(join(tmpdir(), "installed-plugin-dirs-"));
|
|
23
|
+
|
|
24
|
+
afterAll(() => {
|
|
25
|
+
rmSync(outsideRoot, { recursive: true, force: true });
|
|
26
|
+
rmSync(pluginsDir, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/** A directory carrying the `package.json` that marks it as an install. */
|
|
30
|
+
function makePluginDir(parent: string, name: string): string {
|
|
31
|
+
const dir = join(parent, name);
|
|
32
|
+
mkdirSync(dir, { recursive: true });
|
|
33
|
+
writeFileSync(
|
|
34
|
+
join(dir, "package.json"),
|
|
35
|
+
JSON.stringify({ name, version: "1.0.0" }),
|
|
36
|
+
);
|
|
37
|
+
return dir;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
rmSync(pluginsDir, { recursive: true, force: true });
|
|
42
|
+
mkdirSync(pluginsDir, { recursive: true });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("listInstalledPluginDirs", () => {
|
|
46
|
+
test("lists real plugin directories and skips dot entries", () => {
|
|
47
|
+
makePluginDir(pluginsDir, "alpha");
|
|
48
|
+
makePluginDir(pluginsDir, ".hidden");
|
|
49
|
+
mkdirSync(join(pluginsDir, "no-manifest"), { recursive: true });
|
|
50
|
+
|
|
51
|
+
expect(listInstalledPluginDirs().map((p) => p.name)).toEqual(["alpha"]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("skips a symlinked plugin root that points outside the plugins dir", () => {
|
|
55
|
+
const escapee = makePluginDir(outsideRoot, "escapee");
|
|
56
|
+
symlinkSync(escapee, join(pluginsDir, "escapee"));
|
|
57
|
+
makePluginDir(pluginsDir, "contained");
|
|
58
|
+
|
|
59
|
+
// The plugin loader refuses to import from a root that resolves outside
|
|
60
|
+
// the plugins directory, so enumeration must not report it as installed:
|
|
61
|
+
// a caller acting on this list would arm and run code the loader would
|
|
62
|
+
// never activate.
|
|
63
|
+
expect(listInstalledPluginDirs().map((p) => p.name)).toEqual(["contained"]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("skips a symlink that aliases the plugins directory itself", () => {
|
|
67
|
+
symlinkSync(pluginsDir, join(pluginsDir, "self"));
|
|
68
|
+
|
|
69
|
+
expect(listInstalledPluginDirs()).toEqual([]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("keeps a symlinked plugin root that stays inside the plugins dir", () => {
|
|
73
|
+
const real = makePluginDir(pluginsDir, "real");
|
|
74
|
+
symlinkSync(real, join(pluginsDir, "alias"));
|
|
75
|
+
|
|
76
|
+
expect(
|
|
77
|
+
listInstalledPluginDirs()
|
|
78
|
+
.map((p) => p.name)
|
|
79
|
+
.sort(),
|
|
80
|
+
).toEqual(["alias", "real"]);
|
|
81
|
+
});
|
|
82
|
+
});
|