@vellumai/assistant 0.11.2 → 0.11.3-staging.2
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 +58 -3
- 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 +39 -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 +39 -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 +39 -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 +589 -30
- package/package.json +1 -1
- 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-start-guardian-guard.test.ts +18 -4
- package/src/__tests__/canned-reply-release.test.ts +86 -0
- 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__/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 +57 -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 +183 -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-tool-annotations-risk.test.ts +133 -0
- package/src/__tests__/media-stream-server-integration.test.ts +36 -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__/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/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__/voice-session-bridge.test.ts +50 -0
- package/src/calls/media-stream-server.ts +9 -1
- package/src/calls/voice-session-bridge.ts +38 -0
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
- package/src/channels/config.ts +7 -2
- package/src/channels/gateway-verification-sessions.ts +7 -2
- package/src/channels/types.ts +7 -1
- 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 +4 -2
- 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/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 +122 -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 +18 -0
- package/src/cli.ts +1 -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/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
- 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 +2 -2
- 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/visualize/SKILL.md +1 -1
- package/src/config/default-profile-catalog.ts +6 -2
- package/src/config/feature-flag-registry.json +25 -17
- package/src/config/llm-resolver.ts +45 -15
- package/src/config/loader.ts +70 -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__/stt.test.ts +20 -5
- package/src/config/schemas/channels.ts +13 -0
- package/src/config/schemas/memory-retrospective.ts +25 -0
- package/src/config/schemas/plugin-updates.ts +55 -0
- package/src/config/schemas/services.ts +8 -4
- package/src/config/schemas/stt.ts +17 -5
- package/src/config/schemas/timeouts.ts +1 -1
- 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/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-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-integration.test.ts +7 -5
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
- package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
- 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-photo.ts +169 -0
- package/src/live-voice/live-voice-session.ts +108 -4
- package/src/live-voice/protocol.ts +89 -1
- package/src/mcp/client.ts +10 -0
- 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 +332 -0
- package/src/monitoring/db-integrity-sample.ts +6 -1
- package/src/monitoring/plugin-auto-update.ts +359 -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 +12 -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/index.ts +8 -0
- package/src/plugin-api/webhook-url.ts +151 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -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/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 +17 -8
- package/src/plugins/installed-plugin-dirs.ts +101 -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 +67 -0
- 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__/resolve.test.ts +187 -6
- package/src/providers/speech-to-text/deepgram.ts +1 -0
- package/src/providers/speech-to-text/resolve.ts +80 -10
- 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/agent-wake.ts +63 -24
- package/src/runtime/assistant-event-hub.ts +87 -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 +11 -9
- 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 +173 -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__/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-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 +23 -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 +28 -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/notification-routes.ts +0 -14
- package/src/runtime/routes/oauth-providers.ts +1 -0
- package/src/runtime/routes/plugins-routes.ts +106 -1
- 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/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/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/daemon-batch-transcriber.ts +8 -6
- 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 +302 -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/usage/__tests__/subagent-attribution.test.ts +109 -0
- package/src/usage/subagent-attribution.ts +108 -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/schedule-source-key.ts +23 -0
- 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/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
- package/src/workspace/migrations/registry.ts +4 -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/notifications/deferred-emit.ts +0 -147
|
@@ -7,7 +7,7 @@ let diskSample: DiskUsageInfo | null = null;
|
|
|
7
7
|
let diskSampleError: unknown = null;
|
|
8
8
|
|
|
9
9
|
mock.module("../util/disk-usage.js", () => ({
|
|
10
|
-
getDiskUsageInfo: () => {
|
|
10
|
+
getDiskUsageInfo: async () => {
|
|
11
11
|
if (diskSampleError) {
|
|
12
12
|
throw diskSampleError;
|
|
13
13
|
}
|
|
@@ -84,10 +84,10 @@ afterEach(() => {
|
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
describe("disk pressure guard", () => {
|
|
87
|
-
test("locks when sampled usage reaches the threshold", () => {
|
|
87
|
+
test("locks when sampled usage reaches the threshold", async () => {
|
|
88
88
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT);
|
|
89
89
|
|
|
90
|
-
const status = evaluateDiskPressureNow();
|
|
90
|
+
const status = await evaluateDiskPressureNow();
|
|
91
91
|
|
|
92
92
|
expect(status.enabled).toBe(true);
|
|
93
93
|
expect(status.state).toBe("critical");
|
|
@@ -103,9 +103,9 @@ describe("disk pressure guard", () => {
|
|
|
103
103
|
expect(status.blockedCapabilities.length).toBeGreaterThan(0);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
test("acknowledges an active lock without overriding it", () => {
|
|
106
|
+
test("acknowledges an active lock without overriding it", async () => {
|
|
107
107
|
setDiskUsage(99);
|
|
108
|
-
evaluateDiskPressureNow();
|
|
108
|
+
await evaluateDiskPressureNow();
|
|
109
109
|
|
|
110
110
|
const result = acknowledgeDiskPressureLock();
|
|
111
111
|
|
|
@@ -115,14 +115,14 @@ describe("disk pressure guard", () => {
|
|
|
115
115
|
expect(result.status.effectivelyLocked).toBe(true);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
test("unlocks and clears acknowledgement and override when usage falls below threshold", () => {
|
|
118
|
+
test("unlocks and clears acknowledgement and override when usage falls below threshold", async () => {
|
|
119
119
|
setDiskUsage(99);
|
|
120
|
-
evaluateDiskPressureNow();
|
|
120
|
+
await evaluateDiskPressureNow();
|
|
121
121
|
acknowledgeDiskPressureLock();
|
|
122
122
|
overrideDiskPressureLock(DISK_PRESSURE_OVERRIDE_CONFIRMATION);
|
|
123
123
|
|
|
124
124
|
setDiskUsage(20);
|
|
125
|
-
const status = evaluateDiskPressureNow();
|
|
125
|
+
const status = await evaluateDiskPressureNow();
|
|
126
126
|
|
|
127
127
|
expect(status.state).toBe("ok");
|
|
128
128
|
expect(status.locked).toBe(false);
|
|
@@ -133,25 +133,25 @@ describe("disk pressure guard", () => {
|
|
|
133
133
|
expect(status.blockedCapabilities).toEqual([]);
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
test("does not lock within the deadband until usage reaches the critical threshold", () => {
|
|
136
|
+
test("does not lock within the deadband until usage reaches the critical threshold", async () => {
|
|
137
137
|
setDiskUsage(DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT + 2);
|
|
138
138
|
|
|
139
|
-
const status = evaluateDiskPressureNow();
|
|
139
|
+
const status = await evaluateDiskPressureNow();
|
|
140
140
|
|
|
141
141
|
expect(status.state).toBe("warning");
|
|
142
142
|
expect(status.locked).toBe(false);
|
|
143
143
|
expect(status.effectivelyLocked).toBe(false);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
-
test("stays locked while usage stays within the hysteresis deadband", () => {
|
|
146
|
+
test("stays locked while usage stays within the hysteresis deadband", async () => {
|
|
147
147
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT + 1);
|
|
148
|
-
const locked = evaluateDiskPressureNow();
|
|
148
|
+
const locked = await evaluateDiskPressureNow();
|
|
149
149
|
expect(locked.locked).toBe(true);
|
|
150
150
|
const { lockId } = locked;
|
|
151
151
|
|
|
152
152
|
// Below critical (95) but above clear (90): must hold, not flap.
|
|
153
153
|
setDiskUsage(DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT + 2);
|
|
154
|
-
const status = evaluateDiskPressureNow();
|
|
154
|
+
const status = await evaluateDiskPressureNow();
|
|
155
155
|
|
|
156
156
|
expect(status.state).toBe("critical");
|
|
157
157
|
expect(status.locked).toBe(true);
|
|
@@ -160,29 +160,29 @@ describe("disk pressure guard", () => {
|
|
|
160
160
|
expect(status.lockId).toBe(lockId);
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
test("preserves acknowledgement across a dip within the deadband", () => {
|
|
163
|
+
test("preserves acknowledgement across a dip within the deadband", async () => {
|
|
164
164
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT + 1);
|
|
165
|
-
evaluateDiskPressureNow();
|
|
165
|
+
await evaluateDiskPressureNow();
|
|
166
166
|
acknowledgeDiskPressureLock();
|
|
167
167
|
|
|
168
168
|
setDiskUsage(DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT + 2);
|
|
169
|
-
const status = evaluateDiskPressureNow();
|
|
169
|
+
const status = await evaluateDiskPressureNow();
|
|
170
170
|
|
|
171
171
|
expect(status.locked).toBe(true);
|
|
172
172
|
expect(status.acknowledged).toBe(true);
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
test("clears the lock only once usage falls below the clear threshold", () => {
|
|
175
|
+
test("clears the lock only once usage falls below the clear threshold", async () => {
|
|
176
176
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT + 1);
|
|
177
|
-
evaluateDiskPressureNow();
|
|
177
|
+
await evaluateDiskPressureNow();
|
|
178
178
|
|
|
179
179
|
// Still within the deadband: locked.
|
|
180
180
|
setDiskUsage(DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT + 2);
|
|
181
|
-
expect(evaluateDiskPressureNow().locked).toBe(true);
|
|
181
|
+
expect((await evaluateDiskPressureNow()).locked).toBe(true);
|
|
182
182
|
|
|
183
183
|
// Below the clear threshold: released.
|
|
184
184
|
setDiskUsage(DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT - 2);
|
|
185
|
-
const status = evaluateDiskPressureNow();
|
|
185
|
+
const status = await evaluateDiskPressureNow();
|
|
186
186
|
|
|
187
187
|
expect(status.locked).toBe(false);
|
|
188
188
|
expect(status.effectivelyLocked).toBe(false);
|
|
@@ -190,9 +190,9 @@ describe("disk pressure guard", () => {
|
|
|
190
190
|
expect(status.blockedCapabilities).toEqual([]);
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
-
test("overrides an active lock only with the exact confirmation after trimming whitespace", () => {
|
|
193
|
+
test("overrides an active lock only with the exact confirmation after trimming whitespace", async () => {
|
|
194
194
|
setDiskUsage(99);
|
|
195
|
-
evaluateDiskPressureNow();
|
|
195
|
+
await evaluateDiskPressureNow();
|
|
196
196
|
|
|
197
197
|
const invalid = overrideDiskPressureLock("I accept the risks");
|
|
198
198
|
expectRejected(invalid, "invalid_confirmation");
|
|
@@ -208,9 +208,9 @@ describe("disk pressure guard", () => {
|
|
|
208
208
|
expect(valid.status.effectivelyLocked).toBe(false);
|
|
209
209
|
});
|
|
210
210
|
|
|
211
|
-
test("rejects acknowledgement when no lock is active", () => {
|
|
211
|
+
test("rejects acknowledgement when no lock is active", async () => {
|
|
212
212
|
setDiskUsage(10);
|
|
213
|
-
evaluateDiskPressureNow();
|
|
213
|
+
await evaluateDiskPressureNow();
|
|
214
214
|
|
|
215
215
|
const result = acknowledgeDiskPressureLock();
|
|
216
216
|
|
|
@@ -218,9 +218,9 @@ describe("disk pressure guard", () => {
|
|
|
218
218
|
expect(result.status.locked).toBe(false);
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
test("rejects override when no lock is active", () => {
|
|
221
|
+
test("rejects override when no lock is active", async () => {
|
|
222
222
|
setDiskUsage(10);
|
|
223
|
-
evaluateDiskPressureNow();
|
|
223
|
+
await evaluateDiskPressureNow();
|
|
224
224
|
|
|
225
225
|
const result = overrideDiskPressureLock(
|
|
226
226
|
DISK_PRESSURE_OVERRIDE_CONFIRMATION,
|
|
@@ -230,9 +230,9 @@ describe("disk pressure guard", () => {
|
|
|
230
230
|
expect(result.status.locked).toBe(false);
|
|
231
231
|
});
|
|
232
232
|
|
|
233
|
-
test("rejects repeated override while preserving the existing override", () => {
|
|
233
|
+
test("rejects repeated override while preserving the existing override", async () => {
|
|
234
234
|
setDiskUsage(99);
|
|
235
|
-
evaluateDiskPressureNow();
|
|
235
|
+
await evaluateDiskPressureNow();
|
|
236
236
|
const first = overrideDiskPressureLock(DISK_PRESSURE_OVERRIDE_CONFIRMATION);
|
|
237
237
|
expect(first.ok).toBe(true);
|
|
238
238
|
|
|
@@ -245,13 +245,13 @@ describe("disk pressure guard", () => {
|
|
|
245
245
|
expect(second.status.effectivelyLocked).toBe(false);
|
|
246
246
|
});
|
|
247
247
|
|
|
248
|
-
test("sample failures degrade open and do not preserve a prior lock", () => {
|
|
248
|
+
test("sample failures degrade open and do not preserve a prior lock", async () => {
|
|
249
249
|
setDiskUsage(99);
|
|
250
|
-
evaluateDiskPressureNow();
|
|
250
|
+
await evaluateDiskPressureNow();
|
|
251
251
|
expect(getDiskPressureStatus().locked).toBe(true);
|
|
252
252
|
|
|
253
253
|
diskSampleError = new Error("sample failed");
|
|
254
|
-
const status = evaluateDiskPressureNow();
|
|
254
|
+
const status = await evaluateDiskPressureNow();
|
|
255
255
|
|
|
256
256
|
expect(status.enabled).toBe(true);
|
|
257
257
|
expect(status.state).toBe("unknown");
|
|
@@ -278,71 +278,71 @@ describe("disk pressure guard", () => {
|
|
|
278
278
|
expect(__getDiskPressureGuardTimerForTests()).toBeNull();
|
|
279
279
|
});
|
|
280
280
|
|
|
281
|
-
test("does not enter warning until usage reaches the warning threshold", () => {
|
|
281
|
+
test("does not enter warning until usage reaches the warning threshold", async () => {
|
|
282
282
|
// Below 80% and never previously in a pressure state.
|
|
283
283
|
setDiskUsage(DISK_PRESSURE_WARNING_THRESHOLD_PERCENT - 2);
|
|
284
284
|
|
|
285
|
-
const status = evaluateDiskPressureNow();
|
|
285
|
+
const status = await evaluateDiskPressureNow();
|
|
286
286
|
|
|
287
287
|
expect(status.state).toBe("ok");
|
|
288
288
|
});
|
|
289
289
|
|
|
290
|
-
test("holds the warning state across a dip within the warning clear deadband", () => {
|
|
290
|
+
test("holds the warning state across a dip within the warning clear deadband", async () => {
|
|
291
291
|
setDiskUsage(DISK_PRESSURE_WARNING_THRESHOLD_PERCENT + 2);
|
|
292
|
-
expect(evaluateDiskPressureNow().state).toBe("warning");
|
|
292
|
+
expect((await evaluateDiskPressureNow()).state).toBe("warning");
|
|
293
293
|
|
|
294
294
|
// Below the 80% warning threshold but at/above the 77% clear threshold.
|
|
295
295
|
setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT + 1);
|
|
296
|
-
expect(evaluateDiskPressureNow().state).toBe("warning");
|
|
296
|
+
expect((await evaluateDiskPressureNow()).state).toBe("warning");
|
|
297
297
|
});
|
|
298
298
|
|
|
299
|
-
test("clears the warning state once usage falls below the warning clear threshold", () => {
|
|
299
|
+
test("clears the warning state once usage falls below the warning clear threshold", async () => {
|
|
300
300
|
setDiskUsage(DISK_PRESSURE_WARNING_THRESHOLD_PERCENT + 2);
|
|
301
|
-
expect(evaluateDiskPressureNow().state).toBe("warning");
|
|
301
|
+
expect((await evaluateDiskPressureNow()).state).toBe("warning");
|
|
302
302
|
|
|
303
303
|
setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT - 1);
|
|
304
|
-
expect(evaluateDiskPressureNow().state).toBe("ok");
|
|
304
|
+
expect((await evaluateDiskPressureNow()).state).toBe("ok");
|
|
305
305
|
});
|
|
306
306
|
|
|
307
|
-
test("steps a critical lock down into a held warning state", () => {
|
|
307
|
+
test("steps a critical lock down into a held warning state", async () => {
|
|
308
308
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT + 1);
|
|
309
|
-
expect(evaluateDiskPressureNow().state).toBe("critical");
|
|
309
|
+
expect((await evaluateDiskPressureNow()).state).toBe("critical");
|
|
310
310
|
|
|
311
311
|
// Below the 90% critical clear but above the 80% warning threshold.
|
|
312
312
|
setDiskUsage(DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT - 2);
|
|
313
|
-
const stepped = evaluateDiskPressureNow();
|
|
313
|
+
const stepped = await evaluateDiskPressureNow();
|
|
314
314
|
expect(stepped.state).toBe("warning");
|
|
315
315
|
expect(stepped.locked).toBe(false);
|
|
316
316
|
|
|
317
317
|
// Now within the warning clear deadband — warning must hold, not flap to ok.
|
|
318
318
|
setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT + 1);
|
|
319
|
-
expect(evaluateDiskPressureNow().state).toBe("warning");
|
|
319
|
+
expect((await evaluateDiskPressureNow()).state).toBe("warning");
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
test("holds warning when a critical lock drops straight into the warning deadband", () => {
|
|
322
|
+
test("holds warning when a critical lock drops straight into the warning deadband", async () => {
|
|
323
323
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT + 1);
|
|
324
|
-
expect(evaluateDiskPressureNow().state).toBe("critical");
|
|
324
|
+
expect((await evaluateDiskPressureNow()).state).toBe("critical");
|
|
325
325
|
|
|
326
326
|
// A single large cleanup drops usage directly from critical to below the
|
|
327
327
|
// 80% warning threshold but still at/above the 77% clear threshold. The
|
|
328
328
|
// deadband must apply when stepping down out of critical too, so this holds
|
|
329
329
|
// as warning rather than flapping to ok (which would reopen the flap window).
|
|
330
330
|
setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT + 1);
|
|
331
|
-
const stepped = evaluateDiskPressureNow();
|
|
331
|
+
const stepped = await evaluateDiskPressureNow();
|
|
332
332
|
expect(stepped.state).toBe("warning");
|
|
333
333
|
expect(stepped.locked).toBe(false);
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
-
test("clears straight to ok when a critical lock drops below the warning clear threshold", () => {
|
|
336
|
+
test("clears straight to ok when a critical lock drops below the warning clear threshold", async () => {
|
|
337
337
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT + 1);
|
|
338
|
-
expect(evaluateDiskPressureNow().state).toBe("critical");
|
|
338
|
+
expect((await evaluateDiskPressureNow()).state).toBe("critical");
|
|
339
339
|
|
|
340
340
|
// A drop below even the warning-clear threshold is a genuine recovery.
|
|
341
341
|
setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT - 1);
|
|
342
|
-
expect(evaluateDiskPressureNow().state).toBe("ok");
|
|
342
|
+
expect((await evaluateDiskPressureNow()).state).toBe("ok");
|
|
343
343
|
});
|
|
344
344
|
|
|
345
|
-
test("stays ok at a critical usage percentage while ample free space remains", () => {
|
|
345
|
+
test("stays ok at a critical usage percentage while ample free space remains", async () => {
|
|
346
346
|
// 99% used of a large volume still leaves gigabytes free — above the floor.
|
|
347
347
|
const totalMb = 1_000_000;
|
|
348
348
|
const usedMb = Math.round(totalMb * 0.99); // freeMb ~= 10_000 MiB
|
|
@@ -351,31 +351,31 @@ describe("disk pressure guard", () => {
|
|
|
351
351
|
DISK_PRESSURE_MIN_FREE_FLOOR_MB,
|
|
352
352
|
);
|
|
353
353
|
|
|
354
|
-
const status = evaluateDiskPressureNow();
|
|
354
|
+
const status = await evaluateDiskPressureNow();
|
|
355
355
|
|
|
356
356
|
expect(status.state).toBe("ok");
|
|
357
357
|
expect(status.locked).toBe(false);
|
|
358
358
|
expect(status.effectivelyLocked).toBe(false);
|
|
359
359
|
});
|
|
360
360
|
|
|
361
|
-
test("stays ok at a warning usage percentage while ample free space remains", () => {
|
|
361
|
+
test("stays ok at a warning usage percentage while ample free space remains", async () => {
|
|
362
362
|
const totalMb = 1_000_000;
|
|
363
363
|
const usedMb = Math.round(totalMb * 0.85); // 85% used, freeMb ~= 150_000 MiB
|
|
364
364
|
setDiskUsage(usedMb, totalMb);
|
|
365
365
|
|
|
366
|
-
const status = evaluateDiskPressureNow();
|
|
366
|
+
const status = await evaluateDiskPressureNow();
|
|
367
367
|
|
|
368
368
|
expect(status.state).toBe("ok");
|
|
369
369
|
});
|
|
370
370
|
|
|
371
|
-
test("locks at a critical usage percentage once free space drops below the floor", () => {
|
|
371
|
+
test("locks at a critical usage percentage once free space drops below the floor", async () => {
|
|
372
372
|
// High percentage AND little absolute headroom: floor does not apply.
|
|
373
373
|
const totalMb = 100_000;
|
|
374
374
|
const freeMb = DISK_PRESSURE_MIN_FREE_FLOOR_MB - 1;
|
|
375
375
|
setDiskUsage(totalMb - freeMb, totalMb);
|
|
376
376
|
expect(diskSample!.freeMb).toBeLessThan(DISK_PRESSURE_MIN_FREE_FLOOR_MB);
|
|
377
377
|
|
|
378
|
-
const status = evaluateDiskPressureNow();
|
|
378
|
+
const status = await evaluateDiskPressureNow();
|
|
379
379
|
|
|
380
380
|
expect(status.state).toBe("critical");
|
|
381
381
|
expect(status.locked).toBe(true);
|
|
@@ -170,7 +170,7 @@ describe("disk pressure routes", () => {
|
|
|
170
170
|
|
|
171
171
|
test("returns the full status shape for an active lock", async () => {
|
|
172
172
|
setDiskUsage(99);
|
|
173
|
-
evaluateDiskPressureNow();
|
|
173
|
+
await evaluateDiskPressureNow();
|
|
174
174
|
|
|
175
175
|
const result = await callRoute("disk-pressure/status", "GET");
|
|
176
176
|
|
|
@@ -223,7 +223,7 @@ describe("disk pressure routes", () => {
|
|
|
223
223
|
|
|
224
224
|
test("acknowledges an active lock without overriding it", async () => {
|
|
225
225
|
setDiskUsage(99);
|
|
226
|
-
evaluateDiskPressureNow();
|
|
226
|
+
await evaluateDiskPressureNow();
|
|
227
227
|
|
|
228
228
|
const result = await callRoute("disk-pressure/acknowledge", "POST");
|
|
229
229
|
|
|
@@ -234,7 +234,7 @@ describe("disk pressure routes", () => {
|
|
|
234
234
|
|
|
235
235
|
test("overrides an active lock only after the confirmation phrase", async () => {
|
|
236
236
|
setDiskUsage(99);
|
|
237
|
-
evaluateDiskPressureNow();
|
|
237
|
+
await evaluateDiskPressureNow();
|
|
238
238
|
|
|
239
239
|
const result = await callRoute("disk-pressure/override", "POST", {
|
|
240
240
|
confirmation: DISK_PRESSURE_OVERRIDE_CONFIRMATION,
|
|
@@ -247,7 +247,7 @@ describe("disk pressure routes", () => {
|
|
|
247
247
|
|
|
248
248
|
test("rejects an invalid override phrase with INVALID_CONFIRMATION", async () => {
|
|
249
249
|
setDiskUsage(99);
|
|
250
|
-
evaluateDiskPressureNow();
|
|
250
|
+
await evaluateDiskPressureNow();
|
|
251
251
|
|
|
252
252
|
await expectRouteRejects(
|
|
253
253
|
"disk-pressure/override",
|
|
@@ -260,7 +260,7 @@ describe("disk pressure routes", () => {
|
|
|
260
260
|
|
|
261
261
|
test("rejects acknowledgement and override when no lock is active", async () => {
|
|
262
262
|
setDiskUsage(10);
|
|
263
|
-
evaluateDiskPressureNow();
|
|
263
|
+
await evaluateDiskPressureNow();
|
|
264
264
|
|
|
265
265
|
await expectRouteRejects(
|
|
266
266
|
"disk-pressure/acknowledge",
|
|
@@ -280,7 +280,7 @@ describe("disk pressure routes", () => {
|
|
|
280
280
|
|
|
281
281
|
test("rejects repeated acknowledgement", async () => {
|
|
282
282
|
setDiskUsage(99);
|
|
283
|
-
evaluateDiskPressureNow();
|
|
283
|
+
await evaluateDiskPressureNow();
|
|
284
284
|
await callRoute("disk-pressure/acknowledge", "POST");
|
|
285
285
|
|
|
286
286
|
await expectRouteRejects(
|
|
@@ -294,7 +294,7 @@ describe("disk pressure routes", () => {
|
|
|
294
294
|
|
|
295
295
|
test("rejects repeated override", async () => {
|
|
296
296
|
setDiskUsage(99);
|
|
297
|
-
evaluateDiskPressureNow();
|
|
297
|
+
await evaluateDiskPressureNow();
|
|
298
298
|
await callRoute("disk-pressure/override", "POST", {
|
|
299
299
|
confirmation: DISK_PRESSURE_OVERRIDE_CONFIRMATION,
|
|
300
300
|
});
|
|
@@ -321,15 +321,15 @@ describe("disk pressure routes", () => {
|
|
|
321
321
|
|
|
322
322
|
try {
|
|
323
323
|
setDiskUsage(99);
|
|
324
|
-
evaluateDiskPressureNow();
|
|
324
|
+
await evaluateDiskPressureNow();
|
|
325
325
|
await callRoute("disk-pressure/acknowledge", "POST");
|
|
326
326
|
await callRoute("disk-pressure/override", "POST", {
|
|
327
327
|
confirmation: DISK_PRESSURE_OVERRIDE_CONFIRMATION,
|
|
328
328
|
});
|
|
329
329
|
setDiskUsage(98);
|
|
330
|
-
evaluateDiskPressureNow();
|
|
330
|
+
await evaluateDiskPressureNow();
|
|
331
331
|
setDiskUsage(10);
|
|
332
|
-
evaluateDiskPressureNow();
|
|
332
|
+
await evaluateDiskPressureNow();
|
|
333
333
|
await flushPublishedEvents();
|
|
334
334
|
} finally {
|
|
335
335
|
subscription.dispose();
|
|
@@ -196,7 +196,7 @@ describe("disk pressure cleanup tool restrictions", () => {
|
|
|
196
196
|
expect(result.tool.name).toBe("skill_load");
|
|
197
197
|
});
|
|
198
198
|
|
|
199
|
-
test("locking cancels registered terminal background tools with disk pressure reason", () => {
|
|
199
|
+
test("locking cancels registered terminal background tools with disk pressure reason", async () => {
|
|
200
200
|
const bashCancel = mock((_reason?: string) => undefined);
|
|
201
201
|
const hostCancel = mock((_reason?: string) => undefined);
|
|
202
202
|
const otherCancel = mock((_reason?: string) => undefined);
|
|
@@ -227,7 +227,7 @@ describe("disk pressure cleanup tool restrictions", () => {
|
|
|
227
227
|
});
|
|
228
228
|
|
|
229
229
|
setDiskUsage(DISK_PRESSURE_THRESHOLD_PERCENT);
|
|
230
|
-
const status = evaluateDiskPressureNow();
|
|
230
|
+
const status = await evaluateDiskPressureNow();
|
|
231
231
|
|
|
232
232
|
expect(status.locked).toBe(true);
|
|
233
233
|
expect(bashCancel).toHaveBeenCalledWith("disk_pressure");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { promisify } from "node:util";
|
|
1
2
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
3
|
|
|
3
4
|
const MIB = 1024 * 1024;
|
|
@@ -27,11 +28,25 @@ mock.module("node:fs", () => ({
|
|
|
27
28
|
statfsSync: () => statfsResult,
|
|
28
29
|
}));
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// The module under test calls `promisify(execFile)`, so the mock only needs
|
|
32
|
+
// to provide the promisified implementation via the promisify.custom symbol.
|
|
33
|
+
const execFileMock = Object.assign(
|
|
34
|
+
() => {
|
|
35
|
+
throw new Error("callback-style execFile is not used by disk-usage");
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
[promisify.custom]: async (command: string, args: string[]) => {
|
|
39
|
+
spawnCalls.push({ command, args });
|
|
40
|
+
if (spawnResult.status !== 0) {
|
|
41
|
+
throw new Error(`Command failed with exit code ${spawnResult.status}`);
|
|
42
|
+
}
|
|
43
|
+
return { stdout: spawnResult.stdout, stderr: "" };
|
|
44
|
+
},
|
|
34
45
|
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
mock.module("node:child_process", () => ({
|
|
49
|
+
execFile: execFileMock,
|
|
35
50
|
}));
|
|
36
51
|
|
|
37
52
|
mock.module("../config/env-registry.js", () => ({
|
|
@@ -67,8 +82,8 @@ describe("disk usage sampler", () => {
|
|
|
67
82
|
__resetDiskUsageCacheForTests();
|
|
68
83
|
});
|
|
69
84
|
|
|
70
|
-
test("reports regular statfs usage", () => {
|
|
71
|
-
const usage = getDiskUsageInfo();
|
|
85
|
+
test("reports regular statfs usage", async () => {
|
|
86
|
+
const usage = await getDiskUsageInfo();
|
|
72
87
|
|
|
73
88
|
expect(usage).toEqual({
|
|
74
89
|
path: "/workspace",
|
|
@@ -79,15 +94,15 @@ describe("disk usage sampler", () => {
|
|
|
79
94
|
expect(spawnCalls).toHaveLength(0);
|
|
80
95
|
});
|
|
81
96
|
|
|
82
|
-
test("falls back to root when the workspace path does not exist", () => {
|
|
97
|
+
test("falls back to root when the workspace path does not exist", async () => {
|
|
83
98
|
existingPaths = new Set();
|
|
84
99
|
|
|
85
|
-
const usage = getDiskUsageInfo();
|
|
100
|
+
const usage = await getDiskUsageInfo();
|
|
86
101
|
|
|
87
102
|
expect(usage?.path).toBe("/");
|
|
88
103
|
});
|
|
89
104
|
|
|
90
|
-
test("uses PVC capacity and du usage when host filesystem is larger", () => {
|
|
105
|
+
test("uses PVC capacity and du usage when host filesystem is larger", async () => {
|
|
91
106
|
minikubeStorageSize = "1Gi";
|
|
92
107
|
statfsResult = statfsFor(10 * GIB, 8 * GIB);
|
|
93
108
|
spawnResult = {
|
|
@@ -95,7 +110,7 @@ describe("disk usage sampler", () => {
|
|
|
95
110
|
stdout: `${100 * MIB}\t/workspace\n`,
|
|
96
111
|
};
|
|
97
112
|
|
|
98
|
-
const usage = getDiskUsageInfo();
|
|
113
|
+
const usage = await getDiskUsageInfo();
|
|
99
114
|
|
|
100
115
|
expect(usage).toEqual({
|
|
101
116
|
path: "/workspace",
|
|
@@ -108,7 +123,7 @@ describe("disk usage sampler", () => {
|
|
|
108
123
|
]);
|
|
109
124
|
});
|
|
110
125
|
|
|
111
|
-
test("includes /data in PVC du usage when it exists separately", () => {
|
|
126
|
+
test("includes /data in PVC du usage when it exists separately", async () => {
|
|
112
127
|
existingPaths = new Set([workspaceDir, "/data"]);
|
|
113
128
|
minikubeStorageSize = "1Gi";
|
|
114
129
|
statfsResult = statfsFor(10 * GIB, 8 * GIB);
|
|
@@ -117,7 +132,7 @@ describe("disk usage sampler", () => {
|
|
|
117
132
|
stdout: `${100 * MIB}\t/workspace\n${20 * MIB}\t/data\n`,
|
|
118
133
|
};
|
|
119
134
|
|
|
120
|
-
const usage = getDiskUsageInfo();
|
|
135
|
+
const usage = await getDiskUsageInfo();
|
|
121
136
|
|
|
122
137
|
expect(usage?.usedMb).toBe(120);
|
|
123
138
|
expect(spawnCalls).toEqual([
|
|
@@ -125,7 +140,7 @@ describe("disk usage sampler", () => {
|
|
|
125
140
|
]);
|
|
126
141
|
});
|
|
127
142
|
|
|
128
|
-
test("measures workspace du usage on a local Docker hatch", () => {
|
|
143
|
+
test("measures workspace du usage on a local Docker hatch", async () => {
|
|
129
144
|
isContainerized = true;
|
|
130
145
|
isPlatform = false;
|
|
131
146
|
statfsResult = statfsFor(100 * GIB, 40 * GIB);
|
|
@@ -134,7 +149,7 @@ describe("disk usage sampler", () => {
|
|
|
134
149
|
stdout: `${2 * GIB}\t/workspace\n`,
|
|
135
150
|
};
|
|
136
151
|
|
|
137
|
-
const usage = getDiskUsageInfo();
|
|
152
|
+
const usage = await getDiskUsageInfo();
|
|
138
153
|
|
|
139
154
|
// Used reflects only the workspace (du), free reflects the host headroom
|
|
140
155
|
// the volume can grow into, and total is their sum.
|
|
@@ -149,12 +164,12 @@ describe("disk usage sampler", () => {
|
|
|
149
164
|
]);
|
|
150
165
|
});
|
|
151
166
|
|
|
152
|
-
test("does not use du for platform-managed containerized instances", () => {
|
|
167
|
+
test("does not use du for platform-managed containerized instances", async () => {
|
|
153
168
|
isContainerized = true;
|
|
154
169
|
isPlatform = true;
|
|
155
170
|
statfsResult = statfsFor(10 * GIB, 6 * GIB);
|
|
156
171
|
|
|
157
|
-
const usage = getDiskUsageInfo();
|
|
172
|
+
const usage = await getDiskUsageInfo();
|
|
158
173
|
|
|
159
174
|
expect(usage).toEqual({
|
|
160
175
|
path: "/workspace",
|
|
@@ -165,13 +180,13 @@ describe("disk usage sampler", () => {
|
|
|
165
180
|
expect(spawnCalls).toHaveLength(0);
|
|
166
181
|
});
|
|
167
182
|
|
|
168
|
-
test("falls back to statfs when du fails on a local Docker hatch", () => {
|
|
183
|
+
test("falls back to statfs when du fails on a local Docker hatch", async () => {
|
|
169
184
|
isContainerized = true;
|
|
170
185
|
isPlatform = false;
|
|
171
186
|
statfsResult = statfsFor(100 * GIB, 40 * GIB);
|
|
172
187
|
spawnResult = { status: 1, stdout: "" };
|
|
173
188
|
|
|
174
|
-
const usage = getDiskUsageInfo();
|
|
189
|
+
const usage = await getDiskUsageInfo();
|
|
175
190
|
|
|
176
191
|
expect(usage).toEqual({
|
|
177
192
|
path: "/workspace",
|
|
@@ -192,7 +207,7 @@ describe("disk usage sampler", () => {
|
|
|
192
207
|
expect(parseK8sMemoryBytes("0Gi")).toBeNull();
|
|
193
208
|
});
|
|
194
209
|
|
|
195
|
-
test("falls back to statfs when du fails in PVC mode", () => {
|
|
210
|
+
test("falls back to statfs when du fails in PVC mode", async () => {
|
|
196
211
|
minikubeStorageSize = "1Gi";
|
|
197
212
|
statfsResult = statfsFor(10 * GIB, 8 * GIB);
|
|
198
213
|
spawnResult = {
|
|
@@ -200,7 +215,7 @@ describe("disk usage sampler", () => {
|
|
|
200
215
|
stdout: "",
|
|
201
216
|
};
|
|
202
217
|
|
|
203
|
-
const usage = getDiskUsageInfo();
|
|
218
|
+
const usage = await getDiskUsageInfo();
|
|
204
219
|
|
|
205
220
|
expect(usage).toEqual({
|
|
206
221
|
path: "/workspace",
|