@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
|
@@ -447,13 +447,20 @@ export function executeDocumentUpdate(
|
|
|
447
447
|
};
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
-
//
|
|
450
|
+
// No client is connected to render the edit, but the write landed, so this is
|
|
451
|
+
// a success. Reporting it as an error would strand a headless turn (a
|
|
452
|
+
// schedule, SMS, or Telegram channel): post-execution hooks are skipped for
|
|
453
|
+
// errored tools, so the documents-changed broadcast that tells clients about
|
|
454
|
+
// the edit would never fire, and the model would be told to retry a write
|
|
455
|
+
// that already succeeded.
|
|
451
456
|
return {
|
|
452
457
|
content: JSON.stringify({
|
|
453
|
-
success:
|
|
454
|
-
|
|
458
|
+
success: true,
|
|
459
|
+
surface_id: surfaceId,
|
|
460
|
+
mode,
|
|
461
|
+
message: "Document content updated (no client connected to render it)",
|
|
455
462
|
}),
|
|
456
|
-
isError:
|
|
463
|
+
isError: false,
|
|
457
464
|
};
|
|
458
465
|
}
|
|
459
466
|
|
|
@@ -6,11 +6,18 @@ const TIMEOUT_SENTINEL = Symbol("tool-timeout");
|
|
|
6
6
|
/**
|
|
7
7
|
* Convert a config-provided seconds value to a safe milliseconds value,
|
|
8
8
|
* falling back to the default if the input is NaN, non-finite, zero, or negative.
|
|
9
|
+
*
|
|
10
|
+
* `fallbackMs` lets callers governed by a different budget (e.g. the inline
|
|
11
|
+
* grant wait) keep their own floor instead of inheriting the tool-execution
|
|
12
|
+
* default.
|
|
9
13
|
*/
|
|
10
|
-
export function safeTimeoutMs(
|
|
14
|
+
export function safeTimeoutMs(
|
|
15
|
+
sec: unknown,
|
|
16
|
+
fallbackMs: number = DEFAULT_TOOL_EXECUTION_TIMEOUT_SEC * 1000,
|
|
17
|
+
): number {
|
|
11
18
|
const n = Number(sec);
|
|
12
19
|
if (!Number.isFinite(n) || n <= 0) {
|
|
13
|
-
return
|
|
20
|
+
return fallbackMs;
|
|
14
21
|
}
|
|
15
22
|
return n * 1000;
|
|
16
23
|
}
|
package/src/tools/executor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
2
|
|
|
3
3
|
import { getConfig } from "../config/loader.js";
|
|
4
4
|
import { PermissionPrompter } from "../permissions/prompter.js";
|
|
@@ -484,18 +484,19 @@ export function computePerToolTimeoutMs(
|
|
|
484
484
|
* confirmation payload — ahead of approval. Host file tools have no preview
|
|
485
485
|
* for the same reason.
|
|
486
486
|
*/
|
|
487
|
-
function computePreviewDiff(
|
|
487
|
+
async function computePreviewDiff(
|
|
488
488
|
toolName: string,
|
|
489
489
|
input: Record<string, unknown>,
|
|
490
490
|
workingDir: string,
|
|
491
|
-
):
|
|
491
|
+
): Promise<
|
|
492
492
|
| {
|
|
493
493
|
filePath: string;
|
|
494
494
|
oldContent: string;
|
|
495
495
|
newContent: string;
|
|
496
496
|
isNewFile: boolean;
|
|
497
497
|
}
|
|
498
|
-
| undefined
|
|
498
|
+
| undefined
|
|
499
|
+
> {
|
|
499
500
|
try {
|
|
500
501
|
if (toolName === "file_write") {
|
|
501
502
|
// Parse with the tool's own schema so the preview reads the same shape
|
|
@@ -519,7 +520,7 @@ function computePreviewDiff(
|
|
|
519
520
|
return undefined;
|
|
520
521
|
}
|
|
521
522
|
}
|
|
522
|
-
const oldContent = isNewFile ? "" :
|
|
523
|
+
const oldContent = isNewFile ? "" : await readFile(filePath, "utf-8");
|
|
523
524
|
return { filePath, oldContent, newContent: content, isNewFile };
|
|
524
525
|
}
|
|
525
526
|
|
|
@@ -545,7 +546,7 @@ function computePreviewDiff(
|
|
|
545
546
|
if (stat.size > MAX_FILE_SIZE_BYTES) {
|
|
546
547
|
return undefined;
|
|
547
548
|
}
|
|
548
|
-
const content =
|
|
549
|
+
const content = await readFile(filePath, "utf-8");
|
|
549
550
|
const replaceAll = parsed.data.replace_all === true;
|
|
550
551
|
const result = applyEdit(content, oldString, newString, replaceAll);
|
|
551
552
|
if (!result.ok) {
|
|
@@ -61,7 +61,7 @@ export const fileListTool = {
|
|
|
61
61
|
sandboxPolicy(path, context.workingDir, opts),
|
|
62
62
|
);
|
|
63
63
|
|
|
64
|
-
const result = ops.listDirSafe({ path: rawPath, glob });
|
|
64
|
+
const result = await ops.listDirSafe({ path: rawPath, glob });
|
|
65
65
|
|
|
66
66
|
if (!result.ok) {
|
|
67
67
|
const { error } = result;
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
IMAGE_EXTENSIONS,
|
|
13
13
|
readImageFile,
|
|
14
14
|
} from "../shared/filesystem/image-read.js";
|
|
15
|
-
import {
|
|
15
|
+
import { sandboxReadPolicy } from "../shared/filesystem/path-policy.js";
|
|
16
16
|
import {
|
|
17
17
|
invalidToolInputResult,
|
|
18
18
|
toToolInputSchema,
|
|
@@ -43,7 +43,7 @@ export const fileReadInputSchema = z.looseObject({
|
|
|
43
43
|
.catch(undefined),
|
|
44
44
|
limit: z
|
|
45
45
|
.number()
|
|
46
|
-
.describe("Maximum number of lines to read")
|
|
46
|
+
.describe("Maximum number of lines to read (defaults to 2000)")
|
|
47
47
|
.optional()
|
|
48
48
|
.catch(undefined),
|
|
49
49
|
activity: z
|
|
@@ -58,7 +58,7 @@ export const fileReadInputSchema = z.looseObject({
|
|
|
58
58
|
export const fileReadTool = {
|
|
59
59
|
name: "file_read",
|
|
60
60
|
description:
|
|
61
|
-
"Read the contents of a file on your own machine. For image files (JPEG, PNG, GIF, WebP), returns the image for visual analysis. For audio files (MP3, WAV, OGG, FLAC, AAC, M4A), returns the audio for listening. Use host_file_read for files on your guardian's device instead.",
|
|
61
|
+
"Read the contents of a file on your own machine. Text reads return the first 2000 lines unless you pass `limit`; when a read stops short the result says so, and `offset` pages on from there. For image files (JPEG, PNG, GIF, WebP), returns the image for visual analysis. For audio files (MP3, WAV, OGG, FLAC, AAC, M4A), returns the audio for listening. Use host_file_read for files on your guardian's device instead.",
|
|
62
62
|
category: "filesystem",
|
|
63
63
|
executionTarget: "sandbox",
|
|
64
64
|
defaultRiskLevel: RiskLevel.Low,
|
|
@@ -80,10 +80,7 @@ export const fileReadTool = {
|
|
|
80
80
|
// For image files, delegate to the shared image reader.
|
|
81
81
|
const ext = extname(rawPath).toLowerCase();
|
|
82
82
|
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
83
|
-
const pathCheck =
|
|
84
|
-
rawPath,
|
|
85
|
-
context.workingDir,
|
|
86
|
-
);
|
|
83
|
+
const pathCheck = sandboxReadPolicy(rawPath, context.workingDir);
|
|
87
84
|
if (!pathCheck.ok) {
|
|
88
85
|
return {
|
|
89
86
|
content: `Error: ${pathCheck.error}. To read files outside the workspace, use the host_file_read tool instead.`,
|
|
@@ -95,10 +92,7 @@ export const fileReadTool = {
|
|
|
95
92
|
|
|
96
93
|
// For audio files, delegate to the shared audio reader.
|
|
97
94
|
if (AUDIO_EXTENSIONS.has(ext)) {
|
|
98
|
-
const pathCheck =
|
|
99
|
-
rawPath,
|
|
100
|
-
context.workingDir,
|
|
101
|
-
);
|
|
95
|
+
const pathCheck = sandboxReadPolicy(rawPath, context.workingDir);
|
|
102
96
|
if (!pathCheck.ok) {
|
|
103
97
|
return {
|
|
104
98
|
content: `Error: ${pathCheck.error}. To read files outside the workspace, use the host_file_read tool instead.`,
|
|
@@ -109,10 +103,10 @@ export const fileReadTool = {
|
|
|
109
103
|
}
|
|
110
104
|
|
|
111
105
|
const ops = new FileSystemOps((path, opts) =>
|
|
112
|
-
|
|
106
|
+
sandboxReadPolicy(path, context.workingDir, opts),
|
|
113
107
|
);
|
|
114
108
|
|
|
115
|
-
const result = ops.readFileSafe({ path: rawPath, offset, limit });
|
|
109
|
+
const result = await ops.readFileSafe({ path: rawPath, offset, limit });
|
|
116
110
|
|
|
117
111
|
if (!result.ok) {
|
|
118
112
|
const { error } = result;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
2
2
|
import { basename, join, relative } from "node:path";
|
|
3
3
|
|
|
4
4
|
import { minimatch } from "minimatch";
|
|
@@ -48,11 +48,10 @@ const MAX_DISPLAY_LINE_LENGTH = 2000;
|
|
|
48
48
|
// report the result as truncated.
|
|
49
49
|
const MAX_OUTPUT_BYTES = 4 * 1024 * 1024; // 4 MiB
|
|
50
50
|
|
|
51
|
-
// Wall-clock deadline for the whole search.
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
// stop the walk promptly.
|
|
51
|
+
// Wall-clock deadline for the whole search. File I/O yields between files,
|
|
52
|
+
// but the per-file line loop is CPU-bound; checking this deadline (and the
|
|
53
|
+
// abort signal) once per line bounds how long a search over a very large tree
|
|
54
|
+
// can occupy the event loop and lets an external abort stop the walk promptly.
|
|
56
55
|
const MAX_SEARCH_MS = 10_000; // 10 s
|
|
57
56
|
|
|
58
57
|
const DEFAULT_MAX_RESULTS = 200;
|
|
@@ -150,7 +149,7 @@ export const codeSearchTool = {
|
|
|
150
149
|
// Match with the linear-time RE2 engine (via re2js) instead of V8's
|
|
151
150
|
// backtracking RegExp. RE2 guarantees linear-time matching, so a
|
|
152
151
|
// user/subagent-supplied pattern cannot trigger catastrophic backtracking
|
|
153
|
-
// and
|
|
152
|
+
// and pin the event loop inside the per-file line loop. The trade-off is that RE2 rejects
|
|
154
153
|
// backreferences and lookarounds; compile() throws on those, surfaced as a
|
|
155
154
|
// clean error below.
|
|
156
155
|
let regex: RE2JS;
|
|
@@ -189,7 +188,7 @@ export const codeSearchTool = {
|
|
|
189
188
|
// NOT_FOUND / NOT_A_DIRECTORY reporting in file_list.
|
|
190
189
|
let rootStat: import("node:fs").Stats;
|
|
191
190
|
try {
|
|
192
|
-
rootStat =
|
|
191
|
+
rootStat = await stat(root);
|
|
193
192
|
} catch {
|
|
194
193
|
return {
|
|
195
194
|
content: `Error: path not found: ${rawPath}`,
|
|
@@ -198,8 +197,8 @@ export const codeSearchTool = {
|
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
// Start the wall-clock deadline before walking so a pathological regex
|
|
201
|
-
// (or an external abort) can stop the
|
|
202
|
-
//
|
|
200
|
+
// (or an external abort) can stop the scan mid-flight instead of running
|
|
201
|
+
// until the whole tree is exhausted.
|
|
203
202
|
const searchStart = Date.now();
|
|
204
203
|
|
|
205
204
|
const lines: string[] = [];
|
|
@@ -228,7 +227,7 @@ export const codeSearchTool = {
|
|
|
228
227
|
let totalBytes = 0;
|
|
229
228
|
// Number of directory entries visited during the walk (files + subdirs),
|
|
230
229
|
// bounded by MAX_ENTRIES_TRAVERSED so a pathological tree can't run the
|
|
231
|
-
//
|
|
230
|
+
// readdir/stat work unbounded even when no file is ever read.
|
|
232
231
|
let entriesTraversed = 0;
|
|
233
232
|
// Set when an EXPLICIT file root (not a child discovered mid-walk) can't be
|
|
234
233
|
// read — e.g. EACCES/EPERM. A child file's read failure is optional and
|
|
@@ -264,7 +263,10 @@ export const codeSearchTool = {
|
|
|
264
263
|
|
|
265
264
|
// Scan a single regular file for matches. Applies the denied-basename guard
|
|
266
265
|
// and per-file size caps. Returns nothing; mutates the shared accumulators.
|
|
267
|
-
const scanFile = (
|
|
266
|
+
const scanFile = async (
|
|
267
|
+
full: string,
|
|
268
|
+
isExplicitRoot = false,
|
|
269
|
+
): Promise<void> => {
|
|
268
270
|
if (truncated) {
|
|
269
271
|
return;
|
|
270
272
|
}
|
|
@@ -306,7 +308,7 @@ export const codeSearchTool = {
|
|
|
306
308
|
|
|
307
309
|
let size: number;
|
|
308
310
|
try {
|
|
309
|
-
size =
|
|
311
|
+
size = (await stat(full)).size;
|
|
310
312
|
} catch {
|
|
311
313
|
return;
|
|
312
314
|
}
|
|
@@ -323,7 +325,7 @@ export const codeSearchTool = {
|
|
|
323
325
|
|
|
324
326
|
let buf: Buffer;
|
|
325
327
|
try {
|
|
326
|
-
buf =
|
|
328
|
+
buf = await readFile(full);
|
|
327
329
|
} catch (err) {
|
|
328
330
|
// A child file discovered mid-walk is optional — skip it silently. But
|
|
329
331
|
// an explicit file root that can't be read was never searched, so record
|
|
@@ -407,13 +409,13 @@ export const codeSearchTool = {
|
|
|
407
409
|
}
|
|
408
410
|
};
|
|
409
411
|
|
|
410
|
-
const walk = (dir: string, isExplicitRoot = false): void => {
|
|
412
|
+
const walk = async (dir: string, isExplicitRoot = false): Promise<void> => {
|
|
411
413
|
if (truncated) {
|
|
412
414
|
return;
|
|
413
415
|
}
|
|
414
416
|
// Bound the traversal itself, not just file reads: a deep/wide tree of
|
|
415
417
|
// directories (or many entries that never get read) could otherwise run
|
|
416
|
-
// the
|
|
418
|
+
// the readdir/stat work far past the advertised deadline.
|
|
417
419
|
if (Date.now() - searchStart > MAX_SEARCH_MS || context.signal?.aborted) {
|
|
418
420
|
truncated = true;
|
|
419
421
|
timedOut = true;
|
|
@@ -421,7 +423,7 @@ export const codeSearchTool = {
|
|
|
421
423
|
}
|
|
422
424
|
let entries: import("node:fs").Dirent[];
|
|
423
425
|
try {
|
|
424
|
-
entries =
|
|
426
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
425
427
|
} catch (err) {
|
|
426
428
|
// A child directory discovered mid-walk is optional — skip it silently.
|
|
427
429
|
// But an explicit directory root that can't be read (e.g. EACCES/EPERM)
|
|
@@ -458,18 +460,18 @@ export const codeSearchTool = {
|
|
|
458
460
|
if (IGNORED_DIRS.has(entry.name)) {
|
|
459
461
|
continue;
|
|
460
462
|
}
|
|
461
|
-
walk(full);
|
|
463
|
+
await walk(full);
|
|
462
464
|
continue;
|
|
463
465
|
}
|
|
464
466
|
if (!entry.isFile()) {
|
|
465
467
|
continue;
|
|
466
468
|
}
|
|
467
|
-
scanFile(full);
|
|
469
|
+
await scanFile(full);
|
|
468
470
|
}
|
|
469
471
|
};
|
|
470
472
|
|
|
471
473
|
if (rootStat.isDirectory()) {
|
|
472
|
-
walk(root, true);
|
|
474
|
+
await walk(root, true);
|
|
473
475
|
// An explicit directory root that statSync sees but readdirSync can't read
|
|
474
476
|
// (EACCES/EPERM) was never searched — surface a hard error instead of a
|
|
475
477
|
// false "No matches found", mirroring the unreadable explicit-file root.
|
|
@@ -487,7 +489,7 @@ export const codeSearchTool = {
|
|
|
487
489
|
isError: true,
|
|
488
490
|
};
|
|
489
491
|
}
|
|
490
|
-
scanFile(root, true);
|
|
492
|
+
await scanFile(root, true);
|
|
491
493
|
if (rootReadError) {
|
|
492
494
|
return { content: rootReadError, isError: true };
|
|
493
495
|
}
|
|
@@ -129,7 +129,10 @@ export const fileWriteTool = {
|
|
|
129
129
|
sandboxPolicyWithHostFallback(path, context.workingDir, opts),
|
|
130
130
|
);
|
|
131
131
|
|
|
132
|
-
const result = ops.writeFileSafe({
|
|
132
|
+
const result = await ops.writeFileSafe({
|
|
133
|
+
path: rawPath,
|
|
134
|
+
content: fileContent,
|
|
135
|
+
});
|
|
133
136
|
|
|
134
137
|
if (!result.ok) {
|
|
135
138
|
const { error } = result;
|
|
@@ -25,7 +25,12 @@ import type {
|
|
|
25
25
|
* a non-string (or empty) value means "untargeted".
|
|
26
26
|
*/
|
|
27
27
|
export const hostFileEditInputSchema = z.looseObject({
|
|
28
|
-
path: z
|
|
28
|
+
path: z
|
|
29
|
+
.string()
|
|
30
|
+
.min(1)
|
|
31
|
+
.describe(
|
|
32
|
+
"Absolute path on the guardian's device, which is a separate filesystem from your workspace, to edit.",
|
|
33
|
+
),
|
|
29
34
|
old_string: z
|
|
30
35
|
.string()
|
|
31
36
|
.min(1, { message: "old_string must not be empty" })
|
|
@@ -158,7 +163,7 @@ export const hostFileEditTool = {
|
|
|
158
163
|
|
|
159
164
|
const ops = new FileSystemOps(hostPolicy);
|
|
160
165
|
|
|
161
|
-
const result = ops.editFileSafe({
|
|
166
|
+
const result = await ops.editFileSafe({
|
|
162
167
|
path: rawPath,
|
|
163
168
|
oldString,
|
|
164
169
|
newString,
|
|
@@ -10,7 +10,10 @@ import {
|
|
|
10
10
|
AUDIO_EXTENSIONS,
|
|
11
11
|
readAudioFile,
|
|
12
12
|
} from "../shared/filesystem/audio-read.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
DEFAULT_READ_LINE_LIMIT,
|
|
15
|
+
FileSystemOps,
|
|
16
|
+
} from "../shared/filesystem/file-ops-service.js";
|
|
14
17
|
import {
|
|
15
18
|
IMAGE_EXTENSIONS,
|
|
16
19
|
readImageFile,
|
|
@@ -30,12 +33,17 @@ import type {
|
|
|
30
33
|
* Model-input schema, the single source for both runtime validation (via
|
|
31
34
|
* `TOOL_INPUT_SCHEMAS`) and the advertised `input_schema` below — mirrors
|
|
32
35
|
* `filesystem/read.ts`. `offset`/`limit` catch to `undefined` so a
|
|
33
|
-
* non-numeric value
|
|
34
|
-
* `target_client_id` catches so a non-string (or empty) value means
|
|
36
|
+
* non-numeric value falls back to the default line window instead of failing
|
|
37
|
+
* the call; `target_client_id` catches so a non-string (or empty) value means
|
|
35
38
|
* "untargeted".
|
|
36
39
|
*/
|
|
37
40
|
export const hostFileReadInputSchema = z.looseObject({
|
|
38
|
-
path: z
|
|
41
|
+
path: z
|
|
42
|
+
.string()
|
|
43
|
+
.min(1)
|
|
44
|
+
.describe(
|
|
45
|
+
"Absolute path on the guardian's device, which is a separate filesystem from your workspace, to read.",
|
|
46
|
+
),
|
|
39
47
|
offset: z
|
|
40
48
|
.number()
|
|
41
49
|
.describe("Line number to start reading from (1-indexed)")
|
|
@@ -43,7 +51,7 @@ export const hostFileReadInputSchema = z.looseObject({
|
|
|
43
51
|
.catch(undefined),
|
|
44
52
|
limit: z
|
|
45
53
|
.number()
|
|
46
|
-
.describe("Maximum number of lines to read")
|
|
54
|
+
.describe("Maximum number of lines to read (defaults to 2000)")
|
|
47
55
|
.optional()
|
|
48
56
|
.catch(undefined),
|
|
49
57
|
target_client_id: z
|
|
@@ -58,7 +66,7 @@ export const hostFileReadInputSchema = z.looseObject({
|
|
|
58
66
|
export const hostFileReadTool = {
|
|
59
67
|
name: "host_file_read",
|
|
60
68
|
description:
|
|
61
|
-
"Read the contents of a file on your guardian's device, including images (JPEG, PNG, GIF, WebP) and audio (MP3, WAV, OGG, FLAC, AAC, M4A). For files on your own machine, use file_read instead.",
|
|
69
|
+
"Read the contents of a file on your guardian's device, including images (JPEG, PNG, GIF, WebP) and audio (MP3, WAV, OGG, FLAC, AAC, M4A). Text reads return the first 2000 lines unless you pass `limit`; when a read stops short the result says so, and `offset` pages on from there. For files on your own machine, use file_read instead.",
|
|
62
70
|
category: "host-filesystem",
|
|
63
71
|
executionTarget: "host",
|
|
64
72
|
defaultRiskLevel: RiskLevel.Medium,
|
|
@@ -73,7 +81,12 @@ export const hostFileReadTool = {
|
|
|
73
81
|
if (!parsed.success) {
|
|
74
82
|
return invalidToolInputResult("host_file_read", parsed.error);
|
|
75
83
|
}
|
|
76
|
-
const { path: rawPath, offset
|
|
84
|
+
const { path: rawPath, offset } = parsed.data;
|
|
85
|
+
// Resolve the default here rather than leaving it to the read, so the
|
|
86
|
+
// proxied branch below is bounded by the same window as the local one. A
|
|
87
|
+
// proxied read that sent no limit would stream a whole host file across
|
|
88
|
+
// the bridge before anything could trim it.
|
|
89
|
+
const limit = parsed.data.limit ?? DEFAULT_READ_LINE_LIMIT;
|
|
77
90
|
|
|
78
91
|
const targetClientId =
|
|
79
92
|
parsed.data.target_client_id !== ""
|
|
@@ -170,7 +183,7 @@ export const hostFileReadTool = {
|
|
|
170
183
|
|
|
171
184
|
const ops = new FileSystemOps(hostPolicy);
|
|
172
185
|
|
|
173
|
-
const result = ops.readFileSafe({ path: rawPath, offset, limit });
|
|
186
|
+
const result = await ops.readFileSafe({ path: rawPath, offset, limit });
|
|
174
187
|
|
|
175
188
|
if (!result.ok) {
|
|
176
189
|
const { error } = result;
|
|
@@ -24,7 +24,12 @@ import type {
|
|
|
24
24
|
* non-string (or empty) value means "untargeted".
|
|
25
25
|
*/
|
|
26
26
|
export const hostFileWriteInputSchema = z.looseObject({
|
|
27
|
-
path: z
|
|
27
|
+
path: z
|
|
28
|
+
.string()
|
|
29
|
+
.min(1)
|
|
30
|
+
.describe(
|
|
31
|
+
"Absolute path on the guardian's device, which is a separate filesystem from your workspace, to write.",
|
|
32
|
+
),
|
|
28
33
|
content: z.string().describe("The content to write to the file"),
|
|
29
34
|
target_client_id: z
|
|
30
35
|
.string()
|
|
@@ -131,7 +136,10 @@ export const hostFileWriteTool = {
|
|
|
131
136
|
|
|
132
137
|
const ops = new FileSystemOps(hostPolicy);
|
|
133
138
|
|
|
134
|
-
const result = ops.writeFileSafe({
|
|
139
|
+
const result = await ops.writeFileSafe({
|
|
140
|
+
path: rawPath,
|
|
141
|
+
content: fileContent,
|
|
142
|
+
});
|
|
135
143
|
|
|
136
144
|
if (!result.ok) {
|
|
137
145
|
const { error } = result;
|
|
@@ -121,7 +121,7 @@ export const hostShellInputSchema = z.looseObject({
|
|
|
121
121
|
z
|
|
122
122
|
.string()
|
|
123
123
|
.describe(
|
|
124
|
-
"Optional absolute host
|
|
124
|
+
"Optional absolute path on the host's filesystem, which is separate from your workspace (defaults to the host user's home).",
|
|
125
125
|
),
|
|
126
126
|
),
|
|
127
127
|
timeout_seconds: z
|
|
@@ -150,7 +150,7 @@ export const hostShellInputSchema = z.looseObject({
|
|
|
150
150
|
export const hostShellTool = {
|
|
151
151
|
name: "host_bash",
|
|
152
152
|
description:
|
|
153
|
-
"LAST RESORT — Execute a shell command directly on the host machine. You MUST strongly prefer the regular `bash` tool for all commands. Only use `host_bash` when you are absolutely certain the command MUST run on the host machine and CANNOT run in the workspace (e.g., managing host-level system services, accessing host-only peripherals, or interacting with host paths outside the workspace). If in doubt, use `bash` instead. Approval-gated: each invocation must be explicitly approved. Do not use for commands that require injected credentials or secrets.",
|
|
153
|
+
"LAST RESORT — Execute a shell command directly on the host machine. You MUST strongly prefer the regular `bash` tool for all commands. Only use `host_bash` when you are absolutely certain the command MUST run on the host machine and CANNOT run in the workspace (e.g., managing host-level system services, accessing host-only peripherals, or interacting with host paths outside the workspace). If in doubt, use `bash` instead. Paths resolve on the host's filesystem, which is separate from your workspace; write output somewhere on the host and read it back with `host_file_read`. Approval-gated: each invocation must be explicitly approved. Do not use for commands that require injected credentials or secrets.",
|
|
154
154
|
category: "host-terminal",
|
|
155
155
|
executionTarget: "host",
|
|
156
156
|
defaultRiskLevel: RiskLevel.Medium,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { McpServerConfig } from "../../config/schemas/mcp.js";
|
|
2
|
+
import type { McpToolAnnotations } from "../../mcp/client.js";
|
|
2
3
|
import type { McpServerManager } from "../../mcp/manager.js";
|
|
3
4
|
import { RiskLevel } from "../../permissions/types.js";
|
|
4
5
|
import { toProviderSafeToolName } from "../provider-tool-name.js";
|
|
@@ -23,6 +24,29 @@ export interface McpToolMetadata {
|
|
|
23
24
|
name: string;
|
|
24
25
|
description: string;
|
|
25
26
|
inputSchema: Record<string, unknown>;
|
|
27
|
+
annotations?: McpToolAnnotations;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the risk level a tool carries.
|
|
32
|
+
*
|
|
33
|
+
* `readOnlyHint` is self-reported by the server, so it only refines risk
|
|
34
|
+
* downward and only for servers the user has already configured below the
|
|
35
|
+
* high-trust ceiling. Servers left at the default "high" are unaffected, and
|
|
36
|
+
* the hint never raises risk above the server default.
|
|
37
|
+
*/
|
|
38
|
+
function resolveRiskLevel(
|
|
39
|
+
metadata: McpToolMetadata,
|
|
40
|
+
serverConfig: McpServerConfig,
|
|
41
|
+
): RiskLevel {
|
|
42
|
+
const serverRisk = riskMap[serverConfig.defaultRiskLevel] ?? RiskLevel.High;
|
|
43
|
+
if (
|
|
44
|
+
metadata.annotations?.readOnlyHint === true &&
|
|
45
|
+
serverRisk !== RiskLevel.High
|
|
46
|
+
) {
|
|
47
|
+
return RiskLevel.Low;
|
|
48
|
+
}
|
|
49
|
+
return serverRisk;
|
|
26
50
|
}
|
|
27
51
|
|
|
28
52
|
/**
|
|
@@ -36,7 +60,7 @@ export function createMcpTool(
|
|
|
36
60
|
manager: McpServerManager,
|
|
37
61
|
): Tool {
|
|
38
62
|
const namespacedName = mcpToolName(serverId, metadata.name);
|
|
39
|
-
const riskLevel =
|
|
63
|
+
const riskLevel = resolveRiskLevel(metadata, serverConfig);
|
|
40
64
|
const serverDefinesActivity = schemaDefinesProperty(
|
|
41
65
|
metadata.inputSchema,
|
|
42
66
|
"activity",
|
|
@@ -104,14 +104,15 @@ export class PermissionChecker {
|
|
|
104
104
|
toolName: string,
|
|
105
105
|
input: Record<string, unknown>,
|
|
106
106
|
workingDir: string,
|
|
107
|
-
) =>
|
|
107
|
+
) => Promise<
|
|
108
108
|
| {
|
|
109
109
|
filePath: string;
|
|
110
110
|
oldContent: string;
|
|
111
111
|
newContent: string;
|
|
112
112
|
isNewFile: boolean;
|
|
113
113
|
}
|
|
114
|
-
| undefined
|
|
114
|
+
| undefined
|
|
115
|
+
>,
|
|
115
116
|
): Promise<PermissionDecision> {
|
|
116
117
|
// Sandbox/host routing for the prompt comes from the tool's manifest.
|
|
117
118
|
const executionTarget = resolveExecutionTarget(tool);
|
|
@@ -378,7 +379,11 @@ export class PermissionChecker {
|
|
|
378
379
|
};
|
|
379
380
|
}
|
|
380
381
|
|
|
381
|
-
const previewDiff = computePreviewDiff(
|
|
382
|
+
const previewDiff = await computePreviewDiff(
|
|
383
|
+
name,
|
|
384
|
+
input,
|
|
385
|
+
context.workingDir,
|
|
386
|
+
);
|
|
382
387
|
const promptOptions = {
|
|
383
388
|
allowlistOptions: await generateAllowlistOptions(
|
|
384
389
|
name,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
import { deleteSchedule, getSchedule } from "../../schedule/schedule-store.js";
|
|
4
|
+
import { UserError } from "../../util/errors.js";
|
|
4
5
|
import {
|
|
5
6
|
invalidToolInputResult,
|
|
6
7
|
nullAsOmitted,
|
|
@@ -35,7 +36,18 @@ export async function executeScheduleDelete(
|
|
|
35
36
|
return { content: `Error: Schedule not found: ${jobId}`, isError: true };
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
let deleted: boolean;
|
|
40
|
+
try {
|
|
41
|
+
deleted = await deleteSchedule(jobId);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
// The store refuses to delete plugin-sourced rows with a UserError. That
|
|
44
|
+
// refusal is an expected outcome for the model to relay, not a daemon
|
|
45
|
+
// fault to classify as unexpected.
|
|
46
|
+
if (err instanceof UserError) {
|
|
47
|
+
return { content: `Error: ${err.message}`, isError: true };
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
39
51
|
if (!deleted) {
|
|
40
52
|
return {
|
|
41
53
|
content: `Error: Failed to delete schedule: ${jobId}`,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
import { formatScheduleInferenceProfile } from "../../schedule/inference-profile.js";
|
|
3
4
|
import { hasSetConstructs } from "../../schedule/recurrence-engine.js";
|
|
4
5
|
import {
|
|
5
6
|
describeCronExpression,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
getScheduleRuns,
|
|
9
10
|
listSchedules,
|
|
10
11
|
} from "../../schedule/schedule-store.js";
|
|
12
|
+
import { describeScheduleSource } from "../../util/schedule-source-key.js";
|
|
11
13
|
import {
|
|
12
14
|
invalidToolInputResult,
|
|
13
15
|
nullAsOmitted,
|
|
@@ -77,6 +79,13 @@ export async function executeScheduleList(
|
|
|
77
79
|
` Description: ${describeAuthoredPurpose(job)}`,
|
|
78
80
|
];
|
|
79
81
|
|
|
82
|
+
const detailPlugin = describeScheduleSource(job.sourceKey);
|
|
83
|
+
if (detailPlugin) {
|
|
84
|
+
lines.push(
|
|
85
|
+
` Managed by plugin: ${detailPlugin} (definition read-only; only enabled can be changed)`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
80
89
|
if (oneShot) {
|
|
81
90
|
lines.push(` Fire at: ${formatLocalDate(job.nextRunAt)}`);
|
|
82
91
|
} else {
|
|
@@ -93,7 +102,7 @@ export async function executeScheduleList(
|
|
|
93
102
|
` Enabled: ${job.enabled}`,
|
|
94
103
|
` Quiet: ${job.quiet}`,
|
|
95
104
|
` Reuse conversation: ${job.reuseConversation}`,
|
|
96
|
-
` Inference profile: ${job.inferenceProfile
|
|
105
|
+
` Inference profile: ${formatScheduleInferenceProfile(job.inferenceProfile)}`,
|
|
97
106
|
` Message: ${job.message}`,
|
|
98
107
|
);
|
|
99
108
|
|
|
@@ -142,18 +151,20 @@ export async function executeScheduleList(
|
|
|
142
151
|
for (const job of jobs) {
|
|
143
152
|
const status = job.enabled ? "enabled" : "disabled";
|
|
144
153
|
const oneShot = isOneShot(job);
|
|
154
|
+
const plugin = describeScheduleSource(job.sourceKey);
|
|
155
|
+
const managed = plugin ? ` (managed by plugin ${plugin})` : "";
|
|
145
156
|
|
|
146
157
|
if (oneShot) {
|
|
147
158
|
const fireTime = formatLocalDate(job.nextRunAt);
|
|
148
159
|
lines.push(
|
|
149
|
-
` - [${status}] ${job.name} (id: ${job.id}) (one-shot, ${job.mode}) [${job.status}]`,
|
|
160
|
+
` - [${status}] ${job.name} (id: ${job.id}) (one-shot, ${job.mode}) [${job.status}]${managed}`,
|
|
150
161
|
` Description: ${describeAuthoredPurpose(job)}`,
|
|
151
162
|
` fire at: ${fireTime}`,
|
|
152
163
|
);
|
|
153
164
|
} else {
|
|
154
165
|
const next = job.enabled ? formatLocalDate(job.nextRunAt) : "n/a";
|
|
155
166
|
lines.push(
|
|
156
|
-
` - [${status}] ${job.name} (id: ${job.id}) (${job.mode})`,
|
|
167
|
+
` - [${status}] ${job.name} (id: ${job.id}) (${job.mode})${managed}`,
|
|
157
168
|
` Description: ${describeAuthoredPurpose(job)}`,
|
|
158
169
|
` Schedule: [${job.syntax}] ${describeSchedule(job)}`,
|
|
159
170
|
` Next: ${next}`,
|