@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
|
@@ -340,6 +340,110 @@ describe("PlatformPushAdapter", () => {
|
|
|
340
340
|
expect(result.remotePushAccepted).toBeUndefined();
|
|
341
341
|
});
|
|
342
342
|
|
|
343
|
+
// A lock screen renders no markdown, so any marker that survives to the
|
|
344
|
+
// dispatch body reads as literal punctuation. See `stripMarkdownForPreview`.
|
|
345
|
+
describe("markdown flattening", () => {
|
|
346
|
+
test("flattens markdown out of the dispatched title and body", async () => {
|
|
347
|
+
const adapter = new PlatformPushAdapter();
|
|
348
|
+
const payload = makePayload({
|
|
349
|
+
copy: {
|
|
350
|
+
title: "**Build** finished",
|
|
351
|
+
body: [
|
|
352
|
+
"Here is the clip: ",
|
|
353
|
+
"```ts",
|
|
354
|
+
"const a = 1;",
|
|
355
|
+
"```",
|
|
356
|
+
"| name | value |",
|
|
357
|
+
"| --- | --- |",
|
|
358
|
+
"| a | 1 |",
|
|
359
|
+
].join("\n"),
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const result = await adapter.send(payload, makeDestination());
|
|
364
|
+
|
|
365
|
+
expect(result.success).toBe(true);
|
|
366
|
+
const dispatched = fetchCalls[0]!.body;
|
|
367
|
+
expect(dispatched.title).toBe("Build finished");
|
|
368
|
+
const dispatchedBody = dispatched.body as string;
|
|
369
|
+
expect(dispatchedBody).not.toContain("![");
|
|
370
|
+
expect(dispatchedBody).not.toContain("```");
|
|
371
|
+
expect(dispatchedBody).not.toContain("|");
|
|
372
|
+
expect(dispatchedBody).toContain("Here is the clip:");
|
|
373
|
+
expect(dispatchedBody).toContain("const a = 1;");
|
|
374
|
+
expect(dispatchedBody).toContain("name value");
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// Guardian question copy joins its question and instruction with a blank
|
|
378
|
+
// line, and iOS renders the break, so flattening must not collapse it.
|
|
379
|
+
test("preserves newlines in the dispatched body", async () => {
|
|
380
|
+
const adapter = new PlatformPushAdapter();
|
|
381
|
+
const payload = makePayload({
|
|
382
|
+
copy: {
|
|
383
|
+
title: "Question",
|
|
384
|
+
body: "Should I book the flight?\n\nReply here to answer.",
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const result = await adapter.send(payload, makeDestination());
|
|
389
|
+
|
|
390
|
+
expect(result.success).toBe(true);
|
|
391
|
+
expect(fetchCalls[0]!.body.body).toBe(
|
|
392
|
+
"Should I book the flight?\n\nReply here to answer.",
|
|
393
|
+
);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test("leaves plain prose untouched", async () => {
|
|
397
|
+
const adapter = new PlatformPushAdapter();
|
|
398
|
+
const result = await adapter.send(makePayload(), makeDestination());
|
|
399
|
+
|
|
400
|
+
expect(result.success).toBe(true);
|
|
401
|
+
expect(fetchCalls[0]!.body.title).toBe("Reminder");
|
|
402
|
+
expect(fetchCalls[0]!.body.body).toBe("Check the oven!");
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// The pass-through path copies a verbatim `requestedMessage` into both the
|
|
406
|
+
// title and the body, so media-only copy flattens both to nothing. Every
|
|
407
|
+
// empty-copy guard in the pipeline runs upstream of this adapter, and the
|
|
408
|
+
// platform's serializer rejects a blank title, so an unrecovered field
|
|
409
|
+
// costs the whole notification.
|
|
410
|
+
describe("copy that flattens to nothing", () => {
|
|
411
|
+
test("names the media instead of dispatching blank fields", async () => {
|
|
412
|
+
const adapter = new PlatformPushAdapter();
|
|
413
|
+
const embed = "";
|
|
414
|
+
const payload = makePayload({ copy: { title: embed, body: embed } });
|
|
415
|
+
|
|
416
|
+
const result = await adapter.send(payload, makeDestination());
|
|
417
|
+
|
|
418
|
+
expect(result.success).toBe(true);
|
|
419
|
+
expect(fetchCalls[0]!.body.title).toBe("Sent clip");
|
|
420
|
+
expect(fetchCalls[0]!.body.body).toBe("Sent clip");
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test("counts several embeds", async () => {
|
|
424
|
+
const adapter = new PlatformPushAdapter();
|
|
425
|
+
const embeds =
|
|
426
|
+
" ";
|
|
427
|
+
const payload = makePayload({ copy: { title: embeds, body: embeds } });
|
|
428
|
+
|
|
429
|
+
await adapter.send(payload, makeDestination());
|
|
430
|
+
|
|
431
|
+
expect(fetchCalls[0]!.body.title).toBe("Sent 2 attachments");
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
// Nothing nameable is left, so the original beats a blank field: ugly
|
|
435
|
+
// copy still delivers, an empty title is a 400.
|
|
436
|
+
test("keeps the original when there is no media to name", async () => {
|
|
437
|
+
const adapter = new PlatformPushAdapter();
|
|
438
|
+
const payload = makePayload({ copy: { title: "###", body: "###" } });
|
|
439
|
+
|
|
440
|
+
await adapter.send(payload, makeDestination());
|
|
441
|
+
|
|
442
|
+
expect(fetchCalls[0]!.body.title).toBe("###");
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
343
447
|
test("omits optional fields when absent from payload", async () => {
|
|
344
448
|
const adapter = new PlatformPushAdapter();
|
|
345
449
|
const payload: ChannelDeliveryPayload = {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* deduplicated against prior firings of the same schedule.
|
|
4
4
|
*
|
|
5
5
|
* The scheduler supplies a unique per-firing dedupeKey
|
|
6
|
-
* (`schedule:notify:<id>:<timestamp>`) so `
|
|
6
|
+
* (`schedule:notify:<id>:<timestamp>`) so `setEventDedupeKey` is never
|
|
7
7
|
* called for schedule signals and `checkDedupe` never finds a matching
|
|
8
8
|
* row when the LLM decision engine generates a stable key like
|
|
9
9
|
* `schedule:notify:<id>`.
|
|
@@ -23,7 +23,7 @@ describe("oauth provider profiles (DB-seeded)", () => {
|
|
|
23
23
|
);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
test("google provider row contains bearer injection templates for
|
|
26
|
+
test("google provider row contains bearer injection templates for 6 Google API hosts", () => {
|
|
27
27
|
const provider = getProvider("google");
|
|
28
28
|
|
|
29
29
|
expect(provider).toBeDefined();
|
|
@@ -36,7 +36,7 @@ describe("oauth provider profiles (DB-seeded)", () => {
|
|
|
36
36
|
valuePrefix: string;
|
|
37
37
|
}>;
|
|
38
38
|
|
|
39
|
-
expect(templates).toHaveLength(
|
|
39
|
+
expect(templates).toHaveLength(6);
|
|
40
40
|
|
|
41
41
|
const byHost = new Map(templates.map((t) => [t.hostPattern, t]));
|
|
42
42
|
|
|
@@ -45,6 +45,8 @@ describe("oauth provider profiles (DB-seeded)", () => {
|
|
|
45
45
|
"www.googleapis.com",
|
|
46
46
|
"people.googleapis.com",
|
|
47
47
|
"docs.googleapis.com",
|
|
48
|
+
"tasks.googleapis.com",
|
|
49
|
+
"calendar.googleapis.com",
|
|
48
50
|
]) {
|
|
49
51
|
const tpl = byHost.get(host);
|
|
50
52
|
expect(tpl).toBeDefined();
|
|
@@ -1,7 +1,44 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
1
3
|
import { describe, expect, test } from "bun:test";
|
|
2
4
|
|
|
3
5
|
import { PROVIDER_SEED_DATA } from "../oauth/seed-providers.js";
|
|
4
6
|
|
|
7
|
+
const REPO_ROOT = dirname(dirname(dirname(import.meta.dir)));
|
|
8
|
+
const WEB_PUBLIC_DIR = join(REPO_ROOT, "clients/web/public");
|
|
9
|
+
const INTEGRATION_ICON_SOURCE = join(
|
|
10
|
+
REPO_ROOT,
|
|
11
|
+
"clients/web/src/components/integrations/integration-icon.tsx",
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Provider keys the web client draws without a `BUNDLED_LOGO_URLS` entry.
|
|
16
|
+
* Google's mark is multi-colour, so it ships as the `GoogleLogo` component
|
|
17
|
+
* and is returned before the bundled-asset lookup runs.
|
|
18
|
+
*/
|
|
19
|
+
const COMPONENT_RENDERED_PROVIDERS = new Set(["google"]);
|
|
20
|
+
|
|
21
|
+
/** `publicAsset("/images/...")` paths from `BUNDLED_LOGO_URLS`, by key. */
|
|
22
|
+
function readBundledLogoMap(): Map<string, string> {
|
|
23
|
+
const source = readFileSync(INTEGRATION_ICON_SOURCE, "utf8");
|
|
24
|
+
const block = source.match(
|
|
25
|
+
/const BUNDLED_LOGO_URLS: Record<string, string> = \{([\s\S]*?)\n\};/,
|
|
26
|
+
);
|
|
27
|
+
if (!block) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Could not find BUNDLED_LOGO_URLS in ${INTEGRATION_ICON_SOURCE}. If it ` +
|
|
30
|
+
`was renamed or restructured, update this test rather than deleting it.`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
const entries = new Map<string, string>();
|
|
34
|
+
for (const [, key, path] of block[1]!.matchAll(
|
|
35
|
+
/(\w+):\s*publicAsset\("([^"]+)"\)/g,
|
|
36
|
+
)) {
|
|
37
|
+
entries.set(key!, path!);
|
|
38
|
+
}
|
|
39
|
+
return entries;
|
|
40
|
+
}
|
|
41
|
+
|
|
5
42
|
/**
|
|
6
43
|
* Allowed CDN prefixes for the ``logoUrl`` field on ``PROVIDER_SEED_DATA``
|
|
7
44
|
* (``assistant/src/oauth/seed-providers.ts``):
|
|
@@ -41,3 +78,31 @@ describe("PROVIDER_SEED_DATA logo URLs", () => {
|
|
|
41
78
|
expect(invalid).toEqual([]);
|
|
42
79
|
});
|
|
43
80
|
});
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The `logoUrl` above is a fallback for providers registered at runtime. Every
|
|
84
|
+
* provider we seed ourselves must draw from an asset we ship, because an icon
|
|
85
|
+
* CDN can drop a brand at any time and the client then degrades to an initials
|
|
86
|
+
* avatar with nothing in CI to notice: the prefix check above passes just as
|
|
87
|
+
* happily for a URL that 404s. Simple Icons hosts no Microsoft mark and no
|
|
88
|
+
* Slack mark, so the seeded URLs for those brands do not resolve there.
|
|
89
|
+
*/
|
|
90
|
+
describe("PROVIDER_SEED_DATA bundled logo coverage", () => {
|
|
91
|
+
test("every seeded provider renders from a bundled asset", () => {
|
|
92
|
+
const bundled = readBundledLogoMap();
|
|
93
|
+
const uncovered = Object.keys(PROVIDER_SEED_DATA).filter(
|
|
94
|
+
(provider) =>
|
|
95
|
+
!bundled.has(provider) && !COMPONENT_RENDERED_PROVIDERS.has(provider),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
expect(uncovered).toEqual([]);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("every bundled logo path resolves to a file on disk", () => {
|
|
102
|
+
const missingFiles = [...readBundledLogoMap()]
|
|
103
|
+
.filter(([, path]) => !existsSync(join(WEB_PUBLIC_DIR, path)))
|
|
104
|
+
.map(([provider, path]) => ({ provider, path }));
|
|
105
|
+
|
|
106
|
+
expect(missingFiles).toEqual([]);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -291,9 +291,26 @@ describe("serializeProviderSummary", () => {
|
|
|
291
291
|
supports_managed_mode: true,
|
|
292
292
|
managed_service_is_paid: false,
|
|
293
293
|
feature_flag: null,
|
|
294
|
+
acts_as: "user",
|
|
294
295
|
});
|
|
295
296
|
});
|
|
296
297
|
|
|
298
|
+
test("names which sense of connected a provider represents", () => {
|
|
299
|
+
// The provider key does not say, and the naming actively misleads:
|
|
300
|
+
// `slack` is the user integration while its bot is `slack_channel`, but
|
|
301
|
+
// `telegram` is itself the bot. A caller asking "is X connected?" needs
|
|
302
|
+
// this to answer which X it found.
|
|
303
|
+
const sense = (provider: string) =>
|
|
304
|
+
serializeProviderSummary(makeRow({ provider }))!.acts_as;
|
|
305
|
+
|
|
306
|
+
expect(sense("slack")).toBe("user");
|
|
307
|
+
expect(sense("slack_channel")).toBe("assistant");
|
|
308
|
+
expect(sense("discord")).toBe("user");
|
|
309
|
+
expect(sense("discord_channel")).toBe("assistant");
|
|
310
|
+
expect(sense("telegram")).toBe("assistant");
|
|
311
|
+
expect(sense("google")).toBe("user");
|
|
312
|
+
});
|
|
313
|
+
|
|
297
314
|
test("nullifies missing optional fields", () => {
|
|
298
315
|
const row = makeRow({
|
|
299
316
|
displayLabel: null,
|
|
@@ -238,16 +238,19 @@ describe("OpenAIResponsesProvider explicit prompt caching (GPT-5.6+)", () => {
|
|
|
238
238
|
expect(breakpointedItemIndexes()).toEqual([0, 2]);
|
|
239
239
|
});
|
|
240
240
|
|
|
241
|
-
test("volatile single-message first turn:
|
|
241
|
+
test("volatile single-message first turn: the sole item is still marked", async () => {
|
|
242
242
|
const provider = makeProvider("gpt-5.6-sol");
|
|
243
243
|
await provider.sendMessage([userMsg("hi")], {
|
|
244
244
|
config: { mutableLatestUserMessage: true, promptCacheKey: "conv-1" },
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
+
// A volatile message is fixed within its own turn, so marking it prepays
|
|
248
|
+
// one write that the turn's tool-loop iterations read back, covering the
|
|
249
|
+
// instructions and tools that precede it in the cached prefix.
|
|
247
250
|
expect(lastStreamParams?.prompt_cache_options).toEqual({
|
|
248
251
|
mode: "explicit",
|
|
249
252
|
});
|
|
250
|
-
expect(breakpointedItemIndexes()).toEqual([]);
|
|
253
|
+
expect(breakpointedItemIndexes()).toEqual([0]);
|
|
251
254
|
});
|
|
252
255
|
|
|
253
256
|
test("tool loop: single fixed anchor on the turn-start user item, none on function_call_output", async () => {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
resolveRealPath,
|
|
16
16
|
sandboxPolicy,
|
|
17
17
|
sandboxPolicyWithHostFallback,
|
|
18
|
+
sandboxReadPolicy,
|
|
18
19
|
} from "../tools/shared/filesystem/path-policy.js";
|
|
19
20
|
import { getDotEnvPath } from "../util/platform.js";
|
|
20
21
|
|
|
@@ -506,6 +507,162 @@ describe("sandboxPolicyWithHostFallback", () => {
|
|
|
506
507
|
});
|
|
507
508
|
});
|
|
508
509
|
|
|
510
|
+
// ---------------------------------------------------------------------------
|
|
511
|
+
// Sandbox read policy
|
|
512
|
+
// ---------------------------------------------------------------------------
|
|
513
|
+
|
|
514
|
+
describe("sandboxReadPolicy", () => {
|
|
515
|
+
afterEach(() => {
|
|
516
|
+
delete process.env.IS_CONTAINERIZED;
|
|
517
|
+
delete process.env.GATEWAY_SECURITY_DIR;
|
|
518
|
+
delete process.env.CREDENTIAL_SECURITY_DIR;
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
test("matches sandboxPolicy for in-bounds paths", () => {
|
|
522
|
+
const boundary = makeTempDir();
|
|
523
|
+
mkdirSync(join(boundary, "sub"));
|
|
524
|
+
|
|
525
|
+
const result = sandboxReadPolicy("sub/file.txt", boundary);
|
|
526
|
+
expect(result).toEqual(sandboxPolicy("sub/file.txt", boundary));
|
|
527
|
+
expect(result.ok).toBe(true);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
test("reads outside the boundary when containerized", () => {
|
|
531
|
+
const boundary = makeTempDir();
|
|
532
|
+
const installTree = makeTempDir();
|
|
533
|
+
const target = join(installTree, "SKILL.md");
|
|
534
|
+
writeFileSync(target, "# skill");
|
|
535
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
536
|
+
|
|
537
|
+
const result = sandboxReadPolicy(target, boundary);
|
|
538
|
+
expect(result.ok).toBe(true);
|
|
539
|
+
if (result.ok) {
|
|
540
|
+
expect(result.resolved).toBe(target);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
test("follows an in-boundary symlink that points outside", () => {
|
|
545
|
+
const boundary = makeTempDir();
|
|
546
|
+
const outside = makeTempDir();
|
|
547
|
+
const target = join(outside, "reference.md");
|
|
548
|
+
writeFileSync(target, "reference body");
|
|
549
|
+
symlinkSync(target, join(boundary, "link.md"));
|
|
550
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
551
|
+
|
|
552
|
+
const result = sandboxReadPolicy(join(boundary, "link.md"), boundary);
|
|
553
|
+
expect(result.ok).toBe(true);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
test("denies the gateway security dir when containerized", () => {
|
|
557
|
+
const boundary = makeTempDir();
|
|
558
|
+
const securityDir = makeTempDir();
|
|
559
|
+
writeFileSync(join(securityDir, "trust.json"), "{}");
|
|
560
|
+
process.env.GATEWAY_SECURITY_DIR = securityDir;
|
|
561
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
562
|
+
|
|
563
|
+
const result = sandboxReadPolicy(join(securityDir, "trust.json"), boundary);
|
|
564
|
+
expect(result.ok).toBe(false);
|
|
565
|
+
if (!result.ok) {
|
|
566
|
+
expect(result.reason).toBe("denied");
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
test("denies a symlink that resolves into the credential security dir", () => {
|
|
571
|
+
const boundary = makeTempDir();
|
|
572
|
+
const securityDir = makeTempDir();
|
|
573
|
+
writeFileSync(join(securityDir, "keys.enc"), "cipher");
|
|
574
|
+
symlinkSync(join(securityDir, "keys.enc"), join(boundary, "innocent.txt"));
|
|
575
|
+
process.env.CREDENTIAL_SECURITY_DIR = securityDir;
|
|
576
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
577
|
+
|
|
578
|
+
const result = sandboxReadPolicy(join(boundary, "innocent.txt"), boundary);
|
|
579
|
+
expect(result.ok).toBe(false);
|
|
580
|
+
if (!result.ok) {
|
|
581
|
+
expect(result.reason).toBe("denied");
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
test("denies a denylisted basename outside the boundary", () => {
|
|
586
|
+
const boundary = makeTempDir();
|
|
587
|
+
const outside = makeTempDir();
|
|
588
|
+
writeFileSync(join(outside, "backup.key"), "key");
|
|
589
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
590
|
+
|
|
591
|
+
const result = sandboxReadPolicy(join(outside, "backup.key"), boundary);
|
|
592
|
+
expect(result.ok).toBe(false);
|
|
593
|
+
if (!result.ok) {
|
|
594
|
+
expect(result.reason).toBe("denied");
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
test("fails closed to the hard boundary when a security-dir override is relative", () => {
|
|
599
|
+
const boundary = makeTempDir();
|
|
600
|
+
const outside = makeTempDir();
|
|
601
|
+
writeFileSync(join(outside, "file.txt"), "x");
|
|
602
|
+
// Unmirrorable deny set: the real security dir could be anywhere, so the
|
|
603
|
+
// read allowance must not widen past the boundary.
|
|
604
|
+
process.env.GATEWAY_SECURITY_DIR = "relative/security-dir";
|
|
605
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
606
|
+
|
|
607
|
+
const result = sandboxReadPolicy(join(outside, "file.txt"), boundary);
|
|
608
|
+
expect(result.ok).toBe(false);
|
|
609
|
+
if (!result.ok) {
|
|
610
|
+
expect(result.reason).toBe("out_of_bounds");
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// The daemon's own environment carries the actor token signing key, the CES
|
|
615
|
+
// service token, the guardian bootstrap secret, and forwarded provider API
|
|
616
|
+
// keys, so no policy may serve a process environment block.
|
|
617
|
+
test.each([
|
|
618
|
+
"/proc/self/environ",
|
|
619
|
+
"/proc/thread-self/environ",
|
|
620
|
+
"/proc/1/environ",
|
|
621
|
+
"/proc/4242/environ",
|
|
622
|
+
])("denies %s", (path) => {
|
|
623
|
+
const boundary = makeTempDir();
|
|
624
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
625
|
+
|
|
626
|
+
const result = sandboxReadPolicy(path, boundary, { mustExist: false });
|
|
627
|
+
expect(result.ok).toBe(false);
|
|
628
|
+
if (!result.ok) {
|
|
629
|
+
expect(result.reason).toBe("denied");
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
test("denies a process environ path reached through a symlink", () => {
|
|
634
|
+
const boundary = makeTempDir();
|
|
635
|
+
symlinkSync("/proc/self/environ", join(boundary, "innocent.txt"));
|
|
636
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
637
|
+
|
|
638
|
+
const result = sandboxReadPolicy(join(boundary, "innocent.txt"), boundary, {
|
|
639
|
+
mustExist: false,
|
|
640
|
+
});
|
|
641
|
+
expect(result.ok).toBe(false);
|
|
642
|
+
if (!result.ok) {
|
|
643
|
+
expect(result.reason).toBe("denied");
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
test("still allows other /proc entries", () => {
|
|
648
|
+
const boundary = makeTempDir();
|
|
649
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
650
|
+
|
|
651
|
+
const result = sandboxReadPolicy("/proc/self/status", boundary, {
|
|
652
|
+
mustExist: false,
|
|
653
|
+
});
|
|
654
|
+
expect(result.ok).toBe(true);
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
test("does not deny an unrelated file named environ", () => {
|
|
658
|
+
const boundary = makeTempDir();
|
|
659
|
+
writeFileSync(join(boundary, "environ"), "notes");
|
|
660
|
+
|
|
661
|
+
const result = sandboxReadPolicy("environ", boundary);
|
|
662
|
+
expect(result.ok).toBe(true);
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
|
|
509
666
|
// ---------------------------------------------------------------------------
|
|
510
667
|
// Host policy
|
|
511
668
|
// ---------------------------------------------------------------------------
|
|
@@ -575,7 +732,13 @@ describe("resolveRealPath", () => {
|
|
|
575
732
|
});
|
|
576
733
|
|
|
577
734
|
test("falls back to the lexical path when nothing on it exists", () => {
|
|
578
|
-
|
|
735
|
+
// realpath the temp root so a symlinked prefix (macOS /var -> /private/var)
|
|
736
|
+
// is not mistaken for the resolution under test.
|
|
737
|
+
const phantom = join(
|
|
738
|
+
realpathSync(tmpdir()),
|
|
739
|
+
"definitely-not-here-12345",
|
|
740
|
+
"nope.txt",
|
|
741
|
+
);
|
|
579
742
|
expect(resolveRealPath(phantom)).toBe(phantom);
|
|
580
743
|
});
|
|
581
744
|
});
|
|
@@ -49,7 +49,7 @@ describe("referenceMediaBlocksForPersist", () => {
|
|
|
49
49
|
},
|
|
50
50
|
];
|
|
51
51
|
|
|
52
|
-
const referenced = referenceMediaBlocksForPersist(
|
|
52
|
+
const referenced = await referenceMediaBlocksForPersist(
|
|
53
53
|
conv.id,
|
|
54
54
|
conv.createdAt,
|
|
55
55
|
msg.id,
|
|
@@ -101,7 +101,7 @@ describe("referenceMediaBlocksForPersist", () => {
|
|
|
101
101
|
},
|
|
102
102
|
];
|
|
103
103
|
|
|
104
|
-
const referenced = referenceMediaBlocksForPersist(
|
|
104
|
+
const referenced = await referenceMediaBlocksForPersist(
|
|
105
105
|
conv.id,
|
|
106
106
|
conv.createdAt,
|
|
107
107
|
msg.id,
|
|
@@ -28,8 +28,8 @@ mock.module("../agent/image-optimize.js", () => ({
|
|
|
28
28
|
// oversized (never undersized), so the min-dimension gate never matches
|
|
29
29
|
// and the rejection-path upscale is never reached.
|
|
30
30
|
isBelowMinDimension: () => false,
|
|
31
|
-
upscaleImageToMinimum: () => null,
|
|
32
|
-
optimizeImageForTransport: () => ({
|
|
31
|
+
upscaleImageToMinimum: async () => null,
|
|
32
|
+
optimizeImageForTransport: async () => ({
|
|
33
33
|
data: SHRUNK_DATA,
|
|
34
34
|
mediaType: "image/jpeg",
|
|
35
35
|
}),
|
|
@@ -133,7 +133,7 @@ describe("persistUnsendableImageDowngrades (downscalable host)", () => {
|
|
|
133
133
|
);
|
|
134
134
|
|
|
135
135
|
// WHEN the downgrade is persisted
|
|
136
|
-
const rewritten = persistUnsendableImageDowngrades(conv.id);
|
|
136
|
+
const rewritten = await persistUnsendableImageDowngrades(conv.id);
|
|
137
137
|
|
|
138
138
|
// THEN the nested block stays an image, rewritten to the downscaled payload
|
|
139
139
|
expect(rewritten).toBe(1);
|
|
@@ -159,10 +159,10 @@ describe("persistUnsendableImageDowngrades (downscalable host)", () => {
|
|
|
159
159
|
JSON.stringify([toolResultWithImage(oversizedPngBase64())]),
|
|
160
160
|
{ skipIndexing: true },
|
|
161
161
|
);
|
|
162
|
-
expect(persistUnsendableImageDowngrades(conv.id)).toBe(1);
|
|
162
|
+
expect(await persistUnsendableImageDowngrades(conv.id)).toBe(1);
|
|
163
163
|
|
|
164
164
|
// WHEN the downgrade runs again
|
|
165
|
-
const secondRun = persistUnsendableImageDowngrades(conv.id);
|
|
165
|
+
const secondRun = await persistUnsendableImageDowngrades(conv.id);
|
|
166
166
|
|
|
167
167
|
// THEN nothing further is rewritten
|
|
168
168
|
expect(secondRun).toBe(0);
|