@wardby/cli 0.6.0 → 0.8.0
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/.env.example +5 -5
- package/README.md +6 -1
- package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
- package/dist/claude-coding-worker/driver.d.ts +33 -3
- package/dist/claude-coding-worker/driver.js +151 -21
- package/dist/claude-coding-worker/main.js +38 -6
- package/dist/claude-coding-worker/sdk.js +29 -2
- package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
- package/dist/claude-coding-worker/tool-socket.js +111 -0
- package/dist/claude-coding-worker/transcript.d.ts +18 -0
- package/dist/claude-coding-worker/transcript.js +77 -0
- package/dist/claude-plugin/command.d.ts +61 -0
- package/dist/claude-plugin/command.js +376 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +3 -1
- package/dist/cli.js +71 -13
- package/dist/coding/code-host.d.ts +16 -0
- package/dist/coding/code-host.js +60 -0
- package/dist/coding/continuation-wording.d.ts +35 -0
- package/dist/coding/continuation-wording.js +73 -0
- package/dist/coding/linked-issue-note.d.ts +23 -0
- package/dist/coding/linked-issue-note.js +47 -0
- package/dist/coding/mcp-token.d.ts +12 -0
- package/dist/coding/mcp-token.js +26 -0
- package/dist/coding/merge-wording.d.ts +28 -0
- package/dist/coding/merge-wording.js +78 -0
- package/dist/coding/pr-description-note.d.ts +9 -0
- package/dist/coding/pr-description-note.js +32 -0
- package/dist/coding/profile.d.ts +46 -126
- package/dist/coding/profile.js +45 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +264 -346
- package/dist/coding/protocol.js +237 -12
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +17 -0
- package/dist/coding/registry/allowlist.d.ts +12 -0
- package/dist/coding/registry/allowlist.js +14 -1
- package/dist/coding/registry/audit-mode.d.ts +153 -0
- package/dist/coding/registry/audit-mode.js +304 -0
- package/dist/coding/registry/lockfile-shared.d.ts +36 -0
- package/dist/coding/registry/lockfile-shared.js +128 -0
- package/dist/coding/registry/lockfiles.js +1 -1
- package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
- package/dist/coding/registry/npm-lockfile-formats.js +41 -0
- package/dist/coding/registry/npm-lockfile.d.ts +8 -4
- package/dist/coding/registry/npm-lockfile.js +4 -6
- package/dist/coding/registry/npm.js +78 -8
- package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
- package/dist/coding/registry/pnpm-lockfile.js +189 -0
- package/dist/coding/registry/pypi-plan.d.ts +50 -0
- package/dist/coding/registry/pypi-plan.js +406 -0
- package/dist/coding/registry/pypi-requirements.d.ts +58 -0
- package/dist/coding/registry/pypi-requirements.js +155 -0
- package/dist/coding/registry/pypi.d.ts +3 -27
- package/dist/coding/registry/pypi.js +40 -154
- package/dist/coding/registry/refusal-hints.d.ts +20 -0
- package/dist/coding/registry/refusal-hints.js +61 -0
- package/dist/coding/registry/refusal-wording.d.ts +11 -0
- package/dist/coding/registry/refusal-wording.js +56 -0
- package/dist/coding/registry/report.d.ts +70 -8
- package/dist/coding/registry/report.js +112 -5
- package/dist/coding/registry/types.d.ts +58 -8
- package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
- package/dist/coding/registry/yarn-lockfile.js +367 -0
- package/dist/coding/services/catalog.d.ts +37 -351
- package/dist/coding/transcript/claude-code.d.ts +13 -0
- package/dist/coding/transcript/claude-code.js +273 -0
- package/dist/coding/transcript/download-protocol.d.ts +30 -0
- package/dist/coding/transcript/download-protocol.js +18 -0
- package/dist/coding/transcript/format.d.ts +20 -0
- package/dist/coding/transcript/format.js +32 -0
- package/dist/coding/transcript/recorder.d.ts +52 -0
- package/dist/coding/transcript/recorder.js +225 -0
- package/dist/coding/transcript/resume/checkout.d.ts +31 -0
- package/dist/coding/transcript/resume/checkout.js +203 -0
- package/dist/coding/transcript/resume/command.d.ts +17 -0
- package/dist/coding/transcript/resume/command.js +176 -0
- package/dist/coding/transcript/resume/download.d.ts +20 -0
- package/dist/coding/transcript/resume/download.js +153 -0
- package/dist/coding/transcript/resume/launch.d.ts +38 -0
- package/dist/coding/transcript/resume/launch.js +128 -0
- package/dist/coding/transcript/resume/session-file.d.ts +13 -0
- package/dist/coding/transcript/resume/session-file.js +79 -0
- package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
- package/dist/coding/transcript/resume/stand-in.js +49 -0
- package/dist/coding-worker/artifact.d.ts +8 -3
- package/dist/coding-worker/artifact.js +3 -1
- package/dist/coding-worker/debug-trace.d.ts +9 -6
- package/dist/coding-worker/debug-trace.js +16 -19
- package/dist/coding-worker/dependency-cache.d.mts +229 -0
- package/dist/coding-worker/dependency-cache.mjs +2123 -0
- package/dist/coding-worker/driver.d.ts +4 -3
- package/dist/coding-worker/driver.js +124 -39
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/main.js +5 -1
- package/dist/coding-worker/mcp-config.d.ts +27 -0
- package/dist/coding-worker/mcp-config.js +32 -0
- package/dist/coding-worker/sdk.d.ts +36 -0
- package/dist/coding-worker/sdk.js +28 -1
- package/dist/coding-worker/task-note.d.ts +11 -0
- package/dist/coding-worker/task-note.js +13 -0
- package/dist/coding-worker/types.d.ts +15 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/mcp-call-limit.d.ts +8 -0
- package/dist/config/mcp-call-limit.js +18 -0
- package/dist/config/mcp-servers.d.ts +8 -0
- package/dist/config/mcp-servers.js +12 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- package/dist/config/test-simulators.d.ts +92 -0
- package/dist/config/test-simulators.js +333 -0
- package/dist/config/tool-timeout.d.ts +1 -0
- package/dist/config/tool-timeout.js +18 -0
- package/dist/core/async-context.d.ts +2 -0
- package/dist/core/async-context.js +12 -0
- package/dist/core/budget-events.d.ts +108 -0
- package/dist/core/budget-events.js +346 -0
- package/dist/core/budget-groups.d.ts +50 -1
- package/dist/core/budget-groups.js +236 -27
- package/dist/core/budget-stopped-head.d.ts +46 -0
- package/dist/core/budget-stopped-head.js +81 -0
- package/dist/core/budget-topup.d.ts +51 -0
- package/dist/core/budget-topup.js +156 -0
- package/dist/core/budget-wording.d.ts +16 -2
- package/dist/core/budget-wording.js +40 -2
- package/dist/core/coding-mcp.d.ts +36 -0
- package/dist/core/coding-mcp.js +253 -0
- package/dist/core/coding-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -0
- package/dist/core/coding-repository.d.ts +46 -0
- package/dist/core/coding-repository.js +92 -0
- package/dist/core/cron.d.ts +19 -1
- package/dist/core/cron.js +17 -0
- package/dist/core/datastores.js +1 -1
- package/dist/core/deferred-coding.d.ts +14 -0
- package/dist/core/deferred-coding.js +62 -0
- package/dist/core/delegation-child.d.ts +25 -0
- package/dist/core/delegation-child.js +37 -0
- package/dist/core/delegation-slots.d.ts +27 -0
- package/dist/core/delegation-slots.js +44 -0
- package/dist/core/dispatch.d.ts +48 -2
- package/dist/core/dispatch.js +166 -66
- package/dist/core/engine-native.js +1 -1
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +169 -0
- package/dist/core/grants.d.ts +46 -8
- package/dist/core/grants.js +99 -8
- package/dist/core/host-events.d.ts +18 -2
- package/dist/core/host-events.js +291 -27
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +300 -22
- package/dist/core/issue-bridge.d.ts +50 -6
- package/dist/core/issue-bridge.js +124 -33
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +4 -10
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +58 -29
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +14 -1
- package/dist/core/lost-run-children.d.ts +6 -0
- package/dist/core/lost-run-children.js +32 -0
- package/dist/core/mark-ready.d.ts +34 -0
- package/dist/core/mark-ready.js +152 -0
- package/dist/core/markdown-code.d.ts +8 -0
- package/dist/core/markdown-code.js +107 -0
- package/dist/core/mcp-client/client.d.ts +47 -0
- package/dist/core/mcp-client/client.js +141 -0
- package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
- package/dist/core/mcp-client/jsonrpc.js +54 -0
- package/dist/core/mcp-client/results.d.ts +13 -0
- package/dist/core/mcp-client/results.js +42 -0
- package/dist/core/mcp-servers.d.ts +90 -0
- package/dist/core/mcp-servers.js +230 -0
- package/dist/core/mcp-tools.d.ts +108 -0
- package/dist/core/mcp-tools.js +287 -0
- package/dist/core/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +2 -1
- package/dist/core/merge-order-check.js +44 -18
- package/dist/core/notification-dispatcher.js +2 -1
- package/dist/core/notification-templates.d.ts +1 -7
- package/dist/core/notification-templates.js +36 -2
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +4 -3
- package/dist/core/reconciler.js +8 -1
- package/dist/core/related-pull-requests.d.ts +11 -3
- package/dist/core/related-pull-requests.js +49 -20
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/review-fix.d.ts +1 -1
- package/dist/core/review-fix.js +4 -3
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +3 -0
- package/dist/core/review-host-tools.js +102 -14
- package/dist/core/review-reads.d.ts +55 -0
- package/dist/core/review-reads.js +233 -0
- package/dist/core/run-status.d.ts +12 -0
- package/dist/core/run-status.js +12 -0
- package/dist/core/runner.d.ts +145 -49
- package/dist/core/runner.js +719 -216
- package/dist/core/schedule-start.d.ts +12 -0
- package/dist/core/schedule-start.js +14 -0
- package/dist/core/secret-broker-config.d.ts +12 -74
- package/dist/core/secret-broker-config.js +1 -1
- package/dist/core/secret-guard.d.ts +49 -0
- package/dist/core/secret-guard.js +119 -0
- package/dist/core/secret-guarded-stores.d.ts +12 -0
- package/dist/core/secret-guarded-stores.js +41 -0
- package/dist/core/secret-spans.d.ts +50 -0
- package/dist/core/secret-spans.js +94 -0
- package/dist/core/secrets.d.ts +11 -1
- package/dist/core/secrets.js +27 -1
- package/dist/core/serializable-retry.d.ts +18 -0
- package/dist/core/serializable-retry.js +43 -0
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/tool-admin.d.ts +5 -1
- package/dist/core/tool-admin.js +7 -2
- package/dist/core/tool-names.d.ts +13 -0
- package/dist/core/tool-names.js +20 -0
- package/dist/core/webhooks.d.ts +4 -0
- package/dist/core/webhooks.js +68 -49
- package/dist/core/workflow-events.d.ts +14 -2
- package/dist/core/workflow-events.js +4 -0
- package/dist/core/workflow-run-events.d.ts +5 -3
- package/dist/core/workflow-run-events.js +45 -9
- package/dist/core/zod-json-schema.d.ts +4 -0
- package/dist/core/zod-json-schema.js +39 -0
- package/dist/core/zod3-window.d.ts +35 -0
- package/dist/core/zod3-window.js +124 -0
- package/dist/generated/prisma/browser.d.ts +65 -3
- package/dist/generated/prisma/client.d.ts +65 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
- package/dist/generated/prisma/enums.d.ts +10 -0
- package/dist/generated/prisma/enums.js +8 -0
- package/dist/generated/prisma/internal/class.d.ts +110 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
- package/dist/generated/prisma/models/Agent.d.ts +377 -8
- package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
- package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
- package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
- package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
- package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
- package/dist/generated/prisma/models/HostProvider.js +1 -0
- package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
- package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
- package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
- package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
- package/dist/generated/prisma/models/McpServer.js +1 -0
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- package/dist/generated/prisma/models/Principal.d.ts +167 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
- package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
- package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
- package/dist/generated/prisma/models/Run.d.ts +738 -2
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +387 -0
- package/dist/generated/prisma/models/Tool.d.ts +223 -1
- package/dist/generated/prisma/models.d.ts +10 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +2033 -110
- package/dist/import/create.js +48 -4
- package/dist/import/neutral-schema.d.ts +51 -281
- package/dist/import/neutral-schema.js +7 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +10 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/grants-cli.d.ts +6 -4
- package/dist/mcp/auth/grants-cli.js +42 -3
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/resource-server.d.ts +3 -1
- package/dist/mcp/auth/resource-server.js +17 -2
- package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
- package/dist/mcp/context.d.ts +3 -0
- package/dist/mcp/host-events/github-ingress.d.ts +2 -0
- package/dist/mcp/host-events/github-ingress.js +2 -1
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +69 -10
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +295 -28
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +73 -29
- package/dist/mcp/tools/host-providers.d.ts +2 -0
- package/dist/mcp/tools/host-providers.js +215 -0
- package/dist/mcp/tools/mcp-servers.d.ts +26 -0
- package/dist/mcp/tools/mcp-servers.js +481 -0
- package/dist/mcp/tools/memory.js +11 -1
- package/dist/mcp/tools/notification-channels.js +2 -2
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/repositories.js +65 -12
- package/dist/mcp/tools/run-access.d.ts +16 -0
- package/dist/mcp/tools/run-access.js +25 -0
- package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
- package/dist/mcp/tools/run-transcript-download.js +129 -0
- package/dist/mcp/tools/run-transcript.d.ts +19 -0
- package/dist/mcp/tools/run-transcript.js +70 -0
- package/dist/mcp/tools/runs.js +209 -27
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-elicitation-form.js +5 -0
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -61
- package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
- package/dist/mcp/tools/secret-elicitation.js +25 -2
- package/dist/mcp/tools/secrets.js +40 -6
- package/dist/mcp/tools/stop-run.d.ts +2 -0
- package/dist/mcp/tools/stop-run.js +82 -0
- package/dist/mcp/tools/subagents.js +2 -2
- package/dist/mcp/tools/tools.d.ts +7 -5
- package/dist/mcp/tools/tools.js +64 -16
- package/dist/mcp/tools/trigger.js +28 -6
- package/dist/mcp/transport/http-limits.d.ts +2 -0
- package/dist/mcp/transport/http-limits.js +6 -2
- package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
- package/dist/mcp/transport/stdio-link-host.js +67 -0
- package/dist/mcp/transport/streamable-http.d.ts +13 -0
- package/dist/mcp/transport/streamable-http.js +41 -1
- package/dist/mcp/webhooks/ingress.js +10 -0
- package/dist/native-worker/docker-launcher.d.ts +38 -2
- package/dist/native-worker/docker-launcher.js +65 -5
- package/dist/native-worker/gateway-server.d.ts +55 -3
- package/dist/native-worker/gateway-server.js +152 -34
- package/dist/native-worker/gateway.d.ts +29 -1
- package/dist/native-worker/gateway.js +74 -4
- package/dist/native-worker/http-server.d.ts +7 -1
- package/dist/native-worker/http-server.js +62 -7
- package/dist/native-worker/http-transport.js +1 -1
- package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
- package/dist/native-worker/kubernetes-launcher.js +43 -3
- package/dist/native-worker/launch.d.ts +18 -1
- package/dist/native-worker/launch.js +6 -1
- package/dist/native-worker/ledger.d.ts +24 -4
- package/dist/native-worker/ledger.js +62 -8
- package/dist/native-worker/loopback.js +3 -8
- package/dist/native-worker/main.d.ts +2 -1
- package/dist/native-worker/main.js +14 -3
- package/dist/native-worker/protocol.d.ts +130 -577
- package/dist/native-worker/protocol.js +51 -2
- package/dist/native-worker/sandbox-executor.d.ts +17 -2
- package/dist/native-worker/sandbox-executor.js +78 -4
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +1 -1
- package/dist/native-worker/stdio.js +6 -5
- package/dist/native-worker/warm-pool.d.ts +2 -2
- package/dist/native-worker/warm-pool.js +4 -4
- package/dist/native-worker/worker.js +28 -2
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/self-hosted.d.ts +1 -1
- package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
- package/dist/providers/coding-proxy/capability-hash.js +5 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
- package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
- package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
- package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
- package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
- package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
- package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
- package/dist/providers/coding-proxy/hold.d.ts +32 -0
- package/dist/providers/coding-proxy/hold.js +86 -0
- package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
- package/dist/providers/coding-proxy/interrupted.js +104 -0
- package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
- package/dist/providers/coding-proxy/mcp-route.js +166 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
- package/dist/providers/coding-proxy/memory-ledger.js +99 -8
- package/dist/providers/coding-proxy/metering.d.ts +16 -0
- package/dist/providers/coding-proxy/metering.js +27 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
- package/dist/providers/coding-proxy/proxy.d.ts +21 -2
- package/dist/providers/coding-proxy/proxy.js +300 -48
- package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
- package/dist/providers/coding-proxy/registry/audit.js +94 -17
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
- package/dist/providers/coding-proxy/registry/plan.js +201 -48
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
- package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
- package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
- package/dist/providers/coding-proxy/registry/service.js +579 -112
- package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
- package/dist/providers/coding-proxy/registry/store.js +54 -1
- package/dist/providers/coding-proxy/runtime.d.ts +10 -0
- package/dist/providers/coding-proxy/runtime.js +109 -16
- package/dist/providers/coding-proxy/server.d.ts +9 -1
- package/dist/providers/coding-proxy/server.js +55 -1
- package/dist/providers/coding-proxy/types.d.ts +78 -1
- package/dist/providers/datastore/types.d.ts +5 -0
- package/dist/providers/engine/types.d.ts +17 -2
- package/dist/providers/engine/types.js +17 -0
- package/dist/providers/executor/composition.d.ts +10 -3
- package/dist/providers/executor/composition.js +52 -7
- package/dist/providers/executor/container.d.ts +394 -9
- package/dist/providers/executor/container.js +1210 -96
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +50 -1
- package/dist/providers/executor/dbos.js +207 -20
- package/dist/providers/executor/deferred.d.ts +12 -24
- package/dist/providers/executor/deferred.js +10 -29
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +2 -0
- package/dist/providers/executor/routing.js +4 -0
- package/dist/providers/executor/types.d.ts +13 -0
- package/dist/providers/host-tools/invoke.d.ts +37 -0
- package/dist/providers/host-tools/invoke.js +117 -0
- package/dist/providers/host-tools/operations.d.ts +65 -0
- package/dist/providers/host-tools/operations.js +149 -0
- package/dist/providers/host-tools/registry.d.ts +79 -0
- package/dist/providers/host-tools/registry.js +362 -0
- package/dist/providers/host-tools/request-guard.d.ts +17 -0
- package/dist/providers/host-tools/request-guard.js +99 -0
- package/dist/providers/host-tools/self-test.d.ts +64 -0
- package/dist/providers/host-tools/self-test.js +142 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/issue-tracker/types.d.ts +17 -0
- package/dist/providers/issue-tracker/types.js +39 -1
- package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
- package/dist/providers/jobs/claude-tool-setup.js +5 -2
- package/dist/providers/jobs/docker-isolation.d.ts +10 -2
- package/dist/providers/jobs/docker-isolation.js +47 -8
- package/dist/providers/jobs/docker.d.ts +9 -0
- package/dist/providers/jobs/docker.js +60 -11
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
- package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
- package/dist/providers/jobs/kubernetes-api.js +10 -0
- package/dist/providers/jobs/kubernetes-client.js +10 -1
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +32 -3
- package/dist/providers/jobs/kubernetes.d.ts +11 -1
- package/dist/providers/jobs/kubernetes.js +111 -17
- package/dist/providers/jobs/types.d.ts +39 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +29 -2
- package/dist/providers/review-host/github.js +224 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +140 -6
- package/dist/providers/review-host/types.js +9 -1
- package/dist/providers/storage/gcs.d.ts +63 -0
- package/dist/providers/storage/gcs.js +69 -0
- package/dist/providers/storage/index.d.ts +15 -0
- package/dist/providers/storage/index.js +14 -0
- package/dist/providers/storage/local.d.ts +24 -0
- package/dist/providers/storage/local.js +92 -0
- package/dist/providers/storage/meter.d.ts +14 -0
- package/dist/providers/storage/meter.js +34 -0
- package/dist/providers/storage/s3.d.ts +41 -0
- package/dist/providers/storage/s3.js +107 -0
- package/dist/providers/storage/types.d.ts +37 -3
- package/dist/providers/storage/types.js +21 -4
- package/dist/providers/vcs/git.d.ts +39 -4
- package/dist/providers/vcs/git.js +339 -26
- package/dist/providers/vcs/github-remote.d.ts +26 -3
- package/dist/providers/vcs/github-remote.js +124 -14
- package/dist/providers/vcs/github.d.ts +183 -44
- package/dist/providers/vcs/github.js +455 -56
- package/dist/providers/vcs/index.d.ts +1 -1
- package/dist/providers/vcs/index.js +9 -2
- package/dist/providers/vcs/pr-description.d.ts +127 -0
- package/dist/providers/vcs/pr-description.js +270 -0
- package/dist/providers/vcs/remote.d.ts +37 -1
- package/dist/providers/vcs/remote.js +7 -1
- package/dist/providers/vcs/routing.d.ts +16 -8
- package/dist/providers/vcs/routing.js +27 -6
- package/dist/providers/vcs/types.d.ts +150 -5
- package/dist/quickstart/coding-seed.d.ts +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- package/dist/quickstart/index.d.ts +5 -0
- package/dist/quickstart/index.js +21 -0
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +6 -6
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/eval-core.d.ts +12 -2
- package/dist/sandbox/eval-core.js +20 -4
- package/dist/sandbox/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +5 -0
- package/dist/sandbox/host-functions.js +13 -13
- package/dist/sandbox/limits.d.ts +4 -1
- package/dist/sandbox/limits.js +4 -1
- package/dist/sandbox/run-in-sandbox.d.ts +6 -0
- package/dist/sandbox/run-in-sandbox.js +14 -2
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +1 -1
- package/dist/sandbox/secret-broker.d.ts +1 -0
- package/dist/sandbox/secret-broker.js +4 -5
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/tool-timeout.d.ts +32 -0
- package/dist/sandbox/tool-timeout.js +52 -0
- package/dist/sandbox/user-tool.d.ts +8 -1
- package/dist/sandbox/user-tool.js +9 -3
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +8 -1
- package/dist/viewer/api-schema.d.ts +349 -2627
- package/dist/viewer/api-schema.js +7 -0
- package/dist/viewer/build-schemas.js +6 -2
- package/dist/viewer/graph.js +2 -1
- package/dist/viewer/openapi.js +2 -4
- package/dist/wardby-bin.js +15 -0
- package/docs/README.md +11 -1
- package/docs/agent-recipes.md +95 -24
- package/docs/architecture-runtime.md +1 -1
- package/docs/claude-code-plugin.md +164 -0
- package/docs/code-review-agents.md +557 -41
- package/docs/coding-agent-setup.md +566 -8
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +24 -2
- package/docs/coding-worker-isolation.md +183 -37
- package/docs/debugging-agent-runs.md +242 -0
- package/docs/getting-started-gke.md +129 -141
- package/docs/getting-started-identity-provider.md +53 -38
- package/docs/getting-started.md +17 -0
- package/docs/host-providers.md +294 -0
- package/docs/jira-agents.md +17 -8
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/mcp-servers.md +254 -0
- package/docs/native-sandbox.md +143 -31
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +139 -29
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +45 -10
- package/docs/viewer-api.md +6 -0
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +28 -2
- package/help/agent-recipes.md +33 -2
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +3 -0
- package/help/build-claude-code-image.md +1 -1
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- package/help/claude-code-run-pane.md +40 -0
- package/help/code-review-agents.md +177 -6
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +15 -8
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-mcp-pins-unavailable.md +35 -0
- package/help/errors/coding-stream-quota-exceeded.md +33 -0
- package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
- package/help/errors/continuation-closed.md +9 -12
- package/help/errors/database-auth-invalid.md +1 -1
- package/help/errors/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +4 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/host-provider-error.md +40 -0
- package/help/errors/host-tool-failed.md +36 -0
- package/help/errors/mcp-call-limit.md +22 -0
- package/help/errors/mcp-call-timeout.md +22 -0
- package/help/errors/mcp-server-auth-failed.md +22 -0
- package/help/errors/mcp-server-credentials-unavailable.md +45 -0
- package/help/errors/mcp-server-error.md +28 -0
- package/help/errors/mcp-server-unreachable.md +22 -0
- package/help/errors/mcp-servers-off.md +21 -0
- package/help/errors/mcp-tool-not-allowed.md +26 -0
- package/help/errors/mcp-tool-removed.md +22 -0
- package/help/errors/mcp-unavailable.md +25 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-capacity.md +1 -1
- package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
- package/help/errors/native-sandbox-docker-failed.md +1 -1
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
- package/help/errors/native-sandbox-image-not-pinned.md +1 -1
- package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +1 -1
- package/help/errors/native-sandbox-requires-catalog.md +1 -1
- package/help/errors/native-sandbox-unavailable.md +1 -1
- package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
- package/help/errors/native-sandbox-worker-exited.md +4 -3
- package/help/errors/native-sandbox-worker-lost.md +1 -1
- package/help/errors/native-sandbox-worker-unready.md +1 -1
- package/help/errors/package-not-allowed-pending.md +52 -0
- package/help/errors/package-not-allowed.md +51 -0
- package/help/errors/package-refusals.md +43 -0
- package/help/errors/patch-cursor-malformed.md +31 -0
- package/help/errors/repository-not-listed.md +36 -0
- package/help/errors/repository-required.md +36 -0
- package/help/errors/run-lost.md +39 -0
- package/help/errors/run-transcript-download.md +44 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/target-merge.md +40 -0
- package/help/errors/tool-timeout.md +38 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/host-providers.md +40 -0
- package/help/identity-and-access.md +6 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +1 -1
- package/help/low-power-mode.md +7 -1
- package/help/mcp-servers.md +73 -0
- package/help/mcp.md +7 -2
- package/help/merge-order-check.md +5 -0
- package/help/native-capabilities.md +55 -1
- package/help/native-sandbox.md +16 -2
- package/help/operating-agents.md +21 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +17 -10
- package/help/repo-instructions-and-skills.md +3 -1
- package/help/resume-runs-locally.md +134 -0
- package/help/review-fix-rounds.md +33 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +19 -5
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +86 -7
- package/help/troubleshooting/debugging-agent-runs.md +29 -0
- package/package.json +18 -10
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
- package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
- package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
- package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
- package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
- package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
- package/prisma/schema.prisma +468 -109
- package/scripts/git-askpass.sh +1 -1
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { lastPusher } from "./budget-stopped-head.js";
|
|
2
|
+
import { pullRequestOutcome } from "./host-status.js";
|
|
3
|
+
import { MERGE_ORDER_CHECK_NAME } from "./merge-order-check.js";
|
|
4
|
+
const CI_GREEN = new Set(["passing", "none"]);
|
|
5
|
+
/** How far up the run tree (Run.parentRunId) the opt-in may come from. */
|
|
6
|
+
const MAX_ANCESTOR_HOPS = 10;
|
|
7
|
+
const CODING_RUN_SELECT = {
|
|
8
|
+
runId: true,
|
|
9
|
+
repository: true,
|
|
10
|
+
rootCodingRunId: true,
|
|
11
|
+
markedReadyAt: true,
|
|
12
|
+
result: true,
|
|
13
|
+
run: { select: { agentId: true, parentRunId: true, status: true } },
|
|
14
|
+
};
|
|
15
|
+
const passed = (c) => c !== undefined && c.status === "completed" && c.conclusion === "success";
|
|
16
|
+
export async function maybeMarkReady(deps, repository, prNumber, provider) {
|
|
17
|
+
try {
|
|
18
|
+
const host = deps.hosts?.[provider];
|
|
19
|
+
if (!host?.pullRequestOrigin || !host.readOwnChecks || !host.readCi || !host.markReadyForReview)
|
|
20
|
+
return "off";
|
|
21
|
+
const links = await deps.db.agentRepository.findMany({
|
|
22
|
+
where: { provider, repository },
|
|
23
|
+
select: {
|
|
24
|
+
agentId: true,
|
|
25
|
+
access: true,
|
|
26
|
+
triggers: true,
|
|
27
|
+
checkName: true,
|
|
28
|
+
markReadyWhenPassing: true,
|
|
29
|
+
authorizedVia: true,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const optedIn = new Set(links
|
|
33
|
+
.filter((l) => l.access === "write" && l.authorizedVia !== null && l.markReadyWhenPassing)
|
|
34
|
+
.map((l) => l.agentId));
|
|
35
|
+
if (optedIn.size === 0)
|
|
36
|
+
return "off";
|
|
37
|
+
const reviewChecks = links
|
|
38
|
+
.filter((l) => l.access === "write" && l.authorizedVia !== null && l.triggers.includes("pull_request") && l.checkName)
|
|
39
|
+
.map((l) => l.checkName);
|
|
40
|
+
if (reviewChecks.length === 0)
|
|
41
|
+
return "not_ready";
|
|
42
|
+
// readOwnChecks reads at most 10 names; MERGE_ORDER_CHECK_NAME plus the reviewer
|
|
43
|
+
// check names must fit, or the merge-order check would silently be read as absent.
|
|
44
|
+
if (reviewChecks.length > 9)
|
|
45
|
+
return "not_ready";
|
|
46
|
+
const origin = await host.pullRequestOrigin(repository, prNumber);
|
|
47
|
+
if (origin.state !== "open" || origin.draft !== true || origin.isFork || !origin.markerRunId)
|
|
48
|
+
return "not_ready";
|
|
49
|
+
const marked = await deps.db.codingRun.findUnique({
|
|
50
|
+
where: { runId: origin.markerRunId },
|
|
51
|
+
select: CODING_RUN_SELECT,
|
|
52
|
+
});
|
|
53
|
+
if (!marked)
|
|
54
|
+
return "not_ready";
|
|
55
|
+
const root = marked.rootCodingRunId
|
|
56
|
+
? await deps.db.codingRun.findUnique({ where: { runId: marked.rootCodingRunId }, select: CODING_RUN_SELECT })
|
|
57
|
+
: marked;
|
|
58
|
+
if (!root || root.repository.toLowerCase() !== repository.toLowerCase())
|
|
59
|
+
return "not_ready";
|
|
60
|
+
if (pullRequestOutcome(root.result)?.pullRequestNumber !== prNumber)
|
|
61
|
+
return "not_ready";
|
|
62
|
+
if (!(await optedInInRunTree(deps.db, root.run, optedIn)))
|
|
63
|
+
return "not_ready";
|
|
64
|
+
if (root.markedReadyAt)
|
|
65
|
+
return "skipped";
|
|
66
|
+
if (await lastPushStoppedAtBudget(deps.db, root, prNumber))
|
|
67
|
+
return "not_ready";
|
|
68
|
+
const checks = await host.readOwnChecks(repository, origin.headSha, [MERGE_ORDER_CHECK_NAME, ...reviewChecks]);
|
|
69
|
+
if (!reviewChecks.every((name) => passed(checks.get(name))))
|
|
70
|
+
return "not_ready";
|
|
71
|
+
const order = checks.get(MERGE_ORDER_CHECK_NAME);
|
|
72
|
+
if (order !== undefined && !passed(order))
|
|
73
|
+
return "not_ready";
|
|
74
|
+
const ci = await host.readCi(repository, origin.headSha);
|
|
75
|
+
if (!CI_GREEN.has(ci.state) || ci.truncated)
|
|
76
|
+
return "not_ready";
|
|
77
|
+
const claimedAt = new Date();
|
|
78
|
+
// CodingRun.updatedAt is @updatedAt, so this claim (and a release below) bumps it, which
|
|
79
|
+
// feeds the merge-order sweep's ordering. Harmless: the sweep re-derives state from the
|
|
80
|
+
// host each time, it doesn't rely on updatedAt being untouched by mark-ready.
|
|
81
|
+
const claim = await deps.db.codingRun.updateMany({
|
|
82
|
+
where: { runId: root.runId, markedReadyAt: null },
|
|
83
|
+
data: { markedReadyAt: claimedAt },
|
|
84
|
+
});
|
|
85
|
+
if (claim.count === 0)
|
|
86
|
+
return "skipped";
|
|
87
|
+
const release = () => deps.db.codingRun
|
|
88
|
+
.updateMany({ where: { runId: root.runId, markedReadyAt: claimedAt }, data: { markedReadyAt: null } })
|
|
89
|
+
.catch((err) => deps.log?.warn({ err, repository, prNumber }, "could not release the mark-ready claim"));
|
|
90
|
+
try {
|
|
91
|
+
const result = await host.markReadyForReview(repository, prNumber, origin.headSha, origin.markerRunId);
|
|
92
|
+
if (result === "marked") {
|
|
93
|
+
deps.log?.info({ repository, prNumber }, "marked the pull request ready for review");
|
|
94
|
+
return "marked";
|
|
95
|
+
}
|
|
96
|
+
await release();
|
|
97
|
+
return "skipped";
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
await release();
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
deps.log?.warn({ err, repository, prNumber }, "could not mark the pull request ready for review");
|
|
106
|
+
return "failed";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Whether the last run that pushed to the pull request (the root, or a later continuation of it)
|
|
111
|
+
* stopped at its budget: its pushed changes are unfinished work, so the draft stays a draft. A
|
|
112
|
+
* continuation that finished the work makes it eligible again.
|
|
113
|
+
*/
|
|
114
|
+
async function lastPushStoppedAtBudget(db, root, prNumber) {
|
|
115
|
+
return (await lastPusher(db, root, prNumber)).status === "budget_exhausted";
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* True when the opener's agent, or an agent up its run tree (bounded, cycle-safe), is opted in.
|
|
119
|
+
* A coding run's parentRunId is set when a lead delegated to it.
|
|
120
|
+
*/
|
|
121
|
+
async function optedInInRunTree(db, opener, optedIn) {
|
|
122
|
+
if (optedIn.has(opener.agentId))
|
|
123
|
+
return true;
|
|
124
|
+
const seen = new Set();
|
|
125
|
+
let next = opener.parentRunId ?? null;
|
|
126
|
+
for (let hop = 0; next && hop < MAX_ANCESTOR_HOPS && !seen.has(next); hop++) {
|
|
127
|
+
seen.add(next);
|
|
128
|
+
const run = await db.run.findUnique({ where: { id: next }, select: { agentId: true, parentRunId: true } });
|
|
129
|
+
if (!run)
|
|
130
|
+
return false;
|
|
131
|
+
if (optedIn.has(run.agentId))
|
|
132
|
+
return true;
|
|
133
|
+
next = run.parentRunId;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
/** After a reviewer run ends: evaluate the pull request it reviewed. Null when it reviewed none. */
|
|
138
|
+
export async function markReadyAfterRun(deps, runId) {
|
|
139
|
+
try {
|
|
140
|
+
const row = await deps.db.runHostCheck.findUnique({
|
|
141
|
+
where: { runId },
|
|
142
|
+
select: { provider: true, repository: true, prNumber: true, verdict: true },
|
|
143
|
+
});
|
|
144
|
+
if (!row || row.prNumber === null || !row.verdict)
|
|
145
|
+
return null;
|
|
146
|
+
return await maybeMarkReady(deps, row.repository, row.prNumber, row.provider);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
deps.log?.warn({ err, runId }, "could not evaluate mark-ready after the run");
|
|
150
|
+
return "failed";
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub-flavoured Markdown with its code removed, so a mention quoted in code
|
|
3
|
+
* (`` `@app` ``, a fenced or indented block) is documentation, not a request.
|
|
4
|
+
* Close to CommonMark, not a full parser: when in doubt it keeps text, so a
|
|
5
|
+
* real mention is never lost to an odd construct.
|
|
6
|
+
*/
|
|
7
|
+
/** `markdown` without its code blocks and inline code spans. */
|
|
8
|
+
export declare function withoutMarkdownCode(markdown: string): string;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub-flavoured Markdown with its code removed, so a mention quoted in code
|
|
3
|
+
* (`` `@app` ``, a fenced or indented block) is documentation, not a request.
|
|
4
|
+
* Close to CommonMark, not a full parser: when in doubt it keeps text, so a
|
|
5
|
+
* real mention is never lost to an odd construct.
|
|
6
|
+
*/
|
|
7
|
+
const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;
|
|
8
|
+
const INDENTED = /^(?: {4}|\t)/;
|
|
9
|
+
const LIST_ITEM = /^ {0,3}(?:[-*+]|\d{1,9}[.)])(?:\s|$)/;
|
|
10
|
+
const BLANK = /^\s*$/;
|
|
11
|
+
/** Up to three spaces, at least the opening run of the fence's character, then only whitespace. */
|
|
12
|
+
function closesFence(line, fence) {
|
|
13
|
+
let index = 0;
|
|
14
|
+
while (index < 3 && line[index] === " ")
|
|
15
|
+
index += 1;
|
|
16
|
+
const start = index;
|
|
17
|
+
while (line[index] === fence.char)
|
|
18
|
+
index += 1;
|
|
19
|
+
return index - start >= fence.length && line.slice(index).trim() === "";
|
|
20
|
+
}
|
|
21
|
+
/** Fenced and indented code blocks blanked out, line count kept. */
|
|
22
|
+
function withoutCodeBlocks(markdown) {
|
|
23
|
+
const out = [];
|
|
24
|
+
let fence = null;
|
|
25
|
+
// Indented code needs a blank line before it, and indented text under a
|
|
26
|
+
// list item is the item's paragraph, not code.
|
|
27
|
+
let previousBlank = true;
|
|
28
|
+
let inIndentedCode = false;
|
|
29
|
+
let inList = false;
|
|
30
|
+
for (const line of markdown.split(/\r?\n/)) {
|
|
31
|
+
if (fence) {
|
|
32
|
+
if (closesFence(line, fence))
|
|
33
|
+
fence = null;
|
|
34
|
+
out.push("");
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const open = FENCE_OPEN.exec(line);
|
|
38
|
+
// A backtick fence's info string cannot contain a backtick (CommonMark).
|
|
39
|
+
if (open && !(open[1][0] === "`" && line.slice(line.indexOf(open[1]) + open[1].length).includes("`"))) {
|
|
40
|
+
fence = { char: open[1][0], length: open[1].length };
|
|
41
|
+
inIndentedCode = false;
|
|
42
|
+
previousBlank = false;
|
|
43
|
+
out.push("");
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (BLANK.test(line)) {
|
|
47
|
+
previousBlank = true;
|
|
48
|
+
out.push(line);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (INDENTED.test(line) && !inList && (previousBlank || inIndentedCode)) {
|
|
52
|
+
inIndentedCode = true;
|
|
53
|
+
previousBlank = false;
|
|
54
|
+
out.push("");
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
inIndentedCode = false;
|
|
58
|
+
if (LIST_ITEM.test(line))
|
|
59
|
+
inList = true;
|
|
60
|
+
else if (!INDENTED.test(line) && previousBlank)
|
|
61
|
+
inList = false;
|
|
62
|
+
previousBlank = false;
|
|
63
|
+
out.push(line);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/** Inline code spans in one paragraph replaced by a space; an unmatched run of backticks is literal. */
|
|
68
|
+
function withoutCodeSpans(paragraph) {
|
|
69
|
+
const runs = [];
|
|
70
|
+
for (let index = 0; index < paragraph.length;) {
|
|
71
|
+
if (paragraph[index] !== "`") {
|
|
72
|
+
index += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const start = index;
|
|
76
|
+
while (paragraph[index] === "`")
|
|
77
|
+
index += 1;
|
|
78
|
+
runs.push({ start, end: index });
|
|
79
|
+
}
|
|
80
|
+
// A span closes at the next run of exactly the opening run's length.
|
|
81
|
+
const closer = new Array(runs.length).fill(-1);
|
|
82
|
+
const nextOfLength = new Map();
|
|
83
|
+
for (let i = runs.length - 1; i >= 0; i--) {
|
|
84
|
+
const length = runs[i].end - runs[i].start;
|
|
85
|
+
closer[i] = nextOfLength.get(length) ?? -1;
|
|
86
|
+
nextOfLength.set(length, i);
|
|
87
|
+
}
|
|
88
|
+
let result = "";
|
|
89
|
+
let copied = 0;
|
|
90
|
+
for (let i = 0; i < runs.length; i++) {
|
|
91
|
+
const close = closer[i];
|
|
92
|
+
if (close === -1)
|
|
93
|
+
continue;
|
|
94
|
+
result += `${paragraph.slice(copied, runs[i].start)} `;
|
|
95
|
+
copied = runs[close].end;
|
|
96
|
+
i = close;
|
|
97
|
+
}
|
|
98
|
+
return result + paragraph.slice(copied);
|
|
99
|
+
}
|
|
100
|
+
/** `markdown` without its code blocks and inline code spans. */
|
|
101
|
+
export function withoutMarkdownCode(markdown) {
|
|
102
|
+
return withoutCodeBlocks(markdown)
|
|
103
|
+
.join("\n")
|
|
104
|
+
.split(/(\n[ \t]*\n)/)
|
|
105
|
+
.map((part, i) => (i % 2 === 1 ? part : withoutCodeSpans(part)))
|
|
106
|
+
.join("");
|
|
107
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface McpHttpRequest {
|
|
2
|
+
method: "POST" | "DELETE";
|
|
3
|
+
headers: Record<string, string>;
|
|
4
|
+
body?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface McpHttpResponse {
|
|
7
|
+
status: number;
|
|
8
|
+
/** Header names are lower-case. */
|
|
9
|
+
headers: Record<string, string>;
|
|
10
|
+
body: string;
|
|
11
|
+
}
|
|
12
|
+
/** The transport: in production brokeredFetch + safeFetch; in tests a fake. Throws only for network-level failures. */
|
|
13
|
+
export type McpFetch = (request: McpHttpRequest, signal: AbortSignal) => Promise<McpHttpResponse>;
|
|
14
|
+
export interface McpToolEntry {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
inputSchema: Record<string, unknown>;
|
|
18
|
+
annotations?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
export interface McpServerInfo {
|
|
21
|
+
name?: string;
|
|
22
|
+
version?: string;
|
|
23
|
+
protocolVersion: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class McpClientError extends Error {
|
|
26
|
+
readonly code: "mcp_server_unreachable" | "mcp_server_auth_failed" | "mcp_server_error" | "mcp_call_timeout";
|
|
27
|
+
constructor(code: "mcp_server_unreachable" | "mcp_server_auth_failed" | "mcp_server_error" | "mcp_call_timeout", message: string);
|
|
28
|
+
}
|
|
29
|
+
export declare class McpHttpClient {
|
|
30
|
+
private readonly fetchImpl;
|
|
31
|
+
private readonly signal;
|
|
32
|
+
private nextId;
|
|
33
|
+
private sessionId;
|
|
34
|
+
private protocolVersion;
|
|
35
|
+
constructor(options: {
|
|
36
|
+
fetch: McpFetch;
|
|
37
|
+
signal: AbortSignal;
|
|
38
|
+
});
|
|
39
|
+
private headers;
|
|
40
|
+
/** One POST. Maps transport failures and HTTP errors to McpClientError; never puts a body or header value in a message. */
|
|
41
|
+
private post;
|
|
42
|
+
private request;
|
|
43
|
+
initialize(): Promise<McpServerInfo>;
|
|
44
|
+
listTools(): Promise<McpToolEntry[]>;
|
|
45
|
+
callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
|
|
46
|
+
close(): Promise<void>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { MCP_PROTOCOL_VERSION, findResponse, hasServerRequest } from "./jsonrpc.js";
|
|
3
|
+
/** The package version, sent as the client version (package.json sits three levels up from src/core/mcp-client and dist/core/mcp-client). */
|
|
4
|
+
const CLIENT_VERSION = JSON.parse(readFileSync(new URL("../../../package.json", import.meta.url), "utf8")).version;
|
|
5
|
+
const MAX_PAGES = 20;
|
|
6
|
+
const MAX_TOOLS = 500;
|
|
7
|
+
const MAX_ERROR_MESSAGE_CHARS = 500;
|
|
8
|
+
export class McpClientError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
constructor(code, message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.name = "McpClientError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function isRecord(value) {
|
|
17
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
18
|
+
}
|
|
19
|
+
export class McpHttpClient {
|
|
20
|
+
fetchImpl;
|
|
21
|
+
signal;
|
|
22
|
+
nextId = 1;
|
|
23
|
+
sessionId;
|
|
24
|
+
protocolVersion;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.fetchImpl = options.fetch;
|
|
27
|
+
this.signal = options.signal;
|
|
28
|
+
}
|
|
29
|
+
headers() {
|
|
30
|
+
const headers = {
|
|
31
|
+
Accept: "application/json, text/event-stream",
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
};
|
|
34
|
+
if (this.sessionId !== undefined)
|
|
35
|
+
headers["Mcp-Session-Id"] = this.sessionId;
|
|
36
|
+
if (this.protocolVersion !== undefined)
|
|
37
|
+
headers["MCP-Protocol-Version"] = this.protocolVersion;
|
|
38
|
+
return headers;
|
|
39
|
+
}
|
|
40
|
+
/** One POST. Maps transport failures and HTTP errors to McpClientError; never puts a body or header value in a message. */
|
|
41
|
+
async post(payload) {
|
|
42
|
+
let response;
|
|
43
|
+
try {
|
|
44
|
+
response = await this.fetchImpl({ method: "POST", headers: this.headers(), body: JSON.stringify({ jsonrpc: "2.0", ...payload }) }, this.signal);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : "";
|
|
48
|
+
if (this.signal.aborted || message.startsWith("fetch_cancelled_or_timeout")) {
|
|
49
|
+
throw new McpClientError("mcp_call_timeout", "The MCP server call timed out or was cancelled.");
|
|
50
|
+
}
|
|
51
|
+
throw new McpClientError("mcp_server_unreachable", "The MCP server could not be reached.");
|
|
52
|
+
}
|
|
53
|
+
if (response.status === 401 || response.status === 403) {
|
|
54
|
+
throw new McpClientError("mcp_server_auth_failed", `The MCP server refused the credentials (HTTP ${response.status}).`);
|
|
55
|
+
}
|
|
56
|
+
if (response.status < 200 || response.status >= 300) {
|
|
57
|
+
throw new McpClientError("mcp_server_error", `The MCP server answered with HTTP ${response.status}.`);
|
|
58
|
+
}
|
|
59
|
+
return response;
|
|
60
|
+
}
|
|
61
|
+
async request(method, params) {
|
|
62
|
+
const id = this.nextId++;
|
|
63
|
+
const response = await this.post({ id, method, params });
|
|
64
|
+
const contentType = response.headers["content-type"];
|
|
65
|
+
const found = findResponse(response.body, contentType, id);
|
|
66
|
+
if (found === undefined) {
|
|
67
|
+
if (hasServerRequest(response.body, contentType)) {
|
|
68
|
+
throw new McpClientError("mcp_server_error", "The MCP server asked for something Wardby doesn't support (sampling, elicitation or roots).");
|
|
69
|
+
}
|
|
70
|
+
throw new McpClientError("mcp_server_unreachable", "The MCP server sent no response to the request.");
|
|
71
|
+
}
|
|
72
|
+
// Any error member, even a malformed one ("error": null, a string), fails the call: never a TypeError.
|
|
73
|
+
const replyError = found.error;
|
|
74
|
+
if (replyError !== undefined) {
|
|
75
|
+
const text = isRecord(replyError) && typeof replyError.message === "string" ? replyError.message : "unknown error";
|
|
76
|
+
throw new McpClientError("mcp_server_error", `The MCP server returned an error: ${text.slice(0, MAX_ERROR_MESSAGE_CHARS)}`);
|
|
77
|
+
}
|
|
78
|
+
return { result: found.result, response };
|
|
79
|
+
}
|
|
80
|
+
async initialize() {
|
|
81
|
+
const { result, response } = await this.request("initialize", {
|
|
82
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
83
|
+
capabilities: {},
|
|
84
|
+
clientInfo: { name: "wardby", version: CLIENT_VERSION },
|
|
85
|
+
});
|
|
86
|
+
const sessionId = response.headers["mcp-session-id"];
|
|
87
|
+
if (sessionId !== undefined && sessionId !== "")
|
|
88
|
+
this.sessionId = sessionId;
|
|
89
|
+
const body = isRecord(result) ? result : {};
|
|
90
|
+
const protocolVersion = typeof body.protocolVersion === "string" ? body.protocolVersion : MCP_PROTOCOL_VERSION;
|
|
91
|
+
this.protocolVersion = protocolVersion;
|
|
92
|
+
await this.post({ method: "notifications/initialized" });
|
|
93
|
+
const serverInfo = isRecord(body.serverInfo) ? body.serverInfo : {};
|
|
94
|
+
const info = { protocolVersion };
|
|
95
|
+
if (typeof serverInfo.name === "string")
|
|
96
|
+
info.name = serverInfo.name;
|
|
97
|
+
if (typeof serverInfo.version === "string")
|
|
98
|
+
info.version = serverInfo.version;
|
|
99
|
+
return info;
|
|
100
|
+
}
|
|
101
|
+
async listTools() {
|
|
102
|
+
const tools = [];
|
|
103
|
+
let cursor;
|
|
104
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
105
|
+
const { result } = await this.request("tools/list", cursor === undefined ? {} : { cursor });
|
|
106
|
+
const body = isRecord(result) ? result : {};
|
|
107
|
+
for (const entry of Array.isArray(body.tools) ? body.tools : []) {
|
|
108
|
+
if (!isRecord(entry) || typeof entry.name !== "string" || !isRecord(entry.inputSchema))
|
|
109
|
+
continue;
|
|
110
|
+
const tool = {
|
|
111
|
+
name: entry.name,
|
|
112
|
+
description: typeof entry.description === "string" ? entry.description : "",
|
|
113
|
+
inputSchema: entry.inputSchema,
|
|
114
|
+
};
|
|
115
|
+
if (isRecord(entry.annotations))
|
|
116
|
+
tool.annotations = entry.annotations;
|
|
117
|
+
tools.push(tool);
|
|
118
|
+
}
|
|
119
|
+
if (tools.length >= MAX_TOOLS)
|
|
120
|
+
return tools.slice(0, MAX_TOOLS);
|
|
121
|
+
cursor = typeof body.nextCursor === "string" && body.nextCursor !== "" ? body.nextCursor : undefined;
|
|
122
|
+
if (cursor === undefined)
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
return tools;
|
|
126
|
+
}
|
|
127
|
+
async callTool(name, args) {
|
|
128
|
+
const { result } = await this.request("tools/call", { name, arguments: args });
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
async close() {
|
|
132
|
+
if (this.sessionId === undefined)
|
|
133
|
+
return;
|
|
134
|
+
try {
|
|
135
|
+
await this.fetchImpl({ method: "DELETE", headers: this.headers() }, this.signal);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// Closing is best effort.
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** JSON-RPC framing for MCP's Streamable HTTP transport: reads a JSON or SSE response body. */
|
|
2
|
+
export declare const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
3
|
+
export interface JsonRpcResponse {
|
|
4
|
+
id: number | string | null;
|
|
5
|
+
result?: unknown;
|
|
6
|
+
error?: {
|
|
7
|
+
code: number;
|
|
8
|
+
message: string;
|
|
9
|
+
data?: unknown;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Finds the response to `id` in a JSON body or an SSE body. Ignores notifications and server requests. */
|
|
13
|
+
export declare function findResponse(body: string, contentType: string | undefined, id: number): JsonRpcResponse | undefined;
|
|
14
|
+
/** True when the body carried a server-to-client request (has `method` and `id`): we answer none of them. */
|
|
15
|
+
export declare function hasServerRequest(body: string, contentType: string | undefined): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** JSON-RPC framing for MCP's Streamable HTTP transport: reads a JSON or SSE response body. */
|
|
2
|
+
export const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
3
|
+
/** Every JSON-RPC message in a body: a JSON value (object or batch array) or the `data:` frames of an SSE stream. */
|
|
4
|
+
function messages(body, contentType) {
|
|
5
|
+
const parsed = [];
|
|
6
|
+
const isSse = (contentType ?? "").toLowerCase().includes("text/event-stream");
|
|
7
|
+
if (isSse) {
|
|
8
|
+
for (const frame of body.split(/\r?\n\r?\n/)) {
|
|
9
|
+
const data = frame
|
|
10
|
+
.split(/\r?\n/)
|
|
11
|
+
.filter((line) => line.startsWith("data:"))
|
|
12
|
+
.map((line) => {
|
|
13
|
+
const value = line.slice(5);
|
|
14
|
+
return value.startsWith(" ") ? value.slice(1) : value;
|
|
15
|
+
});
|
|
16
|
+
if (data.length === 0)
|
|
17
|
+
continue;
|
|
18
|
+
try {
|
|
19
|
+
parsed.push(JSON.parse(data.join("\n")));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// A malformed frame is skipped.
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
try {
|
|
28
|
+
parsed.push(JSON.parse(body));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Not JSON: no messages.
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const value of parsed) {
|
|
36
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
37
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item))
|
|
38
|
+
out.push(item);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
/** Finds the response to `id` in a JSON body or an SSE body. Ignores notifications and server requests. */
|
|
44
|
+
export function findResponse(body, contentType, id) {
|
|
45
|
+
for (const message of messages(body, contentType)) {
|
|
46
|
+
if (message.id === id && !("method" in message))
|
|
47
|
+
return message;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/** True when the body carried a server-to-client request (has `method` and `id`): we answer none of them. */
|
|
52
|
+
export function hasServerRequest(body, contentType) {
|
|
53
|
+
return messages(body, contentType).some((message) => typeof message.method === "string" && message.id !== undefined && message.id !== null);
|
|
54
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Turns an MCP CallToolResult into the string the model sees. */
|
|
2
|
+
export declare const MCP_RESULT_MAX_CHARS = 100000;
|
|
3
|
+
export interface ToolResultText {
|
|
4
|
+
/** The text the model sees: redacted, then capped at MCP_RESULT_MAX_CHARS. */
|
|
5
|
+
text: string;
|
|
6
|
+
/** True when the server reported an error or the result was unreadable. */
|
|
7
|
+
isError: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The model-facing text of a CallToolResult. `redact` runs on the assembled text before it is
|
|
11
|
+
* truncated, so a secret that straddles the cut is still matched whole.
|
|
12
|
+
*/
|
|
13
|
+
export declare function toolResultText(result: unknown, redact?: (text: string) => string): ToolResultText;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Turns an MCP CallToolResult into the string the model sees. */
|
|
2
|
+
export const MCP_RESULT_MAX_CHARS = 100_000;
|
|
3
|
+
function errorText(message) {
|
|
4
|
+
return JSON.stringify({ error: "mcp_server_error", message });
|
|
5
|
+
}
|
|
6
|
+
function truncate(text) {
|
|
7
|
+
if (text.length <= MCP_RESULT_MAX_CHARS)
|
|
8
|
+
return text;
|
|
9
|
+
return `${text.slice(0, MCP_RESULT_MAX_CHARS)}\n[truncated: ${text.length - MCP_RESULT_MAX_CHARS} characters omitted]`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The model-facing text of a CallToolResult. `redact` runs on the assembled text before it is
|
|
13
|
+
* truncated, so a secret that straddles the cut is still matched whole.
|
|
14
|
+
*/
|
|
15
|
+
export function toolResultText(result, redact = (t) => t) {
|
|
16
|
+
if (result === null || typeof result !== "object" || Array.isArray(result)) {
|
|
17
|
+
return { text: errorText("The MCP server returned an unreadable result."), isError: true };
|
|
18
|
+
}
|
|
19
|
+
const r = result;
|
|
20
|
+
const parts = [];
|
|
21
|
+
let hasText = false;
|
|
22
|
+
for (const part of Array.isArray(r.content) ? r.content : []) {
|
|
23
|
+
if (part === null || typeof part !== "object")
|
|
24
|
+
continue;
|
|
25
|
+
const p = part;
|
|
26
|
+
if (p.type === "text" && typeof p.text === "string") {
|
|
27
|
+
hasText = true;
|
|
28
|
+
parts.push(p.text);
|
|
29
|
+
}
|
|
30
|
+
else if (typeof p.type === "string") {
|
|
31
|
+
parts.push(`[${p.type} omitted]`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
let text = parts.join("\n");
|
|
35
|
+
if (!hasText && r.structuredContent !== undefined && r.structuredContent !== null) {
|
|
36
|
+
text = JSON.stringify(r.structuredContent);
|
|
37
|
+
}
|
|
38
|
+
const safe = truncate(redact(text));
|
|
39
|
+
if (r.isError === true)
|
|
40
|
+
return { text: errorText(safe), isError: true };
|
|
41
|
+
return { text: safe, isError: false };
|
|
42
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote MCP servers: the owner-side domain. Validates a server's URL and name, loads the owner's
|
|
3
|
+
* brokered secrets for it, builds the McpFetch that sends them (brokeredFetch over safeFetch), takes
|
|
4
|
+
* the redacted tool snapshot, and diffs snapshots. Secret values never leave this file in any output:
|
|
5
|
+
* snapshots are redacted by exact value (every encoded form) plus token shapes before they are returned.
|
|
6
|
+
*/
|
|
7
|
+
import type { PrismaClient } from "#prisma";
|
|
8
|
+
import { type McpFetch, type McpServerInfo, type McpToolEntry } from "./mcp-client/client.js";
|
|
9
|
+
import type { SecretsAccessor } from "./secrets.js";
|
|
10
|
+
import type { Logger } from "./logger.js";
|
|
11
|
+
import type { SecretCipher } from "../providers/secrets/types.js";
|
|
12
|
+
import { safeFetch } from "../sandbox/safe-fetch.js";
|
|
13
|
+
export declare class McpServerInputError extends Error {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
/** What the server's owner (or an admin) sees when a stored secret of the server can't be decrypted. */
|
|
17
|
+
export declare const CREDENTIALS_UNAVAILABLE_MESSAGE = "The MCP server's credentials can't be decrypted on this server. Check that every Wardby process (control plane, scheduler, native gateway) uses the same SECRET_APP_KEY, or set the secret again.";
|
|
18
|
+
/**
|
|
19
|
+
* A server's brokered secret exists but its stored value can't be decrypted (another
|
|
20
|
+
* SECRET_APP_KEY, a key-id mismatch, a corrupt ciphertext). Not an input problem: the message is
|
|
21
|
+
* fixed and never carries the cipher's error, the ciphertext or a value.
|
|
22
|
+
*/
|
|
23
|
+
export declare class McpCredentialsUnavailableError extends Error {
|
|
24
|
+
/** Empty while a server is being registered (it has no id yet). */
|
|
25
|
+
readonly serverId: string;
|
|
26
|
+
readonly serverName: string;
|
|
27
|
+
readonly secretName: string;
|
|
28
|
+
readonly code = "mcp_server_credentials_unavailable";
|
|
29
|
+
constructor(
|
|
30
|
+
/** Empty while a server is being registered (it has no id yet). */
|
|
31
|
+
serverId: string, serverName: string, secretName: string);
|
|
32
|
+
}
|
|
33
|
+
/** The one operator line for an undecryptable server secret: ids and names only, never the cipher's error text. */
|
|
34
|
+
export declare function logCredentialsUnavailable(log: Pick<Logger, "warn">, error: McpCredentialsUnavailableError): void;
|
|
35
|
+
export interface McpServerRow {
|
|
36
|
+
id: string;
|
|
37
|
+
ownerId: string;
|
|
38
|
+
name: string;
|
|
39
|
+
url: string;
|
|
40
|
+
secretNames: string[];
|
|
41
|
+
}
|
|
42
|
+
/** Validates a server URL: https, no userinfo, no fragment, default port; returns the normalised string. */
|
|
43
|
+
export declare function normaliseServerUrl(raw: string): string;
|
|
44
|
+
export declare function assertServerName(name: string): void;
|
|
45
|
+
/** The tool name the model sees: `<server>__<tool>` with any other character mapped to `_`. */
|
|
46
|
+
export declare function exposedToolName(serverName: string, toolName: string): string;
|
|
47
|
+
/** A server's saved tool list (toolSnapshot); anything but an array reads as empty. */
|
|
48
|
+
export declare function snapshotOf(server: {
|
|
49
|
+
toolSnapshot: unknown;
|
|
50
|
+
}): McpToolEntry[];
|
|
51
|
+
/** Exposed names of allowed tools; a name too long to expose is left out (refused at attach anyway). */
|
|
52
|
+
export declare function exposedNames(serverName: string, allowedTools: readonly string[]): string[];
|
|
53
|
+
/** Added, removed and changed (description or schema) tool names between two snapshots; order-independent. */
|
|
54
|
+
export declare function diffSnapshots(before: McpToolEntry[], after: McpToolEntry[]): {
|
|
55
|
+
added: string[];
|
|
56
|
+
removed: string[];
|
|
57
|
+
changed: string[];
|
|
58
|
+
};
|
|
59
|
+
/** Redacts every secret value of this server (exact, every encoded and escaped form) plus token shapes. */
|
|
60
|
+
export declare function redactForServer(text: string, values: string[]): string;
|
|
61
|
+
/** The same error with its message redacted; an McpClientError keeps its code, any other keeps its name. */
|
|
62
|
+
export declare function redactError(error: unknown, values: string[]): Error;
|
|
63
|
+
type SecretDb = Pick<PrismaClient, "secret">;
|
|
64
|
+
/**
|
|
65
|
+
* Loads the owner's secrets for the server; each must exist, be owned by ownerId, be brokered, and list
|
|
66
|
+
* the URL's host (McpServerInputError otherwise). A stored value that can't be decrypted throws
|
|
67
|
+
* McpCredentialsUnavailableError.
|
|
68
|
+
*/
|
|
69
|
+
export declare function loadServerSecrets(db: SecretDb, cipher: Pick<SecretCipher, "decrypt">, server: McpServerRow): Promise<{
|
|
70
|
+
accessor: SecretsAccessor;
|
|
71
|
+
values: string[];
|
|
72
|
+
}>;
|
|
73
|
+
/** The McpFetch for one server: brokeredFetch over safeFetch with the timeout and signal; text body, lower-case headers. */
|
|
74
|
+
export declare function serverFetch(server: McpServerRow, accessor: SecretsAccessor, options: {
|
|
75
|
+
timeoutMs: number;
|
|
76
|
+
fetchImpl?: typeof safeFetch;
|
|
77
|
+
}): McpFetch;
|
|
78
|
+
/** initialize + listTools + close; the result is redacted (as JSON text) before it is returned. */
|
|
79
|
+
export declare function fetchSnapshot(server: McpServerRow, deps: {
|
|
80
|
+
db: SecretDb;
|
|
81
|
+
cipher: Pick<SecretCipher, "decrypt">;
|
|
82
|
+
fetchImpl?: typeof safeFetch;
|
|
83
|
+
timeoutMs?: number;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
serverInfo: McpServerInfo;
|
|
86
|
+
tools: McpToolEntry[];
|
|
87
|
+
}>;
|
|
88
|
+
/** For the secret delete guard: names of the owner's MCP servers whose secretNames include the secret. */
|
|
89
|
+
export declare function mcpServersUsingSecret(db: Pick<PrismaClient, "mcpServer">, ownerId: string, secretName: string): Promise<string[]>;
|
|
90
|
+
export {};
|