@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
|
@@ -19,6 +19,7 @@ import type { McpConfig, McpServerConfig } from "../../config/schemas/mcp.js";
|
|
|
19
19
|
import { estimateToolDefinitionTokens } from "../../context/token-estimator.js";
|
|
20
20
|
import { reloadMcpServers } from "../../daemon/mcp-reload-service.js";
|
|
21
21
|
import { McpClient } from "../../mcp/client.js";
|
|
22
|
+
import { getMcpServerManager } from "../../mcp/manager.js";
|
|
22
23
|
import { orchestrateMcpOAuthConnect } from "../../mcp/mcp-auth-orchestrator.js";
|
|
23
24
|
import { getMcpAuthState } from "../../mcp/mcp-auth-state.js";
|
|
24
25
|
import {
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
deleteMcpOAuthCredentials,
|
|
31
32
|
hasMcpOAuthTokens,
|
|
32
33
|
} from "../../mcp/mcp-oauth-provider.js";
|
|
34
|
+
import { readPluginMcpServers } from "../../plugins/mcp-servers.js";
|
|
33
35
|
import { getMcpToolsByServer } from "../../tools/registry.js";
|
|
34
36
|
import { getLogger } from "../../util/logger.js";
|
|
35
37
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
@@ -224,8 +226,33 @@ interface McpServerEntry {
|
|
|
224
226
|
authHeaderName?: string;
|
|
225
227
|
allowedTools?: string[];
|
|
226
228
|
blockedTools?: string[];
|
|
229
|
+
/**
|
|
230
|
+
* Where the definition came from: the workspace `config.json` or a
|
|
231
|
+
* plugin's `mcp.json`. A plugin server is read-only from the CLI's
|
|
232
|
+
* perspective, since `mcp remove` and `mcp update` act on the workspace
|
|
233
|
+
* config, so the caller needs to be able to tell the two apart.
|
|
234
|
+
*/
|
|
235
|
+
source: "workspace" | "plugin";
|
|
236
|
+
/** Plugin that declared this server. Present only when `source` is `plugin`. */
|
|
237
|
+
pluginName?: string;
|
|
227
238
|
}
|
|
228
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Status reported for a plugin-declared server the MCP manager holds no
|
|
242
|
+
* live client for — it has not been started yet, or its connection failed.
|
|
243
|
+
*
|
|
244
|
+
* A plugin server is never health-checked the way a workspace server is.
|
|
245
|
+
* `checkMachineReadableHealth` constructs its own `McpClient`, which
|
|
246
|
+
* resolves `mcp:<serverId>:headers` and `mcp:<serverId>:tokens` from the
|
|
247
|
+
* credential store, and a plugin controls both its server key and its URL,
|
|
248
|
+
* so probing one would send workspace-owned credentials to an endpoint the
|
|
249
|
+
* plugin chose whenever an id happens to match a stored key. Skipping the
|
|
250
|
+
* probe also avoids spawning a plugin's declared stdio command as a side
|
|
251
|
+
* effect of listing. The manager's own client — started with credentials
|
|
252
|
+
* isolated — is the only thing consulted instead.
|
|
253
|
+
*/
|
|
254
|
+
const PLUGIN_SERVER_STATUS = "declared";
|
|
255
|
+
|
|
229
256
|
function detectAuthType(headers: Record<string, string>): "bearer" | "api-key" {
|
|
230
257
|
const authValue = headers["Authorization"] ?? headers["authorization"];
|
|
231
258
|
if (authValue?.startsWith("Bearer ")) {
|
|
@@ -240,65 +267,129 @@ async function handleMcpList(_args: {
|
|
|
240
267
|
const raw = loadRawConfig();
|
|
241
268
|
const mcpConfig = raw.mcp as Partial<McpConfig> | undefined;
|
|
242
269
|
const servers = mcpConfig?.servers ?? {};
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}),
|
|
270
|
+
const configEntries = (
|
|
271
|
+
Object.entries(servers) as [string, McpServerConfig][]
|
|
272
|
+
).filter(([, config]) => config && typeof config === "object");
|
|
273
|
+
|
|
274
|
+
const workspaceEntries: McpServerEntry[] = await Promise.all(
|
|
275
|
+
configEntries.map(async ([id, config]) => {
|
|
276
|
+
const enabled = config.enabled !== false;
|
|
277
|
+
let status: string;
|
|
278
|
+
if (!enabled) {
|
|
279
|
+
status = "disabled";
|
|
280
|
+
} else {
|
|
281
|
+
status = await checkMachineReadableHealth(id, config);
|
|
282
|
+
}
|
|
283
|
+
const hasOAuth =
|
|
284
|
+
config.transport.type !== "stdio" ? await hasMcpOAuthTokens(id) : false;
|
|
285
|
+
|
|
286
|
+
// Check credential store for stored static auth headers
|
|
287
|
+
const storedHeaders = await getMcpHeaders(id);
|
|
288
|
+
// Also check legacy config-level headers
|
|
289
|
+
const configHeaders =
|
|
290
|
+
config.transport.type !== "stdio"
|
|
291
|
+
? config.transport.headers
|
|
292
|
+
: undefined;
|
|
293
|
+
const effectiveHeaders = storedHeaders ?? configHeaders;
|
|
294
|
+
const hasStaticAuth =
|
|
295
|
+
!!effectiveHeaders && Object.keys(effectiveHeaders).length > 0;
|
|
296
|
+
const authType: "none" | "bearer" | "api-key" = hasStaticAuth
|
|
297
|
+
? detectAuthType(effectiveHeaders!)
|
|
298
|
+
: "none";
|
|
299
|
+
const authHeaderName =
|
|
300
|
+
authType === "api-key" && effectiveHeaders
|
|
301
|
+
? Object.keys(effectiveHeaders).find(
|
|
302
|
+
(k) => k.toLowerCase() !== "authorization",
|
|
303
|
+
)
|
|
304
|
+
: undefined;
|
|
305
|
+
|
|
306
|
+
// Strip headers from transport, never return secrets
|
|
307
|
+
const { headers: _stripped, ...safeTransport } =
|
|
308
|
+
config.transport as Record<string, unknown>;
|
|
309
|
+
|
|
310
|
+
return {
|
|
311
|
+
id,
|
|
312
|
+
status,
|
|
313
|
+
transport: safeTransport as McpServerEntry["transport"],
|
|
314
|
+
enabled,
|
|
315
|
+
defaultRiskLevel: config.defaultRiskLevel ?? "high",
|
|
316
|
+
hasOAuth,
|
|
317
|
+
hasStaticAuth,
|
|
318
|
+
authType,
|
|
319
|
+
...(authHeaderName && { authHeaderName }),
|
|
320
|
+
...(config.allowedTools && { allowedTools: config.allowedTools }),
|
|
321
|
+
...(config.blockedTools && { blockedTools: config.blockedTools }),
|
|
322
|
+
source: "workspace" as const,
|
|
323
|
+
};
|
|
324
|
+
}),
|
|
299
325
|
);
|
|
300
326
|
|
|
301
|
-
return {
|
|
327
|
+
return {
|
|
328
|
+
servers: [...workspaceEntries, ...listPluginServerEntries(configEntries)],
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Project plugin-declared servers onto listing entries.
|
|
334
|
+
*
|
|
335
|
+
* Nothing here touches the credential store or the network: a plugin
|
|
336
|
+
* server carries no auth state the assistant owns, and its status comes
|
|
337
|
+
* from the manager's in-memory client rather than a probe (see
|
|
338
|
+
* {@link PLUGIN_SERVER_STATUS}).
|
|
339
|
+
*/
|
|
340
|
+
function listPluginServerEntries(
|
|
341
|
+
configEntries: [string, McpServerConfig][],
|
|
342
|
+
): McpServerEntry[] {
|
|
343
|
+
const { servers, issues } = readPluginMcpServers();
|
|
344
|
+
for (const issue of issues) {
|
|
345
|
+
log.warn(
|
|
346
|
+
{
|
|
347
|
+
plugin: issue.pluginName,
|
|
348
|
+
...(issue.serverKey && { serverKey: issue.serverKey }),
|
|
349
|
+
},
|
|
350
|
+
`Plugin MCP declaration problem: ${issue.message}`,
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// A workspace entry outranks a plugin's declaration of the same id: the
|
|
355
|
+
// user's own configuration is the more specific statement, and it is the
|
|
356
|
+
// one they can edit. `buildEffectiveMcpConfig` applies the same
|
|
357
|
+
// precedence, so this listing describes the set the daemon actually runs.
|
|
358
|
+
const workspaceIds = new Set(configEntries.map(([id]) => id));
|
|
359
|
+
const manager = getMcpServerManager();
|
|
360
|
+
|
|
361
|
+
return servers
|
|
362
|
+
.filter((server) => {
|
|
363
|
+
if (!workspaceIds.has(server.id)) {
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
log.warn(
|
|
367
|
+
{ plugin: server.pluginName, serverId: server.id },
|
|
368
|
+
"Plugin MCP server shadowed by a workspace server of the same id; skipping",
|
|
369
|
+
);
|
|
370
|
+
return false;
|
|
371
|
+
})
|
|
372
|
+
.map((server) => {
|
|
373
|
+
const { headers: _stripped, ...safeTransport } = server.config
|
|
374
|
+
.transport as Record<string, unknown>;
|
|
375
|
+
return {
|
|
376
|
+
id: server.id,
|
|
377
|
+
status: manager.getClient(server.id)?.isConnected
|
|
378
|
+
? "connected"
|
|
379
|
+
: PLUGIN_SERVER_STATUS,
|
|
380
|
+
transport: safeTransport as McpServerEntry["transport"],
|
|
381
|
+
enabled: true,
|
|
382
|
+
defaultRiskLevel: server.config.defaultRiskLevel,
|
|
383
|
+
// A plugin server has no assistant-owned credentials. Resolving
|
|
384
|
+
// these against `mcp:<id>:*` would report, and could disclose, a
|
|
385
|
+
// workspace credential that happens to share the id.
|
|
386
|
+
hasOAuth: false,
|
|
387
|
+
hasStaticAuth: false,
|
|
388
|
+
authType: "none" as const,
|
|
389
|
+
source: "plugin" as const,
|
|
390
|
+
pluginName: server.pluginName,
|
|
391
|
+
};
|
|
392
|
+
});
|
|
302
393
|
}
|
|
303
394
|
|
|
304
395
|
// ---------------------------------------------------------------------------
|
|
@@ -47,6 +47,7 @@ interface MockConversation {
|
|
|
47
47
|
contextCompactedAt: number | null;
|
|
48
48
|
sentMessages: AssistantEvent[];
|
|
49
49
|
sendToClient: (msg: AssistantEvent) => void;
|
|
50
|
+
emit: (msg: AssistantEvent) => void;
|
|
50
51
|
getMessages: () => unknown[];
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -64,6 +65,7 @@ function makeConversation(id = "conv-playground-test"): MockConversation {
|
|
|
64
65
|
contextCompactedAt: null,
|
|
65
66
|
sentMessages,
|
|
66
67
|
sendToClient: (msg) => sentMessages.push(msg),
|
|
68
|
+
emit: (msg) => sentMessages.push(msg),
|
|
67
69
|
getMessages: () => [],
|
|
68
70
|
};
|
|
69
71
|
}
|
|
@@ -72,7 +72,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
72
72
|
if (circuitOpenForMs === 0) {
|
|
73
73
|
if (circuit.compactionCircuitOpenUntil !== null) {
|
|
74
74
|
circuit.compactionCircuitOpenUntil = null;
|
|
75
|
-
conversation.
|
|
75
|
+
conversation.emit({
|
|
76
76
|
type: "compaction_circuit_closed",
|
|
77
77
|
conversationId: conversation.conversationId,
|
|
78
78
|
});
|
|
@@ -80,7 +80,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
80
80
|
} else {
|
|
81
81
|
const openUntil = Date.now() + circuitOpenForMs;
|
|
82
82
|
circuit.compactionCircuitOpenUntil = openUntil;
|
|
83
|
-
conversation.
|
|
83
|
+
conversation.emit({
|
|
84
84
|
type: "compaction_circuit_open",
|
|
85
85
|
conversationId: conversation.conversationId,
|
|
86
86
|
reason: "3_consecutive_failures",
|
|
@@ -52,7 +52,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
52
52
|
circuit.consecutiveCompactionFailures = 0;
|
|
53
53
|
if (circuit.compactionCircuitOpenUntil !== null) {
|
|
54
54
|
circuit.compactionCircuitOpenUntil = null;
|
|
55
|
-
conversation.
|
|
55
|
+
conversation.emit({
|
|
56
56
|
type: "compaction_circuit_closed",
|
|
57
57
|
conversationId: conversation.conversationId,
|
|
58
58
|
});
|
|
@@ -85,6 +85,7 @@ import {
|
|
|
85
85
|
} from "../../cli/lib/uninstall-plugin.js";
|
|
86
86
|
import {
|
|
87
87
|
PluginMergeBaselineError,
|
|
88
|
+
PluginNotCuratedError,
|
|
88
89
|
PluginNotUpgradableError,
|
|
89
90
|
upgradePlugin,
|
|
90
91
|
} from "../../cli/lib/upgrade-plugin.js";
|
|
@@ -606,6 +607,12 @@ const pluginUpgradeRequestSchema = z.object({
|
|
|
606
607
|
.describe(
|
|
607
608
|
"How to reconcile local edits with the pin. `overwrite` (default) discards local edits and re-installs the pin; `ours`/`theirs` three-way merge, resolving conflicting hunks toward the local edit or the pin respectively; `assistant` is not yet supported.",
|
|
608
609
|
),
|
|
610
|
+
marketplaceOnly: z
|
|
611
|
+
.boolean()
|
|
612
|
+
.optional()
|
|
613
|
+
.describe(
|
|
614
|
+
"Refuse the upgrade (409) when the marketplace does not claim this plugin, instead of advancing it to whatever its recorded GitHub ref now resolves to. Set by unattended callers such as the automatic update sweep, for which running code no curator reviewed is never an acceptable outcome. Defaults to false.",
|
|
615
|
+
),
|
|
609
616
|
});
|
|
610
617
|
|
|
611
618
|
const pluginUpgradeResponseSchema = z.object({
|
|
@@ -1465,6 +1472,11 @@ async function handleUpgradePlugin({
|
|
|
1465
1472
|
typeof body.strategy === "string"
|
|
1466
1473
|
? (body.strategy as PluginUpgradeStrategy)
|
|
1467
1474
|
: undefined;
|
|
1475
|
+
// Enforced here, not just by whoever decided to call: `upgradePlugin` fetches
|
|
1476
|
+
// the catalog itself, so an entry that vanishes between a caller's own check
|
|
1477
|
+
// and this handler would otherwise reroute a curated upgrade onto the
|
|
1478
|
+
// install's mutable recorded ref.
|
|
1479
|
+
const marketplaceOnly = body.marketplaceOnly === true;
|
|
1468
1480
|
|
|
1469
1481
|
// Like install, the upgrade target ref is the curated marketplace pin
|
|
1470
1482
|
// (resolved inside `upgradePlugin` via `inspectPlugin`), never a
|
|
@@ -1498,7 +1510,7 @@ async function handleUpgradePlugin({
|
|
|
1498
1510
|
// upgraded revision adds is surfaced to the user by the schedule
|
|
1499
1511
|
// reconciler's `schedule.declared` notification when it arms.
|
|
1500
1512
|
const result = await upgradePlugin(
|
|
1501
|
-
{ name, dryRun, strategy },
|
|
1513
|
+
{ name, dryRun, strategy, marketplaceOnly },
|
|
1502
1514
|
{
|
|
1503
1515
|
fetch: globalThis.fetch.bind(globalThis),
|
|
1504
1516
|
// Tear the old version down BEFORE the staged tree replaces its
|
|
@@ -1568,6 +1580,12 @@ async function handleUpgradePlugin({
|
|
|
1568
1580
|
if (err instanceof PluginNotUpgradableError) {
|
|
1569
1581
|
throw new ConflictError(err.message);
|
|
1570
1582
|
}
|
|
1583
|
+
// A `marketplaceOnly` caller asked about an install the catalog does not
|
|
1584
|
+
// claim. Retrying changes nothing; only a human upgrading it deliberately
|
|
1585
|
+
// (without the flag) can move it, so 409 rather than a retryable 503.
|
|
1586
|
+
if (err instanceof PluginNotCuratedError) {
|
|
1587
|
+
throw new ConflictError(err.message);
|
|
1588
|
+
}
|
|
1571
1589
|
// A rate-limited or temporarily-down source (the plugin repo or the
|
|
1572
1590
|
// marketplace catalog) is a retryable outage, not a conflict — 503.
|
|
1573
1591
|
if (err instanceof PluginSourceUnavailableError) {
|
|
@@ -1625,7 +1643,7 @@ function mapTogglePluginError(err: unknown): RouteError {
|
|
|
1625
1643
|
|
|
1626
1644
|
/**
|
|
1627
1645
|
* Converge plugin-declared schedules against the sentinel this route just
|
|
1628
|
-
* wrote, so a
|
|
1646
|
+
* wrote, so a disabled plugin's rows disarm now rather than at the
|
|
1629
1647
|
* reconciler's next backstop sweep.
|
|
1630
1648
|
*
|
|
1631
1649
|
* Fire-and-forget: the toggle itself already succeeded on disk, so a reconcile
|
|
@@ -1653,15 +1671,27 @@ function reconcilePluginSchedulesInBackground(): void {
|
|
|
1653
1671
|
* names WHICH resource is stale, not the new value. The origin client id is
|
|
1654
1672
|
* threaded through for self-echo suppression.
|
|
1655
1673
|
*/
|
|
1656
|
-
function handleEnablePlugin({
|
|
1674
|
+
async function handleEnablePlugin({
|
|
1675
|
+
pathParams = {},
|
|
1676
|
+
headers,
|
|
1677
|
+
}: RouteHandlerArgs) {
|
|
1657
1678
|
try {
|
|
1658
1679
|
enablePlugin(pathParams.name ?? "");
|
|
1659
|
-
publishPluginsChanged(getOriginClientId(headers));
|
|
1660
|
-
reconcilePluginSchedulesInBackground();
|
|
1661
|
-
return { ok: true };
|
|
1662
1680
|
} catch (err) {
|
|
1663
1681
|
throw mapTogglePluginError(err);
|
|
1664
1682
|
}
|
|
1683
|
+
// A plugin the boot scan skipped for its sentinel has no hooks, tools or
|
|
1684
|
+
// MCP servers in the caches, so clearing the sentinel is not enough to
|
|
1685
|
+
// bring it up. Run the same imperative source reconcile the install and
|
|
1686
|
+
// upgrade routes use, which activates the plugin and then converges its
|
|
1687
|
+
// schedules and MCP servers. Awaited, like the install route, so a client
|
|
1688
|
+
// that lists tools right after enabling sees the plugin up; the reconcile
|
|
1689
|
+
// contains its own failures, so a broken plugin cannot turn a successful
|
|
1690
|
+
// enable into a route error. The invalidation publishes after it for the
|
|
1691
|
+
// same reason: refetching clients should see the post-activation state.
|
|
1692
|
+
await reconcilePluginSourcesNow();
|
|
1693
|
+
publishPluginsChanged(getOriginClientId(headers));
|
|
1694
|
+
return { ok: true };
|
|
1665
1695
|
}
|
|
1666
1696
|
|
|
1667
1697
|
function handleDisablePlugin({ pathParams = {}, headers }: RouteHandlerArgs) {
|
|
@@ -2039,7 +2069,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
2039
2069
|
},
|
|
2040
2070
|
summary: "Upgrade a plugin to its source's current revision",
|
|
2041
2071
|
description:
|
|
2042
|
-
'Move an installed plugin to its source\'s current revision, re-materializing it under `<workspaceDir>/plugins/<name>/`. A marketplace plugin advances to the curated pin; a plugin installed directly from a GitHub URL (untrusted, not in the marketplace) advances to whatever its recorded ref now resolves to — a pinned SHA is immutable (a no-op), a branch/tag/HEAD moves as upstream does — re-materialized verbatim with no curated adapter overlay, exactly as the original untrusted install was. The target ref is never taken from the request (no caller-supplied ref), mirroring `plugins install`\'s curation boundary. A no-op (`outcome: "already-up-to-date"`) when the installed commit already equals the target; pass `dryRun` to preview the move (`outcome: "would-upgrade"`) without touching the install. Installs lacking provenance are re-pinned to the current SHA. The upgraded code is picked up live on the next read (no restart required). `strategy` controls how local edits are reconciled: `overwrite` (default) discards them and re-installs the target wholesale; `ours`/`theirs`/`assistant` perform a three-way merge against the re-materialized install commit, carrying non-conflicting edits from both sides forward and resolving conflicting hunks toward the local edit (`ours`) or the target (`theirs`), or writing git conflict markers into the file and reporting them in `conflicts`/`binaryConflicts` for the assistant to resolve (`assistant`). A merge strategy whose install-time baseline cannot be reconstructed returns 409. Mirrors the CLI\'s `assistant plugins upgrade <name> [--strategy <s>]`.',
|
|
2072
|
+
'Move an installed plugin to its source\'s current revision, re-materializing it under `<workspaceDir>/plugins/<name>/`. A marketplace plugin advances to the curated pin; a plugin installed directly from a GitHub URL (untrusted, not in the marketplace) advances to whatever its recorded ref now resolves to — a pinned SHA is immutable (a no-op), a branch/tag/HEAD moves as upstream does — re-materialized verbatim with no curated adapter overlay, exactly as the original untrusted install was. The target ref is never taken from the request (no caller-supplied ref), mirroring `plugins install`\'s curation boundary. A no-op (`outcome: "already-up-to-date"`) when the installed commit already equals the target; pass `dryRun` to preview the move (`outcome: "would-upgrade"`) without touching the install. Installs lacking provenance are re-pinned to the current SHA. The upgraded code is picked up live on the next read (no restart required). `strategy` controls how local edits are reconciled: `overwrite` (default) discards them and re-installs the target wholesale; `ours`/`theirs`/`assistant` perform a three-way merge against the re-materialized install commit, carrying non-conflicting edits from both sides forward and resolving conflicting hunks toward the local edit (`ours`) or the target (`theirs`), or writing git conflict markers into the file and reporting them in `conflicts`/`binaryConflicts` for the assistant to resolve (`assistant`). A merge strategy whose install-time baseline cannot be reconstructed returns 409. Pass `marketplaceOnly` to refuse the untrusted direct path outright (409), which is what the unattended auto-update sweep does. Mirrors the CLI\'s `assistant plugins upgrade <name> [--strategy <s>]`.',
|
|
2043
2073
|
tags: ["plugins"],
|
|
2044
2074
|
pathParams: [
|
|
2045
2075
|
{
|
|
@@ -2062,7 +2092,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
2062
2092
|
},
|
|
2063
2093
|
"409": {
|
|
2064
2094
|
description:
|
|
2065
|
-
"The install has neither a marketplace entry nor a recorded GitHub source to advance to, or a merge strategy was requested whose install-time baseline cannot be reconstructed.",
|
|
2095
|
+
"The install has neither a marketplace entry nor a recorded GitHub source to advance to, a `marketplaceOnly` upgrade was requested for an install the marketplace does not claim, or a merge strategy was requested whose install-time baseline cannot be reconstructed.",
|
|
2066
2096
|
},
|
|
2067
2097
|
"503": {
|
|
2068
2098
|
description:
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* the shared ROUTES array.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { statSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
|
|
8
11
|
import { z } from "zod";
|
|
9
12
|
|
|
10
13
|
import { getOrCreateConversation } from "../../daemon/conversation-store.js";
|
|
@@ -15,9 +18,10 @@ import {
|
|
|
15
18
|
getUsageCostForRun,
|
|
16
19
|
listRunConversationIds,
|
|
17
20
|
} from "../../persistence/llm-usage-store.js";
|
|
21
|
+
import { isPluginDisabled } from "../../plugins/disabled-state.js";
|
|
18
22
|
import { isDeferSchedule } from "../../schedule/defer-provenance.js";
|
|
19
23
|
import { validateScheduleInferenceProfile } from "../../schedule/inference-profile.js";
|
|
20
|
-
import {
|
|
24
|
+
import { pluginScheduleSourceAvailable } from "../../schedule/plugin-schedule-availability.js";
|
|
21
25
|
import { isPluginSchedulesEnabled } from "../../schedule/plugin-schedules-gate.js";
|
|
22
26
|
import {
|
|
23
27
|
describeRRuleExpression,
|
|
@@ -38,6 +42,7 @@ import {
|
|
|
38
42
|
getLastScheduleConversationId,
|
|
39
43
|
getSchedule,
|
|
40
44
|
getScheduleRuns,
|
|
45
|
+
isEngineLatched,
|
|
41
46
|
listSchedules,
|
|
42
47
|
resolveScheduleConversationGroupId,
|
|
43
48
|
type ScheduleJob,
|
|
@@ -49,6 +54,7 @@ import { buildWakeScheduleOptions } from "../../schedule/wake-schedule-options.j
|
|
|
49
54
|
import { initializeTools } from "../../tools/registry.js";
|
|
50
55
|
import { UserError } from "../../util/errors.js";
|
|
51
56
|
import { getLogger } from "../../util/logger.js";
|
|
57
|
+
import { getWorkspacePluginsDir } from "../../util/platform.js";
|
|
52
58
|
import { normalizeCapabilityManifest } from "../../workflows/capabilities.js";
|
|
53
59
|
import { getWorkflowRunManager } from "../../workflows/run-manager.js";
|
|
54
60
|
import { isOwnerCaller } from "../auth/owner-caller.js";
|
|
@@ -108,6 +114,76 @@ async function assertWakeMutationAllowed(
|
|
|
108
114
|
// Response schemas (shared by all schedule routes)
|
|
109
115
|
// ---------------------------------------------------------------------------
|
|
110
116
|
|
|
117
|
+
const DISARM_REASONS = [
|
|
118
|
+
"user_disabled",
|
|
119
|
+
"plugin_removed",
|
|
120
|
+
"plugin_disabled",
|
|
121
|
+
"declaration_removed",
|
|
122
|
+
"declaration_disabled",
|
|
123
|
+
] as const;
|
|
124
|
+
|
|
125
|
+
type DisarmReason = (typeof DISARM_REASONS)[number];
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Why a plugin-sourced schedule sits disarmed, so a client can say so instead
|
|
129
|
+
* of showing an off row with no explanation.
|
|
130
|
+
*
|
|
131
|
+
* Only a sourced row that is off can have one, which also bounds the disk
|
|
132
|
+
* probes below to those rows. The first matching cause wins, ordered so the
|
|
133
|
+
* most specific answer comes first: the user's own override outranks anything
|
|
134
|
+
* the plugin's files say, a plugin that is gone outranks one that is merely
|
|
135
|
+
* disabled, and a declaration that is gone outranks one that is still there.
|
|
136
|
+
* `declaration_disabled` is the fallback the plugin's own files account for:
|
|
137
|
+
* a declared `enabled: false`, a declaration too broken to arm, or a manifest
|
|
138
|
+
* that no longer parses.
|
|
139
|
+
*
|
|
140
|
+
* Two off states never get a reason, because in neither did the plugin's files
|
|
141
|
+
* turn the schedule off. A row the engine latched (a fired or cancelled
|
|
142
|
+
* one-shot, a bounded recurrence the claim path exhausted) is a schedule that
|
|
143
|
+
* finished, not one that is paused. And when the `plugin-schedules` kill switch
|
|
144
|
+
* is off the reconciler disarms every sourced row regardless of what its
|
|
145
|
+
* declaration says, so no per-row cause is the true one. Both return null, and
|
|
146
|
+
* clients show the row like any other schedule that is off.
|
|
147
|
+
*/
|
|
148
|
+
function deriveDisarmReason(
|
|
149
|
+
job: Pick<
|
|
150
|
+
ScheduleJob,
|
|
151
|
+
| "sourceKey"
|
|
152
|
+
| "enabled"
|
|
153
|
+
| "userEnabled"
|
|
154
|
+
| "status"
|
|
155
|
+
| "nextRunAt"
|
|
156
|
+
| "lastRunAt"
|
|
157
|
+
>,
|
|
158
|
+
): DisarmReason | null {
|
|
159
|
+
if (job.sourceKey === null || job.enabled) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
if (job.userEnabled === false) {
|
|
163
|
+
return "user_disabled";
|
|
164
|
+
}
|
|
165
|
+
if (isEngineLatched(job) || !isPluginSchedulesEnabled()) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const match = /^plugin:([^/]+)\/(.+)$/.exec(job.sourceKey);
|
|
169
|
+
if (!match) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
const [, pluginName, scheduleName] = match;
|
|
173
|
+
const pluginDir = join(getWorkspacePluginsDir(), pluginName!);
|
|
174
|
+
if (!statSync(pluginDir, { throwIfNoEntry: false })?.isDirectory()) {
|
|
175
|
+
return "plugin_removed";
|
|
176
|
+
}
|
|
177
|
+
if (isPluginDisabled(pluginName!)) {
|
|
178
|
+
return "plugin_disabled";
|
|
179
|
+
}
|
|
180
|
+
const declarationDir = join(pluginDir, "schedules", scheduleName!);
|
|
181
|
+
if (!statSync(declarationDir, { throwIfNoEntry: false })?.isDirectory()) {
|
|
182
|
+
return "declaration_removed";
|
|
183
|
+
}
|
|
184
|
+
return "declaration_disabled";
|
|
185
|
+
}
|
|
186
|
+
|
|
111
187
|
const scheduleSchema = z.object({
|
|
112
188
|
id: z.string(),
|
|
113
189
|
name: z.string(),
|
|
@@ -150,6 +226,12 @@ const scheduleSchema = z.object({
|
|
|
150
226
|
.describe(
|
|
151
227
|
"User enable/disable override on a plugin-sourced schedule; null when the declaration's own enabled value applies. Always null for user-created schedules.",
|
|
152
228
|
),
|
|
229
|
+
disarmReason: z
|
|
230
|
+
.enum(DISARM_REASONS)
|
|
231
|
+
.nullable()
|
|
232
|
+
.describe(
|
|
233
|
+
"Why a plugin-sourced schedule is off: the user turned it off, the plugin is gone, the plugin is disabled, the declaration is gone, or the plugin's own files turned it off. Null whenever the schedule is on, and always null for user-created schedules.",
|
|
234
|
+
),
|
|
153
235
|
isOneShot: z.boolean(),
|
|
154
236
|
// A deferred wake ("remind me about this tomorrow") is an ordinary schedule
|
|
155
237
|
// row created by the defer path, distinguishable only by `createdBy`, which
|
|
@@ -302,6 +384,7 @@ function serializeSchedule(
|
|
|
302
384
|
workflowName: j.workflowName,
|
|
303
385
|
sourceKey: j.sourceKey,
|
|
304
386
|
userEnabled: j.userEnabled,
|
|
387
|
+
disarmReason: deriveDisarmReason(j),
|
|
305
388
|
isOneShot: isOneShotForDisplay(j),
|
|
306
389
|
isDeferred: isDeferSchedule(j.createdBy),
|
|
307
390
|
};
|
|
@@ -1240,15 +1323,19 @@ async function handleRunScheduleNow(
|
|
|
1240
1323
|
|
|
1241
1324
|
// A plugin-sourced row runs the plugin's own script or prompt, so run-now is
|
|
1242
1325
|
// only offered while that plugin is something the runtime would activate.
|
|
1243
|
-
// `
|
|
1244
|
-
// a disabled plugin, an unreadable or invalid manifest, and a
|
|
1245
|
-
// that is simply gone. Turning the feature flag off retires the
|
|
1246
|
-
// wholesale and takes the same path. The row can still be armed at
|
|
1247
|
-
// point, because the reconciler that disarms it runs on its own
|
|
1326
|
+
// `pluginScheduleSourceAvailable` covers a plugin the daemon never
|
|
1327
|
+
// activated, a disabled plugin, an unreadable or invalid manifest, and a
|
|
1328
|
+
// declaration that is simply gone. Turning the feature flag off retires the
|
|
1329
|
+
// surface wholesale and takes the same path. The row can still be armed at
|
|
1330
|
+
// this point, because the reconciler that disarms it runs on its own
|
|
1331
|
+
// schedule.
|
|
1332
|
+
// Routes are served by the daemon, so the activation half of the probe reads
|
|
1333
|
+
// a live ledger here. Paths that run in worker processes cannot ask that
|
|
1334
|
+
// question and use the on-disk probe alone.
|
|
1248
1335
|
if (
|
|
1249
1336
|
schedule.sourceKey !== null &&
|
|
1250
1337
|
(!isPluginSchedulesEnabled() ||
|
|
1251
|
-
!(await
|
|
1338
|
+
!(await pluginScheduleSourceAvailable(schedule.sourceKey)))
|
|
1252
1339
|
) {
|
|
1253
1340
|
throw new BadRequestError(
|
|
1254
1341
|
"This schedule's plugin is disabled or no longer declares it, so it cannot be run.",
|
|
@@ -37,7 +37,6 @@ import {
|
|
|
37
37
|
import {
|
|
38
38
|
check,
|
|
39
39
|
classifyRisk,
|
|
40
|
-
generateAllowlistOptions,
|
|
41
40
|
generateScopeOptions,
|
|
42
41
|
} from "../../permissions/checker.js";
|
|
43
42
|
import { resolveGuardianPersonaPath } from "../../prompts/persona-resolver.js";
|
|
@@ -710,19 +709,22 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
|
|
|
710
709
|
isInteractive === false ? "headless" : "conversation";
|
|
711
710
|
const policyContext = { executionTarget, executionContext } as const;
|
|
712
711
|
|
|
713
|
-
const
|
|
712
|
+
const classification = await classifyRisk(
|
|
714
713
|
toolName,
|
|
715
714
|
input,
|
|
716
715
|
workingDir,
|
|
717
716
|
undefined,
|
|
718
717
|
manifestOverride,
|
|
719
718
|
);
|
|
719
|
+
const riskLevel = classification.level;
|
|
720
720
|
const result = await check(
|
|
721
721
|
toolName,
|
|
722
722
|
input,
|
|
723
723
|
workingDir,
|
|
724
724
|
policyContext,
|
|
725
725
|
manifestOverride,
|
|
726
|
+
undefined,
|
|
727
|
+
classification,
|
|
726
728
|
);
|
|
727
729
|
|
|
728
730
|
if (isInteractive === false && result.decision === "prompt") {
|
|
@@ -743,11 +745,9 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
|
|
|
743
745
|
| undefined;
|
|
744
746
|
|
|
745
747
|
if (result.decision === "prompt") {
|
|
746
|
-
const allowlistOptions = await generateAllowlistOptions(toolName, input);
|
|
747
|
-
const scopeOptions = generateScopeOptions(workingDir, toolName);
|
|
748
748
|
promptPayload = {
|
|
749
|
-
allowlistOptions,
|
|
750
|
-
scopeOptions,
|
|
749
|
+
allowlistOptions: classification.allowlistOptions ?? [],
|
|
750
|
+
scopeOptions: generateScopeOptions(workingDir, toolName),
|
|
751
751
|
persistentDecisionsAllowed: true,
|
|
752
752
|
};
|
|
753
753
|
}
|