@vellumai/assistant 0.11.2 → 0.11.3-dev.202608080427.92f668a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +69 -9
- package/docs/flux-turn-detection-spike.md +243 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/docs/trusted-contact-access.md +9 -5
- package/docs/vellum-doctor.md +195 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
- package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
- package/node_modules/@vellumai/environments/src/index.ts +17 -6
- package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
- package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
- package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
- package/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
- package/openapi.yaml +619 -47
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/src/__tests__/agent-image-optimize.test.ts +4 -4
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
- package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
- package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/answered-question-persistence.test.ts +240 -0
- package/src/__tests__/anthropic-provider.test.ts +165 -30
- package/src/__tests__/app-control-flow.test.ts +9 -8
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
- package/src/__tests__/attachments-store.test.ts +130 -68
- package/src/__tests__/attachments.test.ts +36 -36
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/call-controller.test.ts +120 -0
- package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
- package/src/__tests__/canned-reply-release.test.ts +86 -0
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-guardian.test.ts +59 -29
- package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
- package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
- package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +19 -0
- package/src/__tests__/config-schema.test.ts +150 -7
- package/src/__tests__/consult-deadline.test.ts +65 -0
- package/src/__tests__/conversation-agent-loop.test.ts +438 -2
- package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
- package/src/__tests__/conversation-disk-view.test.ts +4 -4
- package/src/__tests__/conversation-error.test.ts +22 -3
- package/src/__tests__/conversation-fork-crud.test.ts +5 -1
- package/src/__tests__/conversation-fork-referential.test.ts +352 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
- package/src/__tests__/conversation-group-tools.test.ts +32 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
- package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
- package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
- package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
- package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
- package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
- package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
- package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
- package/src/__tests__/conversation-queue.test.ts +433 -1
- package/src/__tests__/conversation-retry-route.test.ts +3 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
- package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
- package/src/__tests__/conversation-store.test.ts +26 -10
- package/src/__tests__/conversation-summarize-route.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
- package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
- package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
- package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
- package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
- package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
- package/src/__tests__/credential-prompt-route.test.ts +54 -7
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +89 -28
- package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
- package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
- package/src/__tests__/disk-pressure-guard.test.ts +55 -55
- package/src/__tests__/disk-pressure-routes.test.ts +10 -10
- package/src/__tests__/disk-pressure-tools.test.ts +2 -2
- package/src/__tests__/disk-usage.test.ts +35 -20
- package/src/__tests__/document-sync-tags.test.ts +379 -0
- package/src/__tests__/document-update-default-surface.test.ts +28 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
- package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
- package/src/__tests__/events-dev-bypass-actor.test.ts +294 -1
- package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
- package/src/__tests__/file-list-tool.test.ts +12 -10
- package/src/__tests__/file-ops-service.test.ts +151 -44
- package/src/__tests__/file-read-container-boundary.test.ts +137 -0
- package/src/__tests__/file-read-tool.test.ts +21 -9
- package/src/__tests__/file-url-path-guard.test.ts +83 -0
- package/src/__tests__/filesystem-tools.test.ts +82 -66
- package/src/__tests__/guardian-outbound-http.test.ts +8 -8
- package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
- package/src/__tests__/helpers/hub-clients.ts +42 -0
- package/src/__tests__/helpers/mock-conversation.ts +46 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
- package/src/__tests__/history-repair.test.ts +112 -12
- package/src/__tests__/host-bash-proxy.test.ts +10 -5
- package/src/__tests__/host-bash-routes.test.ts +67 -0
- package/src/__tests__/host-browser-proxy.test.ts +2 -2
- package/src/__tests__/host-cu-proxy.test.ts +3 -7
- package/src/__tests__/host-file-proxy.test.ts +3 -7
- package/src/__tests__/host-file-read-tool.test.ts +5 -1
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
- package/src/__tests__/http-conversation-lineage.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +44 -0
- package/src/__tests__/identity-routes.test.ts +13 -13
- package/src/__tests__/image-conversion.test.ts +29 -26
- package/src/__tests__/image-source-path-reinject.test.ts +2 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
- package/src/__tests__/introduction-card-resolver.test.ts +6 -1
- package/src/__tests__/list-messages-attachments.test.ts +56 -32
- package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
- package/src/__tests__/list-messages-page-latest.test.ts +61 -61
- package/src/__tests__/list-messages-provider-error.test.ts +6 -6
- package/src/__tests__/list-messages-queued.test.ts +49 -6
- package/src/__tests__/list-messages-system-card.test.ts +4 -4
- package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
- package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
- package/src/__tests__/llm-usage-store.test.ts +55 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
- package/src/__tests__/media-stream-output.test.ts +175 -0
- package/src/__tests__/media-stream-server-integration.test.ts +36 -0
- package/src/__tests__/media-stream-stt-session.test.ts +67 -0
- package/src/__tests__/migration-export-http.test.ts +1 -1
- package/src/__tests__/migration-import-commit-http.test.ts +1 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
- package/src/__tests__/migration-validate-http.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +65 -3
- package/src/__tests__/notification-platform-adapter.test.ts +104 -0
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
- package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
- package/src/__tests__/path-policy.test.ts +164 -1
- package/src/__tests__/persist-media-references.test.ts +2 -2
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
- package/src/__tests__/persist-unsendable-image.test.ts +23 -23
- package/src/__tests__/persona-resolver.test.ts +154 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
- package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
- package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
- package/src/__tests__/profiler-routes.test.ts +13 -13
- package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
- package/src/__tests__/proxy-approval-callback.test.ts +3 -3
- package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
- package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
- package/src/__tests__/resolve-trust-class.test.ts +20 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
- package/src/__tests__/run-due-schedules.test.ts +174 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
- package/src/__tests__/schedule-routes.test.ts +730 -8
- package/src/__tests__/schedule-store.test.ts +540 -0
- package/src/__tests__/schedule-tools.test.ts +103 -0
- package/src/__tests__/scheduler-wake.test.ts +5 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
- package/src/__tests__/secure-keys.test.ts +91 -0
- package/src/__tests__/server-history-render.test.ts +97 -7
- package/src/__tests__/size-guard.test.ts +8 -8
- package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
- package/src/__tests__/skill-tool-factory.test.ts +247 -0
- package/src/__tests__/skills-install-staging.test.ts +15 -6
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
- package/src/__tests__/slack-inbound-verification.test.ts +4 -1
- package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
- package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
- package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
- package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
- package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
- package/src/__tests__/subagent-disposal.test.ts +10 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
- package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
- package/src/__tests__/subagent-manager-notify.test.ts +148 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/subagent-persistence.test.ts +141 -0
- package/src/__tests__/subagent-role-registry.test.ts +172 -63
- package/src/__tests__/subagent-role-resolution.test.ts +88 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
- package/src/__tests__/subagent-terminal-message.test.ts +88 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
- package/src/__tests__/subagent-tools.test.ts +1901 -108
- package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
- package/src/__tests__/system-prompt.test.ts +82 -7
- package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
- package/src/__tests__/tool-result-spool.test.ts +74 -18
- package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
- package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
- package/src/__tests__/tools-audio-read.test.ts +10 -10
- package/src/__tests__/tools-get-route.test.ts +85 -12
- package/src/__tests__/tools-list-cli.test.ts +171 -0
- package/src/__tests__/top-level-renderer.test.ts +54 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
- package/src/__tests__/turn-tail-chain.test.ts +135 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
- package/src/__tests__/ui-visual-surface.test.ts +5 -4
- package/src/__tests__/ui-work-result-surface.test.ts +5 -4
- package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
- package/src/__tests__/usage-routes.test.ts +62 -0
- package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
- package/src/__tests__/visible-app-context.test.ts +20 -4
- package/src/__tests__/web-search-history.test.ts +96 -0
- package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
- package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +150 -0
- package/src/acp/failure-error.ts +3 -5
- package/src/agent/attachments.ts +26 -24
- package/src/agent/history-repair/history-repair.ts +27 -26
- package/src/agent/image-optimize.ts +6 -6
- package/src/agent/loop.ts +40 -22
- package/src/agent/message-types.ts +3 -3
- package/src/api/constants/document-tools.ts +55 -0
- package/src/api/events/question-answered.ts +53 -0
- package/src/api/events/tool-result.ts +7 -0
- package/src/api/index.ts +13 -0
- package/src/api/responses/conversation-message.ts +11 -0
- package/src/api/surfaces-oauth-connect.test.ts +96 -0
- package/src/api/surfaces.ts +36 -8
- package/src/approvals/guardian-channel-delivery.ts +83 -0
- package/src/approvals/guardian-expiry-notifier.ts +13 -11
- package/src/approvals/guardian-request-resolvers.ts +222 -135
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +13 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +131 -12
- package/src/calls/__tests__/voice-triage-escalate.test.ts +106 -0
- package/src/calls/call-controller.ts +30 -2
- package/src/calls/call-speech-output.ts +12 -4
- package/src/calls/call-transport.ts +18 -1
- package/src/calls/media-stream-output.ts +53 -5
- package/src/calls/media-stream-server.ts +21 -1
- package/src/calls/media-stream-stt-session.ts +49 -0
- package/src/calls/telephony-synthesis-language.ts +84 -0
- package/src/calls/tts-text-sanitizer.ts +12 -5
- package/src/calls/voice-session-bridge.ts +86 -17
- package/src/calls/voice-triage-escalate.ts +54 -7
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +20 -2
- package/src/channels/gateway-verification-sessions.ts +7 -2
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +37 -1
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/commands/__tests__/cache.test.ts +7 -4
- package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
- package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
- package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
- package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
- package/src/cli/commands/__tests__/plugins.test.ts +692 -0
- package/src/cli/commands/__tests__/schedules.test.ts +136 -37
- package/src/cli/commands/conversations.ts +7 -3
- package/src/cli/commands/credentials.help.ts +7 -0
- package/src/cli/commands/inference-profiles.ts +9 -3
- package/src/cli/commands/inference.help.ts +16 -2
- package/src/cli/commands/mcp.help.ts +17 -6
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/memory-retrospective.ts +18 -0
- package/src/cli/commands/notifications.ts +3 -6
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
- package/src/cli/commands/oauth/connect.test.ts +26 -1
- package/src/cli/commands/oauth/connect.ts +4 -1
- package/src/cli/commands/oauth/index.help.ts +3 -1
- package/src/cli/commands/oauth/providers.ts +3 -0
- package/src/cli/commands/plugins.help.ts +25 -2
- package/src/cli/commands/plugins.ts +289 -10
- package/src/cli/commands/schedules.help.ts +14 -12
- package/src/cli/commands/schedules.ts +19 -5
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/tools.help.ts +4 -2
- package/src/cli/commands/tools.ts +38 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
- package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +161 -0
- package/src/cli/lib/install-from-github.ts +61 -0
- package/src/cli/lib/install-from-platform.ts +13 -2
- package/src/cli/lib/plugin-surfaces.ts +124 -4
- package/src/cli/lib/upgrade-plugin.ts +60 -0
- package/src/cli.ts +1 -1
- package/src/config/__tests__/default-profile-catalog.test.ts +11 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
- package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
- package/src/config/__tests__/profile-tool-support.test.ts +131 -0
- package/src/config/bundled-skills/AGENTS.md +1 -1
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +15 -15
- package/src/config/bundled-skills/schedule/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +53 -22
- package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/bundled-skills/visualize/SKILL.md +1 -1
- package/src/config/call-site-defaults.ts +4 -5
- package/src/config/default-profile-catalog.ts +9 -5
- package/src/config/feature-flag-registry.json +25 -17
- package/src/config/llm-resolver.ts +45 -15
- package/src/config/loader.ts +75 -1
- package/src/config/profile-tool-support.ts +110 -0
- package/src/config/sanitize-for-transfer.ts +11 -0
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/live-voice.test.ts +142 -4
- package/src/config/schemas/__tests__/stt.test.ts +20 -5
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/channels.ts +13 -0
- package/src/config/schemas/live-voice.ts +82 -23
- package/src/config/schemas/llm.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +25 -0
- package/src/config/schemas/plugin-updates.ts +59 -0
- package/src/config/schemas/services.ts +8 -4
- package/src/config/schemas/stt.ts +18 -5
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/schemas/tts.ts +63 -0
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
- package/src/contacts/guardian-delivery-reader.ts +29 -2
- package/src/context/compactor.ts +4 -4
- package/src/context/post-turn-tool-result-truncation.ts +32 -16
- package/src/context/strip-injections.ts +42 -0
- package/src/context/tool-result-spool.ts +32 -18
- package/src/credential-execution/ces-runtime.ts +3 -0
- package/src/credential-execution/client.ts +22 -1
- package/src/credential-execution/process-manager.test.ts +99 -0
- package/src/credential-execution/process-manager.ts +62 -16
- package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
- package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
- package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
- package/src/daemon/channel-ui-capability.ts +4 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
- package/src/daemon/conversation-agent-loop.ts +318 -148
- package/src/daemon/conversation-attachments.ts +1 -1
- package/src/daemon/conversation-error.ts +8 -1
- package/src/daemon/conversation-initial-prompt.ts +16 -38
- package/src/daemon/conversation-lifecycle.ts +154 -32
- package/src/daemon/conversation-messaging.ts +106 -43
- package/src/daemon/conversation-process.ts +131 -33
- package/src/daemon/conversation-queue-manager.ts +10 -0
- package/src/daemon/conversation-runtime-assembly.ts +9 -4
- package/src/daemon/conversation-store.ts +52 -3
- package/src/daemon/conversation-surface-state.ts +9 -0
- package/src/daemon/conversation-surfaces.ts +403 -210
- package/src/daemon/conversation-tool-setup.ts +56 -7
- package/src/daemon/conversation-turn-finalize.ts +134 -89
- package/src/daemon/conversation.ts +111 -27
- package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
- package/src/daemon/disk-pressure-guard.ts +3 -3
- package/src/daemon/doordash-steps.ts +5 -5
- package/src/daemon/external-plugins-bootstrap.ts +7 -1
- package/src/daemon/handlers/config-channels.ts +48 -5
- package/src/daemon/handlers/conversation-history.ts +1 -1
- package/src/daemon/handlers/conversations.ts +62 -17
- package/src/daemon/handlers/shared.ts +12 -0
- package/src/daemon/handlers/skills.ts +11 -1
- package/src/daemon/identity-helpers.ts +38 -10
- package/src/daemon/install-assistant-command.ts +322 -0
- package/src/daemon/lifecycle.ts +14 -3
- package/src/daemon/message-types/conversations.ts +6 -7
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/persist-media-references.ts +23 -14
- package/src/daemon/process-message.ts +6 -6
- package/src/daemon/tool-setup-types.ts +19 -122
- package/src/daemon/tool-side-effects.ts +17 -94
- package/src/daemon/trust-context-types.ts +39 -0
- package/src/daemon/trust-context.ts +14 -6
- package/src/daemon/turn-tail-chain.ts +73 -0
- package/src/daemon/web-search-history.ts +47 -33
- package/src/heartbeat/heartbeat-service.ts +6 -6
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/__tests__/socket-path.test.ts +21 -0
- package/src/ipc/assistant-server.ts +17 -10
- package/src/ipc/cli-client.ts +10 -1
- package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
- package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
- package/src/ipc/socket-cleanup.ts +9 -7
- package/src/ipc/socket-path.ts +4 -96
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
- package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
- package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +932 -0
- package/src/live-voice/__tests__/live-voice-integration.test.ts +12 -5
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +179 -146
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +324 -2
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +131 -2
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-tts.test.ts +148 -2
- package/src/live-voice/__tests__/live-voice-vad.test.ts +313 -32
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/__tests__/progress-phrases.test.ts +167 -0
- package/src/live-voice/__tests__/protocol.test.ts +52 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
- package/src/live-voice/live-voice-archive.ts +13 -13
- package/src/live-voice/live-voice-connection.ts +7 -1
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +168 -0
- package/src/live-voice/live-voice-session.ts +1137 -351
- package/src/live-voice/live-voice-tts.ts +18 -2
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/progress-phrases.ts +105 -2
- package/src/live-voice/protocol.ts +110 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +196 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/client.ts +14 -7
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +195 -240
- package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
- package/src/messaging/providers/callback-routing.ts +1 -0
- package/src/messaging/providers/discord/api.ts +312 -0
- package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
- package/src/messaging/providers/discord/render.test.ts +204 -0
- package/src/messaging/providers/discord/render.ts +195 -0
- package/src/messaging/providers/discord/send.test.ts +179 -0
- package/src/messaging/providers/discord/send.ts +212 -0
- package/src/messaging/providers/discord/transport.ts +81 -0
- package/src/messaging/providers/index.ts +3 -1
- package/src/messaging/providers/retry-policy.test.ts +247 -0
- package/src/messaging/providers/retry-policy.ts +206 -0
- package/src/messaging/providers/slack/mention-source.test.ts +285 -0
- package/src/messaging/providers/slack/mention-source.ts +287 -0
- package/src/messaging/providers/telegram-bot/api.ts +47 -130
- package/src/messaging/providers/whatsapp/api.ts +47 -136
- package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +495 -0
- package/src/monitoring/db-integrity-sample.ts +6 -1
- package/src/monitoring/plugin-auto-update.ts +463 -0
- package/src/monitoring/resource-sampler.ts +21 -5
- package/src/monitoring/worker.ts +13 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
- package/src/notifications/__tests__/broadcaster.test.ts +37 -1
- package/src/notifications/__tests__/copy-composer.test.ts +165 -0
- package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
- package/src/notifications/__tests__/notification-utils.test.ts +249 -0
- package/src/notifications/adapters/platform.ts +31 -2
- package/src/notifications/assistant-reply-producer.ts +79 -32
- package/src/notifications/broadcaster.ts +30 -10
- package/src/notifications/copy-composer.ts +69 -0
- package/src/notifications/emit-signal.ts +82 -15
- package/src/notifications/events-store.ts +10 -2
- package/src/notifications/home-feed-side-effect.ts +6 -3
- package/src/notifications/notification-utils.ts +173 -5
- package/src/notifications/signal.ts +13 -0
- package/src/oauth/AGENTS.md +4 -2
- package/src/oauth/byo-connection.ts +6 -1
- package/src/oauth/credential-token-resolver.ts +3 -10
- package/src/oauth/manual-token-connection.ts +29 -64
- package/src/oauth/manual-token-providers.ts +62 -0
- package/src/oauth/provider-serializer.ts +13 -0
- package/src/oauth/seed-providers.ts +62 -11
- package/src/onboarding/onboarding-events-store.ts +91 -1
- package/src/permissions/question-prompter.test.ts +4 -0
- package/src/permissions/question-prompter.ts +21 -4
- package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
- package/src/persistence/attachments-store.ts +15 -15
- package/src/persistence/conversation-attention-store.ts +30 -10
- package/src/persistence/conversation-bootstrap.ts +17 -0
- package/src/persistence/conversation-crud.ts +363 -97
- package/src/persistence/conversation-group-migration.ts +1 -1
- package/src/persistence/conversation-key-store.ts +38 -10
- package/src/persistence/conversation-lineage.ts +226 -0
- package/src/persistence/conversation-plugin-facade.ts +28 -3
- package/src/persistence/conversation-queries.ts +207 -33
- package/src/persistence/conversation-types.ts +107 -1
- package/src/persistence/jobs-store.ts +32 -8
- package/src/persistence/llm-usage-store.ts +22 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
- package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
- package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
- package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
- package/src/persistence/schema/conversations.ts +32 -0
- package/src/persistence/schema/infrastructure.ts +3 -0
- package/src/persistence/steps.ts +30 -0
- package/src/persistence/subagent-store.ts +148 -6
- package/src/platform/managed-speech.test.ts +20 -0
- package/src/platform/managed-speech.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/index.ts +28 -5
- package/src/plugin-api/webhook-url.ts +151 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
- package/src/plugins/__tests__/mcp-servers.test.ts +370 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
- package/src/plugins/collect-source-versions.ts +4 -27
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
- package/src/plugins/defaults/exploration-drift/package.json +1 -1
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
- package/src/plugins/defaults/image-recovery/recover.ts +67 -57
- package/src/plugins/defaults/index.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
- package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
- package/src/plugins/defaults/memory/job-handlers.ts +87 -5
- package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
- package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
- package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
- package/src/plugins/defaults/memory/v2/router.ts +8 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
- package/src/plugins/external-plugin-loader.ts +64 -8
- package/src/plugins/installed-plugin-dirs.ts +101 -0
- package/src/plugins/mcp-servers.ts +343 -0
- package/src/plugins/mtime-cache.ts +34 -22
- package/src/plugins/types.ts +69 -8
- package/src/prompts/persona-resolver.ts +6 -2
- package/src/prompts/system-prompt.ts +72 -17
- package/src/providers/__tests__/inference.test.ts +40 -0
- package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
- package/src/providers/__tests__/retry-callsite.test.ts +72 -2
- package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
- package/src/providers/anthropic/client.ts +112 -95
- package/src/providers/connection-resolution.ts +35 -1
- package/src/providers/gemini/client.ts +5 -5
- package/src/providers/inference/adapter-factory.ts +16 -10
- package/src/providers/inference/auth.ts +16 -0
- package/src/providers/inference/connection-availability.ts +164 -12
- package/src/providers/inference/connections.ts +25 -1
- package/src/providers/media-resolve.ts +21 -11
- package/src/providers/model-catalog.ts +15 -0
- package/src/providers/openai/chat-completions-provider.ts +4 -4
- package/src/providers/openai/responses-provider.ts +12 -25
- package/src/providers/registry.ts +9 -4
- package/src/providers/retry.ts +25 -0
- package/src/providers/server-tool-pairing.ts +134 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +620 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +472 -12
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +719 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +283 -1
- package/src/providers/speech-to-text/deepgram-realtime.ts +117 -3
- package/src/providers/speech-to-text/deepgram.ts +1 -0
- package/src/providers/speech-to-text/provider-catalog.ts +137 -8
- package/src/providers/speech-to-text/resolve.ts +105 -12
- package/src/providers/speech-to-text/vellum-managed.ts +7 -1
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
- package/src/providers/types.ts +26 -6
- package/src/providers/vellum-model-routing.ts +6 -7
- package/src/runtime/AGENTS.md +2 -0
- package/src/runtime/__tests__/agent-wake.test.ts +16 -16
- package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
- package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
- package/src/runtime/__tests__/local-actor-identity-force-refresh.test.ts +104 -0
- package/src/runtime/agent-wake.ts +63 -24
- package/src/runtime/assistant-event-hub.ts +110 -12
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
- package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
- package/src/runtime/auth/same-actor.ts +56 -8
- package/src/runtime/auth/scopes.ts +12 -0
- package/src/runtime/auth/types.ts +2 -0
- package/src/runtime/background-job-runner.ts +5 -27
- package/src/runtime/channel-readiness-service.ts +59 -3
- package/src/runtime/channel-readiness-types.ts +18 -0
- package/src/runtime/desktop-presence.ts +69 -0
- package/src/runtime/http-server.ts +12 -0
- package/src/runtime/local-actor-identity.ts +29 -14
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +217 -1
- package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
- package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
- package/src/runtime/routes/__tests__/sse-actor-principal-heal.test.ts +165 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +2 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
- package/src/runtime/routes/archive-utils.ts +16 -12
- package/src/runtime/routes/attachment-routes.ts +13 -6
- package/src/runtime/routes/canned-reply-release.ts +54 -0
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-verification-routes.ts +2 -27
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
- package/src/runtime/routes/client-routes.ts +114 -2
- package/src/runtime/routes/conversation-cli-routes.ts +10 -12
- package/src/runtime/routes/conversation-list-routes.ts +59 -10
- package/src/runtime/routes/conversation-management-routes.ts +47 -18
- package/src/runtime/routes/conversation-query-routes.ts +32 -53
- package/src/runtime/routes/conversation-routes.ts +360 -293
- package/src/runtime/routes/credential-prompt-routes.ts +20 -2
- package/src/runtime/routes/debug-routes.ts +4 -1
- package/src/runtime/routes/default-provider-routes.ts +7 -11
- package/src/runtime/routes/documents-routes.ts +44 -1
- package/src/runtime/routes/events-routes.ts +29 -1
- package/src/runtime/routes/host-app-control-routes.ts +2 -0
- package/src/runtime/routes/host-bash-routes.ts +2 -0
- package/src/runtime/routes/host-browser-routes.ts +2 -0
- package/src/runtime/routes/host-cu-routes.ts +2 -0
- package/src/runtime/routes/host-file-routes.ts +2 -0
- package/src/runtime/routes/host-transfer-routes.ts +4 -0
- package/src/runtime/routes/identity-routes.ts +6 -6
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
- package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
- package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
- package/src/runtime/routes/inference-profiles-routes.ts +152 -73
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
- package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
- package/src/runtime/routes/log-export-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +141 -57
- package/src/runtime/routes/notification-routes.ts +0 -14
- package/src/runtime/routes/oauth-providers.ts +1 -0
- package/src/runtime/routes/plugins-routes.ts +127 -4
- package/src/runtime/routes/profiler-routes.ts +4 -2
- package/src/runtime/routes/question-routes.ts +28 -10
- package/src/runtime/routes/retrospective-routes.ts +9 -3
- package/src/runtime/routes/schedule-routes.ts +210 -12
- package/src/runtime/routes/secret-routes.ts +40 -23
- package/src/runtime/routes/settings-routes.ts +41 -13
- package/src/runtime/routes/skills-routes.ts +79 -0
- package/src/runtime/routes/sse-actor-principal-heal.ts +113 -0
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
- package/src/runtime/routes/wake-conversation-routes.ts +23 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +24 -9
- package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
- package/src/runtime/sync/resource-sync-events.ts +79 -1
- package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
- package/src/runtime/sync/worker-daemon-notify.ts +44 -6
- package/src/runtime/verification-outbound-actions.ts +250 -222
- package/src/runtime/verification-templates.ts +41 -30
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
- package/src/schedule/inference-profile.ts +64 -3
- package/src/schedule/plugin-schedule-declarations.ts +518 -0
- package/src/schedule/plugin-schedule-reconciler.ts +605 -0
- package/src/schedule/plugin-schedules-gate.ts +23 -0
- package/src/schedule/schedule-store.ts +520 -26
- package/src/schedule/scheduler.ts +38 -0
- package/src/security/credential-backend.ts +51 -4
- package/src/security/encrypted-store.ts +64 -42
- package/src/security/oauth2.ts +6 -22
- package/src/security/secure-keys.ts +55 -7
- package/src/skills/catalog-install.ts +20 -7
- package/src/skills/inline-command-runner.ts +2 -7
- package/src/skills/skill-history.test.ts +269 -0
- package/src/skills/skill-history.ts +250 -0
- package/src/skills/skillssh-registry.ts +1 -1
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/language-metadata.test.ts +85 -0
- package/src/stt/__tests__/speech-energy.test.ts +79 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +18 -6
- package/src/stt/language-metadata.ts +65 -0
- package/src/stt/speech-energy.ts +115 -12
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +119 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
- package/src/subagent/consult-prompt.ts +3 -1
- package/src/subagent/consult-transcript.ts +1 -1
- package/src/subagent/manager.ts +304 -44
- package/src/subagent/progress-events.ts +35 -0
- package/src/subagent/role-resolution.ts +88 -0
- package/src/subagent/types.ts +303 -67
- package/src/subagent/validate-allowlists.ts +3 -4
- package/src/telegram/__tests__/webhook-health.test.ts +73 -1
- package/src/telegram/webhook-health.ts +101 -3
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
- package/src/telemetry/activation-funnel.ts +6 -1
- package/src/telemetry/live-voice-funnel.ts +75 -0
- package/src/telemetry/telemetry-event-sources.ts +6 -0
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire.generated.ts +2 -0
- package/src/telemetry/types.ts +23 -4
- package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
- package/src/tools/ask-question/ask-question-tool.ts +56 -2
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/calls/call-start.ts +8 -5
- package/src/tools/conversation-groups/move_to_group.ts +10 -12
- package/src/tools/document/document-tool.ts +11 -4
- package/src/tools/execution-timeout.ts +9 -2
- package/src/tools/executor.ts +7 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +7 -13
- package/src/tools/filesystem/search.ts +23 -21
- package/src/tools/filesystem/write.ts +4 -1
- package/src/tools/host-filesystem/edit.ts +7 -2
- package/src/tools/host-filesystem/read.ts +21 -8
- package/src/tools/host-filesystem/write.ts +10 -2
- package/src/tools/host-terminal/host-shell.ts +2 -2
- package/src/tools/mcp/mcp-tool-factory.ts +25 -1
- package/src/tools/permission-checker.ts +8 -3
- package/src/tools/schedule/delete.ts +13 -1
- package/src/tools/schedule/list.ts +14 -3
- package/src/tools/schedule/update.ts +56 -33
- package/src/tools/shared/filesystem/audio-read.ts +6 -4
- package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
- package/src/tools/shared/filesystem/image-read.ts +12 -12
- package/src/tools/shared/filesystem/path-policy.ts +70 -5
- package/src/tools/shared/filesystem/size-guard.ts +6 -6
- package/src/tools/shared/input-misuse.ts +72 -0
- package/src/tools/skills/scaffold-managed.ts +82 -0
- package/src/tools/skills/skill-tool-factory.ts +14 -1
- package/src/tools/subagent/consult-deadline.ts +12 -7
- package/src/tools/subagent/message.ts +3 -1
- package/src/tools/subagent/read.ts +66 -4
- package/src/tools/subagent/spawn.ts +500 -78
- package/src/tools/tool-approval-handler.ts +45 -4
- package/src/tools/types.ts +22 -3
- package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
- package/src/tools/ui-surface/visual-validation.ts +2 -0
- package/src/tts/__tests__/provider-adapters.test.ts +147 -0
- package/src/tts/__tests__/speakable-segments.test.ts +470 -0
- package/src/tts/language-voices.ts +23 -0
- package/src/tts/providers/deepgram-provider.ts +3 -1
- package/src/tts/providers/elevenlabs-provider.ts +73 -1
- package/src/tts/providers/xai-provider.ts +28 -2
- package/src/tts/speakable-segments.ts +293 -23
- package/src/tts/synthesis-stream.ts +7 -0
- package/src/tts/types.ts +7 -0
- package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
- package/src/usage/subagent-attribution.ts +108 -0
- package/src/util/__tests__/language-subtag.test.ts +54 -0
- package/src/util/__tests__/sqlite-retry.test.ts +112 -0
- package/src/util/abort-reasons.ts +16 -0
- package/src/util/ansi.ts +44 -0
- package/src/util/disk-usage.ts +17 -13
- package/src/util/image-conversion.ts +20 -13
- package/src/util/language-subtag.ts +43 -0
- package/src/util/schedule-source-key.ts +23 -0
- package/src/util/unicode.ts +1 -1
- package/src/util/worker-process.ts +7 -1
- package/src/workspace/git-service.ts +33 -9
- package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
- package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +116 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/top-level-renderer.ts +15 -2
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
- package/src/daemon/install-symlink.ts +0 -207
- package/src/live-voice/__tests__/front-decision.test.ts +0 -525
- package/src/live-voice/front-decision.ts +0 -429
- package/src/notifications/deferred-emit.ts +0 -147
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { baseLanguageSubtag, localizedOrDefault } from "../language-subtag.js";
|
|
4
|
+
|
|
5
|
+
describe("baseLanguageSubtag", () => {
|
|
6
|
+
test("lowercases a bare tag", () => {
|
|
7
|
+
expect(baseLanguageSubtag("EN")).toBe("en");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("strips a hyphenated region", () => {
|
|
11
|
+
expect(baseLanguageSubtag("en-US")).toBe("en");
|
|
12
|
+
expect(baseLanguageSubtag("PT-br")).toBe("pt");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("strips an underscore-separated region", () => {
|
|
16
|
+
expect(baseLanguageSubtag("hi_IN")).toBe("hi");
|
|
17
|
+
expect(baseLanguageSubtag("es_419")).toBe("es");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("trims surrounding whitespace", () => {
|
|
21
|
+
expect(baseLanguageSubtag(" hi ")).toBe("hi");
|
|
22
|
+
expect(baseLanguageSubtag(" pt-BR ")).toBe("pt");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("returns undefined for undefined and blank input", () => {
|
|
26
|
+
expect(baseLanguageSubtag(undefined)).toBeUndefined();
|
|
27
|
+
expect(baseLanguageSubtag("")).toBeUndefined();
|
|
28
|
+
expect(baseLanguageSubtag(" ")).toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("localizedOrDefault", () => {
|
|
33
|
+
const table: Readonly<Record<string, string>> = { en: "hello", es: "hola" };
|
|
34
|
+
|
|
35
|
+
test("selects by the language's base subtag", () => {
|
|
36
|
+
expect(localizedOrDefault(table, "es", "hello")).toBe("hola");
|
|
37
|
+
expect(localizedOrDefault(table, "ES-mx", "hello")).toBe("hola");
|
|
38
|
+
expect(localizedOrDefault(table, "en_GB", "fallback")).toBe("hello");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("falls back for unset, blank, and unknown languages", () => {
|
|
42
|
+
expect(localizedOrDefault(table, undefined, "fallback")).toBe("fallback");
|
|
43
|
+
expect(localizedOrDefault(table, "", "fallback")).toBe("fallback");
|
|
44
|
+
expect(localizedOrDefault(table, "ko", "fallback")).toBe("fallback");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("never resolves prototype keys as entries", () => {
|
|
48
|
+
expect(localizedOrDefault(table, "constructor", "fallback")).toBe(
|
|
49
|
+
"fallback",
|
|
50
|
+
);
|
|
51
|
+
expect(localizedOrDefault(table, "toString", "fallback")).toBe("fallback");
|
|
52
|
+
expect(localizedOrDefault(table, "__proto__", "fallback")).toBe("fallback");
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `withSqliteRetry()`, the shared retry wrapper for transient
|
|
3
|
+
* SQLite write contention (`SQLITE_BUSY*` / `SQLITE_IOERR*`).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, expect, test } from "bun:test";
|
|
7
|
+
|
|
8
|
+
import { isRetryableSqliteError, withSqliteRetry } from "../sqlite-retry.js";
|
|
9
|
+
|
|
10
|
+
function sqliteError(code: string): Error {
|
|
11
|
+
const err = new Error(code);
|
|
12
|
+
(err as Error & { code: string }).code = code;
|
|
13
|
+
return err;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("isRetryableSqliteError", () => {
|
|
17
|
+
test("matches the SQLITE_BUSY and SQLITE_IOERR families", () => {
|
|
18
|
+
expect(isRetryableSqliteError(sqliteError("SQLITE_BUSY"))).toBe(true);
|
|
19
|
+
expect(isRetryableSqliteError(sqliteError("SQLITE_BUSY_SNAPSHOT"))).toBe(
|
|
20
|
+
true,
|
|
21
|
+
);
|
|
22
|
+
expect(isRetryableSqliteError(sqliteError("SQLITE_IOERR"))).toBe(true);
|
|
23
|
+
expect(isRetryableSqliteError(sqliteError("SQLITE_IOERR_SHORT_READ"))).toBe(
|
|
24
|
+
true,
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("rejects non-transient errors", () => {
|
|
29
|
+
expect(isRetryableSqliteError(sqliteError("SQLITE_CONSTRAINT"))).toBe(
|
|
30
|
+
false,
|
|
31
|
+
);
|
|
32
|
+
expect(isRetryableSqliteError(new Error("database is locked"))).toBe(false);
|
|
33
|
+
expect(isRetryableSqliteError(null)).toBe(false);
|
|
34
|
+
expect(isRetryableSqliteError(undefined)).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe("withSqliteRetry", () => {
|
|
39
|
+
test("returns the wrapped value on first success", async () => {
|
|
40
|
+
let calls = 0;
|
|
41
|
+
const result = await withSqliteRetry(
|
|
42
|
+
() => {
|
|
43
|
+
calls += 1;
|
|
44
|
+
return "ok";
|
|
45
|
+
},
|
|
46
|
+
{ op: "test-op" },
|
|
47
|
+
);
|
|
48
|
+
expect(result).toBe("ok");
|
|
49
|
+
expect(calls).toBe(1);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("retries transient contention and returns the eventual success", async () => {
|
|
53
|
+
let calls = 0;
|
|
54
|
+
const result = await withSqliteRetry(
|
|
55
|
+
() => {
|
|
56
|
+
calls += 1;
|
|
57
|
+
if (calls <= 2) {
|
|
58
|
+
throw sqliteError("SQLITE_BUSY");
|
|
59
|
+
}
|
|
60
|
+
return "recovered";
|
|
61
|
+
},
|
|
62
|
+
{ op: "test-op", baseDelayMs: 1 },
|
|
63
|
+
);
|
|
64
|
+
expect(result).toBe("recovered");
|
|
65
|
+
expect(calls).toBe(3);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("awaits an async wrapped function", async () => {
|
|
69
|
+
let calls = 0;
|
|
70
|
+
const result = await withSqliteRetry(
|
|
71
|
+
async () => {
|
|
72
|
+
calls += 1;
|
|
73
|
+
if (calls === 1) {
|
|
74
|
+
throw sqliteError("SQLITE_IOERR");
|
|
75
|
+
}
|
|
76
|
+
return 42;
|
|
77
|
+
},
|
|
78
|
+
{ op: "test-op", baseDelayMs: 1 },
|
|
79
|
+
);
|
|
80
|
+
expect(result).toBe(42);
|
|
81
|
+
expect(calls).toBe(2);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("throws immediately on a non-retryable error", async () => {
|
|
85
|
+
let calls = 0;
|
|
86
|
+
await expect(
|
|
87
|
+
withSqliteRetry(
|
|
88
|
+
() => {
|
|
89
|
+
calls += 1;
|
|
90
|
+
throw sqliteError("SQLITE_CONSTRAINT_PRIMARYKEY");
|
|
91
|
+
},
|
|
92
|
+
{ op: "test-op", baseDelayMs: 1 },
|
|
93
|
+
),
|
|
94
|
+
).rejects.toThrow("SQLITE_CONSTRAINT_PRIMARYKEY");
|
|
95
|
+
expect(calls).toBe(1);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("rethrows after exhausting maxRetries", async () => {
|
|
99
|
+
let calls = 0;
|
|
100
|
+
await expect(
|
|
101
|
+
withSqliteRetry(
|
|
102
|
+
() => {
|
|
103
|
+
calls += 1;
|
|
104
|
+
throw sqliteError("SQLITE_BUSY");
|
|
105
|
+
},
|
|
106
|
+
{ op: "test-op", maxRetries: 2, baseDelayMs: 1 },
|
|
107
|
+
),
|
|
108
|
+
).rejects.toThrow("SQLITE_BUSY");
|
|
109
|
+
// Initial attempt + 2 retries.
|
|
110
|
+
expect(calls).toBe(3);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -46,6 +46,22 @@ export function createAbortReason(
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* True when the abort came from a person stopping the turn they are watching
|
|
51
|
+
* (the Stop button, Esc, or the CLI's cancel signal file) rather than from the
|
|
52
|
+
* conversation going away or another subsystem seizing it.
|
|
53
|
+
*
|
|
54
|
+
* The distinction matters for the message queue. A user interrupt ends the
|
|
55
|
+
* turn in flight; it says nothing about the messages the same user queued
|
|
56
|
+
* behind it, so those survive the abort and run on the interrupted turn's
|
|
57
|
+
* drain. Every other kind (dispose, eviction, voice supersession, subagent
|
|
58
|
+
* teardown) is the conversation or its owner disappearing, where a queued
|
|
59
|
+
* message has nothing left to run on and is discarded.
|
|
60
|
+
*/
|
|
61
|
+
export function isUserInterruptAbort(reason: AbortReason | undefined): boolean {
|
|
62
|
+
return reason?.kind === "user_cancel" || reason?.kind === "signal_cancel";
|
|
63
|
+
}
|
|
64
|
+
|
|
49
65
|
export function isAbortReason(value: unknown): value is AbortReason {
|
|
50
66
|
if (typeof value !== "object" || value === null) {
|
|
51
67
|
return false;
|
package/src/util/ansi.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripping of terminal escape sequences and control characters from
|
|
3
|
+
* untrusted strings before they reach a terminal or notification copy.
|
|
4
|
+
*
|
|
5
|
+
* One pattern serves every call site so coverage cannot drift between
|
|
6
|
+
* hand-rolled copies. CSI sequences carry the full parameter and
|
|
7
|
+
* intermediate byte ranges; OSC sequences match through their BEL/ST
|
|
8
|
+
* terminator, with the terminator optional so an unterminated sequence
|
|
9
|
+
* cannot smuggle its body past the strip.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Well-formed ANSI escape sequences: CSI (`ESC [ params intermediates final`,
|
|
14
|
+
* covering colors, cursor moves, erase) and OSC (`ESC ] payload BEL|ST`,
|
|
15
|
+
* covering window-title writes and hyperlinks).
|
|
16
|
+
*/
|
|
17
|
+
const ANSI_SEQUENCE_RE =
|
|
18
|
+
/\u001b\[[0-?]*[ -/]*[@-~]|\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)?/g;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Runs of C0/C1 control characters, including DEL and any bare ESC left by a
|
|
22
|
+
* malformed sequence. `\r` and `\n` are C0, so this also flattens newlines.
|
|
23
|
+
*/
|
|
24
|
+
const CONTROL_CHAR_RUN_RE = /[\u0000-\u001f\u007f-\u009f]+/g;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Remove ANSI CSI/OSC escape sequences, leaving other control characters
|
|
28
|
+
* (newlines, tabs) intact. For multi-line text whose line structure matters.
|
|
29
|
+
*/
|
|
30
|
+
export function stripAnsiSequences(value: string): string {
|
|
31
|
+
return value.replace(ANSI_SEQUENCE_RE, "");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Remove ANSI CSI/OSC escape sequences, then replace every remaining run of
|
|
36
|
+
* C0/C1 control characters with `replacement` (removed by default). For
|
|
37
|
+
* single-line rendering where no control character may survive.
|
|
38
|
+
*/
|
|
39
|
+
export function stripAnsiAndControlChars(
|
|
40
|
+
value: string,
|
|
41
|
+
replacement = "",
|
|
42
|
+
): string {
|
|
43
|
+
return stripAnsiSequences(value).replace(CONTROL_CHAR_RUN_RE, replacement);
|
|
44
|
+
}
|
package/src/util/disk-usage.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
2
|
import { existsSync, statfsSync } from "node:fs";
|
|
3
|
+
import { promisify } from "node:util";
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
getIsContainerized,
|
|
@@ -8,6 +9,8 @@ import {
|
|
|
8
9
|
} from "../config/env-registry.js";
|
|
9
10
|
import { getWorkspaceDir } from "./platform.js";
|
|
10
11
|
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
|
|
11
14
|
export interface DiskUsageInfo {
|
|
12
15
|
path: string;
|
|
13
16
|
totalMb: number;
|
|
@@ -19,21 +22,17 @@ export interface DiskUsageInfo {
|
|
|
19
22
|
* Measure the on-disk usage of one or more directory paths using `du -sb`.
|
|
20
23
|
* Returns the sum of all paths in bytes, or null on failure.
|
|
21
24
|
*/
|
|
22
|
-
function getDirectorySizeBytes(paths: string[]): number | null {
|
|
25
|
+
async function getDirectorySizeBytes(paths: string[]): Promise<number | null> {
|
|
23
26
|
try {
|
|
24
27
|
const existing = paths.filter((p) => existsSync(p));
|
|
25
28
|
if (existing.length === 0) {
|
|
26
29
|
return null;
|
|
27
30
|
}
|
|
28
|
-
const
|
|
29
|
-
encoding: "utf-8",
|
|
31
|
+
const { stdout } = await execFileAsync("du", ["-sb", ...existing], {
|
|
30
32
|
timeout: 30_000,
|
|
31
33
|
});
|
|
32
|
-
if (result.status !== 0) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
34
|
let total = 0;
|
|
36
|
-
for (const line of
|
|
35
|
+
for (const line of stdout.trim().split("\n")) {
|
|
37
36
|
const size = parseInt(line.split("\t")[0], 10);
|
|
38
37
|
if (!isNaN(size) && size > 0) {
|
|
39
38
|
total += size;
|
|
@@ -46,14 +45,19 @@ function getDirectorySizeBytes(paths: string[]): number | null {
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
const DU_CACHE_TTL_MS = 60_000;
|
|
49
|
-
|
|
48
|
+
// Caches the in-flight promise so concurrent callers share one `du` run.
|
|
49
|
+
let duCacheValue: Promise<number | null> | null = null;
|
|
50
50
|
let duCacheTime = 0;
|
|
51
51
|
let duCachePaths: string | null = null;
|
|
52
52
|
|
|
53
|
-
function getCachedDirectorySizeBytes(paths: string[]): number | null {
|
|
53
|
+
function getCachedDirectorySizeBytes(paths: string[]): Promise<number | null> {
|
|
54
54
|
const key = paths.join("\0");
|
|
55
55
|
const now = Date.now();
|
|
56
|
-
if (
|
|
56
|
+
if (
|
|
57
|
+
duCacheValue !== null &&
|
|
58
|
+
duCachePaths === key &&
|
|
59
|
+
now - duCacheTime < DU_CACHE_TTL_MS
|
|
60
|
+
) {
|
|
57
61
|
return duCacheValue;
|
|
58
62
|
}
|
|
59
63
|
duCacheValue = getDirectorySizeBytes(paths);
|
|
@@ -119,7 +123,7 @@ function classifyWorkspaceVolume(
|
|
|
119
123
|
return { kind: "none" };
|
|
120
124
|
}
|
|
121
125
|
|
|
122
|
-
export function getDiskUsageInfo(): DiskUsageInfo | null {
|
|
126
|
+
export async function getDiskUsageInfo(): Promise<DiskUsageInfo | null> {
|
|
123
127
|
try {
|
|
124
128
|
const wsDir = getWorkspaceDir();
|
|
125
129
|
const diskPath = existsSync(wsDir) ? wsDir : "/";
|
|
@@ -135,7 +139,7 @@ export function getDiskUsageInfo(): DiskUsageInfo | null {
|
|
|
135
139
|
if (diskPath !== "/data" && existsSync("/data")) {
|
|
136
140
|
volumePaths.push("/data");
|
|
137
141
|
}
|
|
138
|
-
const usedBytes = getCachedDirectorySizeBytes(volumePaths);
|
|
142
|
+
const usedBytes = await getCachedDirectorySizeBytes(volumePaths);
|
|
139
143
|
if (usedBytes !== null) {
|
|
140
144
|
const totalBytes =
|
|
141
145
|
reporting.kind === "fixed-cap"
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* conversions of the same image (or daemon restarts) skip the sips call.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { execFileSync } from "node:child_process";
|
|
17
16
|
import { createHash } from "node:crypto";
|
|
18
17
|
import {
|
|
19
18
|
closeSync,
|
|
@@ -101,10 +100,10 @@ export interface ConvertToJpegOptions {
|
|
|
101
100
|
quality?: number;
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
function runSips(
|
|
103
|
+
async function runSips(
|
|
105
104
|
inputBytes: Uint8Array,
|
|
106
105
|
options: ConvertToJpegOptions,
|
|
107
|
-
): Buffer | null {
|
|
106
|
+
): Promise<Buffer | null> {
|
|
108
107
|
const stamp = `${Date.now()}-${uuid().slice(0, 8)}`;
|
|
109
108
|
const srcPath = join(tmpdir(), `vellum-img-opt-${stamp}-src`);
|
|
110
109
|
const outPath = join(tmpdir(), `vellum-img-opt-${stamp}-out.jpg`);
|
|
@@ -133,7 +132,15 @@ function runSips(
|
|
|
133
132
|
"--out",
|
|
134
133
|
outPath,
|
|
135
134
|
);
|
|
136
|
-
|
|
135
|
+
const proc = Bun.spawn(["sips", ...args], {
|
|
136
|
+
stdout: "ignore",
|
|
137
|
+
stderr: "ignore",
|
|
138
|
+
timeout: 15_000,
|
|
139
|
+
});
|
|
140
|
+
await proc.exited;
|
|
141
|
+
if (proc.exitCode !== 0) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
137
144
|
return readFileSync(outPath) as Buffer;
|
|
138
145
|
} catch {
|
|
139
146
|
return null;
|
|
@@ -155,10 +162,10 @@ function runSips(
|
|
|
155
162
|
* Convert an image to JPEG, optionally downscaling. Returns null when
|
|
156
163
|
* conversion is unavailable (non-macOS) or fails; callers keep the original.
|
|
157
164
|
*/
|
|
158
|
-
export function convertImageToJpeg(
|
|
165
|
+
export async function convertImageToJpeg(
|
|
159
166
|
bytes: Uint8Array,
|
|
160
167
|
options: ConvertToJpegOptions = {},
|
|
161
|
-
): Buffer | null {
|
|
168
|
+
): Promise<Buffer | null> {
|
|
162
169
|
const hash = createHash("sha256").update(bytes).digest("hex").slice(0, 16);
|
|
163
170
|
// Options qualify the key so full-resolution storage conversions and
|
|
164
171
|
// resized transport conversions of the same source never collide.
|
|
@@ -173,7 +180,7 @@ export function convertImageToJpeg(
|
|
|
173
180
|
return cached;
|
|
174
181
|
}
|
|
175
182
|
|
|
176
|
-
const converted = runSips(bytes, options);
|
|
183
|
+
const converted = await runSips(bytes, options);
|
|
177
184
|
if (!converted) {
|
|
178
185
|
return null;
|
|
179
186
|
}
|
|
@@ -346,12 +353,12 @@ export interface NormalizedImageBytes {
|
|
|
346
353
|
* {@link jpegFilenameFor} when `converted` is true — a MIME-only correction
|
|
347
354
|
* sets `converted: false` and keeps the filename.
|
|
348
355
|
*/
|
|
349
|
-
export function normalizeImageBytes(
|
|
356
|
+
export async function normalizeImageBytes(
|
|
350
357
|
mimeType: string,
|
|
351
358
|
bytes: Uint8Array,
|
|
352
|
-
): NormalizedImageBytes {
|
|
359
|
+
): Promise<NormalizedImageBytes> {
|
|
353
360
|
if (isHeifImage(bytes)) {
|
|
354
|
-
const converted = convertImageToJpeg(bytes, {
|
|
361
|
+
const converted = await convertImageToJpeg(bytes, {
|
|
355
362
|
quality: STORAGE_JPEG_QUALITY,
|
|
356
363
|
});
|
|
357
364
|
if (!converted) {
|
|
@@ -376,14 +383,14 @@ export interface NormalizedImageBase64 {
|
|
|
376
383
|
* Base64 variant of {@link normalizeImageBytes}. Sniffs the decoded head
|
|
377
384
|
* first so non-HEIF payloads skip the full decode.
|
|
378
385
|
*/
|
|
379
|
-
export function normalizeImageBase64(
|
|
386
|
+
export async function normalizeImageBase64(
|
|
380
387
|
mimeType: string,
|
|
381
388
|
dataBase64: string,
|
|
382
|
-
): NormalizedImageBase64 {
|
|
389
|
+
): Promise<NormalizedImageBase64> {
|
|
383
390
|
// 16 base64 chars decode to the 12 bytes the ftyp/signature sniffs need.
|
|
384
391
|
const head = Buffer.from(dataBase64.slice(0, 16), "base64");
|
|
385
392
|
if (isHeifImage(head)) {
|
|
386
|
-
const normalized = normalizeImageBytes(
|
|
393
|
+
const normalized = await normalizeImageBytes(
|
|
387
394
|
mimeType,
|
|
388
395
|
Buffer.from(dataBase64, "base64"),
|
|
389
396
|
);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The lowercased primary subtag of a BCP 47 (or underscore-separated)
|
|
3
|
+
* language tag: "pt-BR" -> "pt", "es_419" -> "es", " EN-us " -> "en".
|
|
4
|
+
* Undefined for undefined or blank input. The one language-tag
|
|
5
|
+
* normalizer in the daemon: every language comparison, table lookup, and
|
|
6
|
+
* prompt interpolation goes through this so a regional variant can never
|
|
7
|
+
* slip past a base-subtag consumer.
|
|
8
|
+
*/
|
|
9
|
+
export function baseLanguageSubtag(language?: string): string | undefined {
|
|
10
|
+
const base = language?.trim().toLowerCase().split(/[-_]/)[0];
|
|
11
|
+
return base ? base : undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Whether the table carries its own entry for the language, keyed by
|
|
16
|
+
* lowercased base subtag. False for unset languages and for prototype keys
|
|
17
|
+
* ("constructor", "toString") rather than table entries. When this is
|
|
18
|
+
* false, {@link localizedOrDefault} returns the fallback, so callers whose
|
|
19
|
+
* fallback is English text can label the result as English (e.g. for a TTS
|
|
20
|
+
* language hint) instead of the requested language.
|
|
21
|
+
*/
|
|
22
|
+
export function hasLocalizedEntry(
|
|
23
|
+
table: Readonly<Record<string, unknown>>,
|
|
24
|
+
language: string | undefined,
|
|
25
|
+
): boolean {
|
|
26
|
+
const base = baseLanguageSubtag(language);
|
|
27
|
+
return base !== undefined && Object.hasOwn(table, base);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Look up a per-language value in a plain-record table keyed by lowercase
|
|
32
|
+
* base subtags, falling back when the language is unset, unknown, or a
|
|
33
|
+
* prototype key ("constructor", "toString") rather than a table entry.
|
|
34
|
+
*/
|
|
35
|
+
export function localizedOrDefault<T>(
|
|
36
|
+
table: Readonly<Record<string, T>>,
|
|
37
|
+
language: string | undefined,
|
|
38
|
+
fallback: T,
|
|
39
|
+
): T {
|
|
40
|
+
return hasLocalizedEntry(table, language)
|
|
41
|
+
? (table[baseLanguageSubtag(language)!] as T)
|
|
42
|
+
: fallback;
|
|
43
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin-declared schedules record their provenance in the `source_key`
|
|
3
|
+
* column as `plugin:<pluginName>/<scheduleName>`. The format is minted by
|
|
4
|
+
* `pluginScheduleSourceKey` in schedule/plugin-schedule-declarations.ts;
|
|
5
|
+
* this leaf parser lets display surfaces (CLI tables, tool output) derive
|
|
6
|
+
* the owning plugin without importing the daemon's schedule modules.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const PLUGIN_SOURCE_KEY_RE = /^plugin:([^/]+)\//;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Display attribution for a schedule row: the owning plugin's name, the raw
|
|
13
|
+
* key when it does not match the format so provenance is never silently
|
|
14
|
+
* dropped, or null when the row is imperative.
|
|
15
|
+
*/
|
|
16
|
+
export function describeScheduleSource(
|
|
17
|
+
sourceKey: string | null | undefined,
|
|
18
|
+
): string | null {
|
|
19
|
+
if (!sourceKey) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return PLUGIN_SOURCE_KEY_RE.exec(sourceKey)?.[1] ?? sourceKey;
|
|
23
|
+
}
|
package/src/util/unicode.ts
CHANGED
|
@@ -20,7 +20,7 @@ export function isHighSurrogate(code: number): boolean {
|
|
|
20
20
|
return code >= HIGH_SURROGATE_START && code <= HIGH_SURROGATE_END;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function isLowSurrogate(code: number): boolean {
|
|
23
|
+
export function isLowSurrogate(code: number): boolean {
|
|
24
24
|
return code >= LOW_SURROGATE_START && code <= LOW_SURROGATE_END;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
unlinkSync,
|
|
18
18
|
} from "node:fs";
|
|
19
19
|
import { dirname } from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
20
21
|
|
|
21
22
|
import { getCurrentLogFilePath } from "./logger.js";
|
|
22
23
|
import { workerMemoryEnv } from "./worker-memory.js";
|
|
@@ -209,8 +210,13 @@ export async function spawnWorkerProcess(args: {
|
|
|
209
210
|
|
|
210
211
|
// Workers are latency-insensitive, so run them in bun's small-heap mode
|
|
211
212
|
// with a RAM-size hint sized to the container — see worker-memory.ts.
|
|
213
|
+
//
|
|
214
|
+
// `fileURLToPath`, not `.pathname`: a URL's pathname is percent-encoded, so
|
|
215
|
+
// an install path containing a space (every macOS desktop install lives
|
|
216
|
+
// under "Application Support") would reach bun as "Application%20Support"
|
|
217
|
+
// and the entry would not be found.
|
|
212
218
|
const child = Bun.spawn({
|
|
213
|
-
cmd: ["bun", "--smol", "run", args.entry
|
|
219
|
+
cmd: ["bun", "--smol", "run", fileURLToPath(args.entry)],
|
|
214
220
|
env: workerMemoryEnv(),
|
|
215
221
|
stdio: ["ignore", "ignore", stderrFd],
|
|
216
222
|
detached,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execFile, spawn
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
2
|
import {
|
|
3
3
|
chmodSync,
|
|
4
4
|
existsSync,
|
|
@@ -413,18 +413,19 @@ export class WorkspaceGitService {
|
|
|
413
413
|
* open, we leave it alone. If no process holds it, it's stale (crashed
|
|
414
414
|
* process) and safe to remove.
|
|
415
415
|
*/
|
|
416
|
-
private cleanStaleLockFile(): void {
|
|
416
|
+
private async cleanStaleLockFile(): Promise<void> {
|
|
417
417
|
const lockPath = join(this.workspaceDir, ".git", "index.lock");
|
|
418
418
|
if (!existsSync(lockPath)) {
|
|
419
419
|
return;
|
|
420
420
|
}
|
|
421
421
|
|
|
422
422
|
try {
|
|
423
|
-
|
|
423
|
+
// lsof exits non-zero when no process holds the file, which rejects the
|
|
424
|
+
// promise and falls through to removal below.
|
|
425
|
+
const { stdout } = await execFileAsync("lsof", ["-t", lockPath], {
|
|
424
426
|
timeout: 3000,
|
|
425
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
426
427
|
});
|
|
427
|
-
if (
|
|
428
|
+
if (stdout.length > 0) {
|
|
428
429
|
log.debug("index.lock held by an active process, skipping removal");
|
|
429
430
|
return;
|
|
430
431
|
}
|
|
@@ -490,7 +491,7 @@ export class WorkspaceGitService {
|
|
|
490
491
|
|
|
491
492
|
// Clean up stale lock files before any git operations.
|
|
492
493
|
if (existsSync(gitDir)) {
|
|
493
|
-
this.cleanStaleLockFile();
|
|
494
|
+
await this.cleanStaleLockFile();
|
|
494
495
|
}
|
|
495
496
|
|
|
496
497
|
if (existsSync(gitDir)) {
|
|
@@ -657,7 +658,7 @@ export class WorkspaceGitService {
|
|
|
657
658
|
await this.ensureInitialized();
|
|
658
659
|
|
|
659
660
|
await this.mutex.withLock(async () => {
|
|
660
|
-
this.cleanStaleLockFile();
|
|
661
|
+
await this.cleanStaleLockFile();
|
|
661
662
|
|
|
662
663
|
// Stage all changes (minus oversized files)
|
|
663
664
|
await this.stageAllLocked();
|
|
@@ -734,7 +735,7 @@ export class WorkspaceGitService {
|
|
|
734
735
|
|
|
735
736
|
try {
|
|
736
737
|
const result = await this.mutex.withLock(async () => {
|
|
737
|
-
this.cleanStaleLockFile();
|
|
738
|
+
await this.cleanStaleLockFile();
|
|
738
739
|
|
|
739
740
|
// Re-check breaker under lock: a queued call that started before the
|
|
740
741
|
// breaker opened should not proceed with expensive git work now that
|
|
@@ -1991,6 +1992,29 @@ export class WorkspaceGitService {
|
|
|
1991
1992
|
return this.execGit(args);
|
|
1992
1993
|
}
|
|
1993
1994
|
|
|
1995
|
+
/**
|
|
1996
|
+
* Run a read-only git command WITHOUT initializing the repository.
|
|
1997
|
+
*
|
|
1998
|
+
* `runReadOnlyGit` is read-only in the sense that its git command does not
|
|
1999
|
+
* write, but it still awaits `ensureInitialized()`, which will create the
|
|
2000
|
+
* repository, write `.gitignore` and the hooks directory, make the initial
|
|
2001
|
+
* commit, and schedule a history compaction when the workspace is not yet a
|
|
2002
|
+
* repo. That makes it unusable from an HTTP GET, which
|
|
2003
|
+
* `src/runtime/AGENTS.md` requires to be side-effect-free.
|
|
2004
|
+
*
|
|
2005
|
+
* This variant skips initialization entirely and throws when the workspace
|
|
2006
|
+
* is not a repository, so a caller that merely wants to *observe* history
|
|
2007
|
+
* can degrade instead of bringing a repo into existence.
|
|
2008
|
+
*/
|
|
2009
|
+
async runReadOnlyGitWithoutInit(
|
|
2010
|
+
args: string[],
|
|
2011
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
2012
|
+
if (!existsSync(join(this.workspaceDir, ".git"))) {
|
|
2013
|
+
throw new Error("Workspace is not a git repository");
|
|
2014
|
+
}
|
|
2015
|
+
return this.execGit(args);
|
|
2016
|
+
}
|
|
2017
|
+
|
|
1994
2018
|
/**
|
|
1995
2019
|
* Run a sequence of git commands atomically under the workspace mutex.
|
|
1996
2020
|
* Use this for write operations that need serialization with other
|
|
@@ -2003,7 +2027,7 @@ export class WorkspaceGitService {
|
|
|
2003
2027
|
): Promise<void> {
|
|
2004
2028
|
await this.ensureInitialized();
|
|
2005
2029
|
await this.mutex.withLock(async () => {
|
|
2006
|
-
this.cleanStaleLockFile();
|
|
2030
|
+
await this.cleanStaleLockFile();
|
|
2007
2031
|
await fn((args) => {
|
|
2008
2032
|
// Intercept commit commands to enforce hook hardening.
|
|
2009
2033
|
if (args[0] === "commit") {
|