@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
|
@@ -291,9 +291,26 @@ describe("serializeProviderSummary", () => {
|
|
|
291
291
|
supports_managed_mode: true,
|
|
292
292
|
managed_service_is_paid: false,
|
|
293
293
|
feature_flag: null,
|
|
294
|
+
acts_as: "user",
|
|
294
295
|
});
|
|
295
296
|
});
|
|
296
297
|
|
|
298
|
+
test("names which sense of connected a provider represents", () => {
|
|
299
|
+
// The provider key does not say, and the naming actively misleads:
|
|
300
|
+
// `slack` is the user integration while its bot is `slack_channel`, but
|
|
301
|
+
// `telegram` is itself the bot. A caller asking "is X connected?" needs
|
|
302
|
+
// this to answer which X it found.
|
|
303
|
+
const sense = (provider: string) =>
|
|
304
|
+
serializeProviderSummary(makeRow({ provider }))!.acts_as;
|
|
305
|
+
|
|
306
|
+
expect(sense("slack")).toBe("user");
|
|
307
|
+
expect(sense("slack_channel")).toBe("assistant");
|
|
308
|
+
expect(sense("discord")).toBe("user");
|
|
309
|
+
expect(sense("discord_channel")).toBe("assistant");
|
|
310
|
+
expect(sense("telegram")).toBe("assistant");
|
|
311
|
+
expect(sense("google")).toBe("user");
|
|
312
|
+
});
|
|
313
|
+
|
|
297
314
|
test("nullifies missing optional fields", () => {
|
|
298
315
|
const row = makeRow({
|
|
299
316
|
displayLabel: null,
|
|
@@ -238,16 +238,19 @@ describe("OpenAIResponsesProvider explicit prompt caching (GPT-5.6+)", () => {
|
|
|
238
238
|
expect(breakpointedItemIndexes()).toEqual([0, 2]);
|
|
239
239
|
});
|
|
240
240
|
|
|
241
|
-
test("volatile single-message first turn:
|
|
241
|
+
test("volatile single-message first turn: the sole item is still marked", async () => {
|
|
242
242
|
const provider = makeProvider("gpt-5.6-sol");
|
|
243
243
|
await provider.sendMessage([userMsg("hi")], {
|
|
244
244
|
config: { mutableLatestUserMessage: true, promptCacheKey: "conv-1" },
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
+
// A volatile message is fixed within its own turn, so marking it prepays
|
|
248
|
+
// one write that the turn's tool-loop iterations read back, covering the
|
|
249
|
+
// instructions and tools that precede it in the cached prefix.
|
|
247
250
|
expect(lastStreamParams?.prompt_cache_options).toEqual({
|
|
248
251
|
mode: "explicit",
|
|
249
252
|
});
|
|
250
|
-
expect(breakpointedItemIndexes()).toEqual([]);
|
|
253
|
+
expect(breakpointedItemIndexes()).toEqual([0]);
|
|
251
254
|
});
|
|
252
255
|
|
|
253
256
|
test("tool loop: single fixed anchor on the turn-start user item, none on function_call_output", async () => {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
resolveRealPath,
|
|
16
16
|
sandboxPolicy,
|
|
17
17
|
sandboxPolicyWithHostFallback,
|
|
18
|
+
sandboxReadPolicy,
|
|
18
19
|
} from "../tools/shared/filesystem/path-policy.js";
|
|
19
20
|
import { getDotEnvPath } from "../util/platform.js";
|
|
20
21
|
|
|
@@ -506,6 +507,162 @@ describe("sandboxPolicyWithHostFallback", () => {
|
|
|
506
507
|
});
|
|
507
508
|
});
|
|
508
509
|
|
|
510
|
+
// ---------------------------------------------------------------------------
|
|
511
|
+
// Sandbox read policy
|
|
512
|
+
// ---------------------------------------------------------------------------
|
|
513
|
+
|
|
514
|
+
describe("sandboxReadPolicy", () => {
|
|
515
|
+
afterEach(() => {
|
|
516
|
+
delete process.env.IS_CONTAINERIZED;
|
|
517
|
+
delete process.env.GATEWAY_SECURITY_DIR;
|
|
518
|
+
delete process.env.CREDENTIAL_SECURITY_DIR;
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
test("matches sandboxPolicy for in-bounds paths", () => {
|
|
522
|
+
const boundary = makeTempDir();
|
|
523
|
+
mkdirSync(join(boundary, "sub"));
|
|
524
|
+
|
|
525
|
+
const result = sandboxReadPolicy("sub/file.txt", boundary);
|
|
526
|
+
expect(result).toEqual(sandboxPolicy("sub/file.txt", boundary));
|
|
527
|
+
expect(result.ok).toBe(true);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
test("reads outside the boundary when containerized", () => {
|
|
531
|
+
const boundary = makeTempDir();
|
|
532
|
+
const installTree = makeTempDir();
|
|
533
|
+
const target = join(installTree, "SKILL.md");
|
|
534
|
+
writeFileSync(target, "# skill");
|
|
535
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
536
|
+
|
|
537
|
+
const result = sandboxReadPolicy(target, boundary);
|
|
538
|
+
expect(result.ok).toBe(true);
|
|
539
|
+
if (result.ok) {
|
|
540
|
+
expect(result.resolved).toBe(target);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
test("follows an in-boundary symlink that points outside", () => {
|
|
545
|
+
const boundary = makeTempDir();
|
|
546
|
+
const outside = makeTempDir();
|
|
547
|
+
const target = join(outside, "reference.md");
|
|
548
|
+
writeFileSync(target, "reference body");
|
|
549
|
+
symlinkSync(target, join(boundary, "link.md"));
|
|
550
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
551
|
+
|
|
552
|
+
const result = sandboxReadPolicy(join(boundary, "link.md"), boundary);
|
|
553
|
+
expect(result.ok).toBe(true);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
test("denies the gateway security dir when containerized", () => {
|
|
557
|
+
const boundary = makeTempDir();
|
|
558
|
+
const securityDir = makeTempDir();
|
|
559
|
+
writeFileSync(join(securityDir, "trust.json"), "{}");
|
|
560
|
+
process.env.GATEWAY_SECURITY_DIR = securityDir;
|
|
561
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
562
|
+
|
|
563
|
+
const result = sandboxReadPolicy(join(securityDir, "trust.json"), boundary);
|
|
564
|
+
expect(result.ok).toBe(false);
|
|
565
|
+
if (!result.ok) {
|
|
566
|
+
expect(result.reason).toBe("denied");
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
test("denies a symlink that resolves into the credential security dir", () => {
|
|
571
|
+
const boundary = makeTempDir();
|
|
572
|
+
const securityDir = makeTempDir();
|
|
573
|
+
writeFileSync(join(securityDir, "keys.enc"), "cipher");
|
|
574
|
+
symlinkSync(join(securityDir, "keys.enc"), join(boundary, "innocent.txt"));
|
|
575
|
+
process.env.CREDENTIAL_SECURITY_DIR = securityDir;
|
|
576
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
577
|
+
|
|
578
|
+
const result = sandboxReadPolicy(join(boundary, "innocent.txt"), boundary);
|
|
579
|
+
expect(result.ok).toBe(false);
|
|
580
|
+
if (!result.ok) {
|
|
581
|
+
expect(result.reason).toBe("denied");
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
test("denies a denylisted basename outside the boundary", () => {
|
|
586
|
+
const boundary = makeTempDir();
|
|
587
|
+
const outside = makeTempDir();
|
|
588
|
+
writeFileSync(join(outside, "backup.key"), "key");
|
|
589
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
590
|
+
|
|
591
|
+
const result = sandboxReadPolicy(join(outside, "backup.key"), boundary);
|
|
592
|
+
expect(result.ok).toBe(false);
|
|
593
|
+
if (!result.ok) {
|
|
594
|
+
expect(result.reason).toBe("denied");
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
test("fails closed to the hard boundary when a security-dir override is relative", () => {
|
|
599
|
+
const boundary = makeTempDir();
|
|
600
|
+
const outside = makeTempDir();
|
|
601
|
+
writeFileSync(join(outside, "file.txt"), "x");
|
|
602
|
+
// Unmirrorable deny set: the real security dir could be anywhere, so the
|
|
603
|
+
// read allowance must not widen past the boundary.
|
|
604
|
+
process.env.GATEWAY_SECURITY_DIR = "relative/security-dir";
|
|
605
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
606
|
+
|
|
607
|
+
const result = sandboxReadPolicy(join(outside, "file.txt"), boundary);
|
|
608
|
+
expect(result.ok).toBe(false);
|
|
609
|
+
if (!result.ok) {
|
|
610
|
+
expect(result.reason).toBe("out_of_bounds");
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// The daemon's own environment carries the actor token signing key, the CES
|
|
615
|
+
// service token, the guardian bootstrap secret, and forwarded provider API
|
|
616
|
+
// keys, so no policy may serve a process environment block.
|
|
617
|
+
test.each([
|
|
618
|
+
"/proc/self/environ",
|
|
619
|
+
"/proc/thread-self/environ",
|
|
620
|
+
"/proc/1/environ",
|
|
621
|
+
"/proc/4242/environ",
|
|
622
|
+
])("denies %s", (path) => {
|
|
623
|
+
const boundary = makeTempDir();
|
|
624
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
625
|
+
|
|
626
|
+
const result = sandboxReadPolicy(path, boundary, { mustExist: false });
|
|
627
|
+
expect(result.ok).toBe(false);
|
|
628
|
+
if (!result.ok) {
|
|
629
|
+
expect(result.reason).toBe("denied");
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
test("denies a process environ path reached through a symlink", () => {
|
|
634
|
+
const boundary = makeTempDir();
|
|
635
|
+
symlinkSync("/proc/self/environ", join(boundary, "innocent.txt"));
|
|
636
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
637
|
+
|
|
638
|
+
const result = sandboxReadPolicy(join(boundary, "innocent.txt"), boundary, {
|
|
639
|
+
mustExist: false,
|
|
640
|
+
});
|
|
641
|
+
expect(result.ok).toBe(false);
|
|
642
|
+
if (!result.ok) {
|
|
643
|
+
expect(result.reason).toBe("denied");
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
test("still allows other /proc entries", () => {
|
|
648
|
+
const boundary = makeTempDir();
|
|
649
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
650
|
+
|
|
651
|
+
const result = sandboxReadPolicy("/proc/self/status", boundary, {
|
|
652
|
+
mustExist: false,
|
|
653
|
+
});
|
|
654
|
+
expect(result.ok).toBe(true);
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
test("does not deny an unrelated file named environ", () => {
|
|
658
|
+
const boundary = makeTempDir();
|
|
659
|
+
writeFileSync(join(boundary, "environ"), "notes");
|
|
660
|
+
|
|
661
|
+
const result = sandboxReadPolicy("environ", boundary);
|
|
662
|
+
expect(result.ok).toBe(true);
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
|
|
509
666
|
// ---------------------------------------------------------------------------
|
|
510
667
|
// Host policy
|
|
511
668
|
// ---------------------------------------------------------------------------
|
|
@@ -575,7 +732,13 @@ describe("resolveRealPath", () => {
|
|
|
575
732
|
});
|
|
576
733
|
|
|
577
734
|
test("falls back to the lexical path when nothing on it exists", () => {
|
|
578
|
-
|
|
735
|
+
// realpath the temp root so a symlinked prefix (macOS /var -> /private/var)
|
|
736
|
+
// is not mistaken for the resolution under test.
|
|
737
|
+
const phantom = join(
|
|
738
|
+
realpathSync(tmpdir()),
|
|
739
|
+
"definitely-not-here-12345",
|
|
740
|
+
"nope.txt",
|
|
741
|
+
);
|
|
579
742
|
expect(resolveRealPath(phantom)).toBe(phantom);
|
|
580
743
|
});
|
|
581
744
|
});
|
|
@@ -49,7 +49,7 @@ describe("referenceMediaBlocksForPersist", () => {
|
|
|
49
49
|
},
|
|
50
50
|
];
|
|
51
51
|
|
|
52
|
-
const referenced = referenceMediaBlocksForPersist(
|
|
52
|
+
const referenced = await referenceMediaBlocksForPersist(
|
|
53
53
|
conv.id,
|
|
54
54
|
conv.createdAt,
|
|
55
55
|
msg.id,
|
|
@@ -101,7 +101,7 @@ describe("referenceMediaBlocksForPersist", () => {
|
|
|
101
101
|
},
|
|
102
102
|
];
|
|
103
103
|
|
|
104
|
-
const referenced = referenceMediaBlocksForPersist(
|
|
104
|
+
const referenced = await referenceMediaBlocksForPersist(
|
|
105
105
|
conv.id,
|
|
106
106
|
conv.createdAt,
|
|
107
107
|
msg.id,
|
|
@@ -28,8 +28,8 @@ mock.module("../agent/image-optimize.js", () => ({
|
|
|
28
28
|
// oversized (never undersized), so the min-dimension gate never matches
|
|
29
29
|
// and the rejection-path upscale is never reached.
|
|
30
30
|
isBelowMinDimension: () => false,
|
|
31
|
-
upscaleImageToMinimum: () => null,
|
|
32
|
-
optimizeImageForTransport: () => ({
|
|
31
|
+
upscaleImageToMinimum: async () => null,
|
|
32
|
+
optimizeImageForTransport: async () => ({
|
|
33
33
|
data: SHRUNK_DATA,
|
|
34
34
|
mediaType: "image/jpeg",
|
|
35
35
|
}),
|
|
@@ -133,7 +133,7 @@ describe("persistUnsendableImageDowngrades (downscalable host)", () => {
|
|
|
133
133
|
);
|
|
134
134
|
|
|
135
135
|
// WHEN the downgrade is persisted
|
|
136
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
136
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
137
137
|
|
|
138
138
|
// THEN the nested block stays an image, rewritten to the downscaled payload
|
|
139
139
|
expect(rewritten).toBe(1);
|
|
@@ -159,10 +159,10 @@ describe("persistUnsendableImageDowngrades (downscalable host)", () => {
|
|
|
159
159
|
JSON.stringify([toolResultWithImage(oversizedPngBase64())]),
|
|
160
160
|
{ skipIndexing: true },
|
|
161
161
|
);
|
|
162
|
-
expect(persistUnsendableImageDowngrades(conv.id)).toBe(1);
|
|
162
|
+
expect(await persistUnsendableImageDowngrades(conv.id)).toBe(1);
|
|
163
163
|
|
|
164
164
|
// WHEN the downgrade runs again
|
|
165
|
-
const secondRun = persistUnsendableImageDowngrades(conv.id);
|
|
165
|
+
const secondRun = await persistUnsendableImageDowngrades(conv.id);
|
|
166
166
|
|
|
167
167
|
// THEN nothing further is rewritten
|
|
168
168
|
expect(secondRun).toBe(0);
|
|
@@ -132,7 +132,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
132
132
|
);
|
|
133
133
|
|
|
134
134
|
// WHEN the downgrade is persisted
|
|
135
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
135
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
136
136
|
|
|
137
137
|
// THEN one message is rewritten with no image block left
|
|
138
138
|
expect(rewritten).toBe(1);
|
|
@@ -162,7 +162,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
162
162
|
);
|
|
163
163
|
|
|
164
164
|
// WHEN the downgrade is persisted
|
|
165
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
165
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
166
166
|
|
|
167
167
|
// THEN only the rejected original is removed
|
|
168
168
|
expect(rewritten).toBe(1);
|
|
@@ -184,7 +184,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
184
184
|
);
|
|
185
185
|
|
|
186
186
|
// WHEN the downgrade is persisted
|
|
187
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
187
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
188
188
|
|
|
189
189
|
// THEN nothing is rewritten and the image remains
|
|
190
190
|
expect(rewritten).toBe(0);
|
|
@@ -202,7 +202,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
202
202
|
});
|
|
203
203
|
|
|
204
204
|
// WHEN the downgrade is persisted
|
|
205
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
205
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
206
206
|
|
|
207
207
|
// THEN the oversized-payload image is removed
|
|
208
208
|
expect(rewritten).toBe(1);
|
|
@@ -224,7 +224,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
224
224
|
);
|
|
225
225
|
|
|
226
226
|
// WHEN the downgrade is persisted
|
|
227
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
227
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
228
228
|
|
|
229
229
|
// THEN the undersized image is removed (upscale is a no-op on this host)
|
|
230
230
|
expect(rewritten).toBe(1);
|
|
@@ -248,7 +248,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
248
248
|
);
|
|
249
249
|
|
|
250
250
|
// WHEN the downgrade is persisted
|
|
251
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
251
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
252
252
|
|
|
253
253
|
// THEN the message is rewritten with the nested image swapped for a note
|
|
254
254
|
expect(rewritten).toBe(1);
|
|
@@ -274,7 +274,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
274
274
|
);
|
|
275
275
|
|
|
276
276
|
// WHEN the downgrade is persisted
|
|
277
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
277
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
278
278
|
|
|
279
279
|
// THEN nothing is rewritten and the nested image remains
|
|
280
280
|
expect(rewritten).toBe(0);
|
|
@@ -302,7 +302,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
302
302
|
);
|
|
303
303
|
|
|
304
304
|
// WHEN the downgrade is persisted
|
|
305
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
305
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
306
306
|
|
|
307
307
|
// THEN the image survives with its media type corrected to the sniffed one
|
|
308
308
|
expect(rewritten).toBe(1);
|
|
@@ -319,7 +319,7 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
319
319
|
});
|
|
320
320
|
|
|
321
321
|
// AND a second run is a no-op (the corrected block no longer mismatches)
|
|
322
|
-
expect(persistUnsendableImageDowngrades(conv.id)).toBe(0);
|
|
322
|
+
expect(await persistUnsendableImageDowngrades(conv.id)).toBe(0);
|
|
323
323
|
});
|
|
324
324
|
|
|
325
325
|
/** Re-running after a rewrite is a safe no-op (no image blocks remain). */
|
|
@@ -332,10 +332,10 @@ describe("persistUnsendableImageDowngrades", () => {
|
|
|
332
332
|
JSON.stringify([imageBlock(makePngBase64(10000, 10000))]),
|
|
333
333
|
{ skipIndexing: true },
|
|
334
334
|
);
|
|
335
|
-
expect(persistUnsendableImageDowngrades(conv.id)).toBe(1);
|
|
335
|
+
expect(await persistUnsendableImageDowngrades(conv.id)).toBe(1);
|
|
336
336
|
|
|
337
337
|
// WHEN the downgrade runs a second time
|
|
338
|
-
const secondRun = persistUnsendableImageDowngrades(conv.id);
|
|
338
|
+
const secondRun = await persistUnsendableImageDowngrades(conv.id);
|
|
339
339
|
|
|
340
340
|
// THEN nothing further is rewritten
|
|
341
341
|
expect(secondRun).toBe(0);
|
|
@@ -346,46 +346,46 @@ describe("unsendableImageReplacement", () => {
|
|
|
346
346
|
/** A still-sendable image must be left alone — never replaced with a note.
|
|
347
347
|
* This is the gate that keeps the in-memory recovery from discarding valid
|
|
348
348
|
* screenshots when only one image in the turn was actually oversized. */
|
|
349
|
-
test("returns null for an image within the provider caps", () => {
|
|
349
|
+
test("returns null for an image within the provider caps", async () => {
|
|
350
350
|
const sendable = imageBlock(makePngBase64(1024, 768)) as Extract<
|
|
351
351
|
ContentBlock,
|
|
352
352
|
{ type: "image" }
|
|
353
353
|
>;
|
|
354
|
-
expect(unsendableImageReplacement(sendable)).toBeNull();
|
|
354
|
+
expect(await unsendableImageReplacement(sendable)).toBeNull();
|
|
355
355
|
});
|
|
356
356
|
|
|
357
357
|
/** An image past the provider caps that cannot be shrunk on this host (fake
|
|
358
358
|
* PNG that sips cannot decode) collapses to the unsendable note. */
|
|
359
|
-
test("returns the unsendable note when an oversized image cannot be shrunk", () => {
|
|
359
|
+
test("returns the unsendable note when an oversized image cannot be shrunk", async () => {
|
|
360
360
|
const oversized = imageBlock(makePngBase64(12000, 9000)) as Extract<
|
|
361
361
|
ContentBlock,
|
|
362
362
|
{ type: "image" }
|
|
363
363
|
>;
|
|
364
|
-
const replacement = unsendableImageReplacement(oversized);
|
|
364
|
+
const replacement = await unsendableImageReplacement(oversized);
|
|
365
365
|
expect(replacement?.type).toBe("text");
|
|
366
366
|
});
|
|
367
367
|
|
|
368
368
|
/** An image below the provider's minimum-size floor (rejected with "Could
|
|
369
369
|
* not process image") that cannot be upscaled on this host collapses to
|
|
370
370
|
* the unsendable note, same as the oversized direction. */
|
|
371
|
-
test("returns the unsendable note when an undersized image cannot be upscaled", () => {
|
|
371
|
+
test("returns the unsendable note when an undersized image cannot be upscaled", async () => {
|
|
372
372
|
const undersized = imageBlock(makePngBase64(16, 14)) as Extract<
|
|
373
373
|
ContentBlock,
|
|
374
374
|
{ type: "image" }
|
|
375
375
|
>;
|
|
376
|
-
const replacement = unsendableImageReplacement(undersized);
|
|
376
|
+
const replacement = await unsendableImageReplacement(undersized);
|
|
377
377
|
expect(replacement?.type).toBe("text");
|
|
378
378
|
});
|
|
379
379
|
|
|
380
380
|
/** A within-limits image whose declared media type disagrees with its bytes
|
|
381
381
|
* is relabeled with the sniffed type instead of being noted out. */
|
|
382
|
-
test("relabels a mislabeled image with its sniffed media type", () => {
|
|
382
|
+
test("relabels a mislabeled image with its sniffed media type", async () => {
|
|
383
383
|
const pngData = makePngBase64(1024, 768);
|
|
384
384
|
const mislabeled = imageBlock(pngData, "image/jpeg") as Extract<
|
|
385
385
|
ContentBlock,
|
|
386
386
|
{ type: "image" }
|
|
387
387
|
>;
|
|
388
|
-
const replacement = unsendableImageReplacement(mislabeled);
|
|
388
|
+
const replacement = await unsendableImageReplacement(mislabeled);
|
|
389
389
|
expect(replacement).toMatchObject({
|
|
390
390
|
type: "image",
|
|
391
391
|
source: { type: "base64", media_type: "image/png", data: pngData },
|
|
@@ -394,9 +394,9 @@ describe("unsendableImageReplacement", () => {
|
|
|
394
394
|
|
|
395
395
|
/** Relabeling a persisted (workspace_ref) image keeps the reference shape —
|
|
396
396
|
* inlining it would bake the full payload into the stored message row. */
|
|
397
|
-
test("relabels a mislabeled workspace_ref without inlining the payload", () => {
|
|
397
|
+
test("relabels a mislabeled workspace_ref without inlining the payload", async () => {
|
|
398
398
|
const pngData = makePngBase64(1024, 768);
|
|
399
|
-
const stored = uploadAttachment("photo.png", "image/png", pngData);
|
|
399
|
+
const stored = await uploadAttachment("photo.png", "image/png", pngData);
|
|
400
400
|
const mislabeledRef = {
|
|
401
401
|
type: "image",
|
|
402
402
|
source: {
|
|
@@ -407,7 +407,7 @@ describe("unsendableImageReplacement", () => {
|
|
|
407
407
|
},
|
|
408
408
|
} as Extract<ContentBlock, { type: "image" }>;
|
|
409
409
|
|
|
410
|
-
const replacement = unsendableImageReplacement(mislabeledRef);
|
|
410
|
+
const replacement = await unsendableImageReplacement(mislabeledRef);
|
|
411
411
|
|
|
412
412
|
expect(replacement).toMatchObject({
|
|
413
413
|
type: "image",
|
|
@@ -419,7 +419,7 @@ describe("unsendableImageReplacement", () => {
|
|
|
419
419
|
});
|
|
420
420
|
// AND the corrected reference no longer matches on a second pass
|
|
421
421
|
expect(
|
|
422
|
-
unsendableImageReplacement(
|
|
422
|
+
await unsendableImageReplacement(
|
|
423
423
|
replacement as Extract<ContentBlock, { type: "image" }>,
|
|
424
424
|
),
|
|
425
425
|
).toBeNull();
|
|
@@ -63,6 +63,8 @@ function seedVellumGuardian(userFile: string | null): void {
|
|
|
63
63
|
|
|
64
64
|
mock.module("../util/platform.js", () => ({
|
|
65
65
|
getWorkspaceDir: () => mockWorkspaceDir,
|
|
66
|
+
getWorkspacePromptPath: (filename: string) =>
|
|
67
|
+
join(mockWorkspaceDir, "prompts", filename),
|
|
66
68
|
}));
|
|
67
69
|
|
|
68
70
|
mock.module("../contacts/contact-store.js", () => ({
|
|
@@ -96,6 +98,7 @@ mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
|
96
98
|
// Import AFTER mocks so the module under test binds to the stubbed
|
|
97
99
|
// implementations.
|
|
98
100
|
import { getGuardianDelivery } from "../contacts/guardian-delivery-reader.js";
|
|
101
|
+
import { resolveUserName } from "../daemon/identity-helpers.js";
|
|
99
102
|
import type { TrustContext } from "../daemon/trust-context-types.js";
|
|
100
103
|
import {
|
|
101
104
|
ensureGuardianPersonaFile,
|
|
@@ -408,3 +411,154 @@ describe("resolveUserSlug (guardian trust WITH requester identity)", () => {
|
|
|
408
411
|
expect(resolveUserSlug(trustContext)).toBeNull();
|
|
409
412
|
});
|
|
410
413
|
});
|
|
414
|
+
|
|
415
|
+
// ── resolveUserSlug — guardian bound on a non-vellum channel ───────
|
|
416
|
+
//
|
|
417
|
+
// warmGuardianBindings warms both the channel-filtered and unfiltered cache
|
|
418
|
+
// keys, but a guardian may be bound only on a non-vellum channel (phone,
|
|
419
|
+
// Telegram). A guardian-class turn sourced elsewhere must still resolve that
|
|
420
|
+
// guardian instead of silently landing on users/default.md.
|
|
421
|
+
|
|
422
|
+
describe("resolveUserSlug (guardian bound on a non-vellum channel)", () => {
|
|
423
|
+
test("falls back to the any-channel guardian when the source channel has none", () => {
|
|
424
|
+
mockGuardianDeliveries = [
|
|
425
|
+
{ channelType: "telegram", address: "guardian-tg", status: "active" },
|
|
426
|
+
];
|
|
427
|
+
mockContactsByAddress["telegram:guardian-tg"] = { userFile: "alice.md" };
|
|
428
|
+
|
|
429
|
+
const trustContext = {
|
|
430
|
+
sourceChannel: "vellum",
|
|
431
|
+
trustClass: "guardian",
|
|
432
|
+
} as TrustContext;
|
|
433
|
+
|
|
434
|
+
expect(resolveUserSlug(trustContext)).toBe("alice");
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
test("any-channel guardian with no userFile resolves the guardian.md fallback", () => {
|
|
438
|
+
mockGuardianDeliveries = [
|
|
439
|
+
{ channelType: "telegram", address: "guardian-tg", status: "active" },
|
|
440
|
+
];
|
|
441
|
+
mockContactsByAddress["telegram:guardian-tg"] = { userFile: null };
|
|
442
|
+
|
|
443
|
+
const trustContext = {
|
|
444
|
+
sourceChannel: "vellum",
|
|
445
|
+
trustClass: "guardian",
|
|
446
|
+
} as TrustContext;
|
|
447
|
+
|
|
448
|
+
expect(resolveUserSlug(trustContext)).toBe("guardian");
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// ── resolveUserSlug — cold cache then construction-time warm ───────
|
|
453
|
+
//
|
|
454
|
+
// The exact shape scheduled tasks and memory consolidation pass through
|
|
455
|
+
// resolveInitialSystemPrompt: guardian class, no requester identity, built in
|
|
456
|
+
// a worker process whose guardian-delivery cache starts cold.
|
|
457
|
+
|
|
458
|
+
describe("resolveUserSlug (cold cache, background shape)", () => {
|
|
459
|
+
test("misses on a cold cache, resolves the guardian after the construction-time warm", async () => {
|
|
460
|
+
pendingWarmDeliveries = [
|
|
461
|
+
{ channelType: "vellum", address: "vellum:self", status: "active" },
|
|
462
|
+
];
|
|
463
|
+
mockContactsByAddress["vellum:vellum:self"] = { userFile: "alice.md" };
|
|
464
|
+
|
|
465
|
+
const trustContext = {
|
|
466
|
+
sourceChannel: "vellum",
|
|
467
|
+
trustClass: "guardian",
|
|
468
|
+
} as TrustContext;
|
|
469
|
+
|
|
470
|
+
// Cold: the sync peek finds nothing and the slug falls back to default.
|
|
471
|
+
expect(resolveUserSlug(trustContext)).toBeNull();
|
|
472
|
+
|
|
473
|
+
// resolveInitialSystemPrompt warms guardian bindings for guardian-class
|
|
474
|
+
// contexts before building; afterwards the same resolution succeeds.
|
|
475
|
+
await getGuardianDelivery({ channelTypes: ["vellum"] });
|
|
476
|
+
|
|
477
|
+
expect(resolveUserSlug(trustContext)).toBe("alice");
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
// ── resolveUserName — guardian-preferred display name ──────────────
|
|
482
|
+
//
|
|
483
|
+
// The sweep job and v2 router address the user by name in their prompts. The
|
|
484
|
+
// name must come from the guardian's own persona file when one is resolvable,
|
|
485
|
+
// falling back to users/default.md.
|
|
486
|
+
|
|
487
|
+
describe("resolveUserName", () => {
|
|
488
|
+
test("prefers the Name label from the guardian's own persona file over default.md", () => {
|
|
489
|
+
seedVellumGuardian("alice.md");
|
|
490
|
+
const usersDir = join(mockWorkspaceDir, "users");
|
|
491
|
+
mkdirSync(usersDir, { recursive: true });
|
|
492
|
+
writeFileSync(join(usersDir, "alice.md"), "**Name:** Alice\n", "utf-8");
|
|
493
|
+
writeFileSync(
|
|
494
|
+
join(usersDir, "default.md"),
|
|
495
|
+
"**Name:** Default User\n",
|
|
496
|
+
"utf-8",
|
|
497
|
+
);
|
|
498
|
+
|
|
499
|
+
expect(resolveUserName(mockWorkspaceDir)).toBe("Alice");
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
test("reads the onboarding-written Preferred name bullet", () => {
|
|
503
|
+
seedVellumGuardian("alice.md");
|
|
504
|
+
const usersDir = join(mockWorkspaceDir, "users");
|
|
505
|
+
mkdirSync(usersDir, { recursive: true });
|
|
506
|
+
writeFileSync(
|
|
507
|
+
join(usersDir, "alice.md"),
|
|
508
|
+
"# User Profile\n\n## Onboarding Context\n\n- **Preferred name:** Ali\n",
|
|
509
|
+
"utf-8",
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
expect(resolveUserName(mockWorkspaceDir)).toBe("Ali");
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
test("reads the scaffold's filled Preferred name/reference line", () => {
|
|
516
|
+
seedVellumGuardian("alice.md");
|
|
517
|
+
const usersDir = join(mockWorkspaceDir, "users");
|
|
518
|
+
mkdirSync(usersDir, { recursive: true });
|
|
519
|
+
writeFileSync(
|
|
520
|
+
join(usersDir, "alice.md"),
|
|
521
|
+
"- Preferred name/reference: Alice\n- Pronouns: she/her\n",
|
|
522
|
+
"utf-8",
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
expect(resolveUserName(mockWorkspaceDir)).toBe("Alice");
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
test("an unfilled scaffold does not swallow the next line and falls back to default.md", () => {
|
|
529
|
+
seedVellumGuardian("alice.md");
|
|
530
|
+
const usersDir = join(mockWorkspaceDir, "users");
|
|
531
|
+
mkdirSync(usersDir, { recursive: true });
|
|
532
|
+
// The bare scaffold: every label present, every value unfilled.
|
|
533
|
+
ensureGuardianPersonaFile("alice.md");
|
|
534
|
+
writeFileSync(join(usersDir, "default.md"), "**Name:** Bob\n", "utf-8");
|
|
535
|
+
|
|
536
|
+
expect(resolveUserName(mockWorkspaceDir)).toBe("Bob");
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
test("a declined_by_user sentinel is not used as a name", () => {
|
|
540
|
+
seedVellumGuardian("alice.md");
|
|
541
|
+
const usersDir = join(mockWorkspaceDir, "users");
|
|
542
|
+
mkdirSync(usersDir, { recursive: true });
|
|
543
|
+
writeFileSync(
|
|
544
|
+
join(usersDir, "alice.md"),
|
|
545
|
+
"- Preferred name/reference: declined_by_user\n",
|
|
546
|
+
"utf-8",
|
|
547
|
+
);
|
|
548
|
+
writeFileSync(join(usersDir, "default.md"), "**Name:** Bob\n", "utf-8");
|
|
549
|
+
|
|
550
|
+
expect(resolveUserName(mockWorkspaceDir)).toBe("Bob");
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
test("falls back to default.md when no guardian resolves", () => {
|
|
554
|
+
const usersDir = join(mockWorkspaceDir, "users");
|
|
555
|
+
mkdirSync(usersDir, { recursive: true });
|
|
556
|
+
writeFileSync(join(usersDir, "default.md"), "**Name:** Bob\n", "utf-8");
|
|
557
|
+
|
|
558
|
+
expect(resolveUserName(mockWorkspaceDir)).toBe("Bob");
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
test("returns null when neither file yields a name", () => {
|
|
562
|
+
expect(resolveUserName(mockWorkspaceDir)).toBeNull();
|
|
563
|
+
});
|
|
564
|
+
});
|