deepline 0.3.405 → 0.3.407

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.
Files changed (111) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +54 -57
  2. package/dist/bundling-sources/sdk/src/play.ts +8 -5
  3. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  4. package/dist/bundling-sources/sdk/src/types.ts +4 -3
  5. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +43 -4
  6. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machine-lifecycle.ts +101 -0
  7. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +4 -0
  8. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +87 -28
  10. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +6 -1
  11. package/dist/cli/auth-4JTX6AGM.js +40 -0
  12. package/dist/cli/{auth-D4GXO4IN.mjs → auth-WURWNNLE.mjs} +4 -4
  13. package/dist/cli/{billing-TQ4UM4D4.js → billing-2QJGXGJX.js} +73 -73
  14. package/dist/cli/{billing-NVV5VSUJ.mjs → billing-BP3E6WIM.mjs} +4 -4
  15. package/dist/cli/{chunk-TECEX3K5.mjs → chunk-4TV43THC.mjs} +3 -3
  16. package/dist/cli/{chunk-YX7JSSJ2.mjs → chunk-6JZZNP5G.mjs} +2 -2
  17. package/dist/cli/{chunk-LM2JHRZM.js → chunk-7LKYHZVB.js} +1 -1
  18. package/dist/cli/{chunk-3DWMYKWU.mjs → chunk-BKC6VMYZ.mjs} +1 -1
  19. package/dist/cli/{chunk-JPNBAZBR.js → chunk-D2ZRMZKF.js} +6 -6
  20. package/dist/cli/{chunk-BZBV2GY2.js → chunk-G4LJS2RE.js} +8 -8
  21. package/dist/cli/{chunk-MZ4LBCV7.js → chunk-G6U74WNM.js} +15 -15
  22. package/dist/cli/{chunk-3MVBOBV4.js → chunk-H6EWQFPQ.js} +2 -2
  23. package/dist/cli/{chunk-AAIV3ACM.js → chunk-IY6GKJ4O.js} +50 -50
  24. package/dist/cli/{chunk-HG5PMETP.mjs → chunk-J67NU4MQ.mjs} +55 -58
  25. package/dist/cli/{chunk-HYAA3F6U.js → chunk-KUQAU5MG.js} +60 -63
  26. package/dist/cli/{chunk-B6ME2XIO.mjs → chunk-L25GBGQU.mjs} +5 -5
  27. package/dist/cli/{chunk-4ONG2MWB.mjs → chunk-N6OAMAO5.mjs} +1 -1
  28. package/dist/cli/{chunk-EVLCUV64.mjs → chunk-P7HOTKOK.mjs} +4 -4
  29. package/dist/cli/{chunk-YRZIKG47.mjs → chunk-QJAX7QN7.mjs} +2 -2
  30. package/dist/cli/{chunk-NAJEB3N4.js → chunk-RMZAOYDN.js} +44 -44
  31. package/dist/cli/{chunk-6HXTHMHZ.js → chunk-RZLXVHNO.js} +26 -26
  32. package/dist/cli/{chunk-NLT6GCWZ.js → chunk-SOQIPKF2.js} +8 -8
  33. package/dist/cli/{chunk-CB6AJNHI.js → chunk-THHM4DPE.js} +4 -4
  34. package/dist/cli/{chunk-3FF3SPSE.mjs → chunk-UFFSOV6I.mjs} +2 -2
  35. package/dist/cli/{chunk-EKWJXPIX.mjs → chunk-UPEOEYZ3.mjs} +1 -1
  36. package/dist/cli/{chunk-MPXPTSGJ.mjs → chunk-XT6GG3QO.mjs} +3 -3
  37. package/dist/cli/{chunk-WGX7SIGL.js → chunk-Y6CX4QPR.js} +65 -65
  38. package/dist/cli/{chunk-TPYRDAU7.mjs → chunk-ZBCTXQ3P.mjs} +1 -1
  39. package/dist/cli/{csv-5AASYDRF.js → csv-7E5BE23B.js} +12 -12
  40. package/dist/cli/{csv-H7LD6IQK.mjs → csv-N6KYTG7L.mjs} +3 -3
  41. package/dist/cli/{db-MJBZBDWZ.js → db-4VLZP33O.js} +25 -25
  42. package/dist/cli/{db-CG3UQUA7.mjs → db-XMBJNVBD.mjs} +4 -4
  43. package/dist/cli/{describe-2A7GARI2.js → describe-4I6EIVXD.js} +10 -10
  44. package/dist/cli/{describe-INFC5ACQ.mjs → describe-WERH4TD2.mjs} +6 -6
  45. package/dist/cli/describe-core.d.mts +2 -2
  46. package/dist/cli/describe-core.d.ts +2 -2
  47. package/dist/cli/{executions-DO47P6MX.mjs → executions-JWQXE7G6.mjs} +4 -4
  48. package/dist/cli/{executions-AUDQ5HOJ.js → executions-W7TWJRBK.js} +6 -6
  49. package/dist/cli/{feedback-MNWNDZVU.js → feedback-FMGRC6KO.js} +7 -7
  50. package/dist/cli/{feedback-XGZSJM2N.mjs → feedback-OEJFX4F7.mjs} +3 -3
  51. package/dist/cli/{git-2ECFQKAA.mjs → git-IVC4KHXX.mjs} +4 -4
  52. package/dist/cli/git-OFXE7G4X.js +24 -0
  53. package/dist/cli/index.js +89 -89
  54. package/dist/cli/index.mjs +32 -32
  55. package/dist/cli/{legacy-noops-534TKEMO.mjs → legacy-noops-LT36CLWZ.mjs} +4 -4
  56. package/dist/cli/{legacy-noops-3UZTD4DS.js → legacy-noops-X3BQ7MUK.js} +7 -7
  57. package/dist/cli/{monitors-G4S54JSX.js → monitors-DLIIAVLW.js} +84 -84
  58. package/dist/cli/{monitors-5ARELE2S.mjs → monitors-MNLCELF7.mjs} +4 -4
  59. package/dist/cli/{org-RIWF2TLI.js → org-CYHDEW7P.js} +64 -64
  60. package/dist/cli/{org-BAMOOXQW.mjs → org-QV5LMUPT.mjs} +4 -4
  61. package/dist/cli/{play-WV4UNGPR.mjs → play-5Z4ROZ3P.mjs} +7 -7
  62. package/dist/cli/{play-32XSQMFK.js → play-MEFXC2QA.js} +231 -231
  63. package/dist/cli/{providers-XKY2CNKH.js → providers-2MKUNFBQ.js} +7 -7
  64. package/dist/cli/{providers-SMSRO23R.mjs → providers-FJLYSHB3.mjs} +4 -4
  65. package/dist/cli/{quickstart-BFYYEVSS.mjs → quickstart-PQO3OQRT.mjs} +3 -3
  66. package/dist/cli/{quickstart-Q2TA72HD.js → quickstart-ULWXKAOT.js} +5 -5
  67. package/dist/cli/search-ANKSJ224.js +30 -0
  68. package/dist/cli/{search-I2TVB2P5.mjs → search-KGAAXMDG.mjs} +5 -5
  69. package/dist/cli/{secrets-BHKICIE3.mjs → secrets-PD5I3KAF.mjs} +4 -4
  70. package/dist/cli/{secrets-B4NYTSL7.js → secrets-X2VGG2PO.js} +13 -13
  71. package/dist/cli/{sessions-IOR2ZNNH.mjs → sessions-3WVEU4PE.mjs} +4 -4
  72. package/dist/cli/{sessions-XY2UREJ7.js → sessions-R3XAKTBQ.js} +5 -5
  73. package/dist/cli/{settings-W6S7B4NH.mjs → settings-645RSFQX.mjs} +7 -7
  74. package/dist/cli/{settings-ASGROQDE.js → settings-ZIDO3IP6.js} +74 -74
  75. package/dist/cli/{setup-YIYQ73OV.js → setup-LH5HOZ3D.js} +41 -41
  76. package/dist/cli/{setup-UUWGI3IN.mjs → setup-LISKIJKP.mjs} +6 -6
  77. package/dist/cli/{skills-CHA4QCGI.mjs → skills-VVQJHLSF.mjs} +4 -4
  78. package/dist/cli/skills-WLHYSVQA.js +29 -0
  79. package/dist/cli/{tools-43ZFJWAQ.js → tools-FTPJCNAM.js} +7 -7
  80. package/dist/cli/{tools-PMZDYKTT.mjs → tools-Y3LOMXFT.mjs} +6 -6
  81. package/dist/cli/update-A622H2DZ.js +29 -0
  82. package/dist/cli/{update-6VSEGTSG.mjs → update-DOBNQNJI.mjs} +6 -6
  83. package/dist/cli/{workflow-26EOXZ7M.js → workflow-LGENKZBV.js} +15 -15
  84. package/dist/cli/{workflow-SVMVLQOF.mjs → workflow-ZMAA5VCN.mjs} +5 -5
  85. package/dist/{client-Buv1_ktG.d.mts → client-6rEB46Lv.d.mts} +55 -57
  86. package/dist/{client-Db1jFLpF.d.ts → client-IrPHUE5J.d.ts} +55 -57
  87. package/dist/{compiler-manifest-N77W75Py.d.ts → compiler-manifest-BHnXE43X.d.mts} +6 -1
  88. package/dist/{compiler-manifest-N77W75Py.d.mts → compiler-manifest-BHnXE43X.d.ts} +6 -1
  89. package/dist/{index-3WOfyVhW.d.mts → index-Da_Y8z5e.d.mts} +1 -1
  90. package/dist/{index-CtIJFTCl.d.ts → index-SODb2ROS.d.ts} +1 -1
  91. package/dist/index.d.mts +13 -10
  92. package/dist/index.d.ts +13 -10
  93. package/dist/index.js +8 -8
  94. package/dist/index.mjs +5 -5
  95. package/dist/install-integrity.json +76 -76
  96. package/dist/plays/bundle-play-file.d.mts +3 -3
  97. package/dist/plays/bundle-play-file.d.ts +3 -3
  98. package/dist/plays/play-description.d.mts +2 -2
  99. package/dist/plays/play-description.d.ts +2 -2
  100. package/dist/plays/run-request.d.mts +2 -2
  101. package/dist/plays/run-request.d.ts +2 -2
  102. package/dist/release.d.mts +1 -1
  103. package/dist/release.d.ts +1 -1
  104. package/dist/release.js +2 -2
  105. package/dist/release.mjs +1 -1
  106. package/package.json +1 -1
  107. package/dist/cli/auth-IJKAKAHG.js +0 -40
  108. package/dist/cli/git-6S64UBWC.js +0 -24
  109. package/dist/cli/search-GK7P3AZY.js +0 -30
  110. package/dist/cli/skills-LKNKHB2I.js +0 -29
  111. package/dist/cli/update-R7FODDIW.js +0 -29
