@vellumai/assistant 0.11.3 → 0.11.4-dev.202608190019.b94dbf2
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/AGENTS.md +9 -3
- package/ARCHITECTURE.md +32 -10
- package/docs/architecture/memory.md +43 -5
- package/docs/architecture/security.md +96 -152
- package/docs/architecture/turn-actor.md +70 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +248 -0
- package/docs/guardian-request-flow.md +35 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/knip.json +3 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/openapi.yaml +289 -113
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-compiler.test.ts +38 -3
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/attachments-store.test.ts +21 -12
- package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
- package/src/__tests__/call-site-routing-provider.test.ts +1 -1
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
- package/src/__tests__/channel-delivery-store.test.ts +14 -14
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/checker.test.ts +20 -314
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/config-loader-backfill.test.ts +3 -3
- package/src/__tests__/config-schema.test.ts +25 -10
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop.test.ts +32 -21
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +63 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
- package/src/__tests__/conversation-fork-crud.test.ts +69 -0
- package/src/__tests__/conversation-fork-referential.test.ts +67 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
- package/src/__tests__/conversation-queue.test.ts +154 -4
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
- package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +7 -10
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/custom-profile-ensure.test.ts +5 -1
- package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
- package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
- package/src/__tests__/document-append-idempotency.test.ts +233 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
- package/src/__tests__/edit-propagation.test.ts +107 -11
- package/src/__tests__/file-ops-service.test.ts +163 -30
- package/src/__tests__/filesystem-tools.test.ts +23 -24
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
- package/src/__tests__/helpers/mock-actor-context.ts +49 -0
- package/src/__tests__/helpers/mock-conversation.ts +13 -1
- package/src/__tests__/host-file-read-tool.test.ts +16 -19
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/injector-chain.test.ts +63 -41
- package/src/__tests__/injector-disk-pressure.test.ts +11 -23
- package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
- package/src/__tests__/llm-context-resolution.test.ts +73 -1
- package/src/__tests__/llm-schema.test.ts +5 -2
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
- package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
- package/src/__tests__/mtime-cache.test.ts +3 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -20
- package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
- package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-disabled-state.test.ts +2 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
- package/src/__tests__/plugin-execution-context.test.ts +73 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
- package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/reaction-persistence.test.ts +200 -7
- package/src/__tests__/require-fresh-approval.test.ts +0 -4
- package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/scoped-approval-grants.test.ts +11 -6
- package/src/__tests__/secret-ingress-channel.test.ts +0 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
- package/src/__tests__/tool-executor.test.ts +68 -39
- package/src/__tests__/turn-events-store.test.ts +43 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-shape-teaching.test.ts +33 -0
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/visible-app-context.test.ts +16 -9
- package/src/__tests__/voice-config-update.test.ts +40 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
- package/src/__tests__/worker-plugin-surface.test.ts +77 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
- package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
- package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
- package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
- package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
- package/src/acp/__tests__/auth-required.test.ts +161 -0
- package/src/acp/acp-claude-oauth.ts +19 -2
- package/src/acp/agent-process.test.ts +100 -0
- package/src/acp/agent-process.ts +29 -26
- package/src/acp/auth-required.ts +102 -0
- package/src/acp/session-manager.test.ts +119 -0
- package/src/acp/session-manager.ts +76 -3
- package/src/api/events/acp-auth-required.ts +55 -0
- package/src/api/events/host-file.ts +2 -2
- package/src/api/index.ts +7 -0
- package/src/api/surfaces.ts +12 -3
- package/src/apps/app-store.ts +3 -0
- package/src/bundler/package-resolver.ts +2 -30
- package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
- package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
- package/src/calls/call-controller.ts +19 -3
- package/src/calls/call-setup-flow.ts +0 -1
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/calls/voice-session-bridge.ts +115 -41
- package/src/calls/voice-triage-escalate.ts +105 -2
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +13 -0
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +30 -0
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/credentials.help.ts +2 -2
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/inference-providers.ts +1 -1
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.help.ts +13 -4
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
- package/src/cli/commands/memory/index.help.ts +84 -28
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-v2.ts +58 -54
- package/src/cli/commands/memory/memory-v3.ts +64 -0
- package/src/cli/commands/memory/memory-validate.ts +18 -0
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/trust.ts +3 -14
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
- package/src/cli/lib/bundled-marketplace.json +14 -1
- package/src/cli/lib/upgrade-plugin.ts +42 -0
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
- package/src/config/__tests__/default-provider.test.ts +6 -1
- package/src/config/__tests__/profile-materialization.test.ts +75 -19
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
- package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/call-site-defaults.ts +11 -5
- package/src/config/default-profile-catalog.ts +179 -16
- package/src/config/default-profile-names.ts +4 -1
- package/src/config/default-provider-resolution.ts +4 -0
- package/src/config/feature-flag-registry.json +12 -12
- package/src/config/llm-context-resolution.ts +11 -3
- package/src/config/llm-resolver.ts +28 -1
- package/src/config/profile-materialization.ts +70 -22
- package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/live-voice.ts +57 -23
- package/src/config/schemas/llm.ts +59 -32
- package/src/config/schemas/mcp.ts +23 -0
- package/src/config/schemas/plugin-updates.ts +6 -2
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/skills.ts +9 -2
- package/src/context/outbound-sanitize.ts +96 -1
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
- package/src/daemon/conversation-agent-loop.ts +31 -19
- package/src/daemon/conversation-messaging.ts +5 -1
- package/src/daemon/conversation-notifiers.ts +20 -10
- package/src/daemon/conversation-process.ts +20 -6
- package/src/daemon/conversation-runtime-assembly.ts +12 -6
- package/src/daemon/conversation-store.ts +14 -4
- package/src/daemon/conversation-surfaces.ts +75 -26
- package/src/daemon/conversation-tool-setup.ts +3 -6
- package/src/daemon/conversation.ts +154 -51
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/mcp-reload-service.ts +36 -6
- package/src/daemon/process-message.ts +13 -26
- package/src/daemon/providers-setup.ts +6 -3
- package/src/daemon/trust-context-types.ts +29 -0
- package/src/daemon/trust-context.ts +12 -7
- package/src/daemon/wake-conversation-ops.ts +3 -2
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +143 -240
- package/src/hooks/hook-loader.ts +3 -3
- package/src/hooks/registry.ts +103 -45
- package/src/hooks/types.ts +5 -0
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/gateway-client.test.ts +1 -1
- package/src/ipc/gateway-client.ts +14 -21
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
- package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/live-voice-archive.ts +2 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +1 -2
- package/src/live-voice/live-voice-session.ts +598 -323
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/protocol.ts +21 -1
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/mcp/__tests__/effective-config.test.ts +238 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
- package/src/mcp/client.ts +16 -11
- package/src/mcp/effective-config.ts +113 -0
- package/src/mcp/manager.ts +11 -6
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +205 -240
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/monitoring/plugin-auto-update.ts +128 -24
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/approval-card-data.ts +33 -0
- package/src/notifications/signal.ts +1 -0
- package/src/permissions/AGENTS.md +16 -0
- package/src/permissions/checker.test.ts +75 -122
- package/src/permissions/checker.ts +44 -560
- package/src/permissions/confirmation-guardian-request.test.ts +15 -11
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +1 -5
- package/src/permissions/question-guardian-request.test.ts +14 -6
- package/src/permissions/question-guardian-request.ts +1 -2
- package/src/persistence/attachments-store.ts +8 -1
- package/src/persistence/bookmark-crud.ts +3 -7
- package/src/persistence/conversation-attention-store.ts +16 -45
- package/src/persistence/conversation-crud.ts +33 -4
- package/src/persistence/conversation-lineage.ts +9 -0
- package/src/persistence/conversation-queries.ts +182 -52
- package/src/persistence/delivery-crud.ts +150 -36
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/external-conversation-store.ts +32 -4
- package/src/persistence/llm-request-log-store.ts +4 -10
- package/src/persistence/llm-usage-store.ts +8 -3
- package/src/persistence/message-reads.test.ts +197 -0
- package/src/persistence/message-reads.ts +211 -0
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
- package/src/persistence/real-user-turn-filter.ts +27 -3
- package/src/persistence/schema/documents.ts +4 -4
- package/src/persistence/steps.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/conversation-turn.ts +195 -5
- package/src/plugin-api/index.ts +38 -6
- package/src/plugin-api/resolve-credential.ts +3 -2
- package/src/plugin-api/store-credential.ts +146 -0
- package/src/plugin-api/vision-support.test.ts +1 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
- package/src/plugins/defaults/main.ts +21 -7
- package/src/plugins/defaults/memory/AGENTS.md +15 -3
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
- package/src/plugins/defaults/memory/buffer-format.ts +165 -0
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
- package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/indexer.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
- package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
- package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
- package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
- package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
- package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
- package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/card.ts +9 -9
- package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
- package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
- package/src/plugins/defaults/memory/v3/edge.ts +13 -57
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/prune.ts +2 -0
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/memory/worker.ts +6 -3
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/external-plugin-loader.ts +47 -0
- package/src/plugins/mcp-servers.ts +361 -0
- package/src/plugins/mtime-cache.ts +37 -46
- package/src/plugins/pipeline.ts +14 -7
- package/src/plugins/plugin-execution-context.ts +35 -11
- package/src/plugins/worker-plugin-surface.ts +33 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
- package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -2
- package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
- package/src/providers/anthropic/client.ts +332 -241
- package/src/providers/call-site-routing.ts +30 -3
- package/src/providers/connection-resolution.ts +194 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/inference/auth.ts +6 -0
- package/src/providers/inference/connection-availability.ts +24 -2
- package/src/providers/inference/connections.ts +2 -0
- package/src/providers/model-catalog.ts +3 -3
- package/src/providers/model-intents.ts +28 -8
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
- package/src/providers/openai/chat-completions-provider.ts +133 -36
- package/src/providers/openai/codex-models.ts +2 -1
- package/src/providers/provider-send-message.ts +32 -3
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
- package/src/providers/speech-to-text/provider-catalog.ts +99 -8
- package/src/providers/speech-to-text/resolve.ts +25 -2
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/routes/route-host-protocol.ts +7 -0
- package/src/routes/worker.ts +48 -15
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/access-request-helper.ts +9 -12
- package/src/runtime/agent-wake.ts +18 -15
- package/src/runtime/effective-capabilities.test.ts +43 -0
- package/src/runtime/effective-capabilities.ts +27 -0
- package/src/runtime/guardian-reply-router.ts +6 -2
- package/src/runtime/pre-first-message-gate.ts +4 -0
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-route-shared.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
- package/src/runtime/routes/conversation-list-routes.ts +181 -23
- package/src/runtime/routes/conversation-management-routes.ts +17 -12
- package/src/runtime/routes/conversation-query-routes.ts +40 -27
- package/src/runtime/routes/conversation-routes.ts +43 -29
- package/src/runtime/routes/credential-prompt-routes.ts +4 -7
- package/src/runtime/routes/credential-routes.ts +26 -82
- package/src/runtime/routes/default-provider-routes.ts +15 -0
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/inbound-message-handler.ts +21 -45
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
- package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
- package/src/runtime/routes/inference-profiles-routes.ts +20 -11
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/mcp-auth-routes.ts +148 -57
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +38 -8
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/settings-routes.ts +6 -6
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/surface-action-routes.ts +20 -19
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
- package/src/runtime/routes/user-route-dispatcher.ts +69 -15
- package/src/runtime/routes/user-route-import.ts +108 -0
- package/src/runtime/routes/user-route-resolution.ts +18 -1
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/schedule/worker.ts +6 -0
- package/src/security/oauth2.ts +6 -22
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +10 -0
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +103 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +21 -40
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +15 -12
- package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
- package/src/tools/acp/spawn.test.ts +97 -0
- package/src/tools/acp/spawn.ts +38 -4
- package/src/tools/credentials/ref-parse.ts +35 -0
- package/src/tools/credentials/resolve.ts +4 -10
- package/src/tools/credentials/store.ts +168 -0
- package/src/tools/document/document-tool.ts +12 -3
- package/src/tools/executor.ts +53 -15
- package/src/tools/filesystem/read.ts +27 -10
- package/src/tools/host-filesystem/read.ts +27 -15
- package/src/tools/network/url-safety.ts +9 -16
- package/src/tools/permission-checker.ts +43 -52
- package/src/tools/registry.ts +2 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
- package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
- package/src/tools/shared/filesystem/types.ts +5 -5
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/tool-types.ts +26 -13
- package/src/tools/types.ts +6 -6
- package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
- package/src/tools/workflows/run-workflow.ts +1 -2
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
- package/src/tts/reasoning-tag-filter.ts +89 -0
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/think-tag-stream.ts +95 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/workspace/byok-default-profile-ensure.ts +76 -24
- package/src/workspace/custom-profile-ensure.ts +4 -24
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
- package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
- package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
- package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/provider-commit-message-generator.ts +7 -5
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/live-voice/__tests__/front-decision.test.ts +0 -645
- package/src/live-voice/front-decision.ts +0 -476
- package/src/permissions/ipc-risk-types.ts +0 -143
- package/src/permissions/risk-types.ts +0 -76
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -11,13 +11,14 @@ import {
|
|
|
11
11
|
readAudioFile,
|
|
12
12
|
} from "../shared/filesystem/audio-read.js";
|
|
13
13
|
import {
|
|
14
|
-
DEFAULT_READ_LINE_LIMIT,
|
|
15
14
|
FileSystemOps,
|
|
15
|
+
READ_CHAR_BUDGET,
|
|
16
16
|
} from "../shared/filesystem/file-ops-service.js";
|
|
17
17
|
import {
|
|
18
18
|
IMAGE_EXTENSIONS,
|
|
19
19
|
readImageFile,
|
|
20
20
|
} from "../shared/filesystem/image-read.js";
|
|
21
|
+
import { legacyReadArgsError } from "../shared/filesystem/legacy-read-args.js";
|
|
21
22
|
import { hostPolicy } from "../shared/filesystem/path-policy.js";
|
|
22
23
|
import {
|
|
23
24
|
invalidToolInputResult,
|
|
@@ -32,9 +33,9 @@ import type {
|
|
|
32
33
|
/**
|
|
33
34
|
* Model-input schema, the single source for both runtime validation (via
|
|
34
35
|
* `TOOL_INPUT_SCHEMAS`) and the advertised `input_schema` below — mirrors
|
|
35
|
-
* `filesystem/read.ts`. `
|
|
36
|
-
* non-numeric value falls back to the default
|
|
37
|
-
* the call; `target_client_id` catches so a non-string (or empty) value means
|
|
36
|
+
* `filesystem/read.ts`. `start_index`/`max_chars` catch to `undefined` so a
|
|
37
|
+
* non-numeric value falls back to the default character window instead of
|
|
38
|
+
* failing the call; `target_client_id` catches so a non-string (or empty) value means
|
|
38
39
|
* "untargeted".
|
|
39
40
|
*/
|
|
40
41
|
export const hostFileReadInputSchema = z.looseObject({
|
|
@@ -44,14 +45,16 @@ export const hostFileReadInputSchema = z.looseObject({
|
|
|
44
45
|
.describe(
|
|
45
46
|
"Absolute path on the guardian's device, which is a separate filesystem from your workspace, to read.",
|
|
46
47
|
),
|
|
47
|
-
|
|
48
|
+
start_index: z
|
|
48
49
|
.number()
|
|
49
|
-
.describe("
|
|
50
|
+
.describe("Character to start reading from (0-indexed). Text files only.")
|
|
50
51
|
.optional()
|
|
51
52
|
.catch(undefined),
|
|
52
|
-
|
|
53
|
+
max_chars: z
|
|
53
54
|
.number()
|
|
54
|
-
.describe(
|
|
55
|
+
.describe(
|
|
56
|
+
"Maximum number of characters to read. Defaults to 20000, which is also the ceiling. Text files only.",
|
|
57
|
+
)
|
|
55
58
|
.optional()
|
|
56
59
|
.catch(undefined),
|
|
57
60
|
target_client_id: z
|
|
@@ -66,7 +69,7 @@ export const hostFileReadInputSchema = z.looseObject({
|
|
|
66
69
|
export const hostFileReadTool = {
|
|
67
70
|
name: "host_file_read",
|
|
68
71
|
description:
|
|
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
|
|
72
|
+
"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 20000 characters unless you pass `max_chars`; when a read stops short the result says so, and `start_index` pages on from there. For files on your own machine, use file_read instead.",
|
|
70
73
|
category: "host-filesystem",
|
|
71
74
|
executionTarget: "host",
|
|
72
75
|
defaultRiskLevel: RiskLevel.Medium,
|
|
@@ -81,12 +84,12 @@ export const hostFileReadTool = {
|
|
|
81
84
|
if (!parsed.success) {
|
|
82
85
|
return invalidToolInputResult("host_file_read", parsed.error);
|
|
83
86
|
}
|
|
84
|
-
const { path: rawPath,
|
|
87
|
+
const { path: rawPath, start_index: startIndex } = parsed.data;
|
|
85
88
|
// Resolve the default here rather than leaving it to the read, so the
|
|
86
89
|
// proxied branch below is bounded by the same window as the local one. A
|
|
87
|
-
// proxied read that sent no
|
|
90
|
+
// proxied read that sent no budget would stream a whole host file across
|
|
88
91
|
// the bridge before anything could trim it.
|
|
89
|
-
const
|
|
92
|
+
const maxChars = parsed.data.max_chars ?? READ_CHAR_BUDGET;
|
|
90
93
|
|
|
91
94
|
const targetClientId =
|
|
92
95
|
parsed.data.target_client_id !== ""
|
|
@@ -153,8 +156,8 @@ export const hostFileReadTool = {
|
|
|
153
156
|
{
|
|
154
157
|
operation: "read",
|
|
155
158
|
path: rawPath,
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
startIndex,
|
|
160
|
+
maxChars,
|
|
158
161
|
targetClientId,
|
|
159
162
|
},
|
|
160
163
|
context.conversationId,
|
|
@@ -181,9 +184,18 @@ export const hostFileReadTool = {
|
|
|
181
184
|
return readAudioFile(pathCheck.resolved);
|
|
182
185
|
}
|
|
183
186
|
|
|
187
|
+
const legacyArgs = legacyReadArgsError("host_file_read", input);
|
|
188
|
+
if (legacyArgs !== undefined) {
|
|
189
|
+
return { content: legacyArgs, isError: true };
|
|
190
|
+
}
|
|
191
|
+
|
|
184
192
|
const ops = new FileSystemOps(hostPolicy);
|
|
185
193
|
|
|
186
|
-
const result = await ops.readFileSafe({
|
|
194
|
+
const result = await ops.readFileSafe({
|
|
195
|
+
path: rawPath,
|
|
196
|
+
startIndex,
|
|
197
|
+
maxChars,
|
|
198
|
+
});
|
|
187
199
|
|
|
188
200
|
if (!result.ok) {
|
|
189
201
|
const { error } = result;
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
import { lookup } from "node:dns/promises";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import {
|
|
4
|
+
looksLikeHostPortShorthand,
|
|
5
|
+
looksLikePathOnlyInput,
|
|
6
|
+
} from "@vellumai/service-contracts/url-normalization";
|
|
4
7
|
|
|
5
|
-
export
|
|
6
|
-
if (/^\[[0-9a-fA-F:.%]+\]:\d+(?:[/?#]|$)/.test(value)) {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
return /^[^/?#@\s:]+:\d+(?:[/?#]|$)/.test(value);
|
|
10
|
-
}
|
|
8
|
+
export type ResolveHostAddresses = (hostname: string) => Promise<string[]>;
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
value.startsWith("../") ||
|
|
17
|
-
value.startsWith("?") ||
|
|
18
|
-
value.startsWith("#")
|
|
19
|
-
);
|
|
20
|
-
}
|
|
10
|
+
// The URL input-shape predicates are defined once, beside the canonicalizer
|
|
11
|
+
// the gateway builds trust-rule patterns with, so what counts as a `host:port`
|
|
12
|
+
// or a path here is what counts there. Re-exported for existing consumers.
|
|
13
|
+
export { looksLikeHostPortShorthand, looksLikePathOnlyInput };
|
|
21
14
|
|
|
22
15
|
export function parseUrl(input: unknown): URL | null {
|
|
23
16
|
if (typeof input !== "string") {
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RiskAllowlistOption,
|
|
3
|
+
RiskDirectoryScopeOption,
|
|
4
|
+
RiskPatternScopeOption,
|
|
5
|
+
} from "@vellumai/gateway-client";
|
|
6
|
+
|
|
1
7
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
2
8
|
import { mapApprovalProvenance } from "../permissions/approval-provenance.js";
|
|
3
9
|
import { buildChannelPermissionCellQuery } from "../permissions/channel-permission-query.js";
|
|
4
10
|
import {
|
|
5
11
|
check,
|
|
6
12
|
classifyRisk,
|
|
7
|
-
generateAllowlistOptions,
|
|
8
13
|
generateScopeOptions,
|
|
9
|
-
getCachedAssessment,
|
|
10
14
|
isDynamicSkillLoadInvocation,
|
|
15
|
+
type RiskClassificationWithMeta,
|
|
11
16
|
} from "../permissions/checker.js";
|
|
12
17
|
import { getAutoApproveThreshold } from "../permissions/gateway-threshold-reader.js";
|
|
13
18
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
@@ -37,19 +42,15 @@ export type PermissionDecision =
|
|
|
37
42
|
decision: string;
|
|
38
43
|
riskLevel: string;
|
|
39
44
|
wasPrompted?: boolean;
|
|
40
|
-
/** ID of the trust rule that matched this invocation (if any).
|
|
45
|
+
/** ID of the trust rule that matched this invocation (if any). */
|
|
41
46
|
matchedTrustRuleId?: string;
|
|
42
|
-
/** Risk metadata from the
|
|
43
|
-
riskMeta
|
|
47
|
+
/** Risk metadata from the invocation's classification. */
|
|
48
|
+
riskMeta: {
|
|
44
49
|
riskLevel: string;
|
|
45
50
|
riskReason: string;
|
|
46
|
-
riskScopeOptions:
|
|
47
|
-
riskAllowlistOptions?:
|
|
48
|
-
|
|
49
|
-
description: string;
|
|
50
|
-
pattern: string;
|
|
51
|
-
}>;
|
|
52
|
-
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
51
|
+
riskScopeOptions: RiskPatternScopeOption[];
|
|
52
|
+
riskAllowlistOptions?: RiskAllowlistOption[];
|
|
53
|
+
riskDirectoryScopeOptions?: RiskDirectoryScopeOption[];
|
|
53
54
|
isContainerized?: boolean;
|
|
54
55
|
};
|
|
55
56
|
approvalMode?: ApprovalMode;
|
|
@@ -61,19 +62,15 @@ export type PermissionDecision =
|
|
|
61
62
|
decision: string;
|
|
62
63
|
riskLevel: string;
|
|
63
64
|
content: string;
|
|
64
|
-
/** ID of the trust rule that matched this invocation (if any).
|
|
65
|
+
/** ID of the trust rule that matched this invocation (if any). */
|
|
65
66
|
matchedTrustRuleId?: string;
|
|
66
|
-
/** Risk metadata from the
|
|
67
|
-
riskMeta
|
|
67
|
+
/** Risk metadata from the invocation's classification. */
|
|
68
|
+
riskMeta: {
|
|
68
69
|
riskLevel: string;
|
|
69
70
|
riskReason: string;
|
|
70
|
-
riskScopeOptions:
|
|
71
|
-
riskAllowlistOptions?:
|
|
72
|
-
|
|
73
|
-
description: string;
|
|
74
|
-
pattern: string;
|
|
75
|
-
}>;
|
|
76
|
-
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
71
|
+
riskScopeOptions: RiskPatternScopeOption[];
|
|
72
|
+
riskAllowlistOptions?: RiskAllowlistOption[];
|
|
73
|
+
riskDirectoryScopeOptions?: RiskDirectoryScopeOption[];
|
|
77
74
|
isContainerized?: boolean;
|
|
78
75
|
};
|
|
79
76
|
approvalMode?: ApprovalMode;
|
|
@@ -89,10 +86,13 @@ export class PermissionChecker {
|
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
/**
|
|
92
|
-
* Run
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
89
|
+
* Run trust rule evaluation and (if needed) user prompting for a tool
|
|
90
|
+
* invocation. Returns whether the tool is allowed to execute, along with
|
|
91
|
+
* the decision string and risk level for lifecycle event reporting.
|
|
92
|
+
*
|
|
93
|
+
* `classification` is the invocation's gateway classification when the
|
|
94
|
+
* executor already holds it (it classifies once, before its gates); absent
|
|
95
|
+
* that, the same input is classified here.
|
|
96
96
|
*/
|
|
97
97
|
async checkPermission(
|
|
98
98
|
name: string,
|
|
@@ -113,10 +113,11 @@ export class PermissionChecker {
|
|
|
113
113
|
}
|
|
114
114
|
| undefined
|
|
115
115
|
>,
|
|
116
|
+
classification?: RiskClassificationWithMeta,
|
|
116
117
|
): Promise<PermissionDecision> {
|
|
117
118
|
// Sandbox/host routing for the prompt comes from the tool's manifest.
|
|
118
119
|
const executionTarget = resolveExecutionTarget(tool);
|
|
119
|
-
|
|
120
|
+
classification ??= await classifyRisk(
|
|
120
121
|
name,
|
|
121
122
|
input,
|
|
122
123
|
context.workingDir,
|
|
@@ -124,26 +125,19 @@ export class PermissionChecker {
|
|
|
124
125
|
undefined,
|
|
125
126
|
context.signal,
|
|
126
127
|
);
|
|
128
|
+
const { level: risk, reason: riskReason } = classification;
|
|
127
129
|
const riskLevel: string = risk;
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// Save ladder (Minimatch globs — what the gateway matches against).
|
|
140
|
-
// Populated for classifiers that produce allowlist options
|
|
141
|
-
// (bash, file, skill); undefined otherwise.
|
|
142
|
-
riskAllowlistOptions: cachedAssessment.allowlistOptions,
|
|
143
|
-
riskDirectoryScopeOptions: cachedAssessment.directoryScopeOptions,
|
|
144
|
-
isContainerized: getIsContainerized(),
|
|
145
|
-
}
|
|
146
|
-
: undefined;
|
|
131
|
+
const riskMeta = {
|
|
132
|
+
riskLevel: classification.level,
|
|
133
|
+
riskReason: classification.reason,
|
|
134
|
+
// Display ladder: bash only, internal, never persisted as a rule.
|
|
135
|
+
riskScopeOptions: classification.scopeOptions,
|
|
136
|
+
// Save ladder: the patterns the gateway matches a rule by, exactly.
|
|
137
|
+
riskAllowlistOptions: classification.allowlistOptions,
|
|
138
|
+
riskDirectoryScopeOptions: classification.directoryScopeOptions,
|
|
139
|
+
isContainerized: getIsContainerized(),
|
|
140
|
+
};
|
|
147
141
|
|
|
148
142
|
// Wrap the rest of permission evaluation so that any exception
|
|
149
143
|
// carries the classified risk level back to the caller. Without
|
|
@@ -158,6 +152,7 @@ export class PermissionChecker {
|
|
|
158
152
|
policyContext,
|
|
159
153
|
undefined,
|
|
160
154
|
context.signal,
|
|
155
|
+
classification,
|
|
161
156
|
);
|
|
162
157
|
|
|
163
158
|
// Every threshold read for this invocation must consult the same
|
|
@@ -240,7 +235,7 @@ export class PermissionChecker {
|
|
|
240
235
|
if (
|
|
241
236
|
context.isInteractive === false &&
|
|
242
237
|
isDynamicSkillLoadInvocation(name, input) &&
|
|
243
|
-
|
|
238
|
+
classification.matchType !== "user_rule"
|
|
244
239
|
) {
|
|
245
240
|
log.info(
|
|
246
241
|
{ toolName: name, riskLevel },
|
|
@@ -385,11 +380,7 @@ export class PermissionChecker {
|
|
|
385
380
|
context.workingDir,
|
|
386
381
|
);
|
|
387
382
|
const promptOptions = {
|
|
388
|
-
allowlistOptions:
|
|
389
|
-
name,
|
|
390
|
-
input,
|
|
391
|
-
context.signal,
|
|
392
|
-
),
|
|
383
|
+
allowlistOptions: classification.allowlistOptions ?? [],
|
|
393
384
|
scopeOptions: generateScopeOptions(context.workingDir, name),
|
|
394
385
|
persistentDecisionsAllowed: !context.requireFreshApproval,
|
|
395
386
|
};
|
|
@@ -410,7 +401,7 @@ export class PermissionChecker {
|
|
|
410
401
|
context.toolUseId,
|
|
411
402
|
riskReason,
|
|
412
403
|
getIsContainerized(),
|
|
413
|
-
|
|
404
|
+
classification.directoryScopeOptions,
|
|
414
405
|
);
|
|
415
406
|
|
|
416
407
|
const decision = response.decision;
|
package/src/tools/registry.ts
CHANGED
|
@@ -431,7 +431,8 @@ export function unregisterPluginTools(pluginName: string): void {
|
|
|
431
431
|
* {@link import("../plugins/mtime-cache.js").getActiveUserPluginTools} and diffs
|
|
432
432
|
* the result into the registry: plugins that vanished are unregistered, new
|
|
433
433
|
* plugins register, and a plugin whose per-tool source mtimes moved is
|
|
434
|
-
* re-registered. Mirrors how hooks resolve through `getUserHookEntriesFor
|
|
434
|
+
* re-registered. Mirrors how hooks resolve through `getUserHookEntriesFor`
|
|
435
|
+
* in `hooks/registry.ts`.
|
|
435
436
|
*
|
|
436
437
|
* This is a pure read of the plugin cache — it does NOT reconcile the cache
|
|
437
438
|
* against the source-versions sentinel, so it never activates a plugin or runs
|
|
@@ -78,26 +78,55 @@ function pathError(
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* so
|
|
85
|
-
* that turn. The cap bounds that; `offset`/`limit` page past it, and
|
|
86
|
-
* {@link truncationNotice} tells the model when it is looking at a window
|
|
87
|
-
* rather than the whole file.
|
|
81
|
+
* Characters returned by a read that names no `max_chars`. Stays under
|
|
82
|
+
* `THRESHOLD_CHARS` in `context/post-turn-tool-result-truncation.ts`, which
|
|
83
|
+
* spools any larger tool result to disk and replaces it inline with a short
|
|
84
|
+
* stub, so a default read returns content rather than a stub.
|
|
88
85
|
*/
|
|
89
|
-
export const
|
|
86
|
+
export const READ_CHAR_BUDGET = 20_000;
|
|
90
87
|
|
|
91
88
|
/**
|
|
92
|
-
* Trailing marker appended when a read stops short of the
|
|
93
|
-
*
|
|
94
|
-
*
|
|
89
|
+
* Trailing marker appended when a read stops short of the end of the file. A
|
|
90
|
+
* model that cannot tell a window from a whole file reasons about code it
|
|
91
|
+
* never saw.
|
|
95
92
|
*/
|
|
96
93
|
function truncationNotice(
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
start: number,
|
|
95
|
+
end: number,
|
|
96
|
+
totalChars: number,
|
|
99
97
|
): string {
|
|
100
|
-
return `\n\n[Truncated:
|
|
98
|
+
return `\n\n[Truncated: characters ${start}-${end} of ${totalChars}. Read on with start_index=${end}.]`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const isHighSurrogate = (code: number): boolean =>
|
|
102
|
+
code >= 0xd800 && code <= 0xdbff;
|
|
103
|
+
const isLowSurrogate = (code: number): boolean =>
|
|
104
|
+
code >= 0xdc00 && code <= 0xdfff;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Character window that never splits a surrogate pair. A split leaves a lone
|
|
108
|
+
* half at each edge, and each encodes to U+FFFD, so the character is lost from
|
|
109
|
+
* both this window and the next one paged in after it.
|
|
110
|
+
*/
|
|
111
|
+
export function surrogateSafeWindow(
|
|
112
|
+
total: number,
|
|
113
|
+
charCodeAt: (index: number) => number,
|
|
114
|
+
requestedStart: number,
|
|
115
|
+
maxChars: number,
|
|
116
|
+
): { start: number; end: number } {
|
|
117
|
+
let start = Math.max(0, Math.min(requestedStart, total));
|
|
118
|
+
if (start > 0 && start < total && isLowSurrogate(charCodeAt(start))) {
|
|
119
|
+
start -= 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let end = Math.min(total, start + maxChars);
|
|
123
|
+
if (end > start && end < total && isHighSurrogate(charCodeAt(end - 1))) {
|
|
124
|
+
// Backing off would empty a one-character window, which stalls paging on
|
|
125
|
+
// the same offset, so take the whole pair instead.
|
|
126
|
+
end = end - 1 > start ? end - 1 : Math.min(total, end + 1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return { start, end };
|
|
101
130
|
}
|
|
102
131
|
|
|
103
132
|
export class FileSystemOps {
|
|
@@ -139,28 +168,27 @@ export class FileSystemOps {
|
|
|
139
168
|
|
|
140
169
|
try {
|
|
141
170
|
const raw = await readFile(filePath, "utf-8");
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// the caller paged past the end or asked for
|
|
158
|
-
// truncated read.
|
|
159
|
-
const lastLineReturned = start + selected.length;
|
|
171
|
+
|
|
172
|
+
// A ceiling, not just a default: a larger window would be spooled to
|
|
173
|
+
// disk and replaced with a stub, returning less than this.
|
|
174
|
+
const maxChars = Math.min(
|
|
175
|
+
READ_CHAR_BUDGET,
|
|
176
|
+
Math.max(0, input.maxChars ?? READ_CHAR_BUDGET),
|
|
177
|
+
);
|
|
178
|
+
const { start, end } = surrogateSafeWindow(
|
|
179
|
+
raw.length,
|
|
180
|
+
(i) => raw.charCodeAt(i),
|
|
181
|
+
input.startIndex ?? 0,
|
|
182
|
+
maxChars,
|
|
183
|
+
);
|
|
184
|
+
const window = raw.slice(start, end);
|
|
185
|
+
|
|
186
|
+
// An empty window means the caller paged past the end or asked for
|
|
187
|
+
// nothing, which is not a truncated read.
|
|
160
188
|
const content =
|
|
161
|
-
|
|
162
|
-
?
|
|
163
|
-
:
|
|
189
|
+
window.length > 0 && end < raw.length
|
|
190
|
+
? window + truncationNotice(start, end, raw.length)
|
|
191
|
+
: window;
|
|
164
192
|
|
|
165
193
|
return { ok: true, value: { content } };
|
|
166
194
|
} catch (err) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guard for callers still passing the line-based `offset`/`limit` read
|
|
3
|
+
* arguments. The tool schemas are loose, so those keys parse and are then
|
|
4
|
+
* dropped, which would silently serve the start of the file to a caller that
|
|
5
|
+
* asked to page into the middle of it.
|
|
6
|
+
*
|
|
7
|
+
* There is no safe translation: `offset` counted lines and `start_index`
|
|
8
|
+
* counts characters, so mapping one onto the other would read the wrong
|
|
9
|
+
* region rather than fail. Naming the rename lets the caller correct itself.
|
|
10
|
+
*/
|
|
11
|
+
export function legacyReadArgsError(
|
|
12
|
+
toolName: string,
|
|
13
|
+
input: Record<string, unknown>,
|
|
14
|
+
): string | undefined {
|
|
15
|
+
const usesLegacy = input.offset !== undefined || input.limit !== undefined;
|
|
16
|
+
const usesCurrent =
|
|
17
|
+
input.start_index !== undefined || input.max_chars !== undefined;
|
|
18
|
+
if (!usesLegacy || usesCurrent) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
return `Error: ${toolName} no longer takes \`offset\`/\`limit\` (lines). Use \`start_index\` (0-indexed characters) and \`max_chars\` instead.`;
|
|
22
|
+
}
|
|
@@ -6,14 +6,14 @@ import type { FsError } from "./errors.js";
|
|
|
6
6
|
|
|
7
7
|
export interface ReadInput {
|
|
8
8
|
path: string;
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
/** Maximum number of
|
|
12
|
-
|
|
9
|
+
/** 0-indexed character to start reading from. */
|
|
10
|
+
startIndex?: number;
|
|
11
|
+
/** Maximum number of characters to read. */
|
|
12
|
+
maxChars?: number;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface ReadOutput {
|
|
16
|
-
/** The
|
|
16
|
+
/** The character window, with a truncation notice when it stops short. */
|
|
17
17
|
content: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -28,10 +28,20 @@ function sanitizeFrontmatterValue(value: string): string {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* Self-correcting error for a scaffold call with no activation hints. Matches
|
|
32
|
+
* the shape of the schema validator's required-field error, which is what a
|
|
33
|
+
* call through the registered tool hits first; this covers direct callers and
|
|
34
|
+
* an explicit empty list, which the schema's presence check accepts.
|
|
35
|
+
*/
|
|
36
|
+
const MISSING_ACTIVATION_HINTS =
|
|
37
|
+
'activation_hints is required: pass 1-4 short trigger phrases stating the intent this skill serves (for example "user asks to deploy staging") so it can be found later by intent, not just by name.';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Validate + normalize a string-array input (sanitize, drop blanks, dedupe).
|
|
41
|
+
* Returns `{ error }` on the first invalid element, or `{ value }` holding
|
|
42
|
+
* the normalized array (undefined when absent or empty). Shared by the
|
|
43
|
+
* includes / activation_hints / avoid_when inputs so they behave identically;
|
|
44
|
+
* whether an absent value is acceptable is the caller's call.
|
|
35
45
|
* Each element goes through sanitizeFrontmatterValue: activation_hints /
|
|
36
46
|
* avoid_when are concatenated verbatim into capability memory text (see
|
|
37
47
|
* buildSkillContent), so an embedded newline could otherwise smuggle an extra
|
|
@@ -184,9 +194,9 @@ export async function executeScaffoldManagedSkill(
|
|
|
184
194
|
};
|
|
185
195
|
}
|
|
186
196
|
|
|
187
|
-
// Validate and normalize the
|
|
188
|
-
//
|
|
189
|
-
// "
|
|
197
|
+
// Validate and normalize the string-array inputs. `includes` lists child
|
|
198
|
+
// skill IDs; activation_hints / avoid_when become the skill's "Use when:" /
|
|
199
|
+
// "Avoid when:" retrieval signal in memory.
|
|
190
200
|
const includesResult = normalizeOptionalStringArray(
|
|
191
201
|
input.includes,
|
|
192
202
|
"includes",
|
|
@@ -204,6 +214,14 @@ export async function executeScaffoldManagedSkill(
|
|
|
204
214
|
return { content: `Error: ${activationHintsResult.error}`, isError: true };
|
|
205
215
|
}
|
|
206
216
|
const activationHints = activationHintsResult.value;
|
|
217
|
+
// Hints are the skill's "Use when:" retrieval text, and scaffolding rewrites
|
|
218
|
+
// the whole SKILL.md, so a write without them leaves (or strips) none.
|
|
219
|
+
if (!activationHints) {
|
|
220
|
+
return {
|
|
221
|
+
content: `Error: ${MISSING_ACTIVATION_HINTS}`,
|
|
222
|
+
isError: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
207
225
|
|
|
208
226
|
const avoidWhenResult = normalizeOptionalStringArray(
|
|
209
227
|
input.avoid_when,
|