@wardby/cli 0.6.0 → 0.7.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/deploy/local/docker-compose.quickstart-coding.yml +13 -0
- package/dist/claude-coding-worker/driver.d.ts +21 -3
- package/dist/claude-coding-worker/driver.js +125 -17
- package/dist/claude-coding-worker/main.js +34 -6
- package/dist/claude-coding-worker/sdk.js +12 -1
- 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/cli-help.d.ts +1 -1
- package/dist/cli-help.js +1 -0
- package/dist/cli.js +24 -10
- 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/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 +235 -12
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +12 -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 +51 -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 +6 -5
- package/dist/coding-worker/debug-trace.js +13 -18
- 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 +116 -38
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- 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 +11 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- package/dist/config/test-simulators.d.ts +82 -0
- package/dist/config/test-simulators.js +305 -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-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -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/dispatch.d.ts +42 -0
- package/dist/core/dispatch.js +131 -56
- package/dist/core/engine-native.js +1 -1
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +168 -0
- package/dist/core/grants.d.ts +19 -6
- package/dist/core/grants.js +55 -6
- package/dist/core/host-events.d.ts +18 -2
- package/dist/core/host-events.js +284 -24
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +298 -20
- 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 +54 -26
- 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/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +2 -1
- package/dist/core/merge-order-check.js +8 -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 +27 -14
- 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 +2 -1
- 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 +99 -13
- 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 +80 -34
- package/dist/core/runner.js +439 -144
- 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 +10 -74
- package/dist/core/secret-guard.d.ts +46 -0
- package/dist/core/secret-guard.js +104 -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/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- 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 +43 -8
- 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 +34 -3
- package/dist/generated/prisma/client.d.ts +34 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +220 -60
- 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 +44 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +428 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +92 -1
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +95 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +92 -1
- package/dist/generated/prisma/models/Agent.d.ts +106 -8
- package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +229 -1
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
- package/dist/generated/prisma/models/CodingRun.d.ts +1637 -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/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +39 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- 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/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.d.ts +4 -0
- package/dist/help-index.json +1320 -69
- package/dist/import/create.js +32 -3
- package/dist/import/neutral-schema.d.ts +50 -281
- package/dist/import/neutral-schema.js +5 -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/ownership.d.ts +7 -7
- 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/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 +58 -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 +198 -16
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +9 -3
- 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 +18 -5
- 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 +34 -12
- 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/secrets.js +2 -2
- 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 +1 -1
- package/dist/mcp/tools/tools.js +25 -9
- 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/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 +41 -3
- package/dist/native-worker/gateway-server.js +124 -27
- package/dist/native-worker/gateway.d.ts +27 -1
- package/dist/native-worker/gateway.js +70 -4
- package/dist/native-worker/http-server.d.ts +3 -1
- package/dist/native-worker/http-server.js +11 -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 +18 -2
- package/dist/native-worker/ledger.js +57 -4
- 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 +129 -577
- package/dist/native-worker/protocol.js +47 -1
- 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/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/memory-ledger.d.ts +15 -2
- package/dist/providers/coding-proxy/memory-ledger.js +84 -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 +15 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
- package/dist/providers/coding-proxy/proxy.d.ts +14 -1
- package/dist/providers/coding-proxy/proxy.js +166 -14
- 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 +4 -0
- package/dist/providers/coding-proxy/runtime.js +78 -16
- package/dist/providers/coding-proxy/server.d.ts +6 -1
- package/dist/providers/coding-proxy/server.js +45 -1
- package/dist/providers/coding-proxy/types.d.ts +65 -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 +47 -7
- package/dist/providers/executor/container.d.ts +361 -8
- package/dist/providers/executor/container.js +1136 -91
- 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/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 +8 -0
- package/dist/providers/jobs/docker-isolation.js +17 -0
- package/dist/providers/jobs/docker.d.ts +1 -0
- package/dist/providers/jobs/docker.js +27 -2
- 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 +2 -0
- package/dist/providers/jobs/kubernetes-isolation.js +17 -1
- package/dist/providers/jobs/kubernetes.d.ts +6 -1
- package/dist/providers/jobs/kubernetes.js +105 -16
- package/dist/providers/jobs/types.d.ts +33 -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 +134 -2
- package/dist/providers/review-host/types.js +8 -0
- 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 +33 -2
- package/dist/providers/vcs/git.js +324 -22
- 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 +214 -6
- package/dist/providers/vcs/github.js +447 -45
- package/dist/providers/vcs/index.js +8 -1
- 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 +33 -1
- package/dist/providers/vcs/routing.d.ts +4 -2
- package/dist/providers/vcs/routing.js +6 -0
- package/dist/providers/vcs/types.d.ts +80 -3
- package/dist/quickstart/coding-seed.d.ts +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- 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/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +1 -0
- package/dist/sandbox/host-functions.js +6 -11
- package/dist/sandbox/secret-broker.js +3 -4
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- 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/openapi.js +2 -4
- package/dist/wardby-bin.js +10 -0
- package/docs/agent-recipes.md +58 -20
- package/docs/code-review-agents.md +551 -41
- package/docs/coding-agent-setup.md +489 -7
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +20 -0
- package/docs/coding-worker-isolation.md +105 -30
- package/docs/getting-started-gke.md +124 -137
- package/docs/getting-started-identity-provider.md +10 -1
- package/docs/getting-started.md +9 -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/native-sandbox.md +119 -23
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +33 -2
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +42 -10
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +24 -2
- package/help/architecture-agent.md +11 -6
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- 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-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/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/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +3 -2
- 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/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/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/identity-and-access.md +2 -0
- 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/merge-order-check.md +5 -0
- package/help/native-capabilities.md +29 -1
- package/help/native-sandbox.md +15 -1
- package/help/operating-agents.md +5 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +10 -7
- package/help/resume-runs-locally.md +131 -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 +78 -7
- package/package.json +17 -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/schema.prisma +311 -97
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -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,12 @@ 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 runSecretValues = readable
|
|
120
|
+
? async () => (await Promise.all(Object.keys(input.userTools).map((tool) => readable(tool)))).flat()
|
|
121
|
+
: undefined;
|
|
122
|
+
const served = {
|
|
76
123
|
async *stream(raw) {
|
|
77
124
|
const { request, params } = await admit(raw, "llm.stream");
|
|
78
125
|
claim(request.callId);
|
|
@@ -178,6 +225,25 @@ export async function runSandboxedEngine(options) {
|
|
|
178
225
|
}
|
|
179
226
|
},
|
|
180
227
|
};
|
|
228
|
+
// What crosses to the worker on every transport: a GatewayError, never an unexpected error's text.
|
|
229
|
+
const gateway = {
|
|
230
|
+
async call(raw) {
|
|
231
|
+
try {
|
|
232
|
+
return await served.call(raw);
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
throw await forWorker(err, runSecretValues, "native gateway request failed");
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
async *stream(raw) {
|
|
239
|
+
try {
|
|
240
|
+
yield* served.stream(raw);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
throw await forWorker(err, runSecretValues, "native gateway model stream failed");
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
};
|
|
181
247
|
const { exitCode } = await options.launcher.run(input, gateway, controller.signal);
|
|
182
248
|
controller.abort();
|
|
183
249
|
if (cancelled || (!finished && (await options.drivability()) === "cancelled")) {
|
|
@@ -6,10 +6,12 @@
|
|
|
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
10
|
*/
|
|
11
11
|
import { type Server } from "node:http";
|
|
12
12
|
import { type GatewayServerDeps } from "./gateway-server.js";
|
|
13
|
+
/** The HTTP listener's own log. Exported so tests can watch it. */
|
|
14
|
+
export declare const httpLog: import("pino").Logger<never, boolean>;
|
|
13
15
|
export declare const NATIVE_GATEWAY_PATH = "/native-gateway/v1/call";
|
|
14
16
|
export interface NativeGatewayListen {
|
|
15
17
|
host: string;
|
|
@@ -6,13 +6,15 @@
|
|
|
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
10
|
*/
|
|
11
11
|
import { createServer } from "node:http";
|
|
12
12
|
import { logger } from "../core/logger.js";
|
|
13
|
+
import { logUnexpectedError } from "./gateway.js";
|
|
13
14
|
import { serveGatewayRequest } from "./gateway-server.js";
|
|
14
|
-
import { GatewayError, MAX_MESSAGE_BYTES } from "./protocol.js";
|
|
15
|
-
|
|
15
|
+
import { GatewayError, MAX_MESSAGE_BYTES, toGatewayError } from "./protocol.js";
|
|
16
|
+
/** The HTTP listener's own log. Exported so tests can watch it. */
|
|
17
|
+
export const httpLog = logger.child({ module: "native-gateway-http" });
|
|
16
18
|
export const NATIVE_GATEWAY_PATH = "/native-gateway/v1/call";
|
|
17
19
|
/** Parses NATIVE_GATEWAY_LISTEN ("host:port" or ":port"); undefined when unset. */
|
|
18
20
|
export function parseGatewayListen(value) {
|
|
@@ -84,13 +86,15 @@ export function createGatewayServer(deps) {
|
|
|
84
86
|
res.end(`${JSON.stringify({ end: true })}\n`);
|
|
85
87
|
}
|
|
86
88
|
catch (err) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
// The gateway's stream fails only with a checked GatewayError (checkedEvents); anything else
|
|
90
|
+
// still crosses as the generic message, never its own text.
|
|
91
|
+
const { code, message, causeCode } = toGatewayError(err);
|
|
92
|
+
const error = { code, message, ...(causeCode ? { causeCode } : {}) };
|
|
90
93
|
res.end(`${JSON.stringify({ error })}\n`);
|
|
91
94
|
}
|
|
92
95
|
})().catch((err) => {
|
|
93
|
-
|
|
96
|
+
// No run's secret values are known here, so only the name and declared code are logged.
|
|
97
|
+
logUnexpectedError(httpLog, err, undefined, "native gateway HTTP handler failed");
|
|
94
98
|
if (!res.headersSent)
|
|
95
99
|
res.writeHead(500);
|
|
96
100
|
res.end();
|
|
@@ -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.
|
|
@@ -15,15 +15,24 @@ import { DISABLED_POWER, wakeTimeoutMs } from "../core/power.js";
|
|
|
15
15
|
import { KubernetesAlreadyExistsError } from "../providers/jobs/kubernetes-api.js";
|
|
16
16
|
import { canonicalResources } from "../providers/jobs/kubernetes-isolation.js";
|
|
17
17
|
import { NATIVE_GATEWAY_PORT } from "./docker-isolation.js";
|
|
18
|
+
import { WORKER_TAIL_TIMEOUT_MS, withTimeout, workerTailFields } from "./docker-launcher.js";
|
|
18
19
|
import { createHash } from "node:crypto";
|
|
19
20
|
import { Readable } from "node:stream";
|
|
20
21
|
import { buildNativeInputSecret, buildNativeRunNetworkPolicy, buildNativeRunPod, buildNativeWarmNetworkPolicy, buildNativeWarmPod, NATIVE_PROBE, NATIVE_RUN_SELECTOR, NATIVE_RUN_SHA_LABEL, NATIVE_WARM_SELECTOR, NATIVE_WARM_TOKEN_LABEL, NATIVE_WORKER_CONTAINER, nativeEnforcementProbe, nativeKubernetesNames, nativeWarmWorkerName, } from "./kubernetes-isolation.js";
|
|
22
|
+
import { NATIVE_SANDBOX_LAUNCH_ABANDONED } from "./launch.js";
|
|
21
23
|
import { warmDeliveryCommand } from "./warm-delivery.js";
|
|
22
24
|
import { NATIVE_SANDBOX_WARM_DELIVERY_FAILED } from "./warm-pool.js";
|
|
23
25
|
const k8sLog = logger.child({ module: "native-kubernetes-launcher" });
|
|
24
26
|
export const NATIVE_SANDBOX_NETWORK_UNENFORCED = "native_sandbox_network_unenforced";
|
|
25
27
|
export const NATIVE_SANDBOX_ISOLATION_MISMATCH = "native_sandbox_isolation_mismatch";
|
|
26
28
|
export const NATIVE_SANDBOX_CAPACITY = "native_sandbox_capacity";
|
|
29
|
+
/**
|
|
30
|
+
* A failed worker's log is read this far back before its tail is redacted and cut. The API server
|
|
31
|
+
* applies `limitBytes` from the start of the selected lines, so it would cut the end (the worker's
|
|
32
|
+
* final failure line): it is only a memory cap, far above what the line bound selects in practice.
|
|
33
|
+
*/
|
|
34
|
+
const WORKER_LOG_TAIL_LINES = 100;
|
|
35
|
+
const WORKER_LOG_TAIL_BYTES = 1024 * 1024;
|
|
27
36
|
/** The API server's refusal of a pod the namespace's ResourceQuota has no room for (403 "exceeded quota"). */
|
|
28
37
|
export function isQuotaRejection(err) {
|
|
29
38
|
if (typeof err !== "object" || err === null)
|
|
@@ -96,7 +105,7 @@ export class KubernetesNativeWorkerLauncher {
|
|
|
96
105
|
throw err;
|
|
97
106
|
}
|
|
98
107
|
}
|
|
99
|
-
async launch(input) {
|
|
108
|
+
async launch(input, launchOptions = {}) {
|
|
100
109
|
const runId = input.runId;
|
|
101
110
|
// Low-power mode: the gateway may be scaled to zero; wake it before anything is created. Guarded
|
|
102
111
|
// so mode off adds no await.
|
|
@@ -106,6 +115,10 @@ export class KubernetesNativeWorkerLauncher {
|
|
|
106
115
|
runId,
|
|
107
116
|
});
|
|
108
117
|
}
|
|
118
|
+
// A wake can take minutes: a run stopped meanwhile gets no pod.
|
|
119
|
+
if (launchOptions.stillWanted && !(await launchOptions.stillWanted())) {
|
|
120
|
+
throw new Error(`${NATIVE_SANDBOX_LAUNCH_ABANDONED}: the run ended while its worker was launching; no worker was started.`);
|
|
121
|
+
}
|
|
109
122
|
const names = nativeKubernetesNames(runId);
|
|
110
123
|
if ((await this.inspect(runId)).state === "missing") {
|
|
111
124
|
const pod = buildNativeRunPod({
|
|
@@ -124,12 +137,37 @@ export class KubernetesNativeWorkerLauncher {
|
|
|
124
137
|
beforePod: () => this.createIfMissing(() => this.api.createSecret(this.ns, buildNativeInputSecret(input, this.ns))),
|
|
125
138
|
});
|
|
126
139
|
await this.options.onNetworkProven(runId);
|
|
140
|
+
// Read before the exit is reported, so the pod (and its log) still exists.
|
|
141
|
+
return this.handleByName(names.pod, (code) => this.logFailedExit(names.pod, code, input, launchOptions));
|
|
127
142
|
}
|
|
128
143
|
else {
|
|
129
144
|
k8sLog.info({ pod: names.pod }, "native worker pod already exists: attaching, not relaunching");
|
|
130
145
|
}
|
|
131
146
|
return this.handle(runId);
|
|
132
147
|
}
|
|
148
|
+
/** A non-zero exit, with the tail of the worker's log (bounded and redacted: workerTailFields), as the Docker launcher logs it. */
|
|
149
|
+
async logFailedExit(podName, code, input, launchOptions) {
|
|
150
|
+
if (code === 0)
|
|
151
|
+
return;
|
|
152
|
+
// One bound for the whole diagnostic, so a hung read never holds back the exit (and the run's end).
|
|
153
|
+
const by = Date.now() + (this.options.diagnosticTimeoutMs ?? WORKER_TAIL_TIMEOUT_MS);
|
|
154
|
+
let log;
|
|
155
|
+
try {
|
|
156
|
+
log = await withTimeout(this.api.readLogTail(this.ns, podName, NATIVE_WORKER_CONTAINER, WORKER_LOG_TAIL_LINES, WORKER_LOG_TAIL_BYTES), by - Date.now());
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// The pod may already be gone, the read may be refused (no pods/log), or it timed out.
|
|
160
|
+
k8sLog.warn({ pod: podName, code, stderrTailOmitted: "log_read_failed" }, "native worker exited non-zero");
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// The read may always begin mid-text, even with fewer lines than the bound: the kubelet splits
|
|
164
|
+
// a line over 16 KiB into partial records (each counted as a line), and log rotation drops the
|
|
165
|
+
// oldest text, so the start is always masked as cut. The byte cap (counted from the start of
|
|
166
|
+
// the selected lines) cuts the end only when it is met.
|
|
167
|
+
const end = Buffer.byteLength(log) >= WORKER_LOG_TAIL_BYTES - 3;
|
|
168
|
+
const tail = await workerTailFields(log, input, launchOptions.secretValues, { start: true, end }, by - Date.now());
|
|
169
|
+
k8sLog.warn({ pod: podName, code, ...tail }, "native worker exited non-zero");
|
|
170
|
+
}
|
|
133
171
|
/**
|
|
134
172
|
* Policy first, so the pod never exists without it; then the pod; then attest and prove it. A
|
|
135
173
|
* quota rejection becomes native_sandbox_capacity. Any failure removes what was made.
|
|
@@ -225,12 +263,14 @@ export class KubernetesNativeWorkerLauncher {
|
|
|
225
263
|
handle(runId) {
|
|
226
264
|
return this.handleByName(nativeKubernetesNames(runId).pod);
|
|
227
265
|
}
|
|
228
|
-
handleByName(podName) {
|
|
266
|
+
handleByName(podName, onExit) {
|
|
229
267
|
const exited = (async () => {
|
|
230
268
|
for (;;) {
|
|
231
269
|
const state = await this.inspectByName(podName);
|
|
232
|
-
if (state.state === "exited")
|
|
270
|
+
if (state.state === "exited") {
|
|
271
|
+
await onExit?.(state.exitCode).catch(() => { });
|
|
233
272
|
return state.exitCode;
|
|
273
|
+
}
|
|
234
274
|
if (state.state === "missing")
|
|
235
275
|
return null;
|
|
236
276
|
await this.sleep(this.options.pollMs ?? 1_000);
|
|
@@ -16,9 +16,25 @@ export interface WorkerHandle {
|
|
|
16
16
|
exited: Promise<number | null>;
|
|
17
17
|
kill(): void;
|
|
18
18
|
}
|
|
19
|
+
export interface WorkerLaunchOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Asked after any slow wait (a low-power wake) and before a worker is created: false means the
|
|
22
|
+
* run ended meanwhile, and the launch stops with NATIVE_SANDBOX_LAUNCH_ABANDONED, creating nothing.
|
|
23
|
+
*/
|
|
24
|
+
stillWanted?: () => Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Every secret value the worker may be handed (each user tool's readable or brokered secrets),
|
|
27
|
+
* for masking a failed worker's output tail before the launcher logs it; the run's capability is
|
|
28
|
+
* masked from the input itself. Rejects when any read fails. Absent or rejected: no tail is
|
|
29
|
+
* logged (fail closed).
|
|
30
|
+
*/
|
|
31
|
+
secretValues?: () => Promise<readonly string[]>;
|
|
32
|
+
}
|
|
33
|
+
/** The run ended while its worker was launching, so none was created. */
|
|
34
|
+
export declare const NATIVE_SANDBOX_LAUNCH_ABANDONED = "native_sandbox_launch_abandoned";
|
|
19
35
|
/** Starts a worker for an HTTP-gateway input and returns at once. */
|
|
20
36
|
export interface DetachedWorkerLauncher {
|
|
21
|
-
launch(input: WorkerInput): Promise<WorkerHandle>;
|
|
37
|
+
launch(input: WorkerInput, options?: WorkerLaunchOptions): Promise<WorkerHandle>;
|
|
22
38
|
/**
|
|
23
39
|
* False when the worker's network isolation only takes effect after it starts (a Kubernetes
|
|
24
40
|
* NetworkPolicy): its session is then created not ready, and the launcher marks it ready once
|
|
@@ -42,4 +58,5 @@ export declare function startSandboxRun(options: {
|
|
|
42
58
|
db: RunnerDb & ConstructorParameters<typeof PrismaGatewayLedger>[0];
|
|
43
59
|
gatewayUrl: string;
|
|
44
60
|
launcher: DetachedWorkerLauncher;
|
|
61
|
+
stillWanted?: () => Promise<boolean>;
|
|
45
62
|
}): Promise<StartSandboxRunOutcome>;
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import { createSandboxSession } from "../core/runner.js";
|
|
11
11
|
import { PrismaGatewayLedger } from "./ledger.js";
|
|
12
|
+
/** The run ended while its worker was launching, so none was created. */
|
|
13
|
+
export const NATIVE_SANDBOX_LAUNCH_ABANDONED = "native_sandbox_launch_abandoned";
|
|
12
14
|
/** The worker as a local child process with an empty environment (by default), its input on stdin. */
|
|
13
15
|
export function processWorkerLauncher(spec) {
|
|
14
16
|
return {
|
|
@@ -39,6 +41,9 @@ export async function startSandboxRun(options) {
|
|
|
39
41
|
});
|
|
40
42
|
if (session.kind === "ended")
|
|
41
43
|
return session;
|
|
42
|
-
const handle = await options.launcher.launch(session.input
|
|
44
|
+
const handle = await options.launcher.launch(session.input, {
|
|
45
|
+
...(options.stillWanted ? { stillWanted: options.stillWanted } : {}),
|
|
46
|
+
secretValues: session.secretValues,
|
|
47
|
+
});
|
|
43
48
|
return { kind: "launched", sessionId: session.sessionId, handle };
|
|
44
49
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* replica can serve any call, and a restart loses nothing.
|
|
8
8
|
*/
|
|
9
9
|
import type { Prisma, PrismaClient } from "#prisma";
|
|
10
|
+
import { ReviewReadLedger } from "../core/review-reads.js";
|
|
10
11
|
export type GatewayLedgerDb = Pick<PrismaClient, "$transaction" | "$queryRaw" | "nativeGatewaySession" | "nativeGatewayCall">;
|
|
11
12
|
export interface GatewaySessionRecord {
|
|
12
13
|
id: string;
|
|
@@ -16,6 +17,8 @@ export interface GatewaySessionRecord {
|
|
|
16
17
|
budgetUsd: number;
|
|
17
18
|
snapshot: unknown;
|
|
18
19
|
networkReadyAt: Date | null;
|
|
20
|
+
/** The run's saved review reads (ReviewReadsState), or null before it reads a pull request. */
|
|
21
|
+
reviewReads?: unknown;
|
|
19
22
|
}
|
|
20
23
|
export interface CreateGatewaySessionInput {
|
|
21
24
|
runId: string;
|
|
@@ -77,6 +80,11 @@ export declare class PrismaGatewayLedger {
|
|
|
77
80
|
markNetworkReady(sessionId: string, at?: Date): Promise<void>;
|
|
78
81
|
/** markNetworkReady by the session's run (a launcher knows the run, not the session). */
|
|
79
82
|
markNetworkReadyForRun(runId: string, at?: Date): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Adds one request's review reads to the session's saved ones, under the session's row lock:
|
|
85
|
+
* reads only add, so parallel tool calls of one run each keep what they read.
|
|
86
|
+
*/
|
|
87
|
+
mergeReviewReads(sessionId: string, reads: ReviewReadLedger): Promise<void>;
|
|
80
88
|
endSession(sessionId: string, status: "finished" | "cancelled"): Promise<void>;
|
|
81
89
|
/** Reserves `reservationUsd` for a model call, or says why not. Serialized per session. */
|
|
82
90
|
reserve(input: {
|
|
@@ -89,8 +97,16 @@ export declare class PrismaGatewayLedger {
|
|
|
89
97
|
complete(sessionId: string, callId: string, usage: SettledUsage): Promise<void>;
|
|
90
98
|
/** Frees a reservation the provider never billed (it refused the request). */
|
|
91
99
|
release(sessionId: string, callId: string): Promise<void>;
|
|
92
|
-
/**
|
|
93
|
-
|
|
100
|
+
/**
|
|
101
|
+
* The outcome is unknown (the connection broke mid-call). Without an estimate the
|
|
102
|
+
* reservation stays held; with one, the call counts at the estimate instead.
|
|
103
|
+
*/
|
|
104
|
+
markUncertain(sessionId: string, callId: string, estimate?: SettledUsage): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Median output tokens of the session's completed model calls (all on the run's one model), or
|
|
107
|
+
* undefined before the first one: the output of a call cut with nothing streamed.
|
|
108
|
+
*/
|
|
109
|
+
medianOutputTokens(sessionId: string): Promise<number | undefined>;
|
|
94
110
|
totals(sessionId: string): Promise<GatewayTotals>;
|
|
95
111
|
/** Claims a one-shot call by callId: the first claimant runs it, a repeat waits or replays. */
|
|
96
112
|
claim(sessionId: string, callId: string, method: string): Promise<ClaimOutcome>;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* called, and is settled at its actual cost after — so any control-plane
|
|
7
7
|
* replica can serve any call, and a restart loses nothing.
|
|
8
8
|
*/
|
|
9
|
+
import { ReviewReadLedger } from "../core/review-reads.js";
|
|
9
10
|
const LEDGER_TX = { maxWait: 5_000, timeout: 20_000 };
|
|
10
11
|
function toSession(row) {
|
|
11
12
|
return { ...row, budgetUsd: Number(row.budgetUsd) };
|
|
@@ -37,6 +38,24 @@ export class PrismaGatewayLedger {
|
|
|
37
38
|
data: { networkReadyAt: at },
|
|
38
39
|
});
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Adds one request's review reads to the session's saved ones, under the session's row lock:
|
|
43
|
+
* reads only add, so parallel tool calls of one run each keep what they read.
|
|
44
|
+
*/
|
|
45
|
+
async mergeReviewReads(sessionId, reads) {
|
|
46
|
+
await this.db.$transaction(async (tx) => {
|
|
47
|
+
const locked = await tx.$queryRaw `
|
|
48
|
+
SELECT "reviewReads" FROM "NativeGatewaySession" WHERE "id" = ${sessionId} FOR UPDATE`;
|
|
49
|
+
if (!locked[0])
|
|
50
|
+
return;
|
|
51
|
+
const saved = ReviewReadLedger.fromJSON(locked[0].reviewReads);
|
|
52
|
+
saved.merge(reads);
|
|
53
|
+
await tx.nativeGatewaySession.update({
|
|
54
|
+
where: { id: sessionId },
|
|
55
|
+
data: { reviewReads: saved.toJSON() },
|
|
56
|
+
});
|
|
57
|
+
}, LEDGER_TX);
|
|
58
|
+
}
|
|
40
59
|
async endSession(sessionId, status) {
|
|
41
60
|
await this.db.nativeGatewaySession.updateMany({ where: { id: sessionId, status: "active" }, data: { status } });
|
|
42
61
|
}
|
|
@@ -86,6 +105,7 @@ export class PrismaGatewayLedger {
|
|
|
86
105
|
outputTokens: usage.outputTokens,
|
|
87
106
|
cachedInputTokens: usage.cachedInputTokens,
|
|
88
107
|
cacheWriteTokens: usage.cacheWriteTokens,
|
|
108
|
+
costEstimated: false,
|
|
89
109
|
completedAt: new Date(),
|
|
90
110
|
},
|
|
91
111
|
});
|
|
@@ -97,16 +117,48 @@ export class PrismaGatewayLedger {
|
|
|
97
117
|
data: { status: "released", completedAt: new Date() },
|
|
98
118
|
});
|
|
99
119
|
}
|
|
100
|
-
/**
|
|
101
|
-
|
|
120
|
+
/**
|
|
121
|
+
* The outcome is unknown (the connection broke mid-call). Without an estimate the
|
|
122
|
+
* reservation stays held; with one, the call counts at the estimate instead.
|
|
123
|
+
*/
|
|
124
|
+
async markUncertain(sessionId, callId, estimate) {
|
|
102
125
|
await this.db.nativeGatewayCall.updateMany({
|
|
103
126
|
where: { sessionId, callId, status: "reserved" },
|
|
104
|
-
data: {
|
|
127
|
+
data: {
|
|
128
|
+
status: "uncertain",
|
|
129
|
+
...(estimate
|
|
130
|
+
? {
|
|
131
|
+
actualCostUsd: estimate.costUsd,
|
|
132
|
+
inputTokens: estimate.inputTokens,
|
|
133
|
+
outputTokens: estimate.outputTokens,
|
|
134
|
+
cachedInputTokens: estimate.cachedInputTokens,
|
|
135
|
+
cacheWriteTokens: estimate.cacheWriteTokens,
|
|
136
|
+
costEstimated: true,
|
|
137
|
+
}
|
|
138
|
+
: {}),
|
|
139
|
+
},
|
|
105
140
|
});
|
|
106
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Median output tokens of the session's completed model calls (all on the run's one model), or
|
|
144
|
+
* undefined before the first one: the output of a call cut with nothing streamed.
|
|
145
|
+
*/
|
|
146
|
+
async medianOutputTokens(sessionId) {
|
|
147
|
+
const rows = await this.db.$queryRaw `
|
|
148
|
+
SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY "outputTokens") AS "median"
|
|
149
|
+
FROM "NativeGatewayCall"
|
|
150
|
+
WHERE "sessionId" = ${sessionId} AND "method" = 'llm.stream' AND "status" = 'completed'
|
|
151
|
+
AND "outputTokens" IS NOT NULL`;
|
|
152
|
+
const median = rows[0]?.median ?? null;
|
|
153
|
+
return median === null ? undefined : Number(median);
|
|
154
|
+
}
|
|
107
155
|
async totals(sessionId) {
|
|
108
156
|
const completed = await this.db.nativeGatewayCall.aggregate({
|
|
109
|
-
where: {
|
|
157
|
+
where: {
|
|
158
|
+
sessionId,
|
|
159
|
+
method: "llm.stream",
|
|
160
|
+
OR: [{ status: "completed" }, { status: "uncertain", costEstimated: true }],
|
|
161
|
+
},
|
|
110
162
|
_sum: {
|
|
111
163
|
inputTokens: true,
|
|
112
164
|
outputTokens: true,
|
|
@@ -183,6 +235,7 @@ async function heldUsd(db, sessionId) {
|
|
|
183
235
|
SELECT COALESCE(SUM(
|
|
184
236
|
CASE
|
|
185
237
|
WHEN "status" = 'completed' THEN COALESCE("actualCostUsd", 0)
|
|
238
|
+
WHEN "status" = 'uncertain' AND "costEstimated" THEN COALESCE("actualCostUsd", 0)
|
|
186
239
|
WHEN "status" IN ('reserved', 'uncertain') THEN COALESCE("reservationUsd", 0)
|
|
187
240
|
ELSE 0
|
|
188
241
|
END
|
|
@@ -5,14 +5,9 @@
|
|
|
5
5
|
* shape a real transport has. For tests and local development; never a
|
|
6
6
|
* sandbox (the worker runs in the server's own process).
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { parseMessage, toGatewayError, WorkerInputSchema } from "./protocol.js";
|
|
9
9
|
import { runNativeWorker } from "./worker.js";
|
|
10
10
|
const wire = (value) => (value === undefined ? value : JSON.parse(JSON.stringify(value)));
|
|
11
|
-
function asGatewayError(err) {
|
|
12
|
-
if (err instanceof GatewayError)
|
|
13
|
-
return new GatewayError(err.code, err.message);
|
|
14
|
-
return new GatewayError("internal", err instanceof Error ? err.message : String(err));
|
|
15
|
-
}
|
|
16
11
|
export function createLoopbackTransport(gateway) {
|
|
17
12
|
return {
|
|
18
13
|
async call(request) {
|
|
@@ -20,7 +15,7 @@ export function createLoopbackTransport(gateway) {
|
|
|
20
15
|
return wire(await gateway.call(wire(request)));
|
|
21
16
|
}
|
|
22
17
|
catch (err) {
|
|
23
|
-
throw
|
|
18
|
+
throw toGatewayError(err);
|
|
24
19
|
}
|
|
25
20
|
},
|
|
26
21
|
async *stream(request) {
|
|
@@ -29,7 +24,7 @@ export function createLoopbackTransport(gateway) {
|
|
|
29
24
|
yield wire(event);
|
|
30
25
|
}
|
|
31
26
|
catch (err) {
|
|
32
|
-
throw
|
|
27
|
+
throw toGatewayError(err);
|
|
33
28
|
}
|
|
34
29
|
},
|
|
35
30
|
};
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Native sandbox worker process entry. Reads its WorkerInput as the first line
|
|
3
3
|
* on stdin, runs the run's engine against the gateway on stdin/stdout
|
|
4
4
|
* (stdio.ts), and exits 0 once it has sent its result. stdout carries only
|
|
5
|
-
* protocol frames; diagnostics (and the shared logger) go to stderr
|
|
5
|
+
* protocol frames; diagnostics (and the shared logger) go to stderr, without any secret value the
|
|
6
|
+
* worker received (stderr-redaction.ts).
|
|
6
7
|
*/
|
|
7
8
|
export {};
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Native sandbox worker process entry. Reads its WorkerInput as the first line
|
|
3
3
|
* on stdin, runs the run's engine against the gateway on stdin/stdout
|
|
4
4
|
* (stdio.ts), and exits 0 once it has sent its result. stdout carries only
|
|
5
|
-
* protocol frames; diagnostics (and the shared logger) go to stderr
|
|
5
|
+
* protocol frames; diagnostics (and the shared logger) go to stderr, without any secret value the
|
|
6
|
+
* worker received (stderr-redaction.ts).
|
|
6
7
|
*/
|
|
7
8
|
import { readFile, stat } from "node:fs/promises";
|
|
8
9
|
import { parseMessage, WorkerInputSchema } from "./protocol.js";
|
|
9
10
|
import { createHttpTransport } from "./http-transport.js";
|
|
10
11
|
import { createStdioTransport } from "./stdio.js";
|
|
12
|
+
import { flushStderrRedaction, installStderrRedaction, rememberSecretValue } from "./stderr-redaction.js";
|
|
11
13
|
import { WARM_WORKER_UNCLAIMED_EXIT } from "./warm-delivery.js";
|
|
12
14
|
import { runNativeWorker } from "./worker.js";
|
|
13
15
|
function firstLine() {
|
|
@@ -57,6 +59,8 @@ async function readInput() {
|
|
|
57
59
|
}
|
|
58
60
|
async function main() {
|
|
59
61
|
const input = parseMessage(await readInput(), WorkerInputSchema);
|
|
62
|
+
if (input.gateway)
|
|
63
|
+
rememberSecretValue(input.gateway.capability);
|
|
60
64
|
// The gateway answers only after the worker asks, so choosing the transport after the input
|
|
61
65
|
// line misses nothing.
|
|
62
66
|
const transport = input.gateway
|
|
@@ -64,11 +68,18 @@ async function main() {
|
|
|
64
68
|
: createStdioTransport(process.stdin, process.stdout);
|
|
65
69
|
await runNativeWorker(input, transport);
|
|
66
70
|
}
|
|
67
|
-
|
|
71
|
+
const fail = (err) => {
|
|
72
|
+
// Anything still buffered for its line's end goes out first, so the failure line stands alone.
|
|
73
|
+
flushStderrRedaction();
|
|
68
74
|
if (err instanceof UnclaimedError) {
|
|
69
75
|
process.stderr.write(`native sandbox worker: ${err.message}\n`);
|
|
70
76
|
process.exit(WARM_WORKER_UNCLAIMED_EXIT);
|
|
71
77
|
}
|
|
72
78
|
process.stderr.write(`native sandbox worker failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
73
79
|
process.exit(1);
|
|
74
|
-
}
|
|
80
|
+
};
|
|
81
|
+
installStderrRedaction();
|
|
82
|
+
// Node's own report of an uncaught error would bypass the redaction: fail the same way instead.
|
|
83
|
+
process.on("uncaughtException", fail);
|
|
84
|
+
process.on("unhandledRejection", fail);
|
|
85
|
+
main().then(() => process.exit(0), fail);
|