@@ -3232,8 +3232,8 @@ export class DeeplineClient {
3232
3232
  /**
3233
3233
  * Search available tools using Deepline's ranked backend search.
3234
3234
  *
3235
- * This is the same discovery surface used by the CLI: it ranks across
3236
- * tool metadata, categories, agent guidance, and input schema fields.
3235
+ * The CLI uses the same search.
3236
+ * The search ranks tool metadata, categories, agent guidance, and input schema fields.
3237
3237
  */
3238
3238
  async searchTools(
3239
3239
  options: ToolSearchOptions = {},
@@ -3308,13 +3308,12 @@ export class DeeplineClient {
3308
3308
  /**
3309
3309
  * Describe a Deepline Agent model and its provider-specific option surface.
3310
3310
  *
3311
- * Combines live AI Gateway model metadata with Deepline's generated AI SDK
3312
- * provider option registry so agents can construct `providerOptions`
3313
- * payloads before executing `deeplineagent`.
3311
+ * The method combines live AI Gateway model metadata with Deepline's generated registry of AI SDK provider options.
3312
+ * Agents can use this information to construct `providerOptions` payloads before they execute `deeplineagent`.
3314
3313
  *
3315
- * The returned option schemas describe accepted provider option shapes, not
3316
- * guaranteed support for every model. Runtime AI SDK/Gateway errors remain
3317
- * authoritative for model-gated values.
3314
+ * The returned schemas describe accepted shapes for provider options.
3315
+ * These schemas do not guarantee that every model supports each option.
3316
+ * Runtime AI SDK and Gateway errors determine support for model-specific values.
3318
3317
  *
3319
3318
  * @param model - Exact-case Gateway model id such as `"openai/gpt-5.6-luna"`
3320
3319
  * @returns Model metadata, provider option shapes, and runnable examples
@@ -3331,8 +3330,8 @@ export class DeeplineClient {
3331
3330
  /**
3332
3331
  * Quote dynamic AI inference pricing for a concrete payload.
3333
3332
  *
3334
- * The result separates a planning estimate from a proven authorization
3335
- * maximum and contains Deepline credits only.
3333
+ * The result contains a planning estimate and a separate, proven authorization maximum.
3334
+ * Both values use Deepline credits.
3336
3335
  */
3337
3336
  async quoteInferenceTool(
3338
3337
  toolId: 'ai_evaluate' | 'ai_inference' | 'deeplineagent',
@@ -3437,13 +3436,16 @@ export class DeeplineClient {
3437
3436
  * entrypoints: the CLI, {@link Deepline.connect}, {@link submitPlay},
3438
3437
  * or {@link runPlay}.
3439
3438
  *
3440
- * Supported invocation surfaces intentionally share this same run contract:
3441
- * `deepline plays run`, repo scripts such as `bun run deepline -- plays run`,
3442
- * SDK context calls like `Deepline.connect().play(name).run()`, and direct
3443
- * `POST /api/v2/plays/run` calls all return a workflow/run id. The completed
3444
- * output is always retrievable from `getPlayStatus(runId).result` (or from
3445
- * `PlayJob.get()` for SDK context calls). Execution logs live under
3446
- * `progress.logs`; they are not part of the user output object.
3439
+ * These interfaces share the run contract and return a workflow or run ID:
3440
+ *
3441
+ * - `deepline plays run`.
3442
+ * - Repository scripts such as `bun run deepline -- plays run`.
3443
+ * - SDK context calls such as `Deepline.connect().play(name).run()`.
3444
+ * - Direct `POST /api/v2/plays/run` calls.
3445
+ *
3446
+ * Read completed output from `getPlayStatus(runId).result`.
3447
+ * For SDK context calls, read output from `PlayJob.get()`.
3448
+ * Execution logs appear under `progress.logs`. The user output object does not contain these logs.
3447
3449
  *
3448
3450
  * @param request - Play run configuration (name, code, input, etc.)
3449
3451
  * @returns Run metadata including the public `workflowId`
@@ -3718,9 +3720,8 @@ export class DeeplineClient {
3718
3720
  /**
3719
3721
  * Compile a bundled play artifact into the server-side compiler manifest.
3720
3722
  *
3721
- * The manifest records imports, trigger bindings, static pipeline shape, and
3722
- * runtime metadata needed before a play artifact can be checked, registered,
3723
- * or run.
3723
+ * The manifest records imports, trigger bindings, static pipeline shape, and runtime metadata.
3724
+ * The compiler needs these records before it checks, registers, or runs a Play artifact.
3724
3725
  */
3725
3726
  async compilePlayManifest(input: {
3726
3727
  name: string;
@@ -3802,8 +3803,8 @@ export class DeeplineClient {
3802
3803
  /**
3803
3804
  * Register an already-bundled play artifact and start a run from it.
3804
3805
  *
3805
- * This is the low-level file-backed run path used by SDK/CLI packaging
3806
- * wrappers after local bundling has produced the runtime artifact.
3806
+ * SDK and CLI packaging wrappers use this low-level run method for file-based Plays.
3807
+ * Local bundling must produce the runtime artifact first.
3807
3808
  */
3808
3809
  async startPlayRunFromBundle(input: {
3809
3810
  name: string;
@@ -3859,15 +3860,15 @@ export class DeeplineClient {
3859
3860
  /**
3860
3861
  * Register a bundled play artifact and start a run from the live revision.
3861
3862
  *
3862
- * Convenience wrapper around {@link registerPlayArtifact} plus
3863
- * {@link startPlayRun}. This is the canonical file-backed path used by wrappers.
3864
- * The returned id can be passed to {@link getPlayStatus} to retrieve the same
3865
- * durable `{ result }` object that the CLI prints after `plays run` completes.
3863
+ * This method wraps {@link registerPlayArtifact} and {@link startPlayRun}.
3864
+ * Packaging wrappers use this method for file-based Plays.
3865
+ * Pass the returned ID to {@link getPlayStatus}.
3866
+ * The method returns the same durable `{ result }` object that the CLI prints after `plays run` completes.
3866
3867
  *
3867
- * @param code - Source string fallback; the bundled artifact should be passed in `options.artifact`
3868
- * @param csvPath - Path to input CSV file, or `null`
3869
- * @param name - Play name (extracted from source if omitted)
3870
- * @param options - Additional submission options
3868
+ * @param code - Fallback source string. Pass the bundled artifact in `options.artifact`.
3869
+ * @param csvPath - Path to the input CSV file, or `null`.
3870
+ * @param name - Play name. The SDK derives it from the source when omitted.
3871
+ * @param options - Additional submission options.
3871
3872
  * @returns Workflow metadata with `workflowId`
3872
3873
  *
3873
3874
  * @example
@@ -3998,9 +3999,8 @@ export class DeeplineClient {
3998
3999
  /**
3999
4000
  * Mint short-lived presigned upload targets for staged play files.
4000
4001
  *
4001
- * Internal primitive used by {@link stagePlayFiles}. The server returns an
4002
- * already-staged ref (no upload needed) for content-addressed files it
4003
- * already holds, or a presigned PUT URL the caller uploads the body to.
4002
+ * Internal primitive used by {@link stagePlayFiles}. For a content-addressed file already in storage, the server returns a staged reference. That file needs no upload.
4003
+ * For other files, the server returns a presigned PUT URL. Upload the file body to that URL.
4004
4004
  */
4005
4005
  async mintStagedPlayFileUploads(
4006
4006
  files: Array<{
@@ -4016,8 +4016,7 @@ export class DeeplineClient {
4016
4016
  /**
4017
4017
  * Resolve staged play files by content hash without uploading bytes.
4018
4018
  *
4019
- * Missing files are returned so callers can upload only the files the server
4020
- * does not already have.
4019
+ * The response identifies missing files. Callers need to upload only these files.
4021
4020
  */
4022
4021
  async resolveStagedPlayFiles(
4023
4022
  files: Array<{
@@ -4658,11 +4657,11 @@ export class DeeplineClient {
4658
4657
  /**
4659
4658
  * Start a fresh run from a prior run's retained input and pinned revision.
4660
4659
  *
4661
- * Every invocation sends an `Idempotency-Key`. When the caller does not
4662
- * supply one, a fresh key is generated once per call so the transport's own
4663
- * network retries converge on a single rerun. Pass the same explicit key
4664
- * across separate invocations to repeat an ambiguous result safely; a
4665
- * different key intentionally starts another rerun.
4660
+ * Every invocation sends an `Idempotency-Key`.
4661
+ * When the caller supplies no key, the SDK creates a fresh key once per call.
4662
+ * The transport reuses that key for network retries, so those retries produce one rerun.
4663
+ * Reuse an explicit key across separate invocations when the previous result is uncertain.
4664
+ * A different key starts another rerun.
4666
4665
  */
4667
4666
  async rerun(
4668
4667
  runId: string,
@@ -5113,8 +5112,8 @@ export class DeeplineClient {
5113
5112
  options?: StopAllRunsOptions,
5114
5113
  ): Promise<StopAllPlayRunsResult>;
5115
5114
  /**
5116
- * Stop every active run visible to the current workspace, or with
5117
- * `dryRun: true` enumerate the exact candidates without cancelling anything.
5115
+ * Stop every active run visible to the current workspace.
5116
+ * With `dryRun: true`, list the exact candidates without cancelling any run.
5118
5117
  *
5119
5118
  * This is the SDK equivalent of:
5120
5119
  *
@@ -5123,8 +5122,8 @@ export class DeeplineClient {
5123
5122
  * deepline runs stop-all --reason "stale lock"
5124
5123
  * ```
5125
5124
  *
5126
- * Use this when a failed parent run left child or waiting runs active and you
5127
- * need to clear the workspace run-slot state without knowing each run id.
5125
+ * Use this method when a failed parent leaves active child or waiting runs.
5126
+ * The method clears workspace run-slot state without requiring each run ID.
5128
5127
  */
5129
5128
  async stopAllRuns(
5130
5129
  options?: StopAllRunsOptions,
@@ -5150,8 +5149,8 @@ export class DeeplineClient {
5150
5149
  }
5151
5150
 
5152
5151
  /**
5153
- * List one page of callable plays; grep retains exhaustive matching results.
5154
- * Use listPlaysPage to retain pagination metadata.
5152
+ * List one page of callable Plays. With grep, the method retains all matching results.
5153
+ * Use listPlaysPage for pagination metadata.
5155
5154
  *
5156
5155
  * Pass `origin: "prebuilt"` for Deepline-managed prebuilts or
5157
5156
  * `origin: "owned"` for org-owned plays.
@@ -5736,8 +5735,7 @@ export class DeeplineClient {
5736
5735
  /**
5737
5736
  * Get the full definition and state of a named play.
5738
5737
  *
5739
- * Returns the play's revision state (draft, live), recent runs,
5740
- * sheet processing summary, and database URL.
5738
+ * The response includes revision state (draft or live), recent runs, a summary of sheet processing, and the database URL.
5741
5739
  *
5742
5740
  * @param name - Play name
5743
5741
  * @returns Complete play detail
@@ -5813,10 +5811,10 @@ export class DeeplineClient {
5813
5811
  /**
5814
5812
  * Get a normalized play description suitable for agents and CLIs.
5815
5813
  *
5816
- * The description includes runnable examples, input/output summaries, clone
5817
- * guidance, revision state, and latest run metadata when available. Pass
5818
- * `{ pipeline: true }` to include the compiled pipeline, which can be
5819
- * hundreds of kilobytes and is otherwise left out.
5814
+ * The description includes runnable examples, input and output summaries, clone guidance, and revision state.
5815
+ * It also includes metadata for the latest run when available.
5816
+ * Set `{ pipeline: true }` to include the compiled pipeline.
5817
+ * The pipeline can be hundreds of kilobytes. The response omits it by default.
5820
5818
  */
5821
5819
  async describePlay(
5822
5820
  name: string,
@@ -5884,8 +5882,7 @@ export class DeeplineClient {
5884
5882
  * Make a play revision live.
5885
5883
  *
5886
5884
  * When `revisionId` is omitted, the current working revision becomes live.
5887
- * The live version is what executes when the play is run by name without
5888
- * specifying an explicit revision.
5885
+ * A call by Play name executes the live revision unless the caller specifies another revision.
5889
5886
  *
5890
5887
  * @param name - Play name
5891
5888
  * @param request - Optional explicit revision to make live
@@ -6211,9 +6208,9 @@ export class DeeplineClient {
6211
6208
  }
6212
6209
 
6213
6210
  /**
6214
- * What Deepline has billed each run so far (customer-visible credits, never
6215
- * provider spend) and whether any of its charges is still settling — the
6216
- * same read the dashboard's runs grid shows. `GET /api/v2/runs/billing`.
6211
+ * Read Deepline credits billed to each run and whether charges are still settling.
6212
+ * The response never shows provider spend. The dashboard runs grid uses the same read.
6213
+ * HTTP endpoint: `GET /api/v2/runs/billing`.
6217
6214
  */
6218
6215
  async getRunBilling(runIds: readonly string[]): Promise<RunBillingResult> {
6219
6216
  const params = new URLSearchParams();
@@ -192,8 +192,8 @@ export type PlayFetchResponse = PlayAuthoringFetchResponse;
192
192
  * A play can be triggered three ways, declared as the third argument to
193
193
  * {@link definePlay}:
194
194
  * - `webhook` — an inbound HTTP call (with optional legacy HMAC or Standard
195
- * Webhooks signature verification);
196
- * - `cron` — a schedule; or
195
+ * Webhooks signature verification).
196
+ * - `cron` — a schedule.
197
197
  * - `sqlListeners` — a **monitor**: the play runs whenever a monitor writes a new
198
198
  * row to its output stream. This is how you build a play "on top of" a monitor
199
199
  * (e.g. run enrichment every time a watched company posts a new job). Each
@@ -1232,8 +1232,8 @@ export class DeeplineContext {
1232
1232
  * Run a named or prebuilt play and wait for its output.
1233
1233
  *
1234
1234
  * This is the high-level SDK equivalent of `ctx.play(name).runSync(input)`.
1235
- * Inside a play runtime, prefer the in-play `ctx.runPlay(key, playRef, input,
1236
- * options)` form so the child run is checkpointed under a stable key.
1235
+ * Inside a Play, prefer `ctx.runPlay(key, playRef, input, options)`.
1236
+ * The runtime checkpoints the child run under a stable key.
1237
1237
  *
1238
1238
  * @param playOrRef - Play name or prebuilt/reference object.
1239
1239
  * @param input - JSON input passed to the play.
@@ -1630,7 +1630,10 @@ export function defineInput<TInput>(
1630
1630
  /**
1631
1631
  * Define a play — a composable TypeScript workflow for the Deepline platform.
1632
1632
  *
1633
- * The returned value is both a callable function, invoked by the Deepline runtime with a runtime context, and a named play handle carrying `.run()`, `.versions()`, `.get()` and `.publish()` for remote lifecycle management. Plays are the primary abstraction for repeatable data pipelines and execute durably, with automatic retries and timeouts.
1633
+ * The returned value is both a callable function and a named Play handle.
1634
+ * The Deepline runtime calls the function with a runtime context.
1635
+ * The handle provides `.run()`, `.versions()`, `.get()`, and `.publish()` for remote lifecycle operations.
1636
+ * Plays define repeatable data pipelines. The runtime executes them durably with automatic retries and timeouts.
1634
1637
  *
1635
1638
  * @typeParam TInput - The input type accepted by the play
1636
1639
  * @typeParam TOutput - The return type of the play
@@ -202,7 +202,7 @@ export const SDK_RELEASE = {
202
202
  // getters keep their established compatibility behavior.
203
203
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
204
204
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
205
- version: '0.3.405',
205
+ version: '0.3.407',
206
206
  updateSummary:
207
207
  'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
208
208
  packageCapabilities: {
@@ -1181,9 +1181,10 @@ export interface StopPlayRunResult {
1181
1181
  /** True if HITL state or its same-message Slack card still needs retrying. */
1182
1182
  hitlCancellationPending?: boolean;
1183
1183
  /**
1184
- * True only when the scheduler and the canonical run ledger disagree (for
1185
- * example a terminal scheduler run whose ledger projection is pending), so
1186
- * the stop could not be confirmed. Never set for a queued cancellation.
1184
+ * True only when the scheduler and the canonical run ledger disagree and
1185
+ * the server could not confirm the stop.
1186
+ * For example, the scheduler can report a terminal run while the ledger
1187
+ * projection is pending. This field is never true for a queued cancellation.
1187
1188
  */
1188
1189
  staleSchedulerState?: boolean;
1189
1190
  /** Server-side error detail when the stop failed (`state: 'failed'`). */
@@ -89,6 +89,45 @@
89
89
  "failureAlert": "github_workflow_run",
90
90
  "domainReportRequired": true
91
91
  },
92
+ {
93
+ "id": "github.cloudflare-tunnel-reconciliation",
94
+ "name": "Cloudflare Tunnel Reconciliation",
95
+ "workflowEvents": ["schedule"],
96
+ "scheduler": "github_actions",
97
+ "cadence": "17 6 * * *",
98
+ "timezone": "UTC",
99
+ "source": ".github/workflows/cloudflare-tunnel-reconciliation.yml",
100
+ "locator": "schedule:",
101
+ "owner": "platform",
102
+ "criticality": "maintenance",
103
+ "purpose": "Report and, only after explicit rollout admission, reclaim exact managed developer tunnel UUIDs from current PR and disconnected-idle evidence while retaining protected, connected, legacy and unknown resources.",
104
+ "successDefinition": "Every selected UUID has a retained, deleted or unresolved outcome with durable intent and rate-budget evidence; disabled rollout and zero eligible resources are explicit no-ops, and unresolved outcomes fail the pass.",
105
+ "failureDefinition": "Provider or GitHub authority is unavailable, ownership or idle eligibility is misclassified, deletion remains unresolved, a continuation cannot finish, or immutable intent and outcome evidence is missing.",
106
+ "startGraceMs": 600000,
107
+ "runTimeoutMs": 84600000,
108
+ "failureAlert": "github_workflow_run",
109
+ "domainReportRequired": true
110
+ },
111
+ {
112
+ "id": "github.cloudflare-tunnel-reconciliation-events",
113
+ "name": "Cloudflare Tunnel Reconciliation events",
114
+ "workflowName": "Cloudflare Tunnel Reconciliation",
115
+ "workflowEvents": ["pull_request_target", "workflow_dispatch"],
116
+ "scheduler": "github_actions",
117
+ "cadence": "runAfter trusted same-repository PR close or explicit operator workflow dispatch",
118
+ "timezone": "UTC",
119
+ "source": ".github/workflows/cloudflare-tunnel-reconciliation.yml",
120
+ "locator": "workflow_dispatch:",
121
+ "owner": "platform",
122
+ "criticality": "maintenance",
123
+ "purpose": "Record PR-close and operator tunnel reconciliation separately from the daily cleanup slot, with the same exact ownership, rollout and retained-evidence controls.",
124
+ "successDefinition": "The admitted event pass completes its exact selected UUIDs with durable outcomes; disabled rollout and no eligible resources are explicit no-ops.",
125
+ "failureDefinition": "Event authority, provider truth, continuation or retained evidence is unavailable, or an exact selected UUID remains unresolved.",
126
+ "startGraceMs": 600000,
127
+ "runTimeoutMs": 84600000,
128
+ "failureAlert": "github_workflow_run",
129
+ "domainReportRequired": true
130
+ },
92
131
  {
93
132
  "id": "github.cleanup-stale-preview-infrastructure",
94
133
  "name": "Cleanup Stale Preview Infrastructure",
@@ -189,9 +228,9 @@
189
228
  "locator": "schedule:",
190
229
  "owner": "platform",
191
230
  "criticality": "maintenance",
192
- "purpose": "Reconcile completed PR Preview Machines and release capacity only after the per-app lease fence allows it.",
193
- "successDefinition": "Fly inventory is reconciled and eligible terminal/closed PR capacity is released; no eligible app is a valid no-op.",
194
- "failureDefinition": "Inventory, lease resolution, scale-down, or empty-app cleanup fails or is ambiguous.",
231
+ "purpose": "Reconcile completed PR Preview Machines and release capacity only after the per-app lease fence allows it. Its named-estate lane plans every named Preview estate (eval reuse keys, runtime up preview branch lanes, one-off namespaces) with `bun scripts/fly-preview-estate-lifecycle.ts --report --named-reclaim-plan` and, only on a workflow_dispatch with reclaim_named_estates=true, scales at most 8 planned estates per pass (interrupted reclaims first, then reclaimable estates idle 24 h by lease, release or reclaim evidence) to zero through the claimed runtime-preview-namespace.yml scale-to-zero, recording the start and lane app before the seam, retiring the release lane and recording reclaimed history; scheduled passes only report it.",
232
+ "successDefinition": "Fly inventory is reconciled and eligible terminal/closed PR capacity is released; every named estate is classified without a read failure, and a dispatched named reclaim leaves each target at zero Machines with its release lane retired and reclaimed history written. No eligible app or estate is a valid no-op.",
233
+ "failureDefinition": "Inventory, lease resolution, scale-down, or empty-app cleanup fails or is ambiguous; a named-estate Fly or authority read fails; a named reclaim is refused inside its claim (active owner, used since discovery, ownership or lane-app refusal) or any role keeps a Machine; or any named reclaim is incomplete (started but its release lane was never retired), which fails every pass until a dispatch finishes it.",
195
234
  "startGraceMs": 600000,
196
235
  "runTimeoutMs": 3600000,
197
236
  "failureAlert": "github_workflow_run",
@@ -207,7 +246,7 @@
207
246
  "locator": "schedule:",
208
247
  "owner": "platform",
209
248
  "criticality": "maintenance",
210
- "purpose": "Classify numbered Fly PR Preview estates by PR lifetime and ownership (report only), record organization Machine headroom, and list failed PR-close and post-CI cleanup runs that completed in the previous UTC day.",
249
+ "purpose": "Classify numbered Fly PR Preview estates by PR lifetime and ownership and named estates by the idle clock (report only), record organization Machine headroom, and list failed PR-close and post-CI cleanup runs that completed in the previous UTC day.",
211
250
  "successDefinition": "Every estate is read and classified without a mutation, headroom is recorded, and no event-driven Preview cleanup run that completed in the previous UTC day failed or was left unfinished.",
212
251
  "failureDefinition": "Fly, GitHub, or estate-authority reads fail for an estate, or a PR-close or post-CI cleanup run that completed in the previous UTC day failed, or one is still unfinished after six hours.",
213
252
  "startGraceMs": 600000,
@@ -25,6 +25,107 @@ export type FlyMachine = {
25
25
  // Fly Machines API expects a Go duration string. Never send bare seconds.
26
26
  export const RECEIPT_GATEWAY_DRAIN_TIMEOUT = '300s';
27
27
 
28
+ /** One Fly app of a Preview estate, named by the role it plays. */
29
+ export type EstateRoleApp = { role: string; app: string };
30
+
31
+ const SCALE_TO_ZERO_DELETE_CONCURRENCY = 8;
32
+ // A force delete returns before Fly drops the Machine from its list; one still
33
+ // `destroying` is not a survivor yet. Re-read on a bounded schedule (about a
34
+ // minute in total) before calling it one.
35
+ const SCALE_TO_ZERO_CONFIRM_DELAYS_MS = [
36
+ 2_000, 3_000, 5_000, 5_000, 10_000, 10_000, 10_000, 15_000,
37
+ ] as const;
38
+
39
+ /**
40
+ * Remove every Machine of a Preview estate, role by role, and prove each role
41
+ * reached zero before touching the next. Compute only: apps, images, secrets,
42
+ * the scheduler schema, queue registration and release lanes are the caller's
43
+ * business and are never touched here.
44
+ *
45
+ * The scaler owns worker desired count, so it must be the first role whenever
46
+ * it is present; otherwise it can replace the last worker between the destroy
47
+ * and the zero assertion. A role whose Machines survive the destroy is a loud
48
+ * failure naming the app and Machine IDs, and later roles are left alone so a
49
+ * retry starts from a known order.
50
+ */
51
+ export async function scaleEstateRolesToZero(input: {
52
+ roles: readonly EstateRoleApp[];
53
+ /**
54
+ * Machines in the app that still exist, excluding any Fly reports as
55
+ * `destroyed`; an app that does not exist has none.
56
+ */
57
+ listMachines: (app: string) => Promise<Array<{ id: string; state?: string }>>;
58
+ deleteMachine: (app: string, machineId: string) => Promise<void>;
59
+ log?: (line: string) => void;
60
+ sleep?: (ms: number) => Promise<void>;
61
+ }): Promise<Array<EstateRoleApp & { destroyed: string[] }>> {
62
+ const sleep =
63
+ input.sleep ??
64
+ ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
65
+ if (input.roles.length === 0) {
66
+ throw new Error('Estate scale-to-zero requires at least one role.');
67
+ }
68
+ const scalerIndex = input.roles.findIndex((role) => role.role === 'scaler');
69
+ if (scalerIndex > 0) {
70
+ throw new Error(
71
+ 'Estate scale-to-zero must remove the scaler before any other role.',
72
+ );
73
+ }
74
+ const seen = new Set<string>();
75
+ for (const { role, app } of input.roles) {
76
+ if (!role.trim() || !app.trim()) {
77
+ throw new Error('Estate scale-to-zero roles need a role and an app.');
78
+ }
79
+ if (seen.has(app)) {
80
+ throw new Error(`Estate scale-to-zero repeats app ${app}.`);
81
+ }
82
+ seen.add(app);
83
+ }
84
+
85
+ const results: Array<EstateRoleApp & { destroyed: string[] }> = [];
86
+ for (const { role, app } of input.roles) {
87
+ const machineIds = (await input.listMachines(app))
88
+ .filter((machine) => machine.state !== 'destroying')
89
+ .map((machine) => machine.id);
90
+ for (
91
+ let offset = 0;
92
+ offset < machineIds.length;
93
+ offset += SCALE_TO_ZERO_DELETE_CONCURRENCY
94
+ ) {
95
+ await Promise.all(
96
+ machineIds
97
+ .slice(offset, offset + SCALE_TO_ZERO_DELETE_CONCURRENCY)
98
+ .map((machineId) => input.deleteMachine(app, machineId)),
99
+ );
100
+ }
101
+ let remaining = await input.listMachines(app);
102
+ for (const delayMs of SCALE_TO_ZERO_CONFIRM_DELAYS_MS) {
103
+ // Only Machines Fly is still tearing down may settle on their own; any
104
+ // other survivor fails now rather than waiting out the schedule.
105
+ if (
106
+ remaining.length === 0 ||
107
+ remaining.some((machine) => machine.state !== 'destroying')
108
+ ) {
109
+ break;
110
+ }
111
+ await sleep(delayMs);
112
+ remaining = await input.listMachines(app);
113
+ }
114
+ if (remaining.length > 0) {
115
+ throw new Error(
116
+ `Preview ${role} did not scale to zero Machines: ${app} still has ${remaining
117
+ .map((machine) => `${machine.id}=${machine.state ?? 'unknown'}`)
118
+ .join(', ')}.`,
119
+ );
120
+ }
121
+ input.log?.(
122
+ `[estate-scale-to-zero] ${role} ${app}: destroyed ${machineIds.length}, now 0`,
123
+ );
124
+ results.push({ role, app, destroyed: machineIds });
125
+ }
126
+ return results;
127
+ }
128
+
28
129
  export async function stopAndDestroyCordonedMachines(input: {
29
130
  machineIds: string[];
30
131
  readMachines: () => FlyMachine[] | Promise<FlyMachine[]>;
@@ -5,6 +5,7 @@ import {
5
5
  dispatchRunLedgerOutboxToLedgerThroughEventWithClientScope,
6
6
  type PostgresSchedulerOptions,
7
7
  type PostgresSchedulerOutboxDrainResult,
8
+ type RunLedgerDispatchLaunch,
8
9
  type RunLedgerOutboxWithClient,
9
10
  } from '../../scheduler-backends/postgres';
10
11
 
@@ -17,6 +18,8 @@ export type GatewayRunLedgerProjectionAdapterInput = {
17
18
  * against the active outbox lease while retaining supported transport hooks.
18
19
  */
19
20
  runtimeApi: WorkerRuntimeApiContext;
21
+ /** Immutable launch already read by the worker that committed the terminal. */
22
+ launch?: RunLedgerDispatchLaunch;
20
23
  withClient: RunLedgerOutboxWithClient;
21
24
  schedulerOptions?: Pick<PostgresSchedulerOptions, 'schema'>;
22
25
  };
@@ -35,6 +38,7 @@ export function createGatewayRunLedgerProjectionAdapter(
35
38
  runId: input.runId,
36
39
  runtimeApi: input.runtimeApi,
37
40
  tokenAuthority: 'gateway' as const,
41
+ ...(input.launch ? { dispatchLaunch: input.launch } : {}),
38
42
  ...(input.runtimeApi.signal ? { signal: input.runtimeApi.signal } : {}),
39
43
  };
40
44
  return {
@@ -872,6 +872,7 @@ function buildDefaultDeps(absurd: Absurd): AbsurdRuntimeWorkerDeps {
872
872
  await createRunLedgerProjectionJob({
873
873
  outbox: createGatewayRunLedgerProjectionAdapter({
874
874
  runId,
875
+ launch,
875
876
  runtimeApi: {
876
877
  ...absurdRuntimeApiFromLaunch(launch),
877
878
  ...(signal ? { signal } : {}),