@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
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channels that installed plugins bring.
|
|
3
|
+
*
|
|
4
|
+
* `getWorkspacePluginsDir` is mocked to a scratch directory so these read real
|
|
5
|
+
* files off disk without touching the machine's workspace.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
const workspacePluginsDir = mkdtempSync(join(tmpdir(), "plugin-channels-"));
|
|
14
|
+
|
|
15
|
+
const realPlatform = await import("../../util/platform.js");
|
|
16
|
+
|
|
17
|
+
mock.module("../../util/platform.js", () => ({
|
|
18
|
+
...realPlatform,
|
|
19
|
+
getWorkspacePluginsDir: () => workspacePluginsDir,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const { discoverPluginChannels } = await import(
|
|
23
|
+
"../plugin-channel-declarations.js"
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
interface PluginOptions {
|
|
27
|
+
/** Contents of `channels/ingress.json`; omit for a plugin with no ingress. */
|
|
28
|
+
ingress?: string;
|
|
29
|
+
manifest?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const INGRESS = JSON.stringify({
|
|
33
|
+
routes: [{ path: "events", kind: "http", description: "inbound" }],
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function writePlugin(name: string, options: PluginOptions = {}): string {
|
|
37
|
+
const dir = join(workspacePluginsDir, name);
|
|
38
|
+
mkdirSync(dir, { recursive: true });
|
|
39
|
+
writeFileSync(
|
|
40
|
+
join(dir, "package.json"),
|
|
41
|
+
JSON.stringify({ name, ...options.manifest }),
|
|
42
|
+
);
|
|
43
|
+
if (options.ingress !== undefined) {
|
|
44
|
+
mkdirSync(join(dir, "channels"), { recursive: true });
|
|
45
|
+
writeFileSync(join(dir, "channels", "ingress.json"), options.ingress);
|
|
46
|
+
}
|
|
47
|
+
return dir;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
rmSync(workspacePluginsDir, { recursive: true, force: true });
|
|
52
|
+
mkdirSync(workspacePluginsDir, { recursive: true });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterAll(() => {
|
|
56
|
+
rmSync(workspacePluginsDir, { recursive: true, force: true });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("discoverPluginChannels", () => {
|
|
60
|
+
test("a plugin is a channel because it declares ingress", async () => {
|
|
61
|
+
writePlugin("courier", {
|
|
62
|
+
ingress: INGRESS,
|
|
63
|
+
manifest: {
|
|
64
|
+
displayName: "Courier",
|
|
65
|
+
description: "Reach the assistant by carrier pigeon.",
|
|
66
|
+
icon: "send",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(await discoverPluginChannels()).toEqual([
|
|
71
|
+
{
|
|
72
|
+
id: "courier",
|
|
73
|
+
source: "plugin:courier",
|
|
74
|
+
label: "Courier",
|
|
75
|
+
subtitle: "Reach the assistant by carrier pigeon.",
|
|
76
|
+
icon: "send",
|
|
77
|
+
supportsVerification: false,
|
|
78
|
+
setupMessages: {
|
|
79
|
+
guardian: "I want to set up Courier. Can you help me?",
|
|
80
|
+
contact:
|
|
81
|
+
"I'd like to reach you on Courier. Can you help me get set up?",
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("ignores a plugin that declares no ingress", async () => {
|
|
88
|
+
// Presentation alone does not make a channel: reaching the assistant from
|
|
89
|
+
// outside is what one is, and ingress is where that is declared.
|
|
90
|
+
writePlugin("notes", { manifest: { displayName: "Notes", icon: "send" } });
|
|
91
|
+
|
|
92
|
+
expect(await discoverPluginChannels()).toEqual([]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("surfaces a channel whose ingress the gateway would reject", async () => {
|
|
96
|
+
// Validation belongs to the gateway, which owns the schema. A plugin with
|
|
97
|
+
// a broken declaration is a channel with broken ingress, and saying so
|
|
98
|
+
// beats dropping it off the page a guardian would look at.
|
|
99
|
+
writePlugin("courier", {
|
|
100
|
+
ingress: "{ not json",
|
|
101
|
+
manifest: { displayName: "Courier" },
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect((await discoverPluginChannels())[0]?.label).toBe("Courier");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("skips a disabled plugin", async () => {
|
|
108
|
+
// Same source of truth the loader uses for hooks, tools and routes: a
|
|
109
|
+
// disabled plugin would otherwise offer a setup flow that cannot run.
|
|
110
|
+
const dir = writePlugin("courier", { ingress: INGRESS });
|
|
111
|
+
writeFileSync(join(dir, ".disabled"), "");
|
|
112
|
+
|
|
113
|
+
expect(await discoverPluginChannels()).toEqual([]);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("refuses to let a plugin take a built-in channel's id", async () => {
|
|
117
|
+
// Two rows sharing an id would be ambiguous to any client keying on one,
|
|
118
|
+
// and letting the plugin win would let it impersonate a built-in.
|
|
119
|
+
writePlugin("slack", {
|
|
120
|
+
ingress: INGRESS,
|
|
121
|
+
manifest: { displayName: "Slack" },
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(await discoverPluginChannels()).toEqual([]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("titles a plugin that names no display name", async () => {
|
|
128
|
+
// Presentation is best-effort, so a bare manifest costs a nicer title and
|
|
129
|
+
// never the row itself.
|
|
130
|
+
writePlugin("meeting-bot", { ingress: INGRESS });
|
|
131
|
+
|
|
132
|
+
expect(await discoverPluginChannels()).toMatchObject([
|
|
133
|
+
{
|
|
134
|
+
id: "meeting-bot",
|
|
135
|
+
source: "plugin:meeting-bot",
|
|
136
|
+
label: "Meeting Bot",
|
|
137
|
+
subtitle: "Provided by the Meeting Bot plugin",
|
|
138
|
+
icon: "message-square",
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("still lists a channel whose manifest cannot be read", async () => {
|
|
144
|
+
// The directory is the plugin's identity, so an unparseable manifest
|
|
145
|
+
// costs its presentation and not its existence.
|
|
146
|
+
const dir = writePlugin("courier", { ingress: INGRESS });
|
|
147
|
+
writeFileSync(join(dir, "package.json"), "{ not json");
|
|
148
|
+
|
|
149
|
+
expect((await discoverPluginChannels())[0]?.label).toBe("Courier");
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("never claims a plugin channel supports verification", async () => {
|
|
153
|
+
// There is no client-side verification flow for one, so clients render it
|
|
154
|
+
// display-only rather than pre-warming a status that cannot arrive.
|
|
155
|
+
writePlugin("courier", { ingress: INGRESS });
|
|
156
|
+
|
|
157
|
+
expect((await discoverPluginChannels())[0]?.supportsVerification).toBe(
|
|
158
|
+
false,
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
});
|
package/src/channels/config.ts
CHANGED
|
@@ -75,8 +75,26 @@ const CHANNEL_POLICIES = {
|
|
|
75
75
|
},
|
|
76
76
|
discord: {
|
|
77
77
|
notification: {
|
|
78
|
-
//
|
|
79
|
-
//
|
|
78
|
+
// Replies to an inbound Discord message do not read this flag: they
|
|
79
|
+
// route by `replyCallbackUrl` through the channel transport. This gates
|
|
80
|
+
// proactive notification only, which needs a guardian binding to
|
|
81
|
+
// address and a destination resolver to reach it. Discord has neither,
|
|
82
|
+
// and `NotificationChannel` is derived from this flag, so enabling it
|
|
83
|
+
// early would let the decision engine pick a channel that resolves to
|
|
84
|
+
// nothing.
|
|
85
|
+
deliveryEnabled: false,
|
|
86
|
+
conversationStrategy: "continue_existing_conversation",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
plugin: {
|
|
90
|
+
notification: {
|
|
91
|
+
// Every plugin-brought channel shares this row, so the answer has to
|
|
92
|
+
// hold for all of them. A reply to an inbound plugin message routes by
|
|
93
|
+
// `replyCallbackUrl` and does not read this flag; proactive notification
|
|
94
|
+
// does, and it needs a guardian binding plus a destination resolver to
|
|
95
|
+
// reach. Neither exists per-plugin, and `NotificationChannel` is derived
|
|
96
|
+
// from this flag, so enabling it would let the decision engine pick a
|
|
97
|
+
// channel that resolves to nothing for whichever plugin it landed on.
|
|
80
98
|
deliveryEnabled: false,
|
|
81
99
|
conversationStrategy: "continue_existing_conversation",
|
|
82
100
|
},
|
|
@@ -122,7 +122,8 @@ export async function createOutboundSession(
|
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
124
|
* Guarded variant of `createOutboundSession` for callers passing an atomic
|
|
125
|
-
* claim guard (`requireSourceSessionPending` /
|
|
125
|
+
* claim guard (`requireSourceSessionPending` /
|
|
126
|
+
* `ifNoneActiveForExternalUserId`). The gateway
|
|
126
127
|
* evaluates the guard in the same synchronous section as the mint; a failed
|
|
127
128
|
* guard returns a conflict marker instead of revoking the concurrent
|
|
128
129
|
* winner's session. Throws when the gateway is unreachable (fail-closed).
|
|
@@ -160,10 +161,14 @@ export async function getPendingSession(
|
|
|
160
161
|
*/
|
|
161
162
|
export async function findActiveSession(
|
|
162
163
|
channel: string,
|
|
164
|
+
filter: {
|
|
165
|
+
expectedExternalUserId?: string;
|
|
166
|
+
verificationPurpose?: "guardian" | "trusted_contact";
|
|
167
|
+
} = {},
|
|
163
168
|
): Promise<VerificationSessionWire | null> {
|
|
164
169
|
return callGateway(
|
|
165
170
|
VERIFICATION_SESSIONS_IPC_METHODS.findActive,
|
|
166
|
-
{ channel },
|
|
171
|
+
{ channel, ...filter },
|
|
167
172
|
SessionLookupIpcResponseSchema,
|
|
168
173
|
);
|
|
169
174
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channels that installed plugins bring.
|
|
3
|
+
*
|
|
4
|
+
* A plugin is a channel because it declares ingress: `channels/ingress.json`
|
|
5
|
+
* is the list of routes the outside world may reach it on, and reaching the
|
|
6
|
+
* assistant from outside is what being a channel means. There is no second
|
|
7
|
+
* file saying so, and nothing a plugin can set to claim the status without
|
|
8
|
+
* declaring the reach that constitutes it.
|
|
9
|
+
*
|
|
10
|
+
* What the gateway does with that file is a separate matter, and stays the
|
|
11
|
+
* gateway's: validating the routes, digesting them, holding them behind a
|
|
12
|
+
* guardian's approval. This reads its presence and nothing else, so a
|
|
13
|
+
* declaration the gateway rejects still surfaces here. That is the honest
|
|
14
|
+
* report, the plugin is a channel and its ingress is broken, and it keeps a
|
|
15
|
+
* schema this module does not own from deciding what a settings page lists.
|
|
16
|
+
*
|
|
17
|
+
* Presentation comes from the plugin's own manifest, where a plugin's title,
|
|
18
|
+
* description and icon already belong. All three are optional and none gate
|
|
19
|
+
* anything: a plugin with ingress and a bare `package.json` still appears,
|
|
20
|
+
* titled from its directory.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { statSync } from "node:fs";
|
|
24
|
+
import { join } from "node:path";
|
|
25
|
+
|
|
26
|
+
import { isPluginDisabled } from "../plugins/disabled-state.js";
|
|
27
|
+
import { parsePluginPresentation } from "../plugins/external-plugin-loader.js";
|
|
28
|
+
import { listInstalledPluginDirs } from "../plugins/installed-plugin-dirs.js";
|
|
29
|
+
import { type AvailableChannel, isChannelId } from "./types.js";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The declaration that makes a plugin a channel. Owned by the gateway, which
|
|
33
|
+
* parses it; named here only to test for it.
|
|
34
|
+
*/
|
|
35
|
+
export const PLUGIN_INGRESS_MANIFEST_RELPATH = "channels/ingress.json";
|
|
36
|
+
|
|
37
|
+
/** Icon for a plugin naming none. The generic "a message arrives here" glyph. */
|
|
38
|
+
const FALLBACK_ICON = "message-square";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Title for a plugin with no `displayName`.
|
|
42
|
+
*
|
|
43
|
+
* Derived rather than defaulted to the raw directory name so `meeting-bot`
|
|
44
|
+
* reads as "Meeting Bot" beside "Slack" and "Telegram". A plugin whose casing
|
|
45
|
+
* matters sets `displayName` and this never runs.
|
|
46
|
+
*/
|
|
47
|
+
function titleFromDirectory(name: string): string {
|
|
48
|
+
return name
|
|
49
|
+
.split(/[-_]/)
|
|
50
|
+
.filter((part) => part.length > 0)
|
|
51
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
52
|
+
.join(" ");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** True when the plugin declares ingress routes. */
|
|
56
|
+
function declaresIngress(pluginDir: string): boolean {
|
|
57
|
+
return (
|
|
58
|
+
statSync(join(pluginDir, PLUGIN_INGRESS_MANIFEST_RELPATH), {
|
|
59
|
+
throwIfNoEntry: false,
|
|
60
|
+
})?.isFile() === true
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Every channel brought by an installed, enabled plugin.
|
|
66
|
+
*
|
|
67
|
+
* A plugin whose directory name is one of the assistant's own channels is
|
|
68
|
+
* skipped: two rows sharing an id would be ambiguous to any client keying on
|
|
69
|
+
* one, and the resolution that lets a plugin win would let it impersonate a
|
|
70
|
+
* built-in channel. The assistant's keep the name.
|
|
71
|
+
*
|
|
72
|
+
* Disabled plugins are skipped too, matching the source of truth the loader
|
|
73
|
+
* uses for hooks, tools and routes: a disabled plugin holds no ingress either,
|
|
74
|
+
* and one that reappeared here would offer a setup flow that cannot run.
|
|
75
|
+
*
|
|
76
|
+
* Order follows the plugins directory, and is stable for a stable install set.
|
|
77
|
+
*/
|
|
78
|
+
export async function discoverPluginChannels(): Promise<AvailableChannel[]> {
|
|
79
|
+
const channels: AvailableChannel[] = [];
|
|
80
|
+
|
|
81
|
+
for (const { name, dir } of listInstalledPluginDirs()) {
|
|
82
|
+
if (isPluginDisabled(name) || isChannelId(name) || !declaresIngress(dir)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const presentation = await parsePluginPresentation(dir);
|
|
86
|
+
const label = presentation?.displayName ?? titleFromDirectory(name);
|
|
87
|
+
channels.push({
|
|
88
|
+
id: name,
|
|
89
|
+
source: `plugin:${name}`,
|
|
90
|
+
label,
|
|
91
|
+
subtitle: presentation?.description ?? `Provided by the ${label} plugin`,
|
|
92
|
+
icon: presentation?.icon ?? FALLBACK_ICON,
|
|
93
|
+
// No client-side verification flow exists for a plugin channel, so
|
|
94
|
+
// clients render it display-only and never pre-warm a status for it.
|
|
95
|
+
supportsVerification: false,
|
|
96
|
+
// Openers for a setup conversation, which is what this field is for.
|
|
97
|
+
// Deliberately not the verification copy the built-ins carry: there is
|
|
98
|
+
// no identity to verify here, and inventing that wording would send
|
|
99
|
+
// someone down a flow that does not exist.
|
|
100
|
+
setupMessages: {
|
|
101
|
+
guardian: `I want to set up ${label}. Can you help me?`,
|
|
102
|
+
contact: `I'd like to reach you on ${label}. Can you help me get set up?`,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return channels;
|
|
108
|
+
}
|
package/src/channels/types.ts
CHANGED
|
@@ -51,6 +51,32 @@ export interface ChannelInfo {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Source that contributes a channel, in the `<kind>[:<id>]` form the tool
|
|
56
|
+
* catalog and process tree already use: `default` for one the assistant ships,
|
|
57
|
+
* `plugin:<name>` for one an installed plugin brings.
|
|
58
|
+
*
|
|
59
|
+
* Composed from the plugin's install directory rather than from anything it
|
|
60
|
+
* declares, so a manifest cannot claim to be another source or pass itself off
|
|
61
|
+
* as built in.
|
|
62
|
+
*/
|
|
63
|
+
export type ChannelSource = "default" | `plugin:${string}`;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* A channel as `/v1/channels/available` reports it: the display metadata plus
|
|
67
|
+
* where it came from.
|
|
68
|
+
*
|
|
69
|
+
* `id` widens to a string here because a plugin channel's id is its plugin
|
|
70
|
+
* name, which is not a member of the closed {@link ChannelId} union. The union
|
|
71
|
+
* still governs everything the assistant routes, verifies and applies
|
|
72
|
+
* admission policy to; `source` is what tells a client which kind it is
|
|
73
|
+
* holding, so nothing has to infer it from the id.
|
|
74
|
+
*/
|
|
75
|
+
export interface AvailableChannel extends Omit<ChannelInfo, "id"> {
|
|
76
|
+
id: string;
|
|
77
|
+
source: ChannelSource;
|
|
78
|
+
}
|
|
79
|
+
|
|
54
80
|
/**
|
|
55
81
|
* Per-channel display metadata for the channels the gateway can currently
|
|
56
82
|
* surface to clients. Add an entry here when surfacing a new channel via
|
|
@@ -155,6 +181,10 @@ export const INTERFACE_IDS = [
|
|
|
155
181
|
// device/service callbacks). Non-interactive — permission prompts route
|
|
156
182
|
// through the guardian system, not an interactive client — and non-host-proxy.
|
|
157
183
|
"route",
|
|
184
|
+
// Turns a plugin-brought channel delivered through the gateway. One id for
|
|
185
|
+
// every plugin, matching the `plugin` channel; which plugin it was is in
|
|
186
|
+
// `sourceMetadata.plugin`.
|
|
187
|
+
"plugin",
|
|
158
188
|
] as const;
|
|
159
189
|
|
|
160
190
|
export type InterfaceId = (typeof INTERFACE_IDS)[number];
|
|
@@ -207,7 +237,13 @@ export function parseInterfaceId(value: unknown): InterfaceId | null {
|
|
|
207
237
|
* than polluting the interface vocabulary. Drives only the per-turn
|
|
208
238
|
* `client_os` context line (e.g. app-builder mobile-first for `ios`/`android`).
|
|
209
239
|
*/
|
|
210
|
-
export const CLIENT_OS_VALUES = [
|
|
240
|
+
export const CLIENT_OS_VALUES = [
|
|
241
|
+
"web",
|
|
242
|
+
"ios",
|
|
243
|
+
"macos",
|
|
244
|
+
"windows",
|
|
245
|
+
"android",
|
|
246
|
+
] as const;
|
|
211
247
|
|
|
212
248
|
export type ClientOs = (typeof CLIENT_OS_VALUES)[number];
|
|
213
249
|
|
package/src/cli/AGENTS.md
CHANGED
|
@@ -123,10 +123,13 @@ registerFooCommand(program);
|
|
|
123
123
|
_synchronously_ at command registration (so it can't be a lazy
|
|
124
124
|
`import()`) may stay hoisted behind a scoped
|
|
125
125
|
`// eslint-disable-next-line cli/no-daemon-internals` with a comment
|
|
126
|
-
explaining why. The
|
|
126
|
+
explaining why. The current cases are `browser/operation-meta`, in
|
|
127
127
|
`commands/browser.ts` (it drives synchronous subcommand generation and
|
|
128
128
|
deliberately pulls no Playwright graph) and `commands/browser.help.ts`
|
|
129
|
-
(which derives the declarative help from the same contract)
|
|
129
|
+
(which derives the declarative help from the same contract); and
|
|
130
|
+
`providers/speech-to-text/provider-catalog`, in `commands/stt.help.ts`
|
|
131
|
+
(a literal map behind type-only imports, which the help text reads to
|
|
132
|
+
name the providers that serve the batch transcription boundary).
|
|
130
133
|
|
|
131
134
|
2. **Lazy-import daemon functionality inside the action.** Running daemon
|
|
132
135
|
logic in-process is encouraged where it avoids an IPC round-trip (which
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import * as nodeFs from "node:fs";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
15
16
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
16
17
|
|
|
17
18
|
import { Command } from "commander";
|
|
@@ -415,8 +416,9 @@ describe("cache set --value", () => {
|
|
|
415
416
|
describe("cache set --file", () => {
|
|
416
417
|
test("reads JSON from a file", async () => {
|
|
417
418
|
mockIpcResult = { ok: true, result: { key: "file-key" } };
|
|
418
|
-
const pkgPath =
|
|
419
|
-
.
|
|
419
|
+
const pkgPath = fileURLToPath(
|
|
420
|
+
new URL("../../../../package.json", import.meta.url),
|
|
421
|
+
);
|
|
420
422
|
|
|
421
423
|
const { exitCode } = await runCommand(["cache", "set", "--file", pkgPath]);
|
|
422
424
|
|
|
@@ -442,8 +444,9 @@ describe("cache set --file", () => {
|
|
|
442
444
|
test("works in TTY mode (no stdin required)", async () => {
|
|
443
445
|
mockStdinIsTTY = true;
|
|
444
446
|
mockIpcResult = { ok: true, result: { key: "file-tty-key" } };
|
|
445
|
-
const pkgPath =
|
|
446
|
-
.
|
|
447
|
+
const pkgPath = fileURLToPath(
|
|
448
|
+
new URL("../../../../package.json", import.meta.url),
|
|
449
|
+
);
|
|
447
450
|
|
|
448
451
|
const { exitCode } = await runCommand(["cache", "set", "--file", pkgPath]);
|
|
449
452
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared harness for CLI command tests: registers a command tree on a fresh
|
|
3
|
+
* Commander program, runs it against captured output sinks, and returns what
|
|
4
|
+
* the command emitted plus the resulting exit code.
|
|
5
|
+
*
|
|
6
|
+
* `process.stdout.write`, `console.log`, and `console.error` are captured for
|
|
7
|
+
* the duration of the run, so command output lands in the result regardless of
|
|
8
|
+
* which sink the command writes to; `process.exitCode` is reset afterwards.
|
|
9
|
+
* The caller passes its own (possibly mock-backed) registration function, so
|
|
10
|
+
* this helper imports nothing from `src/` beyond what any test file may
|
|
11
|
+
* import itself (see the test-machinery isolation rules in assistant/CLAUDE.md).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Command } from "commander";
|
|
15
|
+
|
|
16
|
+
export interface CliCommandRunResult {
|
|
17
|
+
stdout: string;
|
|
18
|
+
stderr: string;
|
|
19
|
+
/** stdout + stderr chunks in emission order, for cross-stream ordering. */
|
|
20
|
+
events: string[];
|
|
21
|
+
exitCode: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function runCliCommand(
|
|
25
|
+
register: (program: Command) => void,
|
|
26
|
+
args: string[],
|
|
27
|
+
): Promise<CliCommandRunResult> {
|
|
28
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
29
|
+
const originalConsoleLog = console.log;
|
|
30
|
+
const originalConsoleError = console.error;
|
|
31
|
+
const stdoutChunks: string[] = [];
|
|
32
|
+
const stderrChunks: string[] = [];
|
|
33
|
+
const events: string[] = [];
|
|
34
|
+
|
|
35
|
+
process.stdout.write = ((chunk: unknown) => {
|
|
36
|
+
const text = typeof chunk === "string" ? chunk : String(chunk);
|
|
37
|
+
stdoutChunks.push(text);
|
|
38
|
+
events.push(text);
|
|
39
|
+
return true;
|
|
40
|
+
}) as typeof process.stdout.write;
|
|
41
|
+
console.log = (...logArgs: unknown[]) => {
|
|
42
|
+
const text = logArgs.map(String).join(" ") + "\n";
|
|
43
|
+
stdoutChunks.push(text);
|
|
44
|
+
events.push(text);
|
|
45
|
+
};
|
|
46
|
+
console.error = (...logArgs: unknown[]) => {
|
|
47
|
+
const text = logArgs.map(String).join(" ") + "\n";
|
|
48
|
+
stderrChunks.push(text);
|
|
49
|
+
events.push(text);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
process.exitCode = 0;
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const program = new Command();
|
|
56
|
+
program.exitOverride();
|
|
57
|
+
program.configureOutput({
|
|
58
|
+
writeErr: () => {},
|
|
59
|
+
writeOut: (str: string) => stdoutChunks.push(str),
|
|
60
|
+
});
|
|
61
|
+
register(program);
|
|
62
|
+
await program.parseAsync(["node", "assistant", ...args]);
|
|
63
|
+
} catch {
|
|
64
|
+
if (process.exitCode === 0) {
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
}
|
|
67
|
+
} finally {
|
|
68
|
+
process.stdout.write = originalStdoutWrite;
|
|
69
|
+
console.log = originalConsoleLog;
|
|
70
|
+
console.error = originalConsoleError;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const exitCode = process.exitCode ?? 0;
|
|
74
|
+
process.exitCode = 0;
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
stdout: stdoutChunks.join(""),
|
|
78
|
+
stderr: stderrChunks.join(""),
|
|
79
|
+
events,
|
|
80
|
+
exitCode,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI plumbing tests for
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* CLI plumbing tests for `assistant conversations wake`. Inline
|
|
3
|
+
* `--external-content` resolves to the fenced `externalContent` body field and
|
|
4
|
+
* implies `--persist`; a script-mode schedule's environment resolves to the
|
|
5
|
+
* `cronRunId` and `scheduleId` body fields. The route fences the untrusted
|
|
6
|
+
* string and applies the schedule's pinned profile (see
|
|
7
|
+
* wake-conversation-routes.test.ts).
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
10
|
import * as nodeFs from "node:fs";
|
|
@@ -88,15 +90,19 @@ function lastBody(): Record<string, unknown> {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
let savedRunId: string | undefined;
|
|
93
|
+
let savedScheduleId: string | undefined;
|
|
91
94
|
|
|
92
95
|
beforeEach(() => {
|
|
93
96
|
lastIpcCall = null;
|
|
94
97
|
loggerCalls.length = 0;
|
|
95
98
|
process.exitCode = 0;
|
|
96
|
-
// The wake action reads __SCHEDULE_RUN_ID for cost attribution
|
|
97
|
-
//
|
|
99
|
+
// The wake action reads __SCHEDULE_RUN_ID for cost attribution and
|
|
100
|
+
// __SCHEDULE_ID for the schedule's pinned inference profile; clear both so
|
|
101
|
+
// they never leak into the captured body.
|
|
98
102
|
savedRunId = process.env.__SCHEDULE_RUN_ID;
|
|
103
|
+
savedScheduleId = process.env.__SCHEDULE_ID;
|
|
99
104
|
delete process.env.__SCHEDULE_RUN_ID;
|
|
105
|
+
delete process.env.__SCHEDULE_ID;
|
|
100
106
|
});
|
|
101
107
|
|
|
102
108
|
describe("conversations wake untrusted-content input", () => {
|
|
@@ -149,9 +155,48 @@ describe("conversations wake untrusted-content input", () => {
|
|
|
149
155
|
});
|
|
150
156
|
});
|
|
151
157
|
|
|
158
|
+
describe("conversations wake schedule environment", () => {
|
|
159
|
+
test("script-mode env threads the run id and the schedule id", async () => {
|
|
160
|
+
process.env.__SCHEDULE_RUN_ID = "run-9";
|
|
161
|
+
process.env.__SCHEDULE_ID = "sched-9";
|
|
162
|
+
const code = await runWake([
|
|
163
|
+
"wake",
|
|
164
|
+
"conv-6",
|
|
165
|
+
"--hint",
|
|
166
|
+
"Digest ready",
|
|
167
|
+
"--json",
|
|
168
|
+
]);
|
|
169
|
+
expect(code).toBe(0);
|
|
170
|
+
expect(lastBody()).toMatchObject({
|
|
171
|
+
cronRunId: "run-9",
|
|
172
|
+
scheduleId: "sched-9",
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("outside a script run neither field is sent", async () => {
|
|
177
|
+
const code = await runWake([
|
|
178
|
+
"wake",
|
|
179
|
+
"conv-7",
|
|
180
|
+
"--hint",
|
|
181
|
+
"Digest ready",
|
|
182
|
+
"--json",
|
|
183
|
+
]);
|
|
184
|
+
expect(code).toBe(0);
|
|
185
|
+
expect(lastBody().cronRunId).toBeUndefined();
|
|
186
|
+
expect(lastBody().scheduleId).toBeUndefined();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
152
190
|
afterEach(() => {
|
|
153
191
|
if (savedRunId !== undefined) {
|
|
154
192
|
process.env.__SCHEDULE_RUN_ID = savedRunId;
|
|
193
|
+
} else {
|
|
194
|
+
delete process.env.__SCHEDULE_RUN_ID;
|
|
195
|
+
}
|
|
196
|
+
if (savedScheduleId !== undefined) {
|
|
197
|
+
process.env.__SCHEDULE_ID = savedScheduleId;
|
|
198
|
+
} else {
|
|
199
|
+
delete process.env.__SCHEDULE_ID;
|
|
155
200
|
}
|
|
156
201
|
process.exitCode = 0;
|
|
157
202
|
});
|
|
@@ -72,6 +72,20 @@ describe("models list", () => {
|
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
test("bare `models` runs list", async () => {
|
|
76
|
+
await run(["models"]);
|
|
77
|
+
expect(lastIpcCall?.method).toBe("inference_models_list");
|
|
78
|
+
expect(lastIpcCall?.params).toEqual({ queryParams: {} });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("bare `models --provider` runs list with the filter", async () => {
|
|
82
|
+
await run(["models", "--provider", "gemini"]);
|
|
83
|
+
expect(lastIpcCall?.method).toBe("inference_models_list");
|
|
84
|
+
expect(lastIpcCall?.params).toEqual({
|
|
85
|
+
queryParams: { provider: "gemini" },
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
75
89
|
test("--json emits structured output", async () => {
|
|
76
90
|
mockIpcResult = {
|
|
77
91
|
ok: true,
|