@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
|
@@ -10,14 +10,16 @@
|
|
|
10
10
|
* session budget before the provider is called and settles at the provider's
|
|
11
11
|
* reported usage; the worker's own usage numbers are never read.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { createNativeRunTools, durableDelegate, failNativeRun, finishNativeRun, nativeRunIntegrations, recordNativeRunProgress, runDrivability, sandboxCapabilityHash, userToolSecretValues, } from "../core/runner.js";
|
|
14
|
+
import { ReviewReadLedger } from "../core/review-reads.js";
|
|
15
15
|
import { DELEGATE_TOOL_PREFIX } from "../core/tool-names.js";
|
|
16
|
+
import { relayedOutputTokens } from "../providers/coding-proxy/interrupted.js";
|
|
16
17
|
import { RoutingLlmProvider } from "../providers/llm/routing.js";
|
|
17
18
|
import { isPrivilegedBridgeName } from "../sandbox/host-functions.js";
|
|
19
|
+
import { DEFAULT_TOOL_TIMEOUT_MS } from "../sandbox/tool-timeout.js";
|
|
20
|
+
import { forWorker, gatewayLog } from "./gateway.js";
|
|
18
21
|
import { PrismaGatewayLedger } from "./ledger.js";
|
|
19
22
|
import { GatewayError, GatewayRequestSchema, parseParams, } from "./protocol.js";
|
|
20
|
-
const serverLog = logger.child({ module: "native-gateway-server" });
|
|
21
23
|
/** Output tokens reserved for a model call that names no maxTokens (as the coding proxy does). */
|
|
22
24
|
export const GATEWAY_DEFAULT_RESERVE_OUTPUT_TOKENS = 4_096;
|
|
23
25
|
/** The most output tokens one call may reserve for. */
|
|
@@ -29,10 +31,10 @@ const ok = (result) => ({
|
|
|
29
31
|
status: 200,
|
|
30
32
|
body: { ok: true, result: result ?? null },
|
|
31
33
|
});
|
|
32
|
-
const fail = (status, code, message) => ({
|
|
34
|
+
const fail = (status, code, message, causeCode) => ({
|
|
33
35
|
kind: "json",
|
|
34
36
|
status,
|
|
35
|
-
body: { ok: false, error: { code, message } },
|
|
37
|
+
body: { ok: false, error: { code, message, ...(causeCode ? { causeCode } : {}) } },
|
|
36
38
|
});
|
|
37
39
|
const STATUS_FOR = {
|
|
38
40
|
invalid_request: 400,
|
|
@@ -46,22 +48,53 @@ const STATUS_FOR = {
|
|
|
46
48
|
};
|
|
47
49
|
/** Serves one gateway request. Never throws: every failure is a response. */
|
|
48
50
|
export async function serveGatewayRequest(deps, authorization, body) {
|
|
51
|
+
// The capability once parsed, then every secret value of the rebuilt run: what a cause code and
|
|
52
|
+
// the log line are checked against. Unset (no bearer), no cause code is sent.
|
|
53
|
+
const scope = {};
|
|
49
54
|
try {
|
|
50
|
-
return await handle(deps, authorization, body);
|
|
55
|
+
return await handle(deps, authorization, body, scope);
|
|
51
56
|
}
|
|
52
57
|
catch (err) {
|
|
53
|
-
|
|
54
|
-
return fail(STATUS_FOR[err.code] ?? 500, err.code, err.message);
|
|
55
|
-
serverLog.error({ err }, "native gateway request failed");
|
|
56
|
-
return fail(500, "internal", "The gateway could not serve this call.");
|
|
58
|
+
return failureResponse(err, scope.secretValues);
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Every secret value the rebuilt run can read (each user tool's readable or brokered values), and
|
|
63
|
+
* the request's own capability: what a cause code is checked against before it leaves the gateway.
|
|
64
|
+
*/
|
|
65
|
+
export function runSecretValues(ctx, capability) {
|
|
66
|
+
return async () => [
|
|
67
|
+
capability,
|
|
68
|
+
...(await userToolSecretValues(ctx.tools, Object.keys(ctx.snapshot.input.userTools))),
|
|
69
|
+
...(await ctx.tools.mcpSecretValues()),
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A failure as its response. Only a checked cause code leaves the gateway (workerGatewayError),
|
|
74
|
+
* never the rest of an unexpected error's message; the server's own log line is redacted by the
|
|
75
|
+
* same values.
|
|
76
|
+
*/
|
|
77
|
+
export async function failureResponse(err, secretValues) {
|
|
78
|
+
const sent = await forWorker(err, secretValues, "native gateway request failed");
|
|
79
|
+
return fail(STATUS_FOR[sent.code] ?? 500, sent.code, sent.message, sent.causeCode);
|
|
80
|
+
}
|
|
81
|
+
/** A model stream whose failure reaches the worker as the same checked error a JSON response carries. */
|
|
82
|
+
export async function* checkedEvents(events, secretValues) {
|
|
83
|
+
try {
|
|
84
|
+
yield* events;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
throw await forWorker(err, secretValues, "native gateway model stream failed");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function handle(deps, authorization, body, scope) {
|
|
60
91
|
const { db } = deps;
|
|
61
92
|
const ledger = new PrismaGatewayLedger(db);
|
|
62
93
|
const token = /^Bearer (\S+)$/.exec(authorization ?? "")?.[1];
|
|
63
94
|
if (!token)
|
|
64
95
|
return fail(401, "unauthorized", "A gateway capability is required.");
|
|
96
|
+
// Until the run's tools are rebuilt, the capability is the secret value an error is checked against.
|
|
97
|
+
scope.secretValues = async () => [token];
|
|
65
98
|
const session = await ledger.findSessionByCapabilityHash(sandboxCapabilityHash(token));
|
|
66
99
|
if (!session)
|
|
67
100
|
return fail(401, "unauthorized", "Unknown gateway capability.");
|
|
@@ -90,19 +123,20 @@ async function handle(deps, authorization, body) {
|
|
|
90
123
|
throw new GatewayError("run_not_drivable", "This run is no longer running.");
|
|
91
124
|
}
|
|
92
125
|
const ctx = await rebuild(deps, session);
|
|
126
|
+
scope.secretValues = runSecretValues(ctx, token);
|
|
93
127
|
switch (request.method) {
|
|
94
128
|
case "llm.stream":
|
|
95
129
|
return {
|
|
96
130
|
kind: "stream",
|
|
97
131
|
status: 200,
|
|
98
|
-
events: streamModel(ctx, ledger, request.callId, params),
|
|
132
|
+
events: checkedEvents(streamModel(ctx, ledger, request.callId, params), scope.secretValues),
|
|
99
133
|
};
|
|
100
134
|
case "llm.countTokens": {
|
|
101
135
|
const p = params;
|
|
102
136
|
return ok(await ctx.llm.countTokens(p.model, p.messages, p.tools));
|
|
103
137
|
}
|
|
104
138
|
case "builtin.call":
|
|
105
|
-
return ok(await builtin(ctx, ledger, request.callId, params, deps.pollWindowMs));
|
|
139
|
+
return ok(await builtin(ctx, ledger, request.callId, params, deps.pollWindowMs, scope.secretValues));
|
|
106
140
|
case "host.call":
|
|
107
141
|
return ok(await hostCall(ctx, ledger, request.callId, params));
|
|
108
142
|
case "progress": {
|
|
@@ -130,10 +164,12 @@ async function rebuild(deps, session) {
|
|
|
130
164
|
const llm = loaded.pricing && providers.llm instanceof RoutingLlmProvider
|
|
131
165
|
? providers.llm.forRun(loaded.pricing.entry)
|
|
132
166
|
: providers.llm;
|
|
167
|
+
const reviewReads = ReviewReadLedger.fromJSON(session.reviewReads);
|
|
133
168
|
return {
|
|
134
169
|
session,
|
|
135
170
|
snapshot,
|
|
136
171
|
llm,
|
|
172
|
+
reviewReads,
|
|
137
173
|
tools: createNativeRunTools({
|
|
138
174
|
runId: session.runId,
|
|
139
175
|
existingRun,
|
|
@@ -143,6 +179,8 @@ async function rebuild(deps, session) {
|
|
|
143
179
|
reviewHosts,
|
|
144
180
|
repoAccess,
|
|
145
181
|
issueTrackers,
|
|
182
|
+
reviewReads,
|
|
183
|
+
deadlineAt: session.deadlineAt,
|
|
146
184
|
}),
|
|
147
185
|
finishContext: { runId: session.runId, db, providers, reviewHosts, repoAccess, issueTrackers },
|
|
148
186
|
delegation: {
|
|
@@ -156,7 +194,8 @@ async function rebuild(deps, session) {
|
|
|
156
194
|
},
|
|
157
195
|
};
|
|
158
196
|
}
|
|
159
|
-
|
|
197
|
+
/** Exported for its unit test; the HTTP handler is its only production caller. */
|
|
198
|
+
export async function* streamModel(ctx, ledger, callId, params) {
|
|
160
199
|
const req = params.request;
|
|
161
200
|
if (req.model !== ctx.snapshot.input.agent.model)
|
|
162
201
|
throw new GatewayError("not_allowed", "A run may only call its own model.");
|
|
@@ -173,12 +212,22 @@ async function* streamModel(ctx, ledger, callId, params) {
|
|
|
173
212
|
}
|
|
174
213
|
let settled = false;
|
|
175
214
|
let sawEvent = false;
|
|
215
|
+
// Set once the provider's response starts: it may bill hidden thinking or reasoning before any event.
|
|
216
|
+
let responseStarted = false;
|
|
217
|
+
// Generated output seen so far (text and tool calls), for an estimate if the stream is cut.
|
|
176
218
|
let streamedText = "";
|
|
177
219
|
try {
|
|
178
|
-
|
|
220
|
+
const hooks = {
|
|
221
|
+
onResponseStarted: () => {
|
|
222
|
+
responseStarted = true;
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
for await (const event of ctx.llm.stream(req, undefined, hooks)) {
|
|
179
226
|
sawEvent = true;
|
|
180
227
|
if (event.type === "text")
|
|
181
228
|
streamedText += event.delta;
|
|
229
|
+
if (event.type === "tool_call")
|
|
230
|
+
streamedText += event.name + event.argsJson;
|
|
182
231
|
if (event.type === "done") {
|
|
183
232
|
settled = true;
|
|
184
233
|
await ledger.complete(ctx.session.id, callId, {
|
|
@@ -194,9 +243,29 @@ async function* streamModel(ctx, ledger, callId, params) {
|
|
|
194
243
|
}
|
|
195
244
|
catch (err) {
|
|
196
245
|
if (!settled) {
|
|
197
|
-
//
|
|
198
|
-
if (sawEvent)
|
|
199
|
-
|
|
246
|
+
// Failed before the response started: the provider billed nothing. Once started: settle at an estimate.
|
|
247
|
+
if (sawEvent || responseStarted) {
|
|
248
|
+
// Bill the input and the output seen so far, never more than the hold. With no output seen
|
|
249
|
+
// (cut while thinking or reasoning), the run's median completed call, or none before the
|
|
250
|
+
// first one: as the coding proxy does. Estimating must never mask the stream error: on any
|
|
251
|
+
// failure, keep the full hold and rethrow the original.
|
|
252
|
+
try {
|
|
253
|
+
const output = streamedText
|
|
254
|
+
? await streamedOutputTokens(ctx.llm, req.model, streamedText)
|
|
255
|
+
: ((await ledger.medianOutputTokens(ctx.session.id)) ?? 0);
|
|
256
|
+
const costUsd = Math.min(reservationUsd, ctx.llm.priceUsd(req.model, { inputTokens, outputTokens: output }));
|
|
257
|
+
await ledger.markUncertain(ctx.session.id, callId, {
|
|
258
|
+
inputTokens,
|
|
259
|
+
outputTokens: output,
|
|
260
|
+
cachedInputTokens: 0,
|
|
261
|
+
cacheWriteTokens: 0,
|
|
262
|
+
costUsd,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
await ledger.markUncertain(ctx.session.id, callId).catch(() => undefined);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
200
269
|
else
|
|
201
270
|
await ledger.release(ctx.session.id, callId);
|
|
202
271
|
settled = true;
|
|
@@ -206,9 +275,7 @@ async function* streamModel(ctx, ledger, callId, params) {
|
|
|
206
275
|
finally {
|
|
207
276
|
if (!settled) {
|
|
208
277
|
// The worker stopped reading (its own budget cutoff) before usage arrived: bill an estimate.
|
|
209
|
-
const output = streamedText
|
|
210
|
-
? await ctx.llm.countTokens(req.model, [{ role: "assistant", content: streamedText }]).catch(() => 0)
|
|
211
|
-
: 0;
|
|
278
|
+
const output = await streamedOutputTokens(ctx.llm, req.model, streamedText);
|
|
212
279
|
await ledger.complete(ctx.session.id, callId, {
|
|
213
280
|
inputTokens,
|
|
214
281
|
outputTokens: output,
|
|
@@ -219,29 +286,67 @@ async function* streamModel(ctx, ledger, callId, params) {
|
|
|
219
286
|
}
|
|
220
287
|
}
|
|
221
288
|
}
|
|
222
|
-
|
|
289
|
+
/** Output tokens of a cut stream's output: counted, else the deliberately high bytes / 3 estimate. */
|
|
290
|
+
async function streamedOutputTokens(llm, model, streamed) {
|
|
291
|
+
if (!streamed)
|
|
292
|
+
return 0;
|
|
293
|
+
return llm
|
|
294
|
+
.countTokens(model, [{ role: "assistant", content: streamed }])
|
|
295
|
+
.catch(() => relayedOutputTokens(Buffer.byteLength(streamed)));
|
|
296
|
+
}
|
|
297
|
+
/** The review tools that record reads (repo_publish_review checks them). */
|
|
298
|
+
const REVIEW_READ_TOOLS = new Set(["repo_pr_read", "repo_read_file"]);
|
|
299
|
+
async function builtin(ctx, ledger, callId, params, pollWindowMs, secretValues) {
|
|
223
300
|
if (!ctx.snapshot.input.builtinTools.includes(params.name)) {
|
|
224
301
|
throw new GatewayError("not_allowed", `"${params.name}" is not a built-in tool of this run.`);
|
|
225
302
|
}
|
|
226
303
|
if (params.name.startsWith(DELEGATE_TOOL_PREFIX)) {
|
|
227
|
-
const outcome = await durableDelegate({ ...ctx.delegation, pollWindowMs, ledger, sessionId: ctx.session.id }, callId, params.name, params.argsJson);
|
|
304
|
+
const outcome = await durableDelegate({ ...ctx.delegation, pollWindowMs, ledger, sessionId: ctx.session.id, secretValues }, callId, params.name, params.argsJson);
|
|
228
305
|
return "pending" in outcome ? { pending: true } : outcome.result;
|
|
229
306
|
}
|
|
230
307
|
const handler = ctx.tools.builtinHandler(params.name);
|
|
231
308
|
if (!handler)
|
|
232
309
|
throw new GatewayError("not_allowed", `"${params.name}" is not a built-in tool of this run.`);
|
|
233
|
-
return replayable(ledger, ctx.session.id, callId, "builtin.call", () =>
|
|
310
|
+
return replayable(ledger, ctx.session.id, callId, "builtin.call", async () => {
|
|
311
|
+
const result = await handler(params.argsJson);
|
|
312
|
+
// Each request rebuilds the tools, so what a read recorded is saved for the publish request's check.
|
|
313
|
+
if (REVIEW_READ_TOOLS.has(params.name))
|
|
314
|
+
await ledger.mergeReviewReads(ctx.session.id, ctx.reviewReads);
|
|
315
|
+
return result;
|
|
316
|
+
});
|
|
234
317
|
}
|
|
235
|
-
|
|
318
|
+
/**
|
|
319
|
+
* Logged (at warn) in place of a user tool's console line when that tool's redaction list cannot
|
|
320
|
+
* be read: without the complete list the line cannot be shown to be free of its secret values, so
|
|
321
|
+
* none of it is logged. The tool's call still succeeds, as a console write does in-process.
|
|
322
|
+
*/
|
|
323
|
+
export const CONSOLE_WITHHELD_MESSAGE = "sandbox tool console line withheld: the tool's secret values could not be read";
|
|
324
|
+
/** Serves one privileged bridge call for a worker (exported for tests). */
|
|
325
|
+
export async function hostCall(ctx, ledger, callId, params) {
|
|
236
326
|
if (!isPrivilegedBridgeName(params.bridge))
|
|
237
327
|
throw new GatewayError("not_allowed", "unknown bridge");
|
|
238
328
|
if (!ctx.snapshot.input.userTools[params.tool]) {
|
|
239
329
|
throw new GatewayError("not_allowed", `"${params.tool}" is not a user tool of this run.`);
|
|
240
330
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
331
|
+
let redact;
|
|
332
|
+
if (params.bridge === "__bridge_console") {
|
|
333
|
+
// Fail closed: a console line is redacted by the tool's complete list or not logged at all.
|
|
334
|
+
const values = await ctx.tools.readableSecretValues(params.tool).then((v) => v, () => undefined);
|
|
335
|
+
if (!values) {
|
|
336
|
+
gatewayLog.warn({ tool: params.tool }, CONSOLE_WITHHELD_MESSAGE);
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
redact = values;
|
|
340
|
+
}
|
|
341
|
+
// The tool's own limit plus a margin (30 s for a default tool), never past the run's deadline,
|
|
342
|
+
// and aborted if the run is stopped meanwhile.
|
|
343
|
+
const stop = ctx.tools.watchStop();
|
|
344
|
+
const signal = AbortSignal.any([AbortSignal.timeout(hostCallTimeoutMs(ctx, params.tool)), stop.signal]);
|
|
345
|
+
const host = ctx.tools.privilegedHostFor(params.tool, signal, redact);
|
|
346
|
+
if (!host) {
|
|
347
|
+
stop.done();
|
|
244
348
|
throw new GatewayError("not_allowed", `"${params.tool}" is not a user tool of this run.`);
|
|
349
|
+
}
|
|
245
350
|
const bridge = host[params.bridge];
|
|
246
351
|
const run = async () => {
|
|
247
352
|
try {
|
|
@@ -252,11 +357,23 @@ async function hostCall(ctx, ledger, callId, params) {
|
|
|
252
357
|
throw new GatewayError("bridge_error", err instanceof Error ? err.message.slice(0, 1024) : "Host function failed.");
|
|
253
358
|
}
|
|
254
359
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
360
|
+
try {
|
|
361
|
+
// Console lines are not worth a ledger row, and a secret value must never be stored in one
|
|
362
|
+
// (a secrets.get is a side-effect-free read, so a retried callId simply reads it again).
|
|
363
|
+
if (params.bridge === "__bridge_console" || params.bridge === "__bridge_secretsGet")
|
|
364
|
+
return await run();
|
|
365
|
+
return await replayable(ledger, ctx.session.id, callId, "host.call", run);
|
|
366
|
+
}
|
|
367
|
+
finally {
|
|
368
|
+
stop.done();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/** Added to a tool's limit for one host call: the worker's own wall time ends the call first. */
|
|
372
|
+
export const GATEWAY_HOST_CALL_MARGIN_MS = 20_000;
|
|
373
|
+
/** How long one host call of `tool` may take: its limit plus the margin, cut to the run's deadline. */
|
|
374
|
+
export function hostCallTimeoutMs(ctx, tool, now = Date.now()) {
|
|
375
|
+
const limitMs = (ctx.tools.toolTimeoutMs(tool) ?? DEFAULT_TOOL_TIMEOUT_MS) + GATEWAY_HOST_CALL_MARGIN_MS;
|
|
376
|
+
return Math.max(0, Math.min(limitMs, ctx.session.deadlineAt.getTime() - now));
|
|
260
377
|
}
|
|
261
378
|
/** Runs a one-shot call once per callId; a retry replays its recorded result. */
|
|
262
379
|
async function replayable(ledger, sessionId, callId, method, run) {
|
|
@@ -284,7 +401,8 @@ async function replayable(ledger, sessionId, callId, method, run) {
|
|
|
284
401
|
throw err;
|
|
285
402
|
}
|
|
286
403
|
}
|
|
287
|
-
|
|
404
|
+
/** The worker's terminal call: the run's one terminal write (masked by finishNativeRun), then the session ends. */
|
|
405
|
+
export async function finish(ctx, ledger, callId, params) {
|
|
288
406
|
const claimed = await ledger.claim(ctx.session.id, callId, "finish");
|
|
289
407
|
if (claimed.outcome !== "claimed")
|
|
290
408
|
return null;
|
|
@@ -12,8 +12,29 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { EngineResult, EngineRunContext } from "../providers/engine/types.js";
|
|
14
14
|
import type { LlmStreamEvent } from "../providers/llm/types.js";
|
|
15
|
+
import pino from "pino";
|
|
15
16
|
import { type PrivilegedHost } from "../sandbox/host-functions.js";
|
|
16
|
-
import {
|
|
17
|
+
import { logger } from "../core/logger.js";
|
|
18
|
+
import { GatewayError, type WorkerInput } from "./protocol.js";
|
|
19
|
+
/**
|
|
20
|
+
* The gateways' log. Both (in-process and HTTP) log an unexpected error here, as `native gateway
|
|
21
|
+
* request failed` (or `native gateway model stream failed`). Exported so tests can watch it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const gatewayLog: pino.Logger<never, boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Logs an unexpected error for the operator, redacted by exact value. A successfully read list is
|
|
26
|
+
* complete (its reader rejects when any secret's read fails), so an empty one means the run has no
|
|
27
|
+
* secret values and the message is logged as is. Fail closed: a thrown value that is not an Error
|
|
28
|
+
* (a string, an object: its text cannot be redacted reliably), or no list (unavailable or
|
|
29
|
+
* unreadable), logs only the error's name and declared code, never its message, stack or content.
|
|
30
|
+
*/
|
|
31
|
+
export declare function logUnexpectedError(log: Pick<typeof logger, "error">, err: unknown, values: readonly string[] | undefined, logMessage: string, fields?: Record<string, unknown>): void;
|
|
32
|
+
/**
|
|
33
|
+
* The one way either gateway turns a failure into what the worker sees: an unexpected error is
|
|
34
|
+
* logged for the operator (redacted by the run's secret values) and becomes the checked
|
|
35
|
+
* GatewayError (workerGatewayError); the values are read once and serve both.
|
|
36
|
+
*/
|
|
37
|
+
export declare function forWorker(err: unknown, secretValues: (() => Promise<Iterable<string>>) | undefined, logMessage: string): Promise<GatewayError>;
|
|
17
38
|
/** The trusted gateway as a transport sees it: untrusted requests in, results or GatewayErrors out. */
|
|
18
39
|
export interface NativeGateway {
|
|
19
40
|
call(request: unknown): Promise<unknown>;
|
|
@@ -37,6 +58,13 @@ export interface SandboxedEngineOptions {
|
|
|
37
58
|
ctx: Pick<EngineRunContext, "providers" | "onText" | "onProgress">;
|
|
38
59
|
builtinHandler: (name: string) => ((argsJson: string) => Promise<string>) | undefined;
|
|
39
60
|
privilegedHostFor: (tool: string, signal: AbortSignal) => PrivilegedHost | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Every secret value the user tool `tool` may read. A failure's cause code that overlaps any of
|
|
63
|
+
* the run's values is not sent to the worker; without this, no cause code is sent.
|
|
64
|
+
*/
|
|
65
|
+
readableSecretValues?: (tool: string) => Promise<string[]>;
|
|
66
|
+
/** Every secret value of the run's attached MCP servers, checked the same way. */
|
|
67
|
+
mcpSecretValues?: () => Promise<string[]>;
|
|
40
68
|
drivability: () => Promise<RunDrivability>;
|
|
41
69
|
launcher: WorkerLauncher;
|
|
42
70
|
}
|
|
@@ -10,10 +10,52 @@
|
|
|
10
10
|
* refused once the run is no longer drivable; built-in tools and privileged
|
|
11
11
|
* sandbox bridges are served only by name from the run's own surface.
|
|
12
12
|
*/
|
|
13
|
-
import
|
|
13
|
+
import pino from "pino";
|
|
14
|
+
import { isPrivilegedBridgeName, redactExactSecretValues, withEscapedForms, } from "../sandbox/host-functions.js";
|
|
14
15
|
import { logger } from "../core/logger.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
16
|
+
import { declaredCodeOf } from "../core/error-code.js";
|
|
17
|
+
import { GatewayError, GatewayRequestSchema, NATIVE_WORKER_PROTOCOL_VERSION, parseParams, ProtocolError, workerGatewayError, } from "./protocol.js";
|
|
18
|
+
/**
|
|
19
|
+
* The gateways' log. Both (in-process and HTTP) log an unexpected error here, as `native gateway
|
|
20
|
+
* request failed` (or `native gateway model stream failed`). Exported so tests can watch it.
|
|
21
|
+
*/
|
|
22
|
+
export const gatewayLog = logger.child({ module: "native-gateway" });
|
|
23
|
+
/** `err` for the log with every exact secret value removed from its (cause-folded) message and stack. */
|
|
24
|
+
function redactedError(err, rawValues) {
|
|
25
|
+
// The same expansion as the console bridge and the worker: a value may sit escaped in the text.
|
|
26
|
+
const values = withEscapedForms(rawValues);
|
|
27
|
+
// pino's own serializer folds the cause chain into message and stack, so a cause is covered too.
|
|
28
|
+
const serialized = pino.stdSerializers.err(err);
|
|
29
|
+
const safe = new Error(redactExactSecretValues(serialized.message, values));
|
|
30
|
+
safe.name = err.name;
|
|
31
|
+
safe.stack = redactExactSecretValues(serialized.stack ?? "", values);
|
|
32
|
+
return safe;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Logs an unexpected error for the operator, redacted by exact value. A successfully read list is
|
|
36
|
+
* complete (its reader rejects when any secret's read fails), so an empty one means the run has no
|
|
37
|
+
* secret values and the message is logged as is. Fail closed: a thrown value that is not an Error
|
|
38
|
+
* (a string, an object: its text cannot be redacted reliably), or no list (unavailable or
|
|
39
|
+
* unreadable), logs only the error's name and declared code, never its message, stack or content.
|
|
40
|
+
*/
|
|
41
|
+
export function logUnexpectedError(log, err, values, logMessage, fields = {}) {
|
|
42
|
+
if (values && err instanceof Error)
|
|
43
|
+
log.error({ ...fields, err: redactedError(err, values) }, logMessage);
|
|
44
|
+
else
|
|
45
|
+
log.error({ ...fields, errName: err instanceof Error ? err.name : typeof err, causeCode: declaredCodeOf(err) }, logMessage);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The one way either gateway turns a failure into what the worker sees: an unexpected error is
|
|
49
|
+
* logged for the operator (redacted by the run's secret values) and becomes the checked
|
|
50
|
+
* GatewayError (workerGatewayError); the values are read once and serve both.
|
|
51
|
+
*/
|
|
52
|
+
export async function forWorker(err, secretValues, logMessage) {
|
|
53
|
+
if (err instanceof GatewayError)
|
|
54
|
+
return workerGatewayError(err, secretValues);
|
|
55
|
+
const values = await secretValues?.().then((v) => [...v], () => undefined);
|
|
56
|
+
logUnexpectedError(gatewayLog, err, values, logMessage);
|
|
57
|
+
return workerGatewayError(err, values ? async () => values : undefined);
|
|
58
|
+
}
|
|
17
59
|
/** Thrown when the worker stopped because the run was cancelled; the runner records `cancelled`. */
|
|
18
60
|
export class SandboxRunCancelledError extends Error {
|
|
19
61
|
}
|
|
@@ -72,7 +114,16 @@ export async function runSandboxedEngine(options) {
|
|
|
72
114
|
throw new GatewayError("duplicate_call", `callId "${callId}" was already used.`);
|
|
73
115
|
usedCallIds.add(callId);
|
|
74
116
|
};
|
|
75
|
-
|
|
117
|
+
/** The run's readable secret values, for checking a failure's cause code before the worker sees it. */
|
|
118
|
+
const readable = options.readableSecretValues;
|
|
119
|
+
const mcpValues = options.mcpSecretValues;
|
|
120
|
+
const runSecretValues = readable
|
|
121
|
+
? async () => [
|
|
122
|
+
...(await Promise.all(Object.keys(input.userTools).map((tool) => readable(tool)))).flat(),
|
|
123
|
+
...(mcpValues ? await mcpValues() : []),
|
|
124
|
+
]
|
|
125
|
+
: undefined;
|
|
126
|
+
const served = {
|
|
76
127
|
async *stream(raw) {
|
|
77
128
|
const { request, params } = await admit(raw, "llm.stream");
|
|
78
129
|
claim(request.callId);
|
|
@@ -178,6 +229,25 @@ export async function runSandboxedEngine(options) {
|
|
|
178
229
|
}
|
|
179
230
|
},
|
|
180
231
|
};
|
|
232
|
+
// What crosses to the worker on every transport: a GatewayError, never an unexpected error's text.
|
|
233
|
+
const gateway = {
|
|
234
|
+
async call(raw) {
|
|
235
|
+
try {
|
|
236
|
+
return await served.call(raw);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
throw await forWorker(err, runSecretValues, "native gateway request failed");
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
async *stream(raw) {
|
|
243
|
+
try {
|
|
244
|
+
yield* served.stream(raw);
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
throw await forWorker(err, runSecretValues, "native gateway model stream failed");
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
};
|
|
181
251
|
const { exitCode } = await options.launcher.run(input, gateway, controller.signal);
|
|
182
252
|
controller.abort();
|
|
183
253
|
if (cancelled || (!finished && (await options.drivability()) === "cancelled")) {
|
|
@@ -6,10 +6,16 @@
|
|
|
6
6
|
*
|
|
7
7
|
* POST /native-gateway/v1/call body: GatewayRequest
|
|
8
8
|
* → application/json { ok: true, result } | { ok: false, error: { code, message } }
|
|
9
|
-
* → application/x-ndjson (llm.stream) { event } … then { end: true } or { error }
|
|
9
|
+
* → application/x-ndjson (llm.stream) { event } … then { end: true } or { error: { code, message, causeCode? } }
|
|
10
|
+
*
|
|
11
|
+
* POST /coding-mcp a coding run's MCP calls, forwarded by the coding proxy's /mcp route
|
|
12
|
+
* (src/core/coding-mcp.ts); its own auth: the run's MCP token, not a
|
|
13
|
+
* gateway capability. 404 when the listener was started without it.
|
|
10
14
|
*/
|
|
11
15
|
import { type Server } from "node:http";
|
|
12
16
|
import { type GatewayServerDeps } from "./gateway-server.js";
|
|
17
|
+
/** The HTTP listener's own log. Exported so tests can watch it. */
|
|
18
|
+
export declare const httpLog: import("pino").Logger<never, boolean>;
|
|
13
19
|
export declare const NATIVE_GATEWAY_PATH = "/native-gateway/v1/call";
|
|
14
20
|
export interface NativeGatewayListen {
|
|
15
21
|
host: string;
|
|
@@ -6,13 +6,21 @@
|
|
|
6
6
|
*
|
|
7
7
|
* POST /native-gateway/v1/call body: GatewayRequest
|
|
8
8
|
* → application/json { ok: true, result } | { ok: false, error: { code, message } }
|
|
9
|
-
* → application/x-ndjson (llm.stream) { event } … then { end: true } or { error }
|
|
9
|
+
* → application/x-ndjson (llm.stream) { event } … then { end: true } or { error: { code, message, causeCode? } }
|
|
10
|
+
*
|
|
11
|
+
* POST /coding-mcp a coding run's MCP calls, forwarded by the coding proxy's /mcp route
|
|
12
|
+
* (src/core/coding-mcp.ts); its own auth: the run's MCP token, not a
|
|
13
|
+
* gateway capability. 404 when the listener was started without it.
|
|
10
14
|
*/
|
|
11
15
|
import { createServer } from "node:http";
|
|
16
|
+
import { CODING_MCP_PATH, handleCodingMcpRequest } from "../core/coding-mcp.js";
|
|
12
17
|
import { logger } from "../core/logger.js";
|
|
18
|
+
import { HTTP_LIMITS, HttpBoundaryError, readBody as readLimitedBody } from "../mcp/transport/http-limits.js";
|
|
19
|
+
import { logUnexpectedError } from "./gateway.js";
|
|
13
20
|
import { serveGatewayRequest } from "./gateway-server.js";
|
|
14
|
-
import { GatewayError, MAX_MESSAGE_BYTES } from "./protocol.js";
|
|
15
|
-
|
|
21
|
+
import { GatewayError, MAX_MESSAGE_BYTES, toGatewayError } from "./protocol.js";
|
|
22
|
+
/** The HTTP listener's own log. Exported so tests can watch it. */
|
|
23
|
+
export const httpLog = logger.child({ module: "native-gateway-http" });
|
|
16
24
|
export const NATIVE_GATEWAY_PATH = "/native-gateway/v1/call";
|
|
17
25
|
/** Parses NATIVE_GATEWAY_LISTEN ("host:port" or ":port"); undefined when unset. */
|
|
18
26
|
export function parseGatewayListen(value) {
|
|
@@ -56,6 +64,10 @@ export function createGatewayServer(deps) {
|
|
|
56
64
|
send(healthy ? 200 : 503, { ok: healthy });
|
|
57
65
|
return;
|
|
58
66
|
}
|
|
67
|
+
if (new URL(req.url ?? "/", "http://gateway").pathname === CODING_MCP_PATH && deps.codingMcp) {
|
|
68
|
+
await serveCodingMcp(req, res, deps.codingMcp);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
59
71
|
if (req.method !== "POST" || req.url !== NATIVE_GATEWAY_PATH) {
|
|
60
72
|
send(404, { ok: false, error: { code: "not_found", message: "not found" } });
|
|
61
73
|
return;
|
|
@@ -84,19 +96,62 @@ export function createGatewayServer(deps) {
|
|
|
84
96
|
res.end(`${JSON.stringify({ end: true })}\n`);
|
|
85
97
|
}
|
|
86
98
|
catch (err) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
99
|
+
// The gateway's stream fails only with a checked GatewayError (checkedEvents); anything else
|
|
100
|
+
// still crosses as the generic message, never its own text.
|
|
101
|
+
const { code, message, causeCode } = toGatewayError(err);
|
|
102
|
+
const error = { code, message, ...(causeCode ? { causeCode } : {}) };
|
|
90
103
|
res.end(`${JSON.stringify({ error })}\n`);
|
|
91
104
|
}
|
|
92
105
|
})().catch((err) => {
|
|
93
|
-
|
|
106
|
+
// No run's secret values are known here, so only the name and declared code are logged.
|
|
107
|
+
logUnexpectedError(httpLog, err, undefined, "native gateway HTTP handler failed");
|
|
94
108
|
if (!res.headersSent)
|
|
95
109
|
res.writeHead(500);
|
|
96
110
|
res.end();
|
|
97
111
|
});
|
|
98
112
|
});
|
|
99
113
|
}
|
|
114
|
+
/** /coding-mcp: one JSON-RPC message per POST, answered as one JSON body (or 202 with none). */
|
|
115
|
+
async function serveCodingMcp(req, res, deps) {
|
|
116
|
+
if (req.method !== "POST") {
|
|
117
|
+
res.setHeader("allow", "POST");
|
|
118
|
+
res.setHeader("content-type", "application/json");
|
|
119
|
+
res.writeHead(405);
|
|
120
|
+
res.end(JSON.stringify({ jsonrpc: "2.0", id: null, error: { code: -32600, message: "Use POST." } }));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
let body;
|
|
124
|
+
try {
|
|
125
|
+
body = await readLimitedBody(req, HTTP_LIMITS.json, AbortSignal.timeout(HTTP_LIMITS.requestMs));
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
const status = err instanceof HttpBoundaryError ? err.status : 400;
|
|
129
|
+
res.setHeader("content-type", "application/json");
|
|
130
|
+
res.writeHead(status);
|
|
131
|
+
res.end(JSON.stringify({
|
|
132
|
+
jsonrpc: "2.0",
|
|
133
|
+
id: null,
|
|
134
|
+
error: { code: -32600, message: "The request body could not be read." },
|
|
135
|
+
}));
|
|
136
|
+
// A body left unread would otherwise keep the socket busy.
|
|
137
|
+
if (status === 413)
|
|
138
|
+
req.resume();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// The proxy gives up on a call at its forward limit (or its worker goes away): the closed response
|
|
142
|
+
// aborts the call in flight rather than leave it running against the MCP server.
|
|
143
|
+
const closed = new AbortController();
|
|
144
|
+
res.on("close", () => {
|
|
145
|
+
if (!res.writableFinished)
|
|
146
|
+
closed.abort();
|
|
147
|
+
});
|
|
148
|
+
const response = await handleCodingMcpRequest(req.headers.authorization, body, deps, closed.signal);
|
|
149
|
+
if (closed.signal.aborted)
|
|
150
|
+
return;
|
|
151
|
+
res.setHeader("content-type", response.contentType);
|
|
152
|
+
res.writeHead(response.status);
|
|
153
|
+
res.end(response.body);
|
|
154
|
+
}
|
|
100
155
|
/** Starts the listener; resolves once it is accepting connections. */
|
|
101
156
|
export async function startGatewayServer(listen, deps) {
|
|
102
157
|
const server = createGatewayServer(deps);
|
|
@@ -16,7 +16,7 @@ export function createHttpTransport(options) {
|
|
|
16
16
|
headers: { "content-type": "application/json", authorization: `Bearer ${options.capability}` },
|
|
17
17
|
body: JSON.stringify(request),
|
|
18
18
|
});
|
|
19
|
-
const gatewayError = (error, status) => new GatewayError((error?.code ?? "internal"), error?.message ?? `gateway answered ${status}
|
|
19
|
+
const gatewayError = (error, status) => new GatewayError((error?.code ?? "internal"), error?.message ?? `gateway answered ${status}`, typeof error?.causeCode === "string" ? error.causeCode : undefined);
|
|
20
20
|
return {
|
|
21
21
|
async call(request) {
|
|
22
22
|
const giveUpAt = Date.now() + retryForMs;
|
|
@@ -14,8 +14,8 @@ import { type Power } from "../core/power.js";
|
|
|
14
14
|
import { type KubernetesApi } from "../providers/jobs/kubernetes-api.js";
|
|
15
15
|
import type { KubernetesPlatform } from "../providers/jobs/kubernetes-platform.js";
|
|
16
16
|
import { type NativeWorkerLimits } from "./docker-isolation.js";
|
|
17
|
-
import type
|
|
18
|
-
import type
|
|
17
|
+
import { type NativeWorkerState } from "./docker-launcher.js";
|
|
18
|
+
import { type WorkerHandle, type WorkerLaunchOptions } from "./launch.js";
|
|
19
19
|
import type { WorkerInput } from "./protocol.js";
|
|
20
20
|
import type { ManagedWorkerLauncher } from "./sandbox-executor.js";
|
|
21
21
|
import { type WarmWorkerLauncher } from "./warm-pool.js";
|
|
@@ -48,6 +48,8 @@ export interface KubernetesNativeWorkerLauncherOptions {
|
|
|
48
48
|
sleep?: (ms: number) => Promise<void>;
|
|
49
49
|
/** Low-power mode: wakes the (possibly scaled-to-zero) native gateway before a launch. Default `DISABLED_POWER`. */
|
|
50
50
|
power?: Power;
|
|
51
|
+
/** The bound on a failed worker's diagnostic (log and secret reads) before its exit is reported. Default WORKER_TAIL_TIMEOUT_MS. */
|
|
52
|
+
diagnosticTimeoutMs?: number;
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
55
|
* An object as the API server would store it, for comparison: keys sorted, and missing, undefined,
|
|
@@ -67,7 +69,9 @@ export declare class KubernetesNativeWorkerLauncher implements ManagedWorkerLaun
|
|
|
67
69
|
private resolveGatewayHost;
|
|
68
70
|
resolveGatewayUrl(): Promise<string>;
|
|
69
71
|
private createIfMissing;
|
|
70
|
-
launch(input: WorkerInput): Promise<WorkerHandle>;
|
|
72
|
+
launch(input: WorkerInput, launchOptions?: WorkerLaunchOptions): Promise<WorkerHandle>;
|
|
73
|
+
/** A non-zero exit, with the tail of the worker's log (bounded and redacted: workerTailFields), as the Docker launcher logs it. */
|
|
74
|
+
private logFailedExit;
|
|
71
75
|
/**
|
|
72
76
|
* Policy first, so the pod never exists without it; then the pod; then attest and prove it. A
|
|
73
77
|
* quota rejection becomes native_sandbox_capacity. Any failure removes what was made.
|