@wardby/cli 0.5.3 → 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/.env.example +33 -0
- package/README.md +25 -14
- package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
- package/dist/claude-coding-worker/context.d.ts +22 -0
- package/dist/claude-coding-worker/context.js +92 -0
- package/dist/claude-coding-worker/driver.d.ts +27 -3
- package/dist/claude-coding-worker/driver.js +161 -20
- package/dist/claude-coding-worker/main.js +34 -6
- package/dist/claude-coding-worker/sdk.js +25 -5
- 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 +6 -2
- package/dist/cli-native-mode.d.ts +9 -0
- package/dist/cli-native-mode.js +20 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +161 -11
- package/dist/coding/claude-context.d.ts +45 -0
- package/dist/coding/claude-context.js +434 -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/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 +50 -118
- package/dist/coding/profile.js +51 -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 +292 -270
- package/dist/coding/protocol.js +322 -15
- 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 +16 -3
- package/dist/coding-worker/artifact.js +5 -3
- 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 +118 -38
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/sdk.d.ts +6 -0
- package/dist/coding-worker/sdk.js +1 -0
- package/dist/coding-worker/skills.d.ts +23 -0
- package/dist/coding-worker/skills.js +117 -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 +13 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/github-allowed-accounts.d.ts +15 -0
- package/dist/config/github-allowed-accounts.js +36 -0
- package/dist/config/low-power.d.ts +12 -0
- package/dist/config/low-power.js +18 -0
- package/dist/config/mobile.d.ts +12 -0
- package/dist/config/mobile.js +18 -0
- package/dist/config/providers.d.ts +65 -3
- package/dist/config/providers.js +147 -11
- 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/db.d.ts +16 -6
- package/dist/core/db.js +12 -10
- 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 +53 -0
- package/dist/core/dispatch.js +167 -57
- package/dist/core/engine-native.js +10 -6
- 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 +67 -5
- package/dist/core/host-events.js +571 -37
- 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 +151 -20
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +16 -11
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +68 -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/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +130 -0
- package/dist/core/merge-order-check.js +343 -0
- package/dist/core/notification-dispatcher.d.ts +70 -0
- package/dist/core/notification-dispatcher.js +368 -0
- package/dist/core/notification-templates.d.ts +19 -0
- package/dist/core/notification-templates.js +139 -0
- package/dist/core/notifications.d.ts +10 -0
- package/dist/core/notifications.js +38 -0
- package/dist/core/pg-auth.d.ts +22 -0
- package/dist/core/pg-auth.js +152 -0
- package/dist/core/power-composition.d.ts +16 -0
- package/dist/core/power-composition.js +37 -0
- package/dist/core/power-idle.d.ts +14 -0
- package/dist/core/power-idle.js +30 -0
- package/dist/core/power.d.ts +71 -0
- package/dist/core/power.js +202 -0
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +8 -5
- package/dist/core/reconciler.js +37 -6
- package/dist/core/related-pull-requests.d.ts +59 -7
- package/dist/core/related-pull-requests.js +140 -25
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/repo-access.d.ts +15 -0
- package/dist/core/repo-access.js +66 -0
- package/dist/core/review-fix.d.ts +38 -1
- package/dist/core/review-fix.js +209 -7
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +23 -0
- package/dist/core/review-host-tools.js +156 -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 +384 -5
- package/dist/core/runner.js +1244 -372
- 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 +39 -0
- package/dist/core/secret-broker-config.js +112 -0
- 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/secrets.d.ts +39 -4
- package/dist/core/secrets.js +148 -40
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/workflow-event-recorder.d.ts +14 -0
- package/dist/core/workflow-event-recorder.js +120 -0
- package/dist/core/workflow-events.d.ts +94 -0
- package/dist/core/workflow-events.js +48 -0
- package/dist/core/workflow-run-events.d.ts +18 -0
- package/dist/core/workflow-run-events.js +75 -0
- 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 +92 -3
- package/dist/generated/prisma/client.d.ts +92 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +364 -54
- package/dist/generated/prisma/enums.d.ts +37 -0
- package/dist/generated/prisma/enums.js +31 -0
- package/dist/generated/prisma/internal/class.d.ts +132 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1332 -142
- package/dist/generated/prisma/internal/prismaNamespace.js +227 -5
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +234 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +227 -5
- package/dist/generated/prisma/models/Agent.d.ts +464 -7
- package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +301 -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 +1841 -1
- package/dist/generated/prisma/models/DeferredReview.d.ts +78 -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 +1713 -0
- package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1551 -0
- package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
- package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
- package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
- package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
- package/dist/generated/prisma/models/NotificationChannel.js +1 -0
- package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
- package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
- package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
- package/dist/generated/prisma/models/NotificationThread.js +1 -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/Run.d.ts +1619 -58
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
- 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 +37 -1
- package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
- package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
- package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
- package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
- package/dist/generated/prisma/models.d.ts +12 -0
- package/dist/help/build.js +4 -2
- package/dist/help/catalog.d.ts +1 -1
- package/dist/help/catalog.js +31 -6
- package/dist/help-index.json +2584 -146
- package/dist/import/create.js +49 -3
- package/dist/import/neutral-schema.d.ts +50 -277
- 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 +11 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/repo-authorization.js +14 -0
- package/dist/mcp/auth/resource-server.d.ts +2 -1
- package/dist/mcp/auth/resource-server.js +7 -2
- package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/browser.js +19 -6
- 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 +6 -0
- package/dist/mcp/host-events/github-ingress.d.ts +25 -1
- package/dist/mcp/host-events/github-ingress.js +70 -1
- package/dist/mcp/index.d.ts +19 -0
- package/dist/mcp/index.js +117 -20
- 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 +277 -24
- 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.d.ts +2 -0
- package/dist/mcp/tools/notification-channels.js +293 -0
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/power.d.ts +2 -0
- package/dist/mcp/tools/power.js +77 -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.d.ts +0 -6
- package/dist/mcp/tools/runs.js +41 -14
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
- package/dist/mcp/tools/secret-broker-compat.js +23 -0
- package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
- package/dist/mcp/tools/secret-elicitation-form.js +205 -10
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -54
- package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
- package/dist/mcp/tools/secret-elicitation.js +110 -12
- package/dist/mcp/tools/secrets.js +186 -9
- 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 +2 -2
- package/dist/mcp/tools/tools.js +47 -11
- 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/composition.d.ts +23 -0
- package/dist/native-worker/composition.js +77 -0
- package/dist/native-worker/docker-isolation.d.ts +65 -0
- package/dist/native-worker/docker-isolation.js +183 -0
- package/dist/native-worker/docker-launcher.d.ts +110 -0
- package/dist/native-worker/docker-launcher.js +297 -0
- package/dist/native-worker/gateway-server.d.ts +77 -0
- package/dist/native-worker/gateway-server.js +412 -0
- package/dist/native-worker/gateway.d.ts +70 -0
- package/dist/native-worker/gateway.js +263 -0
- package/dist/native-worker/http-server.d.ts +24 -0
- package/dist/native-worker/http-server.js +113 -0
- package/dist/native-worker/http-transport.d.ts +17 -0
- package/dist/native-worker/http-transport.js +88 -0
- package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
- package/dist/native-worker/kubernetes-isolation.js +218 -0
- package/dist/native-worker/kubernetes-launcher.d.ts +106 -0
- package/dist/native-worker/kubernetes-launcher.js +375 -0
- package/dist/native-worker/launch.d.ts +62 -0
- package/dist/native-worker/launch.js +49 -0
- package/dist/native-worker/ledger.d.ts +125 -0
- package/dist/native-worker/ledger.js +245 -0
- package/dist/native-worker/loopback.d.ts +12 -0
- package/dist/native-worker/loopback.js +44 -0
- package/dist/native-worker/main.d.ts +8 -0
- package/dist/native-worker/main.js +85 -0
- package/dist/native-worker/protocol.d.ts +296 -0
- package/dist/native-worker/protocol.js +246 -0
- package/dist/native-worker/sandbox-executor.d.ts +83 -0
- package/dist/native-worker/sandbox-executor.js +284 -0
- 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 +29 -0
- package/dist/native-worker/stdio.js +189 -0
- package/dist/native-worker/warm-delivery.d.ts +16 -0
- package/dist/native-worker/warm-delivery.js +33 -0
- package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
- package/dist/native-worker/warm-pool-ledger.js +73 -0
- package/dist/native-worker/warm-pool.d.ts +107 -0
- package/dist/native-worker/warm-pool.js +283 -0
- package/dist/native-worker/worker.d.ts +17 -0
- package/dist/native-worker/worker.js +141 -0
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/authorization-server.d.ts +3 -0
- package/dist/providers/auth/index.js +2 -0
- package/dist/providers/auth/self-hosted.d.ts +14 -2
- package/dist/providers/auth/self-hosted.js +54 -4
- package/dist/providers/chat/fake.d.ts +46 -0
- package/dist/providers/chat/fake.js +39 -0
- package/dist/providers/chat/index.d.ts +4 -0
- package/dist/providers/chat/index.js +8 -0
- package/dist/providers/chat/slack.d.ts +37 -0
- package/dist/providers/chat/slack.js +105 -0
- package/dist/providers/chat/types.d.ts +42 -0
- package/dist/providers/chat/types.js +19 -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/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 +36 -2
- package/dist/providers/engine/types.js +39 -0
- package/dist/providers/executor/composition.d.ts +31 -1
- package/dist/providers/executor/composition.js +81 -8
- package/dist/providers/executor/container.d.ts +385 -9
- package/dist/providers/executor/container.js +1234 -99
- 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 +91 -0
- package/dist/providers/executor/dbos.js +319 -26
- package/dist/providers/executor/deferred.d.ts +44 -0
- package/dist/providers/executor/deferred.js +100 -0
- 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 +39 -10
- package/dist/providers/executor/routing.js +77 -32
- package/dist/providers/executor/types.d.ts +25 -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 +29 -4
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +23 -2
- package/dist/providers/jobs/fake-kubernetes-api.js +45 -1
- package/dist/providers/jobs/kubernetes-api.d.ts +25 -1
- package/dist/providers/jobs/kubernetes-api.js +17 -0
- package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
- package/dist/providers/jobs/kubernetes-client.js +61 -3
- package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
- package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +23 -1
- package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
- package/dist/providers/jobs/kubernetes-platform.js +38 -1
- package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
- package/dist/providers/jobs/kubernetes-preflight.js +4 -2
- package/dist/providers/jobs/kubernetes.d.ts +42 -2
- package/dist/providers/jobs/kubernetes.js +178 -19
- package/dist/providers/jobs/metadata-probes.d.ts +11 -0
- package/dist/providers/jobs/metadata-probes.js +13 -0
- package/dist/providers/jobs/types.d.ts +42 -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 +39 -2
- package/dist/providers/review-host/github.js +274 -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 +157 -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 +246 -12
- package/dist/providers/vcs/github.js +521 -61
- 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 +21 -3
- package/dist/quickstart/coding-seed.js +283 -3
- package/dist/quickstart/images.d.ts +2 -0
- package/dist/quickstart/images.js +7 -1
- 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/brokered-fetch.d.ts +23 -0
- package/dist/sandbox/brokered-fetch.js +37 -0
- 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 +35 -0
- package/dist/sandbox/host-functions.js +150 -91
- package/dist/sandbox/prelude.js +7 -1
- package/dist/sandbox/run-in-sandbox.d.ts +19 -0
- package/dist/sandbox/run-in-sandbox.js +28 -10
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +3 -1
- package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
- package/dist/sandbox/secret-broker-sigv4.js +49 -0
- package/dist/sandbox/secret-broker.d.ts +34 -0
- package/dist/sandbox/secret-broker.js +161 -0
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/user-tool.d.ts +14 -0
- package/dist/sandbox/user-tool.js +32 -0
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +25 -0
- package/dist/viewer/api-schema.d.ts +372 -2454
- package/dist/viewer/api-schema.js +29 -0
- package/dist/viewer/build-schemas.js +10 -3
- package/dist/viewer/event-bus.d.ts +6 -0
- package/dist/viewer/event-bus.js +16 -7
- package/dist/viewer/graph.d.ts +5 -2
- package/dist/viewer/graph.js +7 -2
- package/dist/viewer/http.d.ts +0 -1
- package/dist/viewer/http.js +2 -2
- package/dist/viewer/infra.js +25 -2
- package/dist/viewer/limits.d.ts +4 -0
- package/dist/viewer/limits.js +4 -0
- package/dist/viewer/openapi.d.ts +15 -0
- package/dist/viewer/openapi.js +170 -0
- package/dist/wardby-bin.js +10 -0
- package/docs/README.md +7 -0
- package/docs/agent-recipes.md +114 -27
- package/docs/architecture-runtime.md +16 -1
- package/docs/code-review-agents.md +689 -45
- package/docs/coding-agent-setup.md +602 -12
- package/docs/coding-packages.md +1037 -92
- package/docs/coding-services.md +30 -13
- package/docs/coding-worker-byo-images.md +218 -6
- package/docs/coding-worker-isolation.md +173 -44
- package/docs/getting-started-gke.md +332 -129
- package/docs/getting-started-identity-provider.md +31 -11
- package/docs/getting-started.md +14 -4
- package/docs/jira-agents.md +22 -9
- 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 +731 -0
- package/docs/observability.md +4 -0
- package/docs/release-verification.md +9 -0
- package/docs/security-deployment.md +146 -14
- package/docs/slack-notifications.md +268 -0
- package/docs/tool-secrets.md +284 -0
- package/docs/viewer-api.md +46 -5
- package/docs/viewer-api.openapi.yml +1404 -0
- package/help/admin-viewer.md +29 -3
- package/help/agent-recipes.md +27 -0
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +79 -0
- package/help/build-claude-code-image.md +131 -0
- package/help/build-worker-image.md +6 -7
- package/help/builder-agent.md +19 -6
- package/help/code-review-agents.md +243 -10
- 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 +23 -9
- package/help/deployment-targets.md +25 -14
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-provider-not-configured.md +2 -2
- 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 +28 -0
- 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 +29 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/low-power-disabled.md +29 -0
- package/help/errors/low-power-scale-forbidden.md +35 -0
- package/help/errors/low-power-wake-timeout.md +30 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/mobile-disabled.md +31 -0
- package/help/errors/native-sandbox-capacity.md +22 -0
- package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
- package/help/errors/native-sandbox-docker-failed.md +20 -0
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
- package/help/errors/native-sandbox-image-not-pinned.md +19 -0
- package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +22 -0
- package/help/errors/native-sandbox-requires-catalog.md +31 -0
- package/help/errors/native-sandbox-unavailable.md +19 -0
- package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +21 -0
- package/help/errors/native-sandbox-worker-lost.md +20 -0
- package/help/errors/native-sandbox-worker-unready.md +22 -0
- 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-broker-body-invalid.md +26 -0
- package/help/errors/secret-broker-changed.md +20 -0
- package/help/errors/secret-broker-config-invalid.md +30 -0
- package/help/errors/secret-broker-conflict.md +27 -0
- package/help/errors/secret-broker-destination-denied.md +28 -0
- package/help/errors/secret-broker-value-invalid.md +28 -0
- package/help/errors/secret-brokered.md +24 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/secret-not-brokered.md +25 -0
- package/help/errors/slack-auth-failed.md +48 -0
- package/help/errors/slack-channel-unreachable.md +39 -0
- package/help/errors/slack-not-configured.md +33 -0
- package/help/errors/target-merge.md +40 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/getting-started.md +4 -5
- package/help/github-app-setup.md +132 -0
- package/help/github.md +40 -1
- package/help/identity-and-access.md +7 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +3 -4
- package/help/low-power-mode.md +131 -0
- package/help/merge-order-check.md +122 -0
- package/help/mobile-app.md +54 -0
- package/help/native-capabilities.md +29 -1
- package/help/native-sandbox.md +150 -0
- package/help/observability.md +8 -0
- package/help/operating-agents.md +5 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +80 -16
- package/help/repo-instructions-and-skills.md +91 -0
- package/help/resume-runs-locally.md +131 -0
- package/help/review-fix-rounds.md +43 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +76 -0
- 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 +99 -7
- package/package.json +27 -13
- package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
- package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
- package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
- package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
- package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
- package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
- package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
- package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
- package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
- package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
- package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
- package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
- package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
- package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
- 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 +631 -146
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type Readable } from "node:stream";
|
|
2
2
|
import type { KubernetesJobConfig } from "../../config/providers.js";
|
|
3
|
+
import { type Power } from "../../core/power.js";
|
|
3
4
|
import { type KubernetesApi } from "./kubernetes-api.js";
|
|
4
5
|
import { type ServiceStateReporter } from "./service-state.js";
|
|
5
6
|
import type { CodingProvider } from "../../coding/provider.js";
|
|
6
|
-
import type
|
|
7
|
+
import { type JobHandle, type JobResult, type JobSpec, type JobStatus, type WorkspaceJobLauncher } from "./types.js";
|
|
7
8
|
export interface KubernetesClusterInfo {
|
|
8
9
|
/** The proxy Service's ClusterIP: the enforcement witness's address (8787 reachable, 8788 not). */
|
|
9
10
|
proxyIp: string;
|
|
@@ -19,6 +20,11 @@ export interface KubernetesJobLauncherOptions {
|
|
|
19
20
|
* the gate probes the address `provision` re-reads for that launch, not this memoized one.
|
|
20
21
|
*/
|
|
21
22
|
preflight?: () => Promise<KubernetesClusterInfo | void>;
|
|
23
|
+
/**
|
|
24
|
+
* Low-power mode: `launch()` wakes the (possibly scaled-to-zero) coding proxy before its preflight,
|
|
25
|
+
* and `warmUp()` defers the preflight while the proxy is asleep. Default `DISABLED_POWER` (no-op).
|
|
26
|
+
*/
|
|
27
|
+
power?: Power;
|
|
22
28
|
now?: () => number;
|
|
23
29
|
sleep?: (milliseconds: number) => Promise<void>;
|
|
24
30
|
readyTimeoutMs?: number;
|
|
@@ -67,6 +73,7 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
|
|
|
67
73
|
/** Timeout of one streak exec: ENFORCEMENT_BLOCKED_STREAK probes plus the gaps between them. */
|
|
68
74
|
private readonly streakExecTimeoutMs;
|
|
69
75
|
private preflightResult?;
|
|
76
|
+
private readonly power;
|
|
70
77
|
constructor(options: KubernetesJobLauncherOptions);
|
|
71
78
|
/**
|
|
72
79
|
* Services run as native sidecars in the run pod (kubernetes-isolation.ts), for either provider:
|
|
@@ -94,7 +101,35 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
|
|
|
94
101
|
materializeWorkspace(handle: JobHandle, destination: string): Promise<void>;
|
|
95
102
|
stop(handle: JobHandle, _reason?: string): Promise<void>;
|
|
96
103
|
remove(handle: JobHandle): Promise<void>;
|
|
97
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* Low-power mode: whether the proxy is scaled to zero. A failed check is logged by code only (the
|
|
106
|
+
* leading reason code, else the error's class name -- never the raw message, which could carry
|
|
107
|
+
* cluster detail) and counts as awake, so warm-up runs the preflight as it would without the mode.
|
|
108
|
+
*/
|
|
109
|
+
private proxyAsleep;
|
|
110
|
+
/**
|
|
111
|
+
* Starts the memoized cluster preflight (`runPreflight`) right away, instead of waiting for the
|
|
112
|
+
* first `launch()`, so a long-running server process's own start-up pays the preflight's cost (a
|
|
113
|
+
* canary pod on `kind`: ~20s) rather than that process's first coding run. Never throws: it only
|
|
114
|
+
* reports the outcome (an info line on success, a warning naming the failure code otherwise) so
|
|
115
|
+
* an operator sees a misconfigured cluster at boot. Any `launch()` already awaiting this same
|
|
116
|
+
* attempt (concurrent with this call) still fails exactly as it does today when the preflight
|
|
117
|
+
* failed — it shares the same rejected promise. But unlike a preflight `launch()` starts on its
|
|
118
|
+
* own, a start-up failure here is **not** left stuck memoized: a transient cluster problem at
|
|
119
|
+
* process start must not fail every coding run until restart, so the failed attempt is cleared
|
|
120
|
+
* (only if nothing has already started a newer one — compared by identity, never by state) and
|
|
121
|
+
* the *next* `launch()` runs the preflight fresh. A successful warm-up stays memoized as always.
|
|
122
|
+
* In low-power mode, while the proxy is asleep, warm-up is skipped (the memo stays unset) rather
|
|
123
|
+
* than waking the proxy only for the preflight; the first `launch()` wakes it and runs the preflight.
|
|
124
|
+
*/
|
|
125
|
+
warmUp(): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Memoized: the preflight (or, without one, a single proxy-witness read) runs once per launcher —
|
|
128
|
+
* including its failure, which stays memoized and fails every subsequent `launch()` immediately,
|
|
129
|
+
* for a preflight `launch()` itself started (there was no `warmUp()`, or `warmUp()`'s own failed
|
|
130
|
+
* attempt was already cleared). `warmUp()` is the one caller that clears a failed attempt instead
|
|
131
|
+
* of leaving it stuck; see its own doc comment.
|
|
132
|
+
*/
|
|
98
133
|
private runPreflight;
|
|
99
134
|
/**
|
|
100
135
|
* Waits until the run's NetworkPolicy is enforced on this pod: the keeper (same network namespace
|
|
@@ -130,6 +165,10 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
|
|
|
130
165
|
* must not open the gate at the initial proof either.
|
|
131
166
|
*/
|
|
132
167
|
private waitForPolicyEnforcement;
|
|
168
|
+
/** True when `found` is a requeued record for this spec, which launch() replaces with a fresh one. */
|
|
169
|
+
private isRequeued;
|
|
170
|
+
/** Tells the operator once that a quota refused a pod while no quota is configured for the pre-launch check. */
|
|
171
|
+
private hintQuotaUnconfigured;
|
|
133
172
|
private existingLaunch;
|
|
134
173
|
private provision;
|
|
135
174
|
private createIfMissing;
|
|
@@ -143,6 +182,7 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
|
|
|
143
182
|
private refresh;
|
|
144
183
|
/** Reads only a fixed diagnostic code from a failed worker's bounded log tail; never keeps anything else. */
|
|
145
184
|
private readWorkerDiagnostic;
|
|
185
|
+
readTranscript(handle: JobHandle, maxBytes: number): Promise<string | undefined>;
|
|
146
186
|
private readResultArtifact;
|
|
147
187
|
/**
|
|
148
188
|
* Streams the keeper's workspace through the strict extractor into `staging`.
|
|
@@ -29,10 +29,11 @@ import { finished } from "node:stream/promises";
|
|
|
29
29
|
import { createHash } from "node:crypto";
|
|
30
30
|
import { isIP } from "node:net";
|
|
31
31
|
import { logger } from "../../core/logger.js";
|
|
32
|
-
import {
|
|
32
|
+
import { DISABLED_POWER, wakeTimeoutMs } from "../../core/power.js";
|
|
33
|
+
import { MAX_CODING_ARTIFACT_BYTES, MAX_CODING_INPUT_BYTES, MAX_DEBUG_TRACE_LINE_BYTES, parseCodingWorkerOutputJson, } from "../../coding/protocol.js";
|
|
33
34
|
import { CODING_PROXY_DENY_PORT, CODING_PROXY_PORT } from "./docker-isolation.js";
|
|
34
35
|
import { parseWorkerDiagnosticLine } from "./docker.js";
|
|
35
|
-
import { KubernetesAlreadyExistsError, KubernetesConflictError } from "./kubernetes-api.js";
|
|
36
|
+
import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesQuotaExceededError, } from "./kubernetes-api.js";
|
|
36
37
|
import { ENFORCEMENT_PROBE_DENY_REACHABLE, ENFORCEMENT_PROBE_PROVEN, ENFORCEMENT_PROBE_DENY_REFUSED, ENFORCEMENT_PROBE_PROXY_UNREACHABLE, KEEPER_CONTAINER, KEEPER_SEEDED_MARKER, KUBERNETES_ISOLATION_ERROR, STORAGE_ROOT, TOOL_RUNNER_CONTAINER, WORKER_CONTAINER, assertRunNetworkPolicyMatches, assertRunPodMatches, buildCapabilitySecret, buildRunNetworkPolicy, buildRunPod, enforcementStreakScript, kubernetesRunNames, kubernetesRunNamesForToken, runLabels, serviceContainerName, validateKubernetesSpec, } from "./kubernetes-isolation.js";
|
|
37
38
|
import { claudeToolSetup } from "./claude-tool-setup.js";
|
|
38
39
|
import { podQuotaUsage, quotaShortfall } from "./kubernetes-quota.js";
|
|
@@ -40,6 +41,7 @@ import { readProxyWitness } from "./kubernetes-witness.js";
|
|
|
40
41
|
import { safeExtract } from "./safe-extract.js";
|
|
41
42
|
import { reportServiceState, } from "./service-state.js";
|
|
42
43
|
import { serviceUnreadyError } from "../../coding/services/wording.js";
|
|
44
|
+
import { JobCapacityError, } from "./types.js";
|
|
43
45
|
import { replaceDirectoryFromStaging } from "./workspace-swap.js";
|
|
44
46
|
import { collectExclusions, normalizeCollectExclusions, tarExcludeArgs, } from "../../coding/collect-exclude.js";
|
|
45
47
|
const BACKEND = "kubernetes";
|
|
@@ -183,10 +185,22 @@ const TOKEN = /^[a-f0-9]{20}$/;
|
|
|
183
185
|
const WORKSPACE_STORAGE = `${STORAGE_ROOT}/workspace`;
|
|
184
186
|
const INPUT_STORAGE = `${STORAGE_ROOT}/input`;
|
|
185
187
|
const RESULT_PATH = `${STORAGE_ROOT}/output/result.json`;
|
|
188
|
+
const TRANSCRIPT_PATH = `${STORAGE_ROOT}/output/session.jsonl`;
|
|
186
189
|
/** Stands in for the proxy ClusterIP when building a pod only to count its resources. */
|
|
187
190
|
const QUOTA_PROBE_PROXY_IP = "10.0.0.1";
|
|
191
|
+
/** A Kubernetes object name (RFC 1123 subdomain). */
|
|
192
|
+
const DNS_1123_NAME = /^[a-z0-9]([-a-z0-9.]{0,251}[a-z0-9])?$/;
|
|
188
193
|
const kubernetesLog = logger.child({ module: "kubernetes-jobs" });
|
|
189
|
-
const PHASES = new Set([
|
|
194
|
+
const PHASES = new Set([
|
|
195
|
+
"provisioning",
|
|
196
|
+
"requeued",
|
|
197
|
+
"active",
|
|
198
|
+
"succeeded",
|
|
199
|
+
"failed",
|
|
200
|
+
"stopped",
|
|
201
|
+
"lost",
|
|
202
|
+
"removed",
|
|
203
|
+
]);
|
|
190
204
|
const TERMINAL_PHASES = new Set(["succeeded", "failed", "stopped", "lost", "removed"]);
|
|
191
205
|
// ---------------------------------------------------------------------------
|
|
192
206
|
// Pure helpers: the lifecycle rules.
|
|
@@ -205,6 +219,8 @@ function statusFor(record) {
|
|
|
205
219
|
switch (record.phase) {
|
|
206
220
|
case "provisioning":
|
|
207
221
|
return { state: "pending" };
|
|
222
|
+
case "requeued":
|
|
223
|
+
return { state: "pending", capacityRefused: true };
|
|
208
224
|
case "active":
|
|
209
225
|
return { state: "running" };
|
|
210
226
|
case "succeeded":
|
|
@@ -386,9 +402,11 @@ export class KubernetesJobLauncher {
|
|
|
386
402
|
/** Timeout of one streak exec: ENFORCEMENT_BLOCKED_STREAK probes plus the gaps between them. */
|
|
387
403
|
streakExecTimeoutMs;
|
|
388
404
|
preflightResult;
|
|
405
|
+
power;
|
|
389
406
|
constructor(options) {
|
|
390
407
|
this.options = options;
|
|
391
408
|
this.api = options.api;
|
|
409
|
+
this.power = options.power ?? DISABLED_POWER;
|
|
392
410
|
this.namespace = options.config.namespace;
|
|
393
411
|
this.workspaceRoot = resolve(options.workspaceRoot);
|
|
394
412
|
if (this.workspaceRoot === resolve("/"))
|
|
@@ -495,13 +513,19 @@ export class KubernetesJobLauncher {
|
|
|
495
513
|
this.warn(`kubernetes_spec_rejected: ${error.message}`);
|
|
496
514
|
throw error;
|
|
497
515
|
}
|
|
516
|
+
// Low-power mode: the proxy may be scaled to zero; wake it before the preflight reads it. Guarded
|
|
517
|
+
// (not just a no-op await) so mode off keeps launch() joining an in-flight warm-up synchronously.
|
|
518
|
+
if (this.power.enabled) {
|
|
519
|
+
await this.power.ensureAwake("proxy", { timeoutMs: wakeTimeoutMs(this.readyTimeoutMs), runId: spec.runId });
|
|
520
|
+
}
|
|
498
521
|
await this.runPreflight();
|
|
499
522
|
const names = kubernetesRunNames(spec.runId);
|
|
500
523
|
const handle = { backend: BACKEND, id: `${this.namespace}/${names.token}` };
|
|
501
524
|
const specHash = stableSpecHash(spec);
|
|
502
525
|
const existing = await this.readRecord(names);
|
|
503
|
-
if (existing)
|
|
526
|
+
if (existing && !this.isRequeued(existing, specHash)) {
|
|
504
527
|
return this.existingLaunch(existing.record, specHash, handle);
|
|
528
|
+
}
|
|
505
529
|
const createdAt = this.now();
|
|
506
530
|
const record = {
|
|
507
531
|
schemaVersion: RECORD_SCHEMA_VERSION,
|
|
@@ -513,22 +537,54 @@ export class KubernetesJobLauncher {
|
|
|
513
537
|
phase: "provisioning",
|
|
514
538
|
collectExclude: spec.collectExclude ?? collectExclusions([]),
|
|
515
539
|
};
|
|
516
|
-
|
|
517
|
-
//
|
|
518
|
-
|
|
540
|
+
if (existing) {
|
|
541
|
+
// Replaces the requeued record; a conflict means another replica got there first.
|
|
542
|
+
try {
|
|
543
|
+
await this.api.replaceConfigMap(this.namespace, names.record, this.recordConfigMap(names, record, existing.resourceVersion));
|
|
544
|
+
}
|
|
545
|
+
catch (error) {
|
|
546
|
+
if (!(error instanceof KubernetesConflictError))
|
|
547
|
+
throw error;
|
|
548
|
+
const raced = await this.readRecord(names);
|
|
549
|
+
if (!raced)
|
|
550
|
+
throw error;
|
|
551
|
+
if (!this.isRequeued(raced, specHash))
|
|
552
|
+
return this.existingLaunch(raced.record, specHash, handle);
|
|
553
|
+
// Requeued again by the other replica (its attempt was refused too): start over from that record.
|
|
554
|
+
return this.launch(spec);
|
|
555
|
+
}
|
|
519
556
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
557
|
+
else {
|
|
558
|
+
try {
|
|
559
|
+
// The record is the idempotency fence before any other cluster side effect. A quota refusing
|
|
560
|
+
// this create itself (a count/configmaps quota) is not a capacity refusal: it fails the run.
|
|
561
|
+
await this.api.createConfigMap(this.namespace, this.recordConfigMap(names, record));
|
|
562
|
+
}
|
|
563
|
+
catch (error) {
|
|
564
|
+
if (!(error instanceof KubernetesAlreadyExistsError))
|
|
565
|
+
throw error;
|
|
566
|
+
const raced = await this.readRecord(names);
|
|
567
|
+
if (!raced)
|
|
568
|
+
throw error;
|
|
569
|
+
if (!this.isRequeued(raced, specHash))
|
|
570
|
+
return this.existingLaunch(raced.record, specHash, handle);
|
|
571
|
+
// Another replica requeued it between our read and create: start over from the requeued record.
|
|
572
|
+
return this.launch(spec);
|
|
573
|
+
}
|
|
527
574
|
}
|
|
528
575
|
try {
|
|
529
576
|
await this.provision(spec, names, record);
|
|
530
577
|
}
|
|
531
578
|
catch (error) {
|
|
579
|
+
if (error instanceof KubernetesQuotaExceededError) {
|
|
580
|
+
// Capacity, not failure: leave a record a later launch() provisions afresh.
|
|
581
|
+
await this.updateRecord(names, () => ({ phase: "requeued" })).catch(() => undefined);
|
|
582
|
+
await this.cleanupRun(names, 0);
|
|
583
|
+
this.hintQuotaUnconfigured(error.quotaName);
|
|
584
|
+
throw new JobCapacityError("kubernetes_quota_exceeded: the namespace ResourceQuota has no room for this run", {
|
|
585
|
+
cause: error,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
532
588
|
// Record the failure before deleting the pod, so a replica that observes "no pod" in between
|
|
533
589
|
// can't record `lost` first and have this more specific outcome dropped.
|
|
534
590
|
await this.updateRecord(names, () => ({
|
|
@@ -618,7 +674,69 @@ export class KubernetesJobLauncher {
|
|
|
618
674
|
}
|
|
619
675
|
// -------------------------------------------------------------------------
|
|
620
676
|
// Launch
|
|
621
|
-
/**
|
|
677
|
+
/**
|
|
678
|
+
* Low-power mode: whether the proxy is scaled to zero. A failed check is logged by code only (the
|
|
679
|
+
* leading reason code, else the error's class name -- never the raw message, which could carry
|
|
680
|
+
* cluster detail) and counts as awake, so warm-up runs the preflight as it would without the mode.
|
|
681
|
+
*/
|
|
682
|
+
async proxyAsleep() {
|
|
683
|
+
try {
|
|
684
|
+
return await this.power.isAsleep("proxy");
|
|
685
|
+
}
|
|
686
|
+
catch (error) {
|
|
687
|
+
const code = (error instanceof Error && /^[a-z][a-z0-9_]*(?=:)/.exec(error.message)?.[0]) ||
|
|
688
|
+
(error instanceof Error ? error.name : "unknown");
|
|
689
|
+
this.warn(`kubernetes_preflight_power_check_failed: ${code}`);
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Starts the memoized cluster preflight (`runPreflight`) right away, instead of waiting for the
|
|
695
|
+
* first `launch()`, so a long-running server process's own start-up pays the preflight's cost (a
|
|
696
|
+
* canary pod on `kind`: ~20s) rather than that process's first coding run. Never throws: it only
|
|
697
|
+
* reports the outcome (an info line on success, a warning naming the failure code otherwise) so
|
|
698
|
+
* an operator sees a misconfigured cluster at boot. Any `launch()` already awaiting this same
|
|
699
|
+
* attempt (concurrent with this call) still fails exactly as it does today when the preflight
|
|
700
|
+
* failed — it shares the same rejected promise. But unlike a preflight `launch()` starts on its
|
|
701
|
+
* own, a start-up failure here is **not** left stuck memoized: a transient cluster problem at
|
|
702
|
+
* process start must not fail every coding run until restart, so the failed attempt is cleared
|
|
703
|
+
* (only if nothing has already started a newer one — compared by identity, never by state) and
|
|
704
|
+
* the *next* `launch()` runs the preflight fresh. A successful warm-up stays memoized as always.
|
|
705
|
+
* In low-power mode, while the proxy is asleep, warm-up is skipped (the memo stays unset) rather
|
|
706
|
+
* than waking the proxy only for the preflight; the first `launch()` wakes it and runs the preflight.
|
|
707
|
+
*/
|
|
708
|
+
async warmUp() {
|
|
709
|
+
if (this.power.enabled && (await this.proxyAsleep())) {
|
|
710
|
+
kubernetesLog.info("kubernetes_preflight_deferred: proxy asleep (low-power mode); the first coding run runs the preflight");
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
const attempt = this.runPreflight();
|
|
714
|
+
try {
|
|
715
|
+
await attempt;
|
|
716
|
+
kubernetesLog.info("kubernetes_preflight_warm_up_succeeded: cluster preflight passed at start-up");
|
|
717
|
+
}
|
|
718
|
+
catch (error) {
|
|
719
|
+
// Only clear the memo if it still holds this exact attempt: a concurrent launch() or warmUp()
|
|
720
|
+
// may have already seen this same rejection and started a fresh one (which must survive), and
|
|
721
|
+
// nothing else could have replaced this attempt with anything but a newer one, since
|
|
722
|
+
// runPreflight() never overwrites an already-set, still-pending-or-resolved promise.
|
|
723
|
+
if (this.preflightResult === attempt)
|
|
724
|
+
this.preflightResult = undefined;
|
|
725
|
+
// Same code-only convention as every other failure this launcher logs (e.g. launch()'s
|
|
726
|
+
// kubernetes_spec_rejected above): the error's own message is the fixed reason code set by
|
|
727
|
+
// runPreflight's errorWithCode (KUBERNETES_ISOLATION_ERROR) — never the raw cause, which could
|
|
728
|
+
// carry cluster detail.
|
|
729
|
+
const code = error instanceof Error ? error.message : String(error);
|
|
730
|
+
this.warn(`kubernetes_preflight_warm_up_failed: ${code}`);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Memoized: the preflight (or, without one, a single proxy-witness read) runs once per launcher —
|
|
735
|
+
* including its failure, which stays memoized and fails every subsequent `launch()` immediately,
|
|
736
|
+
* for a preflight `launch()` itself started (there was no `warmUp()`, or `warmUp()`'s own failed
|
|
737
|
+
* attempt was already cleared). `warmUp()` is the one caller that clears a failed attempt instead
|
|
738
|
+
* of leaving it stuck; see its own doc comment.
|
|
739
|
+
*/
|
|
622
740
|
runPreflight() {
|
|
623
741
|
this.preflightResult ??= (async () => {
|
|
624
742
|
try {
|
|
@@ -688,6 +806,22 @@ export class KubernetesJobLauncher {
|
|
|
688
806
|
await this.sleep(ENFORCEMENT_POLL_MS);
|
|
689
807
|
}
|
|
690
808
|
}
|
|
809
|
+
/** True when `found` is a requeued record for this spec, which launch() replaces with a fresh one. */
|
|
810
|
+
isRequeued(found, specHash) {
|
|
811
|
+
if (found.record.phase !== "requeued")
|
|
812
|
+
return false;
|
|
813
|
+
if (found.record.specHash !== specHash)
|
|
814
|
+
throw new Error("job_spec_conflict");
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
/** Tells the operator once that a quota refused a pod while no quota is configured for the pre-launch check. */
|
|
818
|
+
hintQuotaUnconfigured(refusedQuota) {
|
|
819
|
+
if (this.options.config.resourceQuota)
|
|
820
|
+
return;
|
|
821
|
+
const name = refusedQuota !== undefined && DNS_1123_NAME.test(refusedQuota) ? refusedQuota : undefined;
|
|
822
|
+
this.warnOnce(`kubernetes_resource_quota_unconfigured: a pod was refused by ${name ? `ResourceQuota ${name}` : "a ResourceQuota"}; ` +
|
|
823
|
+
`set KUBERNETES_RESOURCE_QUOTA=${name ?? "<name>"} and grant the launcher get on that ResourceQuota so runs wait before they start`);
|
|
824
|
+
}
|
|
691
825
|
existingLaunch(record, specHash, handle) {
|
|
692
826
|
if (record.specHash !== specHash)
|
|
693
827
|
throw new Error("job_spec_conflict");
|
|
@@ -862,14 +996,14 @@ export class KubernetesJobLauncher {
|
|
|
862
996
|
const staging = await mkdtemp(join(tmpdir(), "wardby-k8s-input-"));
|
|
863
997
|
try {
|
|
864
998
|
const source = await lstat(inputArtifact);
|
|
865
|
-
if (!source.isFile() || source.size >
|
|
999
|
+
if (!source.isFile() || source.size > MAX_CODING_INPUT_BYTES) {
|
|
866
1000
|
throw new Error("kubernetes_input_artifact_invalid");
|
|
867
1001
|
}
|
|
868
1002
|
const copy = join(staging, "input.json");
|
|
869
1003
|
await copyFile(inputArtifact, copy);
|
|
870
1004
|
// Re-check the copy: the source could have changed between lstat and copy.
|
|
871
1005
|
const copied = await lstat(copy);
|
|
872
|
-
if (!copied.isFile() || copied.size >
|
|
1006
|
+
if (!copied.isFile() || copied.size > MAX_CODING_INPUT_BYTES) {
|
|
873
1007
|
throw new Error("kubernetes_input_artifact_invalid");
|
|
874
1008
|
}
|
|
875
1009
|
await this.seedDirectory(names, staging, INPUT_STORAGE, timeoutMs);
|
|
@@ -887,7 +1021,8 @@ export class KubernetesJobLauncher {
|
|
|
887
1021
|
// Observation and collection
|
|
888
1022
|
/** Observes a non-terminal run against its pod and persists any transition; returns the stored record. */
|
|
889
1023
|
async refresh(names, record) {
|
|
890
|
-
|
|
1024
|
+
// A requeued run has no pod by design; observing it would record it lost.
|
|
1025
|
+
if (isTerminal(record.phase) || record.phase === "requeued")
|
|
891
1026
|
return record;
|
|
892
1027
|
const pod = await this.api.readPod(this.namespace, names.pod);
|
|
893
1028
|
const observed = observePod(pod, record, this.now(), this.readyTimeoutMs);
|
|
@@ -915,6 +1050,30 @@ export class KubernetesJobLauncher {
|
|
|
915
1050
|
}
|
|
916
1051
|
return undefined;
|
|
917
1052
|
}
|
|
1053
|
+
async readTranscript(handle, maxBytes) {
|
|
1054
|
+
const names = this.namesFor(handle);
|
|
1055
|
+
const found = names && (await this.readRecord(names));
|
|
1056
|
+
if (!names || !found)
|
|
1057
|
+
return undefined;
|
|
1058
|
+
const collector = new BoundedCollector(maxBytes);
|
|
1059
|
+
let exitCode;
|
|
1060
|
+
try {
|
|
1061
|
+
exitCode = await this.api.exec(this.namespace, names.pod, KEEPER_CONTAINER, ["head", "-c", String(maxBytes + 1), TRANSCRIPT_PATH], { stdout: collector, timeoutMs: SHORT_EXEC_TIMEOUT_MS });
|
|
1062
|
+
if (!collector.writableEnded)
|
|
1063
|
+
collector.end();
|
|
1064
|
+
await finished(collector);
|
|
1065
|
+
}
|
|
1066
|
+
catch {
|
|
1067
|
+
// The pod is gone (a stopped run) or unreachable: there is nothing to collect.
|
|
1068
|
+
collector.destroy();
|
|
1069
|
+
return undefined;
|
|
1070
|
+
}
|
|
1071
|
+
if (exitCode !== 0)
|
|
1072
|
+
return undefined;
|
|
1073
|
+
if (collector.exceeded)
|
|
1074
|
+
throw new Error("transcript_too_large");
|
|
1075
|
+
return collector.text();
|
|
1076
|
+
}
|
|
918
1077
|
async readResultArtifact(names, runId) {
|
|
919
1078
|
const collector = new BoundedCollector(MAX_CODING_ARTIFACT_BYTES);
|
|
920
1079
|
let raw;
|
|
@@ -935,7 +1094,7 @@ export class KubernetesJobLauncher {
|
|
|
935
1094
|
}
|
|
936
1095
|
let output;
|
|
937
1096
|
try {
|
|
938
|
-
output =
|
|
1097
|
+
output = parseCodingWorkerOutputJson(raw);
|
|
939
1098
|
}
|
|
940
1099
|
catch (error) {
|
|
941
1100
|
throw errorWithCode("kubernetes_result_artifact_invalid", error);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud metadata endpoints a coding or native worker pod must never reach: they hand out node or
|
|
3
|
+
* workload credentials. The instance metadata service (GCE, EC2 IPv4), the EKS Pod Identity agent (IPv4
|
|
4
|
+
* and IPv6), and EC2's IPv6 IMDS endpoint. Probed on port 80, where every one of them serves. A pod without
|
|
5
|
+
* IPv6 fails the last connect immediately, which counts as unreachable — correct either way.
|
|
6
|
+
* src/sandbox/fetch-policy.ts blocks the same addresses for in-process fetches.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CLOUD_METADATA_PROBES: readonly {
|
|
9
|
+
host: string;
|
|
10
|
+
port: number;
|
|
11
|
+
}[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud metadata endpoints a coding or native worker pod must never reach: they hand out node or
|
|
3
|
+
* workload credentials. The instance metadata service (GCE, EC2 IPv4), the EKS Pod Identity agent (IPv4
|
|
4
|
+
* and IPv6), and EC2's IPv6 IMDS endpoint. Probed on port 80, where every one of them serves. A pod without
|
|
5
|
+
* IPv6 fails the last connect immediately, which counts as unreachable — correct either way.
|
|
6
|
+
* src/sandbox/fetch-policy.ts blocks the same addresses for in-process fetches.
|
|
7
|
+
*/
|
|
8
|
+
export const CLOUD_METADATA_PROBES = Object.freeze([
|
|
9
|
+
Object.freeze({ host: "169.254.169.254", port: 80 }),
|
|
10
|
+
Object.freeze({ host: "169.254.170.23", port: 80 }),
|
|
11
|
+
Object.freeze({ host: "fd00:ec2::254", port: 80 }),
|
|
12
|
+
Object.freeze({ host: "fd00:ec2::23", port: 80 }),
|
|
13
|
+
]);
|
|
@@ -21,6 +21,14 @@ export interface JobSpec {
|
|
|
21
21
|
/** Required only for Claude's credential-free repository tool container. */
|
|
22
22
|
toolImage?: string;
|
|
23
23
|
inputArtifact: string;
|
|
24
|
+
/** Set only when the run's dependency cache is on (CodingRun.dependencyCache); absent otherwise, never false. */
|
|
25
|
+
dependencyCache?: true;
|
|
26
|
+
/**
|
|
27
|
+
* Claude Code only, set only when the run keeps its session (CodingRun.sessionResume); absent otherwise,
|
|
28
|
+
* never false. The worker's SDK config dir, where the session file grows, gets its own size-limited
|
|
29
|
+
* scratch so a long session never fills the worker's shared /tmp.
|
|
30
|
+
*/
|
|
31
|
+
sessionResume?: true;
|
|
24
32
|
timeoutSec: number;
|
|
25
33
|
limits: JobResourceLimits;
|
|
26
34
|
labels: Record<string, string>;
|
|
@@ -42,6 +50,12 @@ export interface JobHandle {
|
|
|
42
50
|
}
|
|
43
51
|
export type JobStatus = {
|
|
44
52
|
state: "pending" | "running";
|
|
53
|
+
/**
|
|
54
|
+
* Only ever on `pending`: the backend refused this job's launch for capacity (JobCapacityError)
|
|
55
|
+
* and nothing of it is running, nor will it start on its own. A caller that finds its job so
|
|
56
|
+
* may return the run to its queue and later `launch` the same spec again.
|
|
57
|
+
*/
|
|
58
|
+
capacityRefused?: true;
|
|
45
59
|
} | {
|
|
46
60
|
state: "succeeded";
|
|
47
61
|
} | {
|
|
@@ -61,11 +75,24 @@ export interface JobResult {
|
|
|
61
75
|
/** Output-schema failure locations (`path:code`) that passed SAFE_CODING_OUTPUT_ISSUE; never values. */
|
|
62
76
|
diagnosticIssues?: string[];
|
|
63
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* The backend has no room for this job right now (Kubernetes: the namespace ResourceQuota). No
|
|
80
|
+
* workload of the job is left running; the backend may keep a record of the refusal (Kubernetes
|
|
81
|
+
* does: its run record, which `status` then reports as `pending` with `capacityRefused`). The
|
|
82
|
+
* caller may launch the same spec again later.
|
|
83
|
+
*/
|
|
84
|
+
export declare class JobCapacityError extends Error {
|
|
85
|
+
readonly code = "coding_capacity_exceeded";
|
|
86
|
+
constructor(message: string, options?: ErrorOptions);
|
|
87
|
+
}
|
|
64
88
|
/**
|
|
65
89
|
* Lifecycle invariants implemented by every launcher:
|
|
66
90
|
*
|
|
67
91
|
* - `launch` is idempotent by runId for an identical spec and rejects a
|
|
68
92
|
* different spec for the same runId.
|
|
93
|
+
* - `launch` may reject with JobCapacityError when the backend has no room for
|
|
94
|
+
* the job; nothing of it is then left running, and a later `launch` of the
|
|
95
|
+
* same spec provisions it afresh.
|
|
69
96
|
* - pending may become running or terminal; running may become terminal;
|
|
70
97
|
* terminal states never change.
|
|
71
98
|
* - `collect` is repeatable for a terminal job until `remove` succeeds.
|
|
@@ -88,9 +115,24 @@ export interface JobLauncher {
|
|
|
88
115
|
* itself stays the authority.
|
|
89
116
|
*/
|
|
90
117
|
hasCapacityFor?: (spec: JobSpec) => Promise<boolean>;
|
|
118
|
+
/**
|
|
119
|
+
* Starts any one-time start-up check (e.g. Kubernetes's memoized cluster preflight) right away,
|
|
120
|
+
* instead of waiting for the first `launch()`. Never throws — a failure is only logged — and
|
|
121
|
+
* `launch()` still runs and reports the same check itself, memoized exactly as if this had never
|
|
122
|
+
* been called. Composition roots call this, fire-and-forget, only from a long-running server
|
|
123
|
+
* process's own start-up (`wardby serve`, the MCP server, `wardby scheduler`); never from a
|
|
124
|
+
* one-shot CLI command. Absent on a launcher with nothing to warm up (e.g. Docker).
|
|
125
|
+
*/
|
|
126
|
+
warmUp?: () => Promise<void>;
|
|
91
127
|
launch: (spec: JobSpec) => Promise<JobHandle>;
|
|
92
128
|
status: (handle: JobHandle) => Promise<JobStatus>;
|
|
93
129
|
collect: (handle: JobHandle) => Promise<JobResult>;
|
|
130
|
+
/**
|
|
131
|
+
* The run's session transcript file (the worker's session.jsonl), at most `maxBytes`; undefined
|
|
132
|
+
* when there is none or the job's storage is gone (a stopped job). Throws `transcript_too_large`
|
|
133
|
+
* when larger. Never cached in the job record: it is not redacted yet. Call before `remove`.
|
|
134
|
+
*/
|
|
135
|
+
readTranscript?: (handle: JobHandle, maxBytes: number) => Promise<string | undefined>;
|
|
94
136
|
stop: (handle: JobHandle, reason?: string) => Promise<void>;
|
|
95
137
|
remove: (handle: JobHandle) => Promise<void>;
|
|
96
138
|
}
|
|
@@ -3,4 +3,16 @@
|
|
|
3
3
|
* values are carried in a versioned input artifact, never expanded into an
|
|
4
4
|
* arbitrary environment map or shell command.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The backend has no room for this job right now (Kubernetes: the namespace ResourceQuota). No
|
|
8
|
+
* workload of the job is left running; the backend may keep a record of the refusal (Kubernetes
|
|
9
|
+
* does: its run record, which `status` then reports as `pending` with `capacityRefused`). The
|
|
10
|
+
* caller may launch the same spec again later.
|
|
11
|
+
*/
|
|
12
|
+
export class JobCapacityError extends Error {
|
|
13
|
+
code = "coding_capacity_exceeded";
|
|
14
|
+
constructor(message, options) {
|
|
15
|
+
super(message, options);
|
|
16
|
+
this.name = "JobCapacityError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import Anthropic from "@anthropic-ai/sdk";
|
|
8
8
|
import { ClaudeLlmProvider } from "./claude-provider.js";
|
|
9
|
+
import { simulatorModelClientOptions } from "../../config/test-simulators.js";
|
|
9
10
|
export function anthropicCredentialsPresent(env = process.env) {
|
|
10
11
|
return Boolean(env.ANTHROPIC_API_KEY);
|
|
11
12
|
}
|
|
@@ -14,6 +15,9 @@ export class AnthropicLlmProvider extends ClaudeLlmProvider {
|
|
|
14
15
|
if (!client && !apiKey) {
|
|
15
16
|
throw new Error("ANTHROPIC_API_KEY is not set — required by the Anthropic LlmProvider adapter.");
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
+
// WARDBY_TEST_SIMULATORS (test only): the scripted model, with a placeholder key the
|
|
19
|
+
// credential-free fetch drops; the real key never goes there.
|
|
20
|
+
const simulator = client ? null : simulatorModelClientOptions("anthropic");
|
|
21
|
+
super(client ?? new Anthropic(simulator ?? { apiKey }), lookup);
|
|
18
22
|
}
|
|
19
23
|
}
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bedrock-Claude adapter for the LlmProvider seam. `@anthropic-ai/bedrock-sdk`
|
|
3
|
-
* is imported only here; all protocol/pricing-dispatch logic lives in the
|
|
4
|
-
* shared ClaudeLlmProvider base class (claude-provider.ts) — AnthropicBedrock
|
|
5
|
-
* exposes the identical .messages.stream() surface as @anthropic-ai/sdk, so
|
|
6
|
-
* this file's only job is constructing the right client.
|
|
7
|
-
*
|
|
8
|
-
* Named BedrockClaudeLlmProvider, not BedrockLlmProvider: Bedrock hosts
|
|
9
|
-
* multiple model vendors, and this adapter only ever speaks the
|
|
10
|
-
* Anthropic-native protocol for Claude models. A future non-Claude Bedrock
|
|
11
|
-
* adapter gets its own name, not a rename of this one.
|
|
12
|
-
*/
|
|
13
1
|
import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
|
|
14
2
|
import { ClaudeLlmProvider } from "./claude-provider.js";
|
|
15
3
|
import type { CatalogLookup } from "./catalog-lookup.js";
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* Anthropic-native protocol for Claude models. A future non-Claude Bedrock
|
|
11
11
|
* adapter gets its own name, not a rename of this one.
|
|
12
12
|
*/
|
|
13
|
+
import { refuseBedrockUnderTestSimulators } from "../../config/test-simulators.js";
|
|
13
14
|
import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
|
|
14
15
|
import { ClaudeLlmProvider } from "./claude-provider.js";
|
|
15
16
|
export function bedrockCredentialsPresent(env = process.env) {
|
|
@@ -23,6 +24,9 @@ export class BedrockClaudeLlmProvider extends ClaudeLlmProvider {
|
|
|
23
24
|
if (!client && !region) {
|
|
24
25
|
throw new Error("BEDROCK_REGION (or AWS_REGION) is required by the Bedrock Claude LlmProvider adapter.");
|
|
25
26
|
}
|
|
27
|
+
// WARDBY_TEST_SIMULATORS (test only) refuses Bedrock: AWS-signed calls cannot go to the simulator.
|
|
28
|
+
if (!client)
|
|
29
|
+
refuseBedrockUnderTestSimulators();
|
|
26
30
|
super(client ?? new AnthropicBedrock({ awsRegion: region }), lookup);
|
|
27
31
|
}
|
|
28
32
|
}
|
|
@@ -106,5 +106,7 @@ export type ClaudeStreamEvent = {
|
|
|
106
106
|
} | {
|
|
107
107
|
type: "message_stop";
|
|
108
108
|
};
|
|
109
|
-
export declare function mapClaudeStream(events: AsyncIterable<ClaudeStreamEvent>, priceUsd: (usage: LlmUsage) => number
|
|
109
|
+
export declare function mapClaudeStream(events: AsyncIterable<ClaudeStreamEvent>, priceUsd: (usage: LlmUsage) => number,
|
|
110
|
+
/** Called at message_start: the response has started, and output may be billed from here on. */
|
|
111
|
+
onResponseStarted?: () => void): AsyncIterable<LlmStreamEvent>;
|
|
110
112
|
export {};
|
|
@@ -98,7 +98,9 @@ export function withCacheBreakpoints(req) {
|
|
|
98
98
|
});
|
|
99
99
|
return { ...req, ...(system ? { system } : {}), messages };
|
|
100
100
|
}
|
|
101
|
-
export async function* mapClaudeStream(events, priceUsd
|
|
101
|
+
export async function* mapClaudeStream(events, priceUsd,
|
|
102
|
+
/** Called at message_start: the response has started, and output may be billed from here on. */
|
|
103
|
+
onResponseStarted) {
|
|
102
104
|
const toolBuffers = new Map();
|
|
103
105
|
let start = {};
|
|
104
106
|
let outputTokens = 0;
|
|
@@ -106,6 +108,7 @@ export async function* mapClaudeStream(events, priceUsd) {
|
|
|
106
108
|
for await (const ev of events) {
|
|
107
109
|
switch (ev.type) {
|
|
108
110
|
case "message_start":
|
|
111
|
+
onResponseStarted?.();
|
|
109
112
|
start = ev.message.usage ?? {};
|
|
110
113
|
outputTokens = ev.message.usage?.output_tokens ?? 0;
|
|
111
114
|
break;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* stays exactly what each concrete adapter (anthropic.ts, bedrock.ts) has in
|
|
6
6
|
* common, and nothing more.
|
|
7
7
|
*/
|
|
8
|
-
import type { LlmMessage, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
|
|
8
|
+
import type { LlmMessage, LlmRequest, LlmStreamEvent, LlmStreamHooks, LlmToolDef } from "./types.js";
|
|
9
9
|
import { type CatalogLookup } from "./catalog-lookup.js";
|
|
10
10
|
import type { CatalogEntry } from "./catalog-types.js";
|
|
11
11
|
import type { CatalogLlmAdapter } from "./routing.js";
|
|
@@ -27,7 +27,7 @@ export declare class ClaudeLlmProvider implements CatalogLlmAdapter {
|
|
|
27
27
|
private readonly lookup;
|
|
28
28
|
constructor(client: ClaudeMessagesClient, lookup?: CatalogLookup);
|
|
29
29
|
withEntry(entry: CatalogEntry): ClaudeLlmProvider;
|
|
30
|
-
stream(req: LlmRequest, signal?: AbortSignal): AsyncIterable<LlmStreamEvent>;
|
|
30
|
+
stream(req: LlmRequest, signal?: AbortSignal, hooks?: LlmStreamHooks): AsyncIterable<LlmStreamEvent>;
|
|
31
31
|
countTokens(model: string, messages: LlmMessage[], tools?: LlmToolDef[]): Promise<number>;
|
|
32
32
|
priceUsd(model: string, usage: {
|
|
33
33
|
inputTokens: number;
|
|
@@ -21,14 +21,14 @@ export class ClaudeLlmProvider {
|
|
|
21
21
|
withEntry(entry) {
|
|
22
22
|
return new ClaudeLlmProvider(this.client, pinnedLookup(entry));
|
|
23
23
|
}
|
|
24
|
-
async *stream(req, signal) {
|
|
24
|
+
async *stream(req, signal, hooks) {
|
|
25
25
|
// Defence in depth behind config-time validation: a level the model
|
|
26
26
|
// doesn't accept would fail the whole call, so it is dropped here.
|
|
27
27
|
const { effort, ...rest } = req;
|
|
28
28
|
const accepted = effort && this.lookup(req.model).efforts.includes(effort);
|
|
29
29
|
const claudeReq = withCacheBreakpoints(toClaudeRequest(accepted ? { ...rest, effort } : rest, DEFAULT_MAX_TOKENS));
|
|
30
30
|
const raw = this.client.messages.stream({ model: req.model, ...claudeReq }, { signal });
|
|
31
|
-
yield* mapClaudeStream(raw, (usage) => this.priceUsd(req.model, usage));
|
|
31
|
+
yield* mapClaudeStream(raw, (usage) => this.priceUsd(req.model, usage), hooks?.onResponseStarted);
|
|
32
32
|
}
|
|
33
33
|
async countTokens(model, messages, tools) {
|
|
34
34
|
this.lookup(model); // fail-closed on a model the catalog does not serve
|