@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
|
@@ -154,6 +154,20 @@ export interface InstallPluginOptions {
|
|
|
154
154
|
readonly trustedSource?: PluginFetchSource;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Consent gate invoked after the plugin tree is fully staged and before it is
|
|
159
|
+
* finalized (dependencies installed, provenance recorded, swapped live). The
|
|
160
|
+
* caller inspects the staged tree to see what the plugin declares (e.g.
|
|
161
|
+
* schedules) and asks the user. Returning `false` aborts the install: the
|
|
162
|
+
* staging directory is removed, nothing is swapped, and
|
|
163
|
+
* {@link PluginInstallDeclinedError} is thrown.
|
|
164
|
+
*/
|
|
165
|
+
export type ConfirmStagedInstall = (staged: {
|
|
166
|
+
readonly name: string;
|
|
167
|
+
/** Absolute path of the fully materialized staging directory. */
|
|
168
|
+
readonly stagingDir: string;
|
|
169
|
+
}) => Promise<boolean>;
|
|
170
|
+
|
|
157
171
|
/** Dependencies injected by the caller. */
|
|
158
172
|
export interface InstallPluginDeps {
|
|
159
173
|
/** HTTP client. Production callers pass `globalThis.fetch.bind(globalThis)`. */
|
|
@@ -168,6 +182,8 @@ export interface InstallPluginDeps {
|
|
|
168
182
|
readonly runInstallDeps?: DependencyInstaller;
|
|
169
183
|
/** Forwarded to {@link finalizeStagedInstall}; see {@link FinalizeStagedInstallParams.beforeSwap}. */
|
|
170
184
|
readonly beforeSwap?: () => Promise<void>;
|
|
185
|
+
/** Consent gate between staging and finalize; see {@link ConfirmStagedInstall}. */
|
|
186
|
+
readonly confirmStaged?: ConfirmStagedInstall;
|
|
171
187
|
}
|
|
172
188
|
|
|
173
189
|
/** Successful install result. */
|
|
@@ -214,6 +230,19 @@ export class PluginPostinstallError extends Error {
|
|
|
214
230
|
}
|
|
215
231
|
}
|
|
216
232
|
|
|
233
|
+
/**
|
|
234
|
+
* The caller's {@link ConfirmStagedInstall} gate declined the staged install.
|
|
235
|
+
* Nothing was installed and the staging directory was removed. The caller that
|
|
236
|
+
* supplied the gate owns the user-facing messaging, so this error signals the
|
|
237
|
+
* outcome rather than something to report as a failure.
|
|
238
|
+
*/
|
|
239
|
+
export class PluginInstallDeclinedError extends Error {
|
|
240
|
+
constructor(pluginName: string) {
|
|
241
|
+
super(`Install of "${pluginName}" was declined.`);
|
|
242
|
+
this.name = "PluginInstallDeclinedError";
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
217
246
|
/** A plugin with the same name is already installed and `--force` was not passed. */
|
|
218
247
|
export class PluginAlreadyInstalledError extends Error {
|
|
219
248
|
constructor(
|
|
@@ -503,6 +532,8 @@ export async function installPlugin(
|
|
|
503
532
|
throw new PluginNotFoundError(name, ref, sourceLabel(effectiveSource));
|
|
504
533
|
}
|
|
505
534
|
|
|
535
|
+
await confirmStagedOrAbort(name, stagingDir, deps.confirmStaged);
|
|
536
|
+
|
|
506
537
|
await finalizeStagedInstall(stagingDir, {
|
|
507
538
|
name,
|
|
508
539
|
source: effectiveSource,
|
|
@@ -517,6 +548,36 @@ export async function installPlugin(
|
|
|
517
548
|
return { name, target, fileCount, ref, commit, committedAt };
|
|
518
549
|
}
|
|
519
550
|
|
|
551
|
+
/**
|
|
552
|
+
* Run the caller's {@link ConfirmStagedInstall} gate over the staged tree. A
|
|
553
|
+
* decline (or a gate that throws) removes the staging directory so no partial
|
|
554
|
+
* install is left behind; a decline then surfaces as
|
|
555
|
+
* {@link PluginInstallDeclinedError}. A no-op when no gate was supplied.
|
|
556
|
+
*
|
|
557
|
+
* Shared by {@link installPlugin} and the platform-endpoint install so both
|
|
558
|
+
* abort a declined install the same way.
|
|
559
|
+
*/
|
|
560
|
+
export async function confirmStagedOrAbort(
|
|
561
|
+
name: string,
|
|
562
|
+
stagingDir: string,
|
|
563
|
+
confirmStaged: ConfirmStagedInstall | undefined,
|
|
564
|
+
): Promise<void> {
|
|
565
|
+
if (!confirmStaged) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
let confirmed = false;
|
|
569
|
+
try {
|
|
570
|
+
confirmed = await confirmStaged({ name, stagingDir });
|
|
571
|
+
} finally {
|
|
572
|
+
if (!confirmed) {
|
|
573
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (!confirmed) {
|
|
577
|
+
throw new PluginInstallDeclinedError(name);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
520
581
|
/** Inputs for {@link finalizeStagedInstall}. */
|
|
521
582
|
export interface FinalizeStagedInstallParams {
|
|
522
583
|
readonly name: string;
|
|
@@ -33,6 +33,8 @@ import { getWorkspacePluginsDir } from "../../util/platform.js";
|
|
|
33
33
|
import { APP_VERSION } from "../../version.js";
|
|
34
34
|
import type { FetchLike } from "./fetch-like.js";
|
|
35
35
|
import {
|
|
36
|
+
type ConfirmStagedInstall,
|
|
37
|
+
confirmStagedOrAbort,
|
|
36
38
|
finalizeStagedInstall,
|
|
37
39
|
type InstallPluginResult,
|
|
38
40
|
PluginAlreadyInstalledError,
|
|
@@ -123,6 +125,8 @@ export interface InstallFromPlatformDeps {
|
|
|
123
125
|
readonly maxAttempts?: number;
|
|
124
126
|
/** Sleep between retries. Injected so tests don't wait real time. */
|
|
125
127
|
readonly sleep?: (ms: number) => Promise<void>;
|
|
128
|
+
/** Consent gate between staging and finalize; see {@link ConfirmStagedInstall}. */
|
|
129
|
+
readonly confirmStaged?: ConfirmStagedInstall;
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
/** Total attempts (initial + retries) for a transient upstream status. */
|
|
@@ -194,6 +198,8 @@ export async function installPluginFromPlatform(
|
|
|
194
198
|
throw new PluginNotFoundError(name, meta.ref ?? "", meta.repo ?? name);
|
|
195
199
|
}
|
|
196
200
|
|
|
201
|
+
await confirmStagedOrAbort(name, stagingDir, deps.confirmStaged);
|
|
202
|
+
|
|
197
203
|
// Record provenance for future update/version UX. The endpoint re-roots the
|
|
198
204
|
// tarball to the plugin root, so the recorded ref is the pinned commit and
|
|
199
205
|
// the ETag documents exactly which bytes were verified.
|
|
@@ -223,7 +229,7 @@ export async function installPluginFromPlatform(
|
|
|
223
229
|
*/
|
|
224
230
|
export async function installPluginViaPlatform(
|
|
225
231
|
opts: { name: string; force?: boolean; conversationId?: string },
|
|
226
|
-
deps: { fetch: FetchLike },
|
|
232
|
+
deps: { fetch: FetchLike; confirmStaged?: ConfirmStagedInstall },
|
|
227
233
|
): Promise<InstallPluginResult> {
|
|
228
234
|
const platformBaseUrl = getPlatformBaseUrl();
|
|
229
235
|
const apiKey = await resolveAssistantApiKey();
|
|
@@ -237,7 +243,12 @@ export async function installPluginViaPlatform(
|
|
|
237
243
|
...(opts.conversationId ? { conversationId: opts.conversationId } : {}),
|
|
238
244
|
assistantVersion: APP_VERSION,
|
|
239
245
|
},
|
|
240
|
-
{
|
|
246
|
+
{
|
|
247
|
+
fetch: deps.fetch,
|
|
248
|
+
platformBaseUrl,
|
|
249
|
+
...(apiKey ? { apiKey } : {}),
|
|
250
|
+
...(deps.confirmStaged ? { confirmStaged: deps.confirmStaged } : {}),
|
|
251
|
+
},
|
|
241
252
|
);
|
|
242
253
|
}
|
|
243
254
|
|
|
@@ -10,17 +10,29 @@
|
|
|
10
10
|
* (see the external plugin loader's tool walk).
|
|
11
11
|
* - `skills/<id>/SKILL.md` → a skill owned by the plugin (see the skills
|
|
12
12
|
* catalog's `discoverPluginResidentSkills`).
|
|
13
|
+
* - `schedules/<name>/` → a declared schedule (see the daemon's plugin
|
|
14
|
+
* schedule declaration parser).
|
|
13
15
|
*
|
|
14
16
|
* This module re-derives those same sets so `plugins inspect` can report exactly
|
|
15
17
|
* what a plugin contributes. Detection is intentionally a self-contained walk of
|
|
16
|
-
* the install tree
|
|
17
|
-
* skills catalog
|
|
18
|
-
* the runtime actually loads.
|
|
18
|
+
* the install tree (`cli/lib` does not reach into the daemon-internal loader,
|
|
19
|
+
* skills catalog, or schedule parser), but it mirrors their conventions so
|
|
20
|
+
* inspect agrees with what the runtime actually loads.
|
|
19
21
|
*/
|
|
20
22
|
|
|
21
|
-
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
23
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
22
24
|
import { join } from "node:path";
|
|
23
25
|
|
|
26
|
+
/** A schedule the plugin declares under `schedules/`. */
|
|
27
|
+
export interface PluginScheduleSurface {
|
|
28
|
+
/** Schedule name: the declaration directory's name. */
|
|
29
|
+
readonly name: string;
|
|
30
|
+
/** Raw schedule `expression` string from the declaration's config. */
|
|
31
|
+
readonly cadence: string;
|
|
32
|
+
/** `execute` for a markdown prompt entrypoint, `script` for `index.sh`. */
|
|
33
|
+
readonly mode: "execute" | "script";
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
/** The surfaces an installed plugin contributes, each sorted and de-duplicated. */
|
|
25
37
|
export interface PluginSurfaces {
|
|
26
38
|
/** Skill ids shipped at `skills/<id>/SKILL.md`. */
|
|
@@ -36,6 +48,18 @@ export interface PluginSurfaces {
|
|
|
36
48
|
* importing and executing untrusted plugin code, which inspection avoids.
|
|
37
49
|
*/
|
|
38
50
|
readonly tools: readonly string[];
|
|
51
|
+
/**
|
|
52
|
+
* Schedules declared under `schedules/`, each a `<name>/` directory with a
|
|
53
|
+
* `config.json` plus exactly one `index.md` (`execute`) or `index.sh`
|
|
54
|
+
* (`script`) entrypoint. This is a display surface, not the arming path:
|
|
55
|
+
* a file directly under `schedules/` and structurally malformed directories
|
|
56
|
+
* (a bad entrypoint set, an empty prompt body, frontmatter in `index.md`, an
|
|
57
|
+
* unreadable config, a missing `expression`) are skipped rather than reported
|
|
58
|
+
* as errors. Detection stays permissive beyond structure: `expression`
|
|
59
|
+
* validity is not checked CLI-side, so a declaration whose expression the
|
|
60
|
+
* daemon rejects is still listed here.
|
|
61
|
+
*/
|
|
62
|
+
readonly schedules: readonly PluginScheduleSurface[];
|
|
39
63
|
}
|
|
40
64
|
|
|
41
65
|
/**
|
|
@@ -97,6 +121,101 @@ function listSkillIds(skillsDir: string): string[] {
|
|
|
97
121
|
return ids.sort();
|
|
98
122
|
}
|
|
99
123
|
|
|
124
|
+
/** Matches a `---` delimited YAML frontmatter block at the start of a file. */
|
|
125
|
+
const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
|
|
126
|
+
|
|
127
|
+
/** Read the raw `expression` string from a parsed schedule config, or `null`. */
|
|
128
|
+
function readConfigExpression(config: unknown): string | null {
|
|
129
|
+
if (typeof config !== "object" || config === null || Array.isArray(config)) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const expression = (config as Record<string, unknown>).expression;
|
|
133
|
+
return typeof expression === "string" && expression.trim() !== ""
|
|
134
|
+
? expression
|
|
135
|
+
: null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Read a `<name>/` directory declaration: `config.json` supplies the cadence
|
|
140
|
+
* and the single `index.md`/`index.sh` entrypoint decides the mode. `null` for
|
|
141
|
+
* anything the loader would refuse (zero or multiple `index.*` entries, an
|
|
142
|
+
* unsupported entrypoint, an `index.md` carrying frontmatter or an empty
|
|
143
|
+
* prompt body, an unreadable config, a missing expression).
|
|
144
|
+
*/
|
|
145
|
+
function readDirectorySchedule(
|
|
146
|
+
dirPath: string,
|
|
147
|
+
): { cadence: string; mode: PluginScheduleSurface["mode"] } | null {
|
|
148
|
+
let children;
|
|
149
|
+
try {
|
|
150
|
+
children = readdirSync(dirPath, { withFileTypes: true });
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const entrypoints = children
|
|
155
|
+
.filter((c) => c.isFile() && c.name.startsWith("index."))
|
|
156
|
+
.map((c) => c.name);
|
|
157
|
+
if (entrypoints.length !== 1) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
const entrypoint = entrypoints[0]!;
|
|
161
|
+
if (entrypoint !== "index.md" && entrypoint !== "index.sh") {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
if (entrypoint === "index.md") {
|
|
165
|
+
let body: string;
|
|
166
|
+
try {
|
|
167
|
+
body = readFileSync(join(dirPath, "index.md"), "utf8");
|
|
168
|
+
} catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
// Directory-form config belongs in config.json, so the loader refuses an
|
|
172
|
+
// index.md with frontmatter; it also refuses an empty prompt body.
|
|
173
|
+
if (FRONTMATTER_REGEX.test(body) || !body.trim()) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
let config: unknown;
|
|
178
|
+
try {
|
|
179
|
+
config = JSON.parse(readFileSync(join(dirPath, "config.json"), "utf8"));
|
|
180
|
+
} catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const cadence = readConfigExpression(config);
|
|
184
|
+
if (cadence === null) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
return { cadence, mode: entrypoint === "index.md" ? "execute" : "script" };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* List the schedules a plugin declares under `schedules/`, mirroring the
|
|
192
|
+
* declaration parser's directory-only form. A file directly under
|
|
193
|
+
* `schedules/` is not a declaration, so it is skipped. Returns schedules
|
|
194
|
+
* sorted by name; a missing directory yields `[]`.
|
|
195
|
+
*/
|
|
196
|
+
function listSchedules(schedulesDir: string): PluginScheduleSurface[] {
|
|
197
|
+
let entries;
|
|
198
|
+
try {
|
|
199
|
+
entries = readdirSync(schedulesDir, { withFileTypes: true });
|
|
200
|
+
} catch {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const schedules: PluginScheduleSurface[] = [];
|
|
205
|
+
for (const entry of entries) {
|
|
206
|
+
if (entry.name.startsWith(".") || !entry.isDirectory()) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const parsed = readDirectorySchedule(join(schedulesDir, entry.name));
|
|
210
|
+
if (parsed) {
|
|
211
|
+
schedules.push({ name: entry.name, ...parsed });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return schedules.sort((a, b) =>
|
|
215
|
+
a.name < b.name ? -1 : a.name > b.name ? 1 : 0,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
100
219
|
/**
|
|
101
220
|
* Detect the {@link PluginSurfaces} an installed plugin contributes by walking
|
|
102
221
|
* its install tree at `pluginDir`. Surface types with no contributions come
|
|
@@ -110,5 +229,6 @@ export function detectPluginSurfaces(pluginDir: string): PluginSurfaces {
|
|
|
110
229
|
skills: listSkillIds(join(pluginDir, "skills")),
|
|
111
230
|
hooks: listModuleBasenames(join(pluginDir, "hooks")),
|
|
112
231
|
tools: [...new Set(toolNames)].sort(),
|
|
232
|
+
schedules: listSchedules(join(pluginDir, "schedules")),
|
|
113
233
|
};
|
|
114
234
|
}
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* verbatim, with no curated adapter overlay, exactly as the original untrusted
|
|
18
18
|
* install was (see {@link directUpgrade}).
|
|
19
19
|
*
|
|
20
|
+
* Because that target is a mutable ref, taking it means running whatever
|
|
21
|
+
* upstream pushed since, which is a choice only a human should make. A caller
|
|
22
|
+
* with nobody in the loop passes `marketplaceOnly` to rule it out: the direct
|
|
23
|
+
* path then throws {@link PluginNotCuratedError} instead of advancing.
|
|
24
|
+
*
|
|
20
25
|
* This is deliberately a distinct operation from install: `install` is
|
|
21
26
|
* first-time materialization (and errors on an existing install unless
|
|
22
27
|
* `--force` is passed), whereas `upgrade` moves an existing install forward.
|
|
@@ -54,6 +59,8 @@ import {
|
|
|
54
59
|
type PluginLocalInfo,
|
|
55
60
|
} from "./inspect-plugin.js";
|
|
56
61
|
import {
|
|
62
|
+
type ConfirmStagedInstall,
|
|
63
|
+
confirmStagedOrAbort,
|
|
57
64
|
finalizeStagedInstall,
|
|
58
65
|
type GitRunner,
|
|
59
66
|
installPlugin,
|
|
@@ -112,6 +119,20 @@ export interface UpgradePluginOptions {
|
|
|
112
119
|
* {@link DEFAULT_PLUGIN_UPGRADE_STRATEGY}.
|
|
113
120
|
*/
|
|
114
121
|
readonly strategy?: PluginUpgradeStrategy;
|
|
122
|
+
/**
|
|
123
|
+
* Refuse to advance an install the marketplace does not claim, instead of
|
|
124
|
+
* falling back to {@link directUpgrade}.
|
|
125
|
+
*
|
|
126
|
+
* A direct install's upgrade target is a mutable upstream ref, so taking it
|
|
127
|
+
* means fetching and executing whatever was pushed since. Callers with
|
|
128
|
+
* nobody in the loop (the unattended auto-update sweep) set this so that
|
|
129
|
+
* outcome is impossible for them, and it is enforced here rather than by the
|
|
130
|
+
* caller's own pre-check: the catalog is fetched again inside this call, so
|
|
131
|
+
* an entry that disappears in between would otherwise silently reroute a
|
|
132
|
+
* curated upgrade into a direct one. Defaults to false, which is what an
|
|
133
|
+
* interactive `assistant plugins upgrade` wants.
|
|
134
|
+
*/
|
|
135
|
+
readonly marketplaceOnly?: boolean;
|
|
115
136
|
}
|
|
116
137
|
|
|
117
138
|
/** Dependencies injected by the caller. */
|
|
@@ -138,6 +159,14 @@ export interface UpgradePluginDeps {
|
|
|
138
159
|
* for dry runs or no-op upgrades (they never reach the swap).
|
|
139
160
|
*/
|
|
140
161
|
readonly beforeSwap?: () => Promise<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Consent gate between staging and finalize, identical to the install
|
|
164
|
+
* path's ({@link ConfirmStagedInstall}): the caller inspects the staged
|
|
165
|
+
* upgraded tree (e.g. its declared schedules) and may abort before
|
|
166
|
+
* anything replaces the live install. Applies to overwrite and merge
|
|
167
|
+
* upgrades alike; dry runs and no-ops never stage, so it is not invoked.
|
|
168
|
+
*/
|
|
169
|
+
readonly confirmStaged?: ConfirmStagedInstall;
|
|
141
170
|
}
|
|
142
171
|
|
|
143
172
|
/** Result of an upgrade attempt. */
|
|
@@ -198,6 +227,23 @@ export class PluginNotUpgradableError extends Error {
|
|
|
198
227
|
}
|
|
199
228
|
}
|
|
200
229
|
|
|
230
|
+
/**
|
|
231
|
+
* A `marketplaceOnly` upgrade was requested for an install the marketplace does
|
|
232
|
+
* not claim, so the only revision available is a mutable upstream ref the
|
|
233
|
+
* caller refuses to take.
|
|
234
|
+
*
|
|
235
|
+
* Distinct from {@link PluginNotUpgradableError}: the install *can* be
|
|
236
|
+
* upgraded, just not without a human choosing to accept unreviewed code.
|
|
237
|
+
*/
|
|
238
|
+
export class PluginNotCuratedError extends Error {
|
|
239
|
+
constructor(readonly pluginName: string) {
|
|
240
|
+
super(
|
|
241
|
+
`Plugin "${pluginName}" cannot be upgraded automatically: it has no marketplace entry, so its only upgrade target is a mutable upstream ref. Run 'assistant plugins upgrade ${pluginName}' to move it deliberately.`,
|
|
242
|
+
);
|
|
243
|
+
this.name = "PluginNotCuratedError";
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
201
247
|
/**
|
|
202
248
|
* A merge strategy (`ours`/`theirs`) was requested but the install-time
|
|
203
249
|
* baseline needed for a three-way merge cannot be reconstructed.
|
|
@@ -234,6 +280,8 @@ function pluginTarget(name: string, deps: UpgradePluginDeps): string {
|
|
|
234
280
|
* Throws {@link PluginNotInstalledError} when no copy is installed,
|
|
235
281
|
* {@link PluginNotUpgradableError} when the install is neither in the
|
|
236
282
|
* marketplace nor carries a recorded GitHub source to advance,
|
|
283
|
+
* {@link PluginNotCuratedError} when `marketplaceOnly` was requested for an
|
|
284
|
+
* install the marketplace does not claim,
|
|
237
285
|
* {@link PluginMergeBaselineError} when a merge strategy is requested but the
|
|
238
286
|
* install-time baseline cannot be reconstructed,
|
|
239
287
|
* {@link PluginSourceUnavailableError} when the marketplace catalog or the
|
|
@@ -292,6 +340,10 @@ export async function upgradePlugin(
|
|
|
292
340
|
"it has no marketplace entry and no installed copy to upgrade",
|
|
293
341
|
);
|
|
294
342
|
}
|
|
343
|
+
if (opts.marketplaceOnly) {
|
|
344
|
+
// The caller only accepts a curated pin, and this install has none.
|
|
345
|
+
throw new PluginNotCuratedError(name);
|
|
346
|
+
}
|
|
295
347
|
return directUpgrade({ name, local, dryRun, strategy }, deps);
|
|
296
348
|
}
|
|
297
349
|
case "remote-unavailable":
|
|
@@ -401,6 +453,7 @@ export async function upgradePlugin(
|
|
|
401
453
|
runPostinstall: deps.runPostinstall,
|
|
402
454
|
runInstallDeps: deps.runInstallDeps,
|
|
403
455
|
beforeSwap: deps.beforeSwap,
|
|
456
|
+
confirmStaged: deps.confirmStaged,
|
|
404
457
|
},
|
|
405
458
|
);
|
|
406
459
|
|
|
@@ -591,6 +644,7 @@ async function directUpgrade(
|
|
|
591
644
|
runPostinstall: deps.runPostinstall,
|
|
592
645
|
runInstallDeps: deps.runInstallDeps,
|
|
593
646
|
beforeSwap: deps.beforeSwap,
|
|
647
|
+
confirmStaged: deps.confirmStaged,
|
|
594
648
|
},
|
|
595
649
|
);
|
|
596
650
|
|
|
@@ -747,6 +801,12 @@ async function mergeUpgrade(
|
|
|
747
801
|
conflictLabels,
|
|
748
802
|
});
|
|
749
803
|
|
|
804
|
+
// Same staging-to-finalize consent boundary as `installPlugin`: the
|
|
805
|
+
// caller sees the fully merged tree before it replaces the live install.
|
|
806
|
+
// A decline removes the staging dir and throws; the outer catch's rmSync
|
|
807
|
+
// is then a no-op.
|
|
808
|
+
await confirmStagedOrAbort(name, stagingDir, deps.confirmStaged);
|
|
809
|
+
|
|
750
810
|
const toCommit = theirs.commit ?? ctx.toCommit;
|
|
751
811
|
const toTimestamp = theirs.committedAt ?? ctx.toTimestamp;
|
|
752
812
|
await finalizeStagedInstall(stagingDir, {
|
package/src/cli.ts
CHANGED
|
@@ -513,7 +513,7 @@ export async function startCli(): Promise<void> {
|
|
|
513
513
|
if (content === "/conversations") {
|
|
514
514
|
pendingSessionPick = true;
|
|
515
515
|
try {
|
|
516
|
-
const rows = listConversations(20);
|
|
516
|
+
const rows = listConversations({ limit: 20 });
|
|
517
517
|
const conversations = rows.map((r) => ({
|
|
518
518
|
id: r.id,
|
|
519
519
|
title: r.title || "Untitled",
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
type DefaultProviderConfig,
|
|
24
24
|
type LLMCallSite,
|
|
25
|
+
LLMCallSiteEnum,
|
|
25
26
|
LLMSchema,
|
|
26
27
|
type ProfileEntry,
|
|
27
28
|
} from "../schemas/llm.js";
|
|
@@ -245,7 +246,10 @@ describe("resolver integration", () => {
|
|
|
245
246
|
},
|
|
246
247
|
});
|
|
247
248
|
const body = CODE_DEFAULT_PROFILE_ENTRIES["latency-optimized"]!;
|
|
248
|
-
for (const callSite of [
|
|
249
|
+
for (const callSite of [
|
|
250
|
+
"voiceFrontDoor",
|
|
251
|
+
"voiceProgressNarration",
|
|
252
|
+
] as const) {
|
|
249
253
|
const resolved = resolveCallSiteConfig(callSite, llm);
|
|
250
254
|
expect(resolved.model).toBe(body.model as string);
|
|
251
255
|
expect(resolved.model).not.toBe("claude-opus-4-6");
|
|
@@ -265,6 +269,12 @@ describe("resolver integration", () => {
|
|
|
265
269
|
});
|
|
266
270
|
|
|
267
271
|
describe("schema validation", () => {
|
|
272
|
+
test("voiceFrontDoor is the only front callsite", () => {
|
|
273
|
+
expect(
|
|
274
|
+
LLMCallSiteEnum.options.filter((callSite) => callSite.includes("Front")),
|
|
275
|
+
).toEqual(["voiceFrontDoor"]);
|
|
276
|
+
});
|
|
277
|
+
|
|
268
278
|
test("always-available default names are valid references; os-beta only when materialized", () => {
|
|
269
279
|
expect(() => LLMSchema.parse({ activeProfile: "balanced" })).not.toThrow();
|
|
270
280
|
expect(() =>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
existsSync,
|
|
3
3
|
mkdirSync,
|
|
4
|
+
readdirSync,
|
|
4
5
|
readFileSync,
|
|
5
6
|
rmSync,
|
|
6
7
|
writeFileSync,
|
|
@@ -267,4 +268,76 @@ describe("deployment-context embedding-provider default (via loadConfig)", () =>
|
|
|
267
268
|
>;
|
|
268
269
|
expect(v3Raw.live).toBe(true);
|
|
269
270
|
});
|
|
271
|
+
|
|
272
|
+
describe("quarantine-reseed carries memory.v3.live forward", () => {
|
|
273
|
+
function removeQuarantineFiles(): void {
|
|
274
|
+
for (const name of readdirSync(WORKSPACE_DIR)) {
|
|
275
|
+
if (name.startsWith("config.json.corrupt-")) {
|
|
276
|
+
rmSync(join(WORKSPACE_DIR, name), { force: true });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function readV3Raw(): Record<string, unknown> {
|
|
282
|
+
const raw = readConfig();
|
|
283
|
+
return ((raw.memory as Record<string, unknown>).v3 ?? {}) as Record<
|
|
284
|
+
string,
|
|
285
|
+
unknown
|
|
286
|
+
>;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
afterEach(() => {
|
|
290
|
+
removeQuarantineFiles();
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test("a corrupt live-v3 config is quarantined and the reseed keeps live=true", () => {
|
|
294
|
+
// Truncated mid-write JSON from a memory-v3 assistant: unparseable,
|
|
295
|
+
// but the live flag survives in the raw text.
|
|
296
|
+
writeFileSync(
|
|
297
|
+
CONFIG_PATH,
|
|
298
|
+
`{\n "memory": {\n "v3": {\n "live": true\n }\n },\n "llm": {\n "activeProf`,
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
const config = loadConfig();
|
|
302
|
+
|
|
303
|
+
// The corrupt file was quarantined and the reseeded config carries the
|
|
304
|
+
// tier forward, both in-memory (this boot runs v3) and on disk
|
|
305
|
+
// (migration 105 is checkpointed on existing workspaces and never
|
|
306
|
+
// re-runs, so the persisted value is the only durable record).
|
|
307
|
+
expect(config.memory.v3.live).toBe(true);
|
|
308
|
+
expect(readV3Raw()).toEqual({ live: true });
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("a corrupt config without live=true reseeds with the leaf absent", () => {
|
|
312
|
+
writeFileSync(
|
|
313
|
+
CONFIG_PATH,
|
|
314
|
+
`{\n "memory": {\n "v3": {\n "live": false\n }\n },\n "llm": {\n "activeProf`,
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const config = loadConfig();
|
|
318
|
+
|
|
319
|
+
// Never carry `false` forward: an absent leaf is the only way to keep
|
|
320
|
+
// "no decision recorded" representable for migration 105.
|
|
321
|
+
expect(config.memory.v3.live).toBe(false);
|
|
322
|
+
expect(readV3Raw()).toEqual({});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
test("a deleted config with an earlier live-v3 quarantine still carries live=true", () => {
|
|
326
|
+
if (existsSync(CONFIG_PATH)) {
|
|
327
|
+
rmSync(CONFIG_PATH, { force: true });
|
|
328
|
+
}
|
|
329
|
+
writeFileSync(
|
|
330
|
+
join(
|
|
331
|
+
WORKSPACE_DIR,
|
|
332
|
+
"config.json.corrupt-2026-08-01T10-00-00.000Z.json",
|
|
333
|
+
),
|
|
334
|
+
JSON.stringify({ memory: { v3: { live: true } } }, null, 2),
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
const config = loadConfig();
|
|
338
|
+
|
|
339
|
+
expect(config.memory.v3.live).toBe(true);
|
|
340
|
+
expect(readV3Raw()).toEqual({ live: true });
|
|
341
|
+
});
|
|
342
|
+
});
|
|
270
343
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards over the `memory.retrospective` switches that decide whether the
|
|
3
|
+
* retrospective pass runs at all, and how its fork is materialized.
|
|
4
|
+
*
|
|
5
|
+
* The defaults are the contract: a workspace that says nothing must behave
|
|
6
|
+
* exactly as it did before the fields existed: retrospectives on, forks
|
|
7
|
+
* cloned.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
import { MemoryRetrospectiveConfigSchema } from "../schemas/memory-retrospective.js";
|
|
13
|
+
|
|
14
|
+
describe("memory.retrospective config schema", () => {
|
|
15
|
+
test("an empty block leaves retrospectives on and forks cloning", () => {
|
|
16
|
+
const parsed = MemoryRetrospectiveConfigSchema.parse({});
|
|
17
|
+
expect(parsed.enabled).toBe(true);
|
|
18
|
+
expect(parsed.forkStrategy).toBe("cloning");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("enabled is a boolean-only kill switch", () => {
|
|
22
|
+
expect(
|
|
23
|
+
MemoryRetrospectiveConfigSchema.parse({ enabled: false }).enabled,
|
|
24
|
+
).toBe(false);
|
|
25
|
+
expect(
|
|
26
|
+
MemoryRetrospectiveConfigSchema.safeParse({ enabled: "false" }).success,
|
|
27
|
+
).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("forkStrategy accepts only cloning and reference", () => {
|
|
31
|
+
expect(
|
|
32
|
+
MemoryRetrospectiveConfigSchema.parse({ forkStrategy: "reference" })
|
|
33
|
+
.forkStrategy,
|
|
34
|
+
).toBe("reference");
|
|
35
|
+
expect(
|
|
36
|
+
MemoryRetrospectiveConfigSchema.safeParse({ forkStrategy: "referential" })
|
|
37
|
+
.success,
|
|
38
|
+
).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards over the `pluginUpdates` config block — the opt-in that decides
|
|
3
|
+
* whether installed plugins move on their own.
|
|
4
|
+
*
|
|
5
|
+
* The defaults are the contract: a workspace that says nothing must behave
|
|
6
|
+
* exactly as it did before the block existed (manual, nothing upgrades), and
|
|
7
|
+
* an opted-in workspace must land on the `theirs` merge strategy.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
import { PluginUpdatesConfigSchema } from "../schemas/plugin-updates.js";
|
|
13
|
+
|
|
14
|
+
describe("pluginUpdates config schema", () => {
|
|
15
|
+
test("defaults are manual / theirs / hourly", () => {
|
|
16
|
+
expect(PluginUpdatesConfigSchema.parse({})).toEqual({
|
|
17
|
+
mode: "manual",
|
|
18
|
+
strategy: "theirs",
|
|
19
|
+
checkIntervalMs: 3_600_000,
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("mode accepts only manual and auto", () => {
|
|
24
|
+
expect(PluginUpdatesConfigSchema.parse({ mode: "auto" }).mode).toBe("auto");
|
|
25
|
+
expect(
|
|
26
|
+
PluginUpdatesConfigSchema.safeParse({ mode: "sometimes" }).success,
|
|
27
|
+
).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("the unattended-hostile `assistant` strategy is not selectable", () => {
|
|
31
|
+
// It resolves conflicts by writing git conflict markers into the plugin's
|
|
32
|
+
// files, which unattended would leave broken code on disk.
|
|
33
|
+
expect(
|
|
34
|
+
PluginUpdatesConfigSchema.safeParse({ strategy: "assistant" }).success,
|
|
35
|
+
).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("sub-5-minute sweep intervals are rejected", () => {
|
|
39
|
+
expect(
|
|
40
|
+
PluginUpdatesConfigSchema.safeParse({ checkIntervalMs: 1_000 }).success,
|
|
41
|
+
).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
});
|