deepline 0.3.89 → 0.3.91
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/contracts/install-commands.json +29 -0
- package/dist/bundling-sources/sdk/src/client.ts +221 -43
- package/dist/bundling-sources/sdk/src/index.ts +4 -0
- package/dist/bundling-sources/sdk/src/monitor-fleet-contract.ts +2 -556
- package/dist/bundling-sources/sdk/src/monitor-fleets.ts +2 -2
- package/dist/bundling-sources/sdk/src/pagination.ts +25 -0
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +11 -9
- package/dist/bundling-sources/sdk/src/types.ts +29 -1
- package/dist/bundling-sources/shared_libs/integration-contracts/monitor-fleet-contract.ts +549 -0
- package/dist/bundling-sources/shared_libs/monitors/analytics-public.ts +10 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/errors.ts +96 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/limits.ts +8 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/plan.ts +320 -0
- package/dist/bundling-sources/shared_libs/monitors/fleets/verdict.ts +106 -0
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +8 -1
- package/dist/bundling-sources/shared_libs/monitors/inbound-queue.ts +4 -4
- package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +59 -0
- package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +7 -9
- package/dist/bundling-sources/shared_libs/monitors/monitor-fleet-limits.ts +2 -12
- package/dist/bundling-sources/shared_libs/monitors/package.json +113 -4
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +56 -9
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-consumer-health.ts +2 -2
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +2 -2
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-public-aliases.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +245 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-message.ts +38 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-ack-probe.ts +94 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-delivery.ts +60 -0
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue.ts +60 -0
- package/dist/bundling-sources/shared_libs/monitors/snitcher-install-validation.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/snitcher-ip2company.ts +2 -2
- package/dist/bundling-sources/shared_libs/monitors/snitcher-radar.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/tracking-provider-integrations.ts +1 -1
- package/dist/bundling-sources/shared_libs/observability/build-context.ts +13 -0
- package/dist/bundling-sources/shared_libs/observability/log-metadata.ts +160 -0
- package/dist/bundling-sources/shared_libs/observability/request-context.ts +68 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +690 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +35 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/neon-constants.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +272 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +46 -1
- package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-runtime/async-play-invocation.ts +0 -1
- package/dist/bundling-sources/shared_libs/play-runtime/bounceban-batching.ts +137 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +779 -140
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +46 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-payload-contract.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +103 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +725 -0
- package/dist/bundling-sources/shared_libs/play-runtime/db-session-lease-store.ts +578 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +521 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-receipt-gateway.ts +1378 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/runtime-topology.ts +1024 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-gateway-route-probe.ts +193 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machine-lifecycle.ts +104 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +1844 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/process-tree.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-drain.ts +262 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-surface.ts +98 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +303 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-tuple-publication-guardian.ts +70 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-tuple-recovery.ts +519 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/vercel-fly-rollback-alignment.ts +280 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/vercel-production-gate.ts +159 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +29 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +23 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-invocation-fence.ts +442 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-protocol.ts +3 -3
- package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +18 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +66 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +145 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/memory-store.ts +114 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/ports.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/postgres-store.ts +170 -0
- package/dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts +1322 -0
- package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +112 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +8 -0
- package/dist/bundling-sources/shared_libs/play-runtime/perf-trace.ts +127 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +24 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/index.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/job.ts +41 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/ports.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +54 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/contracts.ts +114 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/engine-suspension.ts +108 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/index.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/job.ts +97 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/ports.ts +104 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/postgres-fence-adapter.ts +263 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/worker-terminal-projection.ts +64 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/contracts.ts +29 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/index.ts +15 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/job.ts +65 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/ports.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/index.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +142 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/ports.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/postgres-adapter.ts +102 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +60 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/index.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +78 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +54 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +71 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +5 -8
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +3 -5
- package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +168 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +44 -5
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/child-play-resolver.ts +26 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +3662 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/progress-sidecar.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-deadline.ts +84 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +91 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +424 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +321 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +110 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +625 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +72 -9
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +6 -12
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +0 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +14 -44
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +103 -208
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-authority.ts +201 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-env.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +67 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-release-environment.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-contract.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-scheduler-topology.ts +14 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +108 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-deadline-reconciliation.ts +88 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +124 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-run-task.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +193 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-lifecycle.ts +269 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-suffix.ts +73 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +6642 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +897 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-metrics.ts +120 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +76 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +476 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +147 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/index.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/lazy.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/play-run-recovery.ts +98 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-budget-state.ts +260 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1416 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +1255 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +942 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +14636 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +888 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +355 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +46 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runner-push.ts +60 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-api-origin.ts +33 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-gateway-health.ts +64 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +835 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +1218 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-operation.ts +207 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-scheduler-schema.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-capacity.ts +123 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-launch-read-observability.ts +78 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/submit-admission.ts +169 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/terminal-contract.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-queue-metrics.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +249 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +296 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/native-batch.ts +3 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +20 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +60 -15
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +14 -1
- package/dist/bundling-sources/shared_libs/play-runtime/webhook-receipt-retry.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +165 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +15 -23
- package/dist/bundling-sources/shared_libs/play-runtime/workflow-executor-auth.ts +169 -0
- package/dist/bundling-sources/shared_libs/play-runtime/zerobounce-batching.ts +122 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/bundling/repository-adapter.ts +24 -0
- package/dist/bundling-sources/shared_libs/plays/child-run-projection.ts +174 -0
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/api-client.ts +267 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/control-plane-types.ts +73 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +162 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +87 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/source-file-path.ts +26 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/target-paths.ts +36 -0
- package/dist/bundling-sources/shared_libs/plays/deployment-status.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/docflow.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/launch/input-contract.ts +400 -0
- package/dist/bundling-sources/shared_libs/plays/launch/prepare.ts +96 -0
- package/dist/bundling-sources/shared_libs/plays/local-file-discovery.ts +385 -0
- package/dist/bundling-sources/shared_libs/plays/play-grep-search.ts +112 -0
- package/dist/bundling-sources/shared_libs/plays/play-reference.ts +117 -0
- package/dist/bundling-sources/shared_libs/plays/run-input-summary.ts +260 -0
- package/dist/bundling-sources/shared_libs/plays/run-summary-types.ts +49 -0
- package/dist/bundling-sources/shared_libs/plays/secrets/errors.ts +19 -0
- package/dist/bundling-sources/shared_libs/plays/share/copy.ts +271 -0
- package/dist/bundling-sources/shared_libs/plays/share/metrics.ts +140 -0
- package/dist/bundling-sources/shared_libs/plays/share/public-read-model.ts +86 -0
- package/dist/bundling-sources/shared_libs/plays/share/seo-quality.ts +181 -0
- package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +658 -0
- package/dist/bundling-sources/shared_libs/plays/share/types.ts +197 -0
- package/dist/bundling-sources/shared_libs/plays/sheet-filter.ts +347 -0
- package/dist/bundling-sources/shared_libs/plays/slack-hitl-timeout-error.ts +37 -0
- package/dist/bundling-sources/shared_libs/plays/standard-webhooks.ts +117 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +6 -1
- package/dist/bundling-sources/shared_libs/plays/status-result.ts +388 -0
- package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/transform-factor-structure.ts +377 -0
- package/dist/bundling-sources/shared_libs/plays/webhook-payload.ts +113 -0
- package/dist/bundling-sources/shared_libs/product-notifications/configuration.ts +7 -1
- package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +3 -2
- package/dist/bundling-sources/shared_libs/product-notifications/overflow.ts +18 -0
- package/dist/bundling-sources/shared_libs/product-notifications/rolling-limit.ts +24 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +624 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-payload.ts +140 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-transport.ts +75 -0
- package/dist/bundling-sources/shared_libs/runtime-env.ts +6 -0
- package/dist/bundling-sources/shared_libs/security/email-blacklist.ts +42 -0
- package/dist/bundling-sources/shared_libs/security/header-safe-env.ts +10 -3
- package/dist/bundling-sources/shared_libs/security/slack-sanitize.ts +133 -0
- package/dist/cli/getting-started.d.mts +52 -0
- package/dist/cli/getting-started.d.ts +52 -0
- package/dist/cli/getting-started.js +65 -0
- package/dist/cli/getting-started.mjs +36 -0
- package/dist/cli/index.d.mts +9 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +895 -407
- package/dist/cli/index.mjs +893 -414
- package/dist/{compiler-manifest-DsLbQaew.d.mts → compiler-manifest-x14KL83E.d.mts} +4 -2
- package/dist/{compiler-manifest-DsLbQaew.d.ts → compiler-manifest-x14KL83E.d.ts} +4 -2
- package/dist/index.d.mts +124 -154
- package/dist/index.d.ts +124 -154
- package/dist/index.js +132 -28
- package/dist/index.mjs +132 -28
- package/dist/install-integrity.json +182 -2
- package/dist/monitor-fleet-contract.d.mts +131 -0
- package/dist/monitor-fleet-contract.d.ts +131 -0
- package/dist/monitor-fleet-contract.js +406 -0
- package/dist/monitor-fleet-contract.mjs +367 -0
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/release.d.mts +255 -0
- package/dist/release.d.ts +255 -0
- package/dist/release.js +210 -0
- package/dist/release.mjs +183 -0
- package/package.json +21 -4
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { PlayRunnerEvent } from '../protocol';
|
|
2
|
+
|
|
3
|
+
export const PLAY_RUNNER_STDOUT_EVENT_MODE_ENV =
|
|
4
|
+
'DEEPLINE_PLAY_RUNNER_STDOUT_EVENT_MODE';
|
|
5
|
+
|
|
6
|
+
export const PLAY_RUNNER_STDOUT_EVENT_MODE_COMPACT = 'compact';
|
|
7
|
+
|
|
8
|
+
const PROGRESS_SIDECAR_LOG_PATTERNS = [
|
|
9
|
+
/Starting map over \d+ items/i,
|
|
10
|
+
/Map completed:/i,
|
|
11
|
+
/\bBatch pass \d+/i,
|
|
12
|
+
/\bQueue depth before drain:/i,
|
|
13
|
+
/Executing tool batch/i,
|
|
14
|
+
/^\[perf\] runtime map /i,
|
|
15
|
+
/^\[perf\] runtime receipt /i,
|
|
16
|
+
/^\[perf\] runtime state(?:[ =])/i,
|
|
17
|
+
/^\[perf\]\[worker\.receipt_writer\.retry\] /i,
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
function shouldEmitProgressSidecarLog(line: string): boolean {
|
|
21
|
+
return PROGRESS_SIDECAR_LOG_PATTERNS.some((pattern) => pattern.test(line));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function shouldEmitProgressSidecarEvent(
|
|
25
|
+
event: PlayRunnerEvent,
|
|
26
|
+
): boolean {
|
|
27
|
+
if (event.type === 'execution_event') {
|
|
28
|
+
return event.event.type !== 'map.row.updated';
|
|
29
|
+
}
|
|
30
|
+
if (event.type === 'log') {
|
|
31
|
+
// Customer-authored ctx.log/console output is part of the run contract,
|
|
32
|
+
// not a diagnostic sample. Push every play line so detached runners have
|
|
33
|
+
// useful live logs; keep worker chatter sampled to the progress patterns.
|
|
34
|
+
return event.source === 'play' || shouldEmitProgressSidecarLog(event.line);
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function shouldEmitStdoutEvent(
|
|
40
|
+
event: PlayRunnerEvent,
|
|
41
|
+
mode = process.env[PLAY_RUNNER_STDOUT_EVENT_MODE_ENV]?.trim(),
|
|
42
|
+
): boolean {
|
|
43
|
+
if (mode !== PLAY_RUNNER_STDOUT_EVENT_MODE_COMPACT) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
return event.type === 'result';
|
|
47
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { PlayRunnerExecutionConfig } from '../protocol';
|
|
2
|
+
import {
|
|
3
|
+
STANDARD_PLAY_SANDBOX_RUNTIME_LIMITS,
|
|
4
|
+
validatePlaySandboxRuntimeLimits,
|
|
5
|
+
} from '../../plays/sandbox-runtime-limits';
|
|
6
|
+
|
|
7
|
+
export interface PlayRunnerRuntimeDeadlineOptions {
|
|
8
|
+
limitMs: number;
|
|
9
|
+
onDeadline: () => void | Promise<void>;
|
|
10
|
+
onError?: (error: unknown) => void;
|
|
11
|
+
setTimeoutImpl?: (callback: () => void, delayMs: number) => unknown;
|
|
12
|
+
clearTimeoutImpl?: (handle: unknown) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PlayRunnerRuntimeDeadlineHandle {
|
|
16
|
+
/** Claim normal settlement. False means the deadline already won. */
|
|
17
|
+
claimCompletion: () => boolean;
|
|
18
|
+
/** Settles only if the deadline callback unexpectedly returns or rejects. */
|
|
19
|
+
deadlineSettled: Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function startConfiguredPlayRunnerRuntimeDeadline(input: {
|
|
23
|
+
config: Pick<PlayRunnerExecutionConfig, 'context'>;
|
|
24
|
+
onDeadline: (runtimeLimitSeconds: number) => void | Promise<void>;
|
|
25
|
+
onError?: (error: unknown) => void;
|
|
26
|
+
setTimeoutImpl?: (callback: () => void, delayMs: number) => unknown;
|
|
27
|
+
clearTimeoutImpl?: (handle: unknown) => void;
|
|
28
|
+
}): PlayRunnerRuntimeDeadlineHandle {
|
|
29
|
+
const runtimeLimits = validatePlaySandboxRuntimeLimits(
|
|
30
|
+
input.config.context.sandboxRuntimeLimits ?? {
|
|
31
|
+
...STANDARD_PLAY_SANDBOX_RUNTIME_LIMITS,
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
const runtimeLimitSeconds = runtimeLimits.timeoutSeconds;
|
|
35
|
+
return startPlayRunnerRuntimeDeadline({
|
|
36
|
+
limitMs: runtimeLimitSeconds * 1_000,
|
|
37
|
+
onDeadline: () => input.onDeadline(runtimeLimitSeconds),
|
|
38
|
+
onError: input.onError,
|
|
39
|
+
setTimeoutImpl: input.setTimeoutImpl,
|
|
40
|
+
clearTimeoutImpl: input.clearTimeoutImpl,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enforce the user-code deadline inside the sandbox runner. Daytona's detached
|
|
46
|
+
* session has no asynchronous command timeout, so the parked worker's outer
|
|
47
|
+
* ceiling is only a salvage backstop and must not be the primary deadline.
|
|
48
|
+
*/
|
|
49
|
+
export function startPlayRunnerRuntimeDeadline(
|
|
50
|
+
options: PlayRunnerRuntimeDeadlineOptions,
|
|
51
|
+
): PlayRunnerRuntimeDeadlineHandle {
|
|
52
|
+
const limitMs = Math.max(1, Math.floor(options.limitMs));
|
|
53
|
+
const setTimeoutImpl =
|
|
54
|
+
options.setTimeoutImpl ??
|
|
55
|
+
((callback, delayMs) => setTimeout(callback, delayMs));
|
|
56
|
+
const clearTimeoutImpl =
|
|
57
|
+
options.clearTimeoutImpl ??
|
|
58
|
+
((handle) => clearTimeout(handle as ReturnType<typeof setTimeout>));
|
|
59
|
+
let fired = false;
|
|
60
|
+
let completionClaimed = false;
|
|
61
|
+
let settleDeadline = () => {};
|
|
62
|
+
const deadlineSettled = new Promise<void>((resolve) => {
|
|
63
|
+
settleDeadline = resolve;
|
|
64
|
+
});
|
|
65
|
+
const handle = setTimeoutImpl(() => {
|
|
66
|
+
if (fired || completionClaimed) return;
|
|
67
|
+
fired = true;
|
|
68
|
+
void Promise.resolve(options.onDeadline())
|
|
69
|
+
.catch((error) => {
|
|
70
|
+
options.onError?.(error);
|
|
71
|
+
})
|
|
72
|
+
.finally(() => settleDeadline());
|
|
73
|
+
}, limitMs);
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
claimCompletion: () => {
|
|
77
|
+
if (fired || completionClaimed) return false;
|
|
78
|
+
completionClaimed = true;
|
|
79
|
+
clearTimeoutImpl(handle);
|
|
80
|
+
return true;
|
|
81
|
+
},
|
|
82
|
+
deadlineSettled,
|
|
83
|
+
};
|
|
84
|
+
}
|
package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Privacy-safe runner-to-gateway evidence. Keep payloads, URLs, bearer tokens,
|
|
5
|
+
* response bodies, and raw error messages out of this shape: it is written to
|
|
6
|
+
* sandbox stderr and correlated with Fly gateway logs during an incident.
|
|
7
|
+
*/
|
|
8
|
+
export type RunnerGatewayTransportOperation =
|
|
9
|
+
| 'runner_heartbeat'
|
|
10
|
+
| 'runner_terminal';
|
|
11
|
+
|
|
12
|
+
export type RunnerGatewayTransportOutcome =
|
|
13
|
+
| 'ok'
|
|
14
|
+
| 'terminal'
|
|
15
|
+
| 'redirect'
|
|
16
|
+
| 'gateway_4xx'
|
|
17
|
+
| 'gateway_5xx'
|
|
18
|
+
| 'protocol_error'
|
|
19
|
+
| 'timeout'
|
|
20
|
+
| 'network_error';
|
|
21
|
+
|
|
22
|
+
export type RunnerGatewayTransportEvent = {
|
|
23
|
+
operation: RunnerGatewayTransportOperation;
|
|
24
|
+
attempt: number;
|
|
25
|
+
transportAttemptId: string;
|
|
26
|
+
durationMs: number;
|
|
27
|
+
outcome: RunnerGatewayTransportOutcome;
|
|
28
|
+
status?: number;
|
|
29
|
+
errorCode?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type RunnerGatewayTransportSummary = {
|
|
33
|
+
attempts: number;
|
|
34
|
+
last: RunnerGatewayTransportEvent;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const SAFE_ERROR_CODE = /^(?:E[A-Z0-9_]+|ERR_[A-Z0-9_]+|UND_ERR_[A-Z0-9_]+)$/;
|
|
38
|
+
const SAFE_ERROR_NAMES = new Set(['AbortError', 'TimeoutError', 'TypeError']);
|
|
39
|
+
|
|
40
|
+
export function createRunnerGatewayTransportAttemptId(): string {
|
|
41
|
+
return randomUUID();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Return a compact class/code without serializing untrusted error text. */
|
|
45
|
+
export function runnerGatewayTransportErrorCode(error: unknown): string {
|
|
46
|
+
const candidates: unknown[] = [error];
|
|
47
|
+
if (error && typeof error === 'object' && 'cause' in error) {
|
|
48
|
+
candidates.push((error as { cause?: unknown }).cause);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for (const candidate of candidates) {
|
|
52
|
+
if (!candidate || typeof candidate !== 'object') continue;
|
|
53
|
+
const code = (candidate as { code?: unknown }).code;
|
|
54
|
+
if (typeof code === 'string' && SAFE_ERROR_CODE.test(code)) return code;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const name = error instanceof Error ? error.name : '';
|
|
58
|
+
return SAFE_ERROR_NAMES.has(name) ? name : 'unknown';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function updateRunnerGatewayTransportSummary(
|
|
62
|
+
previous: RunnerGatewayTransportSummary | null,
|
|
63
|
+
event: RunnerGatewayTransportEvent,
|
|
64
|
+
): RunnerGatewayTransportSummary {
|
|
65
|
+
return {
|
|
66
|
+
attempts: (previous?.attempts ?? 0) + 1,
|
|
67
|
+
last: event,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** A safe, compact string suitable for the durable failed-run error. */
|
|
72
|
+
export function formatRunnerGatewayTransportSummary(
|
|
73
|
+
summary: RunnerGatewayTransportSummary | undefined,
|
|
74
|
+
): string {
|
|
75
|
+
if (!summary) return 'gateway_transport_evidence=unavailable';
|
|
76
|
+
const { last } = summary;
|
|
77
|
+
return [
|
|
78
|
+
`gateway_transport_attempts=${summary.attempts}`,
|
|
79
|
+
`gateway_transport_operation=${last.operation}`,
|
|
80
|
+
`gateway_transport_attempt=${last.attempt}`,
|
|
81
|
+
`gateway_transport_id=${last.transportAttemptId}`,
|
|
82
|
+
`gateway_transport_outcome=${last.outcome}`,
|
|
83
|
+
`gateway_transport_duration_ms=${last.durationMs}`,
|
|
84
|
+
...(last.status === undefined
|
|
85
|
+
? []
|
|
86
|
+
: [`gateway_transport_status=${last.status}`]),
|
|
87
|
+
...(last.errorCode
|
|
88
|
+
? [`gateway_transport_error_code=${last.errorCode}`]
|
|
89
|
+
: []),
|
|
90
|
+
].join(' ');
|
|
91
|
+
}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { RUNTIME_CLAIM_HEARTBEAT_DIVISOR } from '../runtime-constants';
|
|
2
|
+
import { PLAY_RUNTIME_TRANSPORT_ATTEMPT_HEADER } from '../runtime-contract';
|
|
3
|
+
import {
|
|
4
|
+
createRunnerGatewayTransportAttemptId,
|
|
5
|
+
runnerGatewayTransportErrorCode,
|
|
6
|
+
updateRunnerGatewayTransportSummary,
|
|
7
|
+
type RunnerGatewayTransportEvent,
|
|
8
|
+
type RunnerGatewayTransportSummary,
|
|
9
|
+
} from './runtime-gateway-transport';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Push-execution runner heartbeat loop (runs INSIDE the Daytona sandbox).
|
|
13
|
+
*
|
|
14
|
+
* B2-final park-and-wake: the worker PARKS after the detached start and holds
|
|
15
|
+
* no claim while the sandbox executes, so there is no lease to extend. The
|
|
16
|
+
* heartbeat is a liveness + CANCELLATION channel: it calls the receipt
|
|
17
|
+
* gateway's `runner_heartbeat` action on a
|
|
18
|
+
* `leaseSeconds / RUNTIME_CLAIM_HEARTBEAT_DIVISOR` cadence; the gateway bumps
|
|
19
|
+
* the attempt row's liveness timestamp and reads the play-level run status.
|
|
20
|
+
*
|
|
21
|
+
* The gateway response is the cancellation channel:
|
|
22
|
+
* - `{ ok: true, schedulerStatus }` -> run still live. Customer execution
|
|
23
|
+
* remains fenced until `schedulerStatus === "waiting"`, proving the worker
|
|
24
|
+
* durably parked after observing this runner's heartbeat.
|
|
25
|
+
* - `{ ok: false, terminal }` -> the run was cancelled/failed elsewhere; the
|
|
26
|
+
* runner must abort the same way the worker's CancelledTask path does. Inside
|
|
27
|
+
* the sandbox that means terminating the process loudly — the terminal is
|
|
28
|
+
* owned by the scheduler, never by a zombie runner.
|
|
29
|
+
*
|
|
30
|
+
* Reachability is bounded (FIX 5): a heartbeat that cannot reach the gateway
|
|
31
|
+
* for longer than one full lease window self-terminates the runner. An
|
|
32
|
+
* unreachable gateway also means receipts/tools/terminal-push are down — the
|
|
33
|
+
* run cannot make durable progress — and a cancelled run must never keep
|
|
34
|
+
* burning sandbox compute invisibly. The parked attempt's ceiling timeout +
|
|
35
|
+
* salvage then owns the outcome.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export type RunnerHeartbeatTerminal = 'cancelled' | 'failed' | 'completed';
|
|
39
|
+
|
|
40
|
+
export type RunnerHeartbeatResponse =
|
|
41
|
+
| {
|
|
42
|
+
ok: true;
|
|
43
|
+
schedulerStatus: 'queued' | 'running' | 'waiting';
|
|
44
|
+
}
|
|
45
|
+
| { ok: false; terminal: RunnerHeartbeatTerminal };
|
|
46
|
+
|
|
47
|
+
export type RunnerHeartbeatStop =
|
|
48
|
+
| { reason: 'terminal'; terminal: RunnerHeartbeatTerminal }
|
|
49
|
+
| {
|
|
50
|
+
reason: 'unreachable';
|
|
51
|
+
sinceMs: number;
|
|
52
|
+
lastError: string;
|
|
53
|
+
gatewayTransport?: RunnerGatewayTransportSummary;
|
|
54
|
+
}
|
|
55
|
+
| { reason: 'stopped' };
|
|
56
|
+
|
|
57
|
+
export interface RunnerHeartbeatLoopOptions {
|
|
58
|
+
gatewayBaseUrl: string;
|
|
59
|
+
executorToken: string;
|
|
60
|
+
runId: string;
|
|
61
|
+
leaseSeconds: number;
|
|
62
|
+
/**
|
|
63
|
+
* Invoked once when the loop decides the runner must self-terminate (terminal
|
|
64
|
+
* cancellation channel, or gateway unreachable past the lease window). The
|
|
65
|
+
* caller wires this to a loud process termination.
|
|
66
|
+
*/
|
|
67
|
+
onSelfTerminate: (stop: RunnerHeartbeatStop) => void;
|
|
68
|
+
/** Injectable for tests. Defaults to a bearer POST to the gateway. */
|
|
69
|
+
sendHeartbeat?: (input: {
|
|
70
|
+
gatewayBaseUrl: string;
|
|
71
|
+
executorToken: string;
|
|
72
|
+
runId: string;
|
|
73
|
+
leaseSeconds: number;
|
|
74
|
+
attempt?: number;
|
|
75
|
+
}) => Promise<RunnerHeartbeatResponse>;
|
|
76
|
+
/** Injectable timer for tests. Defaults to setInterval. */
|
|
77
|
+
setIntervalImpl?: (fn: () => void, ms: number) => { unref?: () => void };
|
|
78
|
+
clearIntervalImpl?: (handle: unknown) => void;
|
|
79
|
+
/** Injectable clock for tests. Defaults to Date.now. */
|
|
80
|
+
nowImpl?: () => number;
|
|
81
|
+
/** Injectable logger for tests. Defaults to console.warn. */
|
|
82
|
+
warn?: (message: string, detail: Record<string, unknown>) => void;
|
|
83
|
+
/** Receives privacy-safe sandbox-to-gateway transport evidence. */
|
|
84
|
+
onTransport?: (event: RunnerGatewayTransportEvent) => void;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface RunnerHeartbeatLoopHandle {
|
|
88
|
+
/** Stop the loop (called when execution settles normally). */
|
|
89
|
+
stop: () => void;
|
|
90
|
+
/**
|
|
91
|
+
* Resolves after the receipt gateway accepts the first heartbeat. Detached
|
|
92
|
+
* Daytona launch uses this as its handoff fence: the worker must not park
|
|
93
|
+
* until the runner can reach the durable control plane.
|
|
94
|
+
*/
|
|
95
|
+
firstHeartbeat: Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Resolves only after a heartbeat response proves the scheduler durably
|
|
98
|
+
* parked this attempt. Customer play execution must await this fence.
|
|
99
|
+
*/
|
|
100
|
+
executionAcknowledged: Promise<void>;
|
|
101
|
+
/** Trigger an immediate heartbeat while waiting for the park acknowledgement. */
|
|
102
|
+
requestHeartbeat: () => void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const APP_RUNTIME_COMPAT_PATH = '/api/v2/plays/runtime';
|
|
106
|
+
export const RUNNER_HEARTBEAT_REQUEST_TIMEOUT_MS = 10_000;
|
|
107
|
+
// The detached startup deadline is shorter than the normal 40s cadence.
|
|
108
|
+
// Retry initial transport failures while customer execution remains fenced.
|
|
109
|
+
const RUNNER_STARTUP_HEARTBEAT_INTERVAL_MS = 1_000;
|
|
110
|
+
|
|
111
|
+
export async function sendRunnerHeartbeat(
|
|
112
|
+
input: {
|
|
113
|
+
gatewayBaseUrl: string;
|
|
114
|
+
executorToken: string;
|
|
115
|
+
runId: string;
|
|
116
|
+
leaseSeconds: number;
|
|
117
|
+
attempt?: number;
|
|
118
|
+
},
|
|
119
|
+
options: {
|
|
120
|
+
fetchImpl?: typeof fetch;
|
|
121
|
+
timeoutMs?: number;
|
|
122
|
+
nowImpl?: () => number;
|
|
123
|
+
createTransportAttemptId?: () => string;
|
|
124
|
+
onTransport?: (event: RunnerGatewayTransportEvent) => void;
|
|
125
|
+
} = {},
|
|
126
|
+
): Promise<RunnerHeartbeatResponse> {
|
|
127
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
128
|
+
const now = options.nowImpl ?? Date.now;
|
|
129
|
+
const timeoutMs = Math.max(
|
|
130
|
+
1,
|
|
131
|
+
options.timeoutMs ?? RUNNER_HEARTBEAT_REQUEST_TIMEOUT_MS,
|
|
132
|
+
);
|
|
133
|
+
const controller = new AbortController();
|
|
134
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
135
|
+
const url = `${input.gatewayBaseUrl.replace(/\/$/, '')}${APP_RUNTIME_COMPAT_PATH}`;
|
|
136
|
+
const startedAt = now();
|
|
137
|
+
const transportAttemptId =
|
|
138
|
+
options.createTransportAttemptId?.() ??
|
|
139
|
+
createRunnerGatewayTransportAttemptId();
|
|
140
|
+
let transportReported = false;
|
|
141
|
+
const reportTransport = (
|
|
142
|
+
outcome: RunnerGatewayTransportEvent['outcome'],
|
|
143
|
+
detail: Pick<RunnerGatewayTransportEvent, 'status' | 'errorCode'> = {},
|
|
144
|
+
) => {
|
|
145
|
+
if (transportReported) return;
|
|
146
|
+
transportReported = true;
|
|
147
|
+
try {
|
|
148
|
+
options.onTransport?.({
|
|
149
|
+
operation: 'runner_heartbeat',
|
|
150
|
+
attempt: input.attempt ?? 1,
|
|
151
|
+
transportAttemptId,
|
|
152
|
+
durationMs: Math.max(0, now() - startedAt),
|
|
153
|
+
outcome,
|
|
154
|
+
...detail,
|
|
155
|
+
});
|
|
156
|
+
} catch {
|
|
157
|
+
// Diagnostics must never alter the runner's durable control path.
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
const response = await fetchImpl(url, {
|
|
162
|
+
method: 'POST',
|
|
163
|
+
headers: {
|
|
164
|
+
'content-type': 'application/json',
|
|
165
|
+
authorization: `Bearer ${input.executorToken}`,
|
|
166
|
+
[PLAY_RUNTIME_TRANSPORT_ATTEMPT_HEADER]: transportAttemptId,
|
|
167
|
+
},
|
|
168
|
+
body: JSON.stringify({
|
|
169
|
+
action: 'runner_heartbeat',
|
|
170
|
+
runId: input.runId,
|
|
171
|
+
}),
|
|
172
|
+
redirect: 'manual',
|
|
173
|
+
signal: controller.signal,
|
|
174
|
+
});
|
|
175
|
+
if (response.status >= 300 && response.status < 400) {
|
|
176
|
+
// A redirect means the request escaped the gateway to Vercel Deployment
|
|
177
|
+
// Protection (the sandbox holds no bypass credential). Treat it as a hard
|
|
178
|
+
// transport failure so the unreachable window logic engages, never as ok.
|
|
179
|
+
await response.text().catch(() => '');
|
|
180
|
+
reportTransport('redirect', { status: response.status });
|
|
181
|
+
throw new Error(
|
|
182
|
+
`runner_heartbeat was redirected (${response.status}); expected the receipt gateway.`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
if (!response.ok) {
|
|
186
|
+
const body = await response.text().catch(() => '');
|
|
187
|
+
let errorCode: string | undefined;
|
|
188
|
+
try {
|
|
189
|
+
const parsed = JSON.parse(body) as { code?: unknown };
|
|
190
|
+
if (
|
|
191
|
+
typeof parsed.code === 'string' &&
|
|
192
|
+
/^[A-Z0-9_]{1,64}$/.test(parsed.code)
|
|
193
|
+
) {
|
|
194
|
+
errorCode = parsed.code;
|
|
195
|
+
}
|
|
196
|
+
} catch {
|
|
197
|
+
// A non-JSON gateway failure still has a useful status code.
|
|
198
|
+
}
|
|
199
|
+
reportTransport(response.status >= 500 ? 'gateway_5xx' : 'gateway_4xx', {
|
|
200
|
+
status: response.status,
|
|
201
|
+
...(errorCode ? { errorCode } : {}),
|
|
202
|
+
});
|
|
203
|
+
throw new Error(`runner_heartbeat failed (${response.status}): ${body}`);
|
|
204
|
+
}
|
|
205
|
+
const body = (await response.json().catch(() => null)) as
|
|
206
|
+
| RunnerHeartbeatResponse
|
|
207
|
+
| { ok?: unknown; terminal?: unknown; schedulerStatus?: unknown }
|
|
208
|
+
| null;
|
|
209
|
+
if (
|
|
210
|
+
body &&
|
|
211
|
+
body.ok === false &&
|
|
212
|
+
(body as { terminal?: unknown }).terminal
|
|
213
|
+
) {
|
|
214
|
+
const terminal = (body as { terminal?: unknown }).terminal;
|
|
215
|
+
if (
|
|
216
|
+
terminal === 'cancelled' ||
|
|
217
|
+
terminal === 'failed' ||
|
|
218
|
+
terminal === 'completed'
|
|
219
|
+
) {
|
|
220
|
+
reportTransport('terminal', { status: response.status });
|
|
221
|
+
return { ok: false, terminal };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (body && body.ok === true) {
|
|
225
|
+
const schedulerStatus = (body as { schedulerStatus?: unknown })
|
|
226
|
+
.schedulerStatus;
|
|
227
|
+
// Rolling-deploy compatibility: an older gateway returns only
|
|
228
|
+
// `{ ok: true }`. Treat that as live-but-not-acknowledged so the runner
|
|
229
|
+
// stays fenced and retries until a new gateway reports `waiting`.
|
|
230
|
+
if (schedulerStatus === undefined) {
|
|
231
|
+
reportTransport('ok', { status: response.status });
|
|
232
|
+
return { ok: true, schedulerStatus: 'running' };
|
|
233
|
+
}
|
|
234
|
+
if (
|
|
235
|
+
schedulerStatus !== 'queued' &&
|
|
236
|
+
schedulerStatus !== 'running' &&
|
|
237
|
+
schedulerStatus !== 'waiting'
|
|
238
|
+
) {
|
|
239
|
+
reportTransport('protocol_error', { status: response.status });
|
|
240
|
+
throw new Error(
|
|
241
|
+
`runner_heartbeat returned an invalid scheduler status: ${JSON.stringify(schedulerStatus)}`,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
reportTransport('ok', { status: response.status });
|
|
245
|
+
return { ok: true, schedulerStatus };
|
|
246
|
+
}
|
|
247
|
+
reportTransport('protocol_error', { status: response.status });
|
|
248
|
+
throw new Error(
|
|
249
|
+
`runner_heartbeat returned an unrecognized body: ${JSON.stringify(body)}`,
|
|
250
|
+
);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (!transportReported) {
|
|
253
|
+
reportTransport(controller.signal.aborted ? 'timeout' : 'network_error', {
|
|
254
|
+
errorCode: runnerGatewayTransportErrorCode(error),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (controller.signal.aborted) {
|
|
258
|
+
throw new Error(`runner_heartbeat timed out after ${timeoutMs}ms.`);
|
|
259
|
+
}
|
|
260
|
+
throw error;
|
|
261
|
+
} finally {
|
|
262
|
+
clearTimeout(timeout);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function startRunnerHeartbeatLoop(
|
|
267
|
+
options: RunnerHeartbeatLoopOptions,
|
|
268
|
+
): RunnerHeartbeatLoopHandle {
|
|
269
|
+
const setIntervalImpl =
|
|
270
|
+
options.setIntervalImpl ??
|
|
271
|
+
((fn, ms) => setInterval(fn, ms) as unknown as { unref?: () => void });
|
|
272
|
+
const clearIntervalImpl =
|
|
273
|
+
options.clearIntervalImpl ??
|
|
274
|
+
((handle) => clearInterval(handle as ReturnType<typeof setInterval>));
|
|
275
|
+
const now = options.nowImpl ?? Date.now;
|
|
276
|
+
const warn =
|
|
277
|
+
options.warn ??
|
|
278
|
+
((message, detail) =>
|
|
279
|
+
console.warn(`[play-runner.heartbeat] ${message}`, detail));
|
|
280
|
+
let gatewayTransport: RunnerGatewayTransportSummary | null = null;
|
|
281
|
+
const onTransport = (event: RunnerGatewayTransportEvent) => {
|
|
282
|
+
const notify = () => {
|
|
283
|
+
try {
|
|
284
|
+
options.onTransport?.(event);
|
|
285
|
+
} catch {
|
|
286
|
+
// Caller-provided diagnostics must never terminate a healthy runner.
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
if (event.outcome === 'ok' || event.outcome === 'terminal') {
|
|
290
|
+
gatewayTransport = null;
|
|
291
|
+
notify();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
gatewayTransport = updateRunnerGatewayTransportSummary(
|
|
295
|
+
gatewayTransport,
|
|
296
|
+
event,
|
|
297
|
+
);
|
|
298
|
+
warn('gateway_transport', {
|
|
299
|
+
runId: options.runId,
|
|
300
|
+
...event,
|
|
301
|
+
});
|
|
302
|
+
notify();
|
|
303
|
+
};
|
|
304
|
+
const sendHeartbeat =
|
|
305
|
+
options.sendHeartbeat ??
|
|
306
|
+
((input: {
|
|
307
|
+
gatewayBaseUrl: string;
|
|
308
|
+
executorToken: string;
|
|
309
|
+
runId: string;
|
|
310
|
+
leaseSeconds: number;
|
|
311
|
+
attempt?: number;
|
|
312
|
+
}) => sendRunnerHeartbeat(input, { onTransport }));
|
|
313
|
+
|
|
314
|
+
const leaseMs = Math.max(1_000, Math.floor(options.leaseSeconds * 1_000));
|
|
315
|
+
const cadenceMs = Math.max(
|
|
316
|
+
250,
|
|
317
|
+
Math.floor(leaseMs / RUNTIME_CLAIM_HEARTBEAT_DIVISOR),
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
let stopped = false;
|
|
321
|
+
let inFlight = false;
|
|
322
|
+
let heartbeatAttempt = 0;
|
|
323
|
+
let lastSuccessAt = now();
|
|
324
|
+
let handle: { unref?: () => void } | null = null;
|
|
325
|
+
let resolveFirstHeartbeat: (() => void) | null = null;
|
|
326
|
+
const firstHeartbeat = new Promise<void>((resolve) => {
|
|
327
|
+
resolveFirstHeartbeat = resolve;
|
|
328
|
+
});
|
|
329
|
+
let resolveExecutionAcknowledged: (() => void) | null = null;
|
|
330
|
+
const executionAcknowledged = new Promise<void>((resolve) => {
|
|
331
|
+
resolveExecutionAcknowledged = resolve;
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const stopLoop = () => {
|
|
335
|
+
if (stopped) return;
|
|
336
|
+
stopped = true;
|
|
337
|
+
if (handle) {
|
|
338
|
+
clearIntervalImpl(handle);
|
|
339
|
+
handle = null;
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const selfTerminate = (stop: RunnerHeartbeatStop) => {
|
|
344
|
+
if (stopped) return;
|
|
345
|
+
stopLoop();
|
|
346
|
+
options.onSelfTerminate(stop);
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const tick = () => {
|
|
350
|
+
if (stopped || inFlight) return;
|
|
351
|
+
inFlight = true;
|
|
352
|
+
heartbeatAttempt += 1;
|
|
353
|
+
void sendHeartbeat({
|
|
354
|
+
gatewayBaseUrl: options.gatewayBaseUrl,
|
|
355
|
+
executorToken: options.executorToken,
|
|
356
|
+
runId: options.runId,
|
|
357
|
+
leaseSeconds: options.leaseSeconds,
|
|
358
|
+
attempt: heartbeatAttempt,
|
|
359
|
+
})
|
|
360
|
+
.then((result) => {
|
|
361
|
+
if (stopped) return;
|
|
362
|
+
if (result.ok === false) {
|
|
363
|
+
selfTerminate({ reason: 'terminal', terminal: result.terminal });
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
lastSuccessAt = now();
|
|
367
|
+
if (resolveFirstHeartbeat) {
|
|
368
|
+
resolveFirstHeartbeat();
|
|
369
|
+
resolveFirstHeartbeat = null;
|
|
370
|
+
// Restore the steady-state cadence only after durable startup succeeds.
|
|
371
|
+
if (handle) clearIntervalImpl(handle);
|
|
372
|
+
handle = setIntervalImpl(tick, cadenceMs);
|
|
373
|
+
handle.unref?.();
|
|
374
|
+
}
|
|
375
|
+
if (
|
|
376
|
+
result.schedulerStatus === 'waiting' &&
|
|
377
|
+
resolveExecutionAcknowledged
|
|
378
|
+
) {
|
|
379
|
+
resolveExecutionAcknowledged();
|
|
380
|
+
resolveExecutionAcknowledged = null;
|
|
381
|
+
}
|
|
382
|
+
})
|
|
383
|
+
.catch((error) => {
|
|
384
|
+
if (stopped) return;
|
|
385
|
+
const sinceMs = now() - lastSuccessAt;
|
|
386
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
387
|
+
if (sinceMs > leaseMs) {
|
|
388
|
+
selfTerminate({
|
|
389
|
+
reason: 'unreachable',
|
|
390
|
+
sinceMs,
|
|
391
|
+
lastError: message,
|
|
392
|
+
...(gatewayTransport ? { gatewayTransport } : {}),
|
|
393
|
+
});
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
warn('heartbeat_failed_retrying', {
|
|
397
|
+
runId: options.runId,
|
|
398
|
+
sinceMs,
|
|
399
|
+
leaseMs,
|
|
400
|
+
error: message,
|
|
401
|
+
});
|
|
402
|
+
})
|
|
403
|
+
.finally(() => {
|
|
404
|
+
inFlight = false;
|
|
405
|
+
});
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
// Keep this timer referenced until the first accepted heartbeat: a pending
|
|
409
|
+
// Promise alone does not keep Node alive after an initial transport failure.
|
|
410
|
+
handle = setIntervalImpl(
|
|
411
|
+
tick,
|
|
412
|
+
Math.min(cadenceMs, RUNNER_STARTUP_HEARTBEAT_INTERVAL_MS),
|
|
413
|
+
);
|
|
414
|
+
// Fire one immediately so a cancel that landed before the first interval is
|
|
415
|
+
// observed within a cadence, not a full lease window.
|
|
416
|
+
tick();
|
|
417
|
+
|
|
418
|
+
return {
|
|
419
|
+
stop: stopLoop,
|
|
420
|
+
firstHeartbeat,
|
|
421
|
+
executionAcknowledged,
|
|
422
|
+
requestHeartbeat: tick,
|
|
423
|
+
};
|
|
424
|
+
}
|