deepline 0.3.392 → 0.3.393

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 (145) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +156 -24
  2. package/dist/bundling-sources/sdk/src/compat.ts +9 -0
  3. package/dist/bundling-sources/sdk/src/http.ts +5 -1
  4. package/dist/bundling-sources/sdk/src/index.ts +5 -0
  5. package/dist/bundling-sources/sdk/src/plays/run-request.ts +182 -6
  6. package/dist/bundling-sources/sdk/src/release.ts +4 -1
  7. package/dist/bundling-sources/sdk/src/types.ts +13 -0
  8. package/dist/bundling-sources/shared_libs/integration-contracts/request-warnings.ts +64 -0
  9. package/dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-storage-contract.ts +315 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +41 -8
  11. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +418 -44
  12. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +36 -3
  13. package/dist/bundling-sources/shared_libs/play-runtime/durable-invocation-fence.ts +36 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +11 -3
  15. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +1 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +19 -1
  17. package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +26 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +158 -10
  19. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +235 -2
  20. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +92 -58
  21. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +7 -1
  22. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +30 -7
  23. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1161 -316
  24. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +28 -15
  25. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +24 -3
  26. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +31 -0
  27. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +37 -4
  28. package/dist/bundling-sources/shared_libs/plays/dataset.ts +172 -79
  29. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +173 -1
  30. package/dist/cli/{auth-6JSA2ZCW.mjs → auth-5PXHA232.mjs} +4 -4
  31. package/dist/cli/auth-P3MVDTXM.js +39 -0
  32. package/dist/cli/{billing-Q5BLQHIU.js → billing-JFB2XLSO.js} +101 -74
  33. package/dist/cli/{billing-MRRO643H.mjs → billing-Z2N7ZAGM.mjs} +32 -5
  34. package/dist/cli/{chunk-CVLM3WMJ.js → chunk-2HAD745V.js} +242 -183
  35. package/dist/cli/{chunk-HGYBEAQP.mjs → chunk-2LGC4EFT.mjs} +3 -3
  36. package/dist/cli/{chunk-A3APGZFP.mjs → chunk-4PT2VA3A.mjs} +2 -2
  37. package/dist/cli/{chunk-6DBOU7UH.js → chunk-4XX6443T.js} +176 -87
  38. package/dist/cli/{chunk-2QLML6G4.mjs → chunk-5KWKZIQR.mjs} +4 -4
  39. package/dist/cli/{chunk-2G7DXFHI.mjs → chunk-5PRVMXKB.mjs} +27 -2
  40. package/dist/cli/{chunk-DSWSEHRX.mjs → chunk-6I73X254.mjs} +1 -1
  41. package/dist/cli/{chunk-ZTACINO5.mjs → chunk-7HR7BGZL.mjs} +13 -3
  42. package/dist/cli/{chunk-BB3FNYFY.js → chunk-AARX5L4B.js} +2 -2
  43. package/dist/cli/{chunk-WMS5U6YB.js → chunk-CDFH2DYL.js} +20 -19
  44. package/dist/cli/{chunk-R3O2CZ4H.mjs → chunk-FQ6VHPW4.mjs} +2 -2
  45. package/dist/cli/{chunk-MU6M3URX.mjs → chunk-HLEESTCH.mjs} +1 -1
  46. package/dist/cli/{chunk-Q6EOHNRH.mjs → chunk-JI2B4RZP.mjs} +119 -6
  47. package/dist/cli/{chunk-2Q3GEFL4.mjs → chunk-KIYU2TGL.mjs} +2 -2
  48. package/dist/cli/{chunk-Y6VOGHF2.mjs → chunk-KZZC33PY.mjs} +0 -181
  49. package/dist/cli/{chunk-UCKJQG25.js → chunk-L2SYLGRP.js} +8 -8
  50. package/dist/cli/{chunk-2GAHHSLB.mjs → chunk-LMMEAMA7.mjs} +3 -2
  51. package/dist/cli/{chunk-YAZCDBXX.mjs → chunk-LZPCDB7U.mjs} +3 -2
  52. package/dist/cli/{chunk-RV6ALZIX.js → chunk-M7Y7JYZX.js} +32 -7
  53. package/dist/cli/{chunk-QGKPTBRR.js → chunk-MS6GUPBB.js} +3 -3
  54. package/dist/cli/{chunk-4SFPVW7A.js → chunk-OXNOAD6Y.js} +26 -26
  55. package/dist/cli/{chunk-JOFPQGXW.js → chunk-PTDECJGP.js} +50 -50
  56. package/dist/cli/{chunk-5O4B6AUN.js → chunk-PWSWAN7Q.js} +25 -2
  57. package/dist/cli/{chunk-YN6YA7ZZ.mjs → chunk-Q26LUSQ2.mjs} +79 -20
  58. package/dist/cli/{chunk-3VN4FTE3.js → chunk-RDXFGPJU.js} +1 -182
  59. package/dist/cli/{chunk-7E66A24V.mjs → chunk-RKMB3N7K.mjs} +25 -2
  60. package/dist/cli/{chunk-JSLPHFP7.js → chunk-RWHWF5ZJ.js} +3 -2
  61. package/dist/cli/{chunk-3FV4GBRK.mjs → chunk-STNYIMIV.mjs} +97 -8
  62. package/dist/cli/chunk-UBKA33KY.mjs +310 -0
  63. package/dist/cli/{chunk-PAIMOGCM.js → chunk-UHNDVD3P.js} +125 -12
  64. package/dist/cli/{chunk-24VEN5PQ.mjs → chunk-UOGZUA24.mjs} +179 -17
  65. package/dist/cli/{chunk-T7OKJ2T6.js → chunk-VIQJIX2P.js} +73 -63
  66. package/dist/cli/{chunk-RIV2GS5E.js → chunk-VIWE6WRK.js} +627 -465
  67. package/dist/cli/{chunk-EY7RFC6A.js → chunk-W4WOMXR3.js} +15 -15
  68. package/dist/cli/chunk-XDVT3GOM.js +310 -0
  69. package/dist/cli/{chunk-2FQG2HU4.js → chunk-Z3OOZM5L.js} +8 -8
  70. package/dist/cli/{csv-E4QGUIGI.mjs → csv-KJWZHKCH.mjs} +3 -3
  71. package/dist/cli/{csv-26U5T24Z.js → csv-P3Z3YE7H.js} +12 -12
  72. package/dist/cli/{db-JTRJIAQW.mjs → db-NCM4CQIS.mjs} +6 -5
  73. package/dist/cli/{db-QHBFLMVL.js → db-NUZGJNQC.js} +31 -30
  74. package/dist/cli/{describe-E3DE3ZK3.mjs → describe-WT6MM2GO.mjs} +17 -16
  75. package/dist/cli/{describe-FDV2V74F.js → describe-YGSEN5WC.js} +24 -23
  76. package/dist/cli/{executions-VZYOGVQY.js → executions-PCOLHN7Q.js} +8 -7
  77. package/dist/cli/{executions-B3GTNPRE.mjs → executions-XS2IPJ4W.mjs} +6 -5
  78. package/dist/cli/{feedback-CR55FJA2.js → feedback-4MSH7TFU.js} +7 -7
  79. package/dist/cli/{feedback-4CEBR3OV.mjs → feedback-CCLTS5SV.mjs} +3 -3
  80. package/dist/cli/{git-NM2PHHZ4.mjs → git-K2DHPMPC.mjs} +4 -4
  81. package/dist/cli/git-RNM45FX4.js +23 -0
  82. package/dist/cli/index.js +96 -92
  83. package/dist/cli/index.mjs +46 -42
  84. package/dist/cli/{legacy-noops-A7MSW5ND.mjs → legacy-noops-B5S4AR3P.mjs} +4 -4
  85. package/dist/cli/{legacy-noops-ZUA4YFIH.js → legacy-noops-GPNOPFXV.js} +7 -7
  86. package/dist/cli/{monitors-NVPRQYP3.mjs → monitors-JLMAIPRG.mjs} +6 -5
  87. package/dist/cli/{monitors-ZE3TLZ4H.js → monitors-ZAWD7NSN.js} +87 -86
  88. package/dist/cli/{org-U7A6DV5D.js → org-P2KN4CES.js} +66 -65
  89. package/dist/cli/{org-KUBILNQV.mjs → org-T3JTHP4G.mjs} +6 -5
  90. package/dist/cli/{play-HRDXQ4QE.mjs → play-NK6BLRGL.mjs} +11 -10
  91. package/dist/cli/play-PDXR6JFB.js +158 -0
  92. package/dist/cli/{providers-OHIWI453.mjs → providers-3NQRA7IT.mjs} +6 -5
  93. package/dist/cli/{providers-VD6YTVQZ.js → providers-5QRZN3DT.js} +9 -8
  94. package/dist/cli/{quickstart-UBV2FONF.mjs → quickstart-PIA2JGPV.mjs} +3 -3
  95. package/dist/cli/{quickstart-ETTCWPA4.js → quickstart-R7NUZGNW.js} +5 -5
  96. package/dist/cli/run-identity-G257GQED.js +25 -0
  97. package/dist/cli/run-identity-MRNCEGV2.mjs +25 -0
  98. package/dist/cli/{search-F44IZRT7.mjs → search-AIDIIGLY.mjs} +7 -6
  99. package/dist/cli/search-QRWL7MFM.js +27 -0
  100. package/dist/cli/{secrets-CAEMRORF.js → secrets-BT3PGMWN.js} +15 -14
  101. package/dist/cli/{secrets-R6XOJZKU.mjs → secrets-OQNHL45O.mjs} +6 -5
  102. package/dist/cli/{sessions-6GC7OFTT.js → sessions-EYXWOSWK.js} +5 -5
  103. package/dist/cli/{sessions-RLN6UQS3.mjs → sessions-SF7WJPJP.mjs} +4 -4
  104. package/dist/cli/{settings-DPNVUAV2.js → settings-BA3GHBOD.js} +76 -75
  105. package/dist/cli/{settings-KIPAMRPP.mjs → settings-Y57JTFDD.mjs} +9 -8
  106. package/dist/cli/{setup-TU2F7PU5.mjs → setup-7GR5GBHA.mjs} +6 -6
  107. package/dist/cli/{setup-DTL3L5SG.js → setup-RERXYC66.js} +41 -41
  108. package/dist/cli/{skills-UV5MYJ46.mjs → skills-SJWIQAV5.mjs} +4 -4
  109. package/dist/cli/skills-V7EY75HB.js +28 -0
  110. package/dist/cli/tools-H5HLBCHH.js +41 -0
  111. package/dist/cli/{tools-QRRNDCQ7.mjs → tools-ZF3JXPNL.mjs} +10 -9
  112. package/dist/cli/update-472HA3LT.js +28 -0
  113. package/dist/cli/{update-4426TF35.mjs → update-FFFYQAOJ.mjs} +6 -6
  114. package/dist/cli/{workflow-HNLOVISB.js → workflow-SZJVQH4T.js} +17 -16
  115. package/dist/cli/{workflow-N4U5VLZ3.mjs → workflow-XVFEEGAS.mjs} +7 -6
  116. package/dist/{client-e6Qh5ZIg.d.mts → client-DU5dtHDy.d.mts} +153 -4
  117. package/dist/{client-Uxuy-xQ2.d.ts → client-mCE88hC4.d.ts} +153 -4
  118. package/dist/{compiler-manifest-CY2v8ab0.d.ts → compiler-manifest-DE4RdAiY.d.mts} +61 -1
  119. package/dist/{compiler-manifest-CY2v8ab0.d.mts → compiler-manifest-DE4RdAiY.d.ts} +61 -1
  120. package/dist/{index-B9fBZH1g.d.mts → index-BI6nWgaV.d.mts} +1 -1
  121. package/dist/{index-BZ6uzZJl.d.ts → index-Bi-f7HFT.d.ts} +1 -1
  122. package/dist/index.d.mts +5 -5
  123. package/dist/index.d.ts +5 -5
  124. package/dist/index.js +120 -29
  125. package/dist/index.mjs +111 -20
  126. package/dist/install-integrity.json +91 -86
  127. package/dist/plays/bundle-play-file.d.mts +3 -3
  128. package/dist/plays/bundle-play-file.d.ts +3 -3
  129. package/dist/plays/bundle-play-file.mjs +2 -2
  130. package/dist/plays/run-request.d.mts +2 -2
  131. package/dist/plays/run-request.d.ts +2 -2
  132. package/dist/plays/run-request.js +5 -2
  133. package/dist/plays/run-request.mjs +4 -1
  134. package/dist/release.d.mts +4 -1
  135. package/dist/release.d.ts +4 -1
  136. package/dist/release.js +2 -2
  137. package/dist/release.mjs +1 -1
  138. package/package.json +1 -1
  139. package/dist/cli/auth-67TAELQL.js +0 -39
  140. package/dist/cli/git-I5JTK6YU.js +0 -23
  141. package/dist/cli/play-A2V7YDU7.js +0 -157
  142. package/dist/cli/search-WWXMBVPH.js +0 -26
  143. package/dist/cli/skills-SWOSEZLB.js +0 -28
  144. package/dist/cli/tools-IL2YCDQ6.js +0 -40
  145. package/dist/cli/update-BERDPEYR.js +0 -28
@@ -148,14 +148,15 @@ import { isStopAllPlayRunsDryRunResult } from './types';
148
148
  import type { MonitorDefinition } from './monitors';
149
149
  import type { MonitorFleetDefinition } from './monitor-fleets';
150
150
  import type { PlayStagedFileRef } from './plays/local-file-discovery';
151
+ import type { RuntimeSheetRunRowMembershipPage } from '../../shared_libs/play-data-plane/runtime-sheet-storage-contract';
151
152
  import {
152
- buildPlayRunStartBody,
153
153
  isPlayRunPackage,
154
154
  mintStagedPlayFileUploads,
155
155
  normalizePlayRunStart,
156
156
  PLAY_RUN_START_STREAM_PATH,
157
157
  stagePlayFiles,
158
158
  startPlayRun,
159
+ preparePlayRunAdmission,
159
160
  type MintStagedFileUpload,
160
161
  type ResolvedStartPlayRunRequest,
161
162
  } from './plays/run-request';
@@ -366,8 +367,7 @@ function resolvePlayRunRuntimeSelection(
366
367
  // app free to use its native runtime (local for a local app, prod for prod).
367
368
  const configured = env.DEEPLINE_RUNTIME_ENVIRONMENT?.trim();
368
369
  const configuredNamespace = env.DEEPLINE_RUNTIME_NAMESPACE?.trim();
369
- const configuredToken =
370
- env.DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN?.trim();
370
+ const configuredToken = env.DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN?.trim();
371
371
  const configuredPlacementPolicy =
372
372
  env.DEEPLINE_RUNTIME_SANDBOX_PLACEMENT_POLICY?.trim();
373
373
  if (!configured) {
@@ -412,8 +412,7 @@ function resolvePlayRunRuntimeSelection(
412
412
  'INVALID_RUNTIME_NAMESPACE',
413
413
  );
414
414
  }
415
- const configuredBackendValue =
416
- env.DEEPLINE_PLAY_RUNNER_BACKEND?.trim();
415
+ const configuredBackendValue = env.DEEPLINE_PLAY_RUNNER_BACKEND?.trim();
417
416
  const configuredBackend =
418
417
  configuredBackendValue === 'daytona' || configuredBackendValue === 'modal'
419
418
  ? configuredBackendValue
@@ -487,8 +486,7 @@ function runtimeSelectionHeaders(
487
486
  'RUNTIME_ENVIRONMENT_TOKEN_REQUIRED',
488
487
  );
489
488
  }
490
- const receivers =
491
- env.DEEPLINE_RUNTIME_RETAINED_PIPELINE_RECEIVERS?.trim();
489
+ const receivers = env.DEEPLINE_RUNTIME_RETAINED_PIPELINE_RECEIVERS?.trim();
492
490
  return {
493
491
  [RUNTIME_ENVIRONMENT_TOKEN_HEADER]: token,
494
492
  ...(receivers ? { [RETAINED_PIPELINE_RECEIVERS_HEADER]: receivers } : {}),
@@ -1101,6 +1099,14 @@ export type PlaySheetRowsResult = {
1101
1099
  deltaCursor?: number;
1102
1100
  };
1103
1101
 
1102
+ export type PlayRunRowHistoryOptions = {
1103
+ playName: string;
1104
+ runId: string;
1105
+ tableNamespace: string;
1106
+ limit?: number;
1107
+ cursor?: string;
1108
+ };
1109
+
1104
1110
  export type PlaySecretMetadata = {
1105
1111
  _id: string;
1106
1112
  orgId: string;
@@ -1185,6 +1191,10 @@ export type RunsNamespace = {
1185
1191
  /** Cancel the page request, including its response body and retry waits. */
1186
1192
  signal?: AbortSignal;
1187
1193
  }) => Promise<PlaySheetRowsResult>;
1194
+ /** One immutable history page; incomplete legacy coverage stays explicit. */
1195
+ rowHistory: (
1196
+ input: PlayRunRowHistoryOptions,
1197
+ ) => Promise<RuntimeSheetRunRowMembershipPage>;
1188
1198
  /** Stop a running/waiting run. */
1189
1199
  stop: (
1190
1200
  runId: string,
@@ -2504,6 +2514,8 @@ export type BillingUsageResult = {
2504
2514
  * @sdkReference client 030 client.billing
2505
2515
  */
2506
2516
  export type BillingNamespace = {
2517
+ /** Read a bounded sandbox-session estimate; excludes tools and Customer DB. */
2518
+ quote: (input: BillingQuoteRequest) => Promise<BillingQuoteResult>;
2507
2519
  /** Current workspace provider benefits; discovery does not authorize a call. */
2508
2520
  entitlements: () => Promise<BillingEntitlements>;
2509
2521
  /** Charge the saved payment method and add Deepline credits to the active workspace. */
@@ -2572,6 +2584,30 @@ export type BillingNamespace = {
2572
2584
  }) => Promise<{ url: string }>;
2573
2585
  };
2574
2586
 
2587
+ export type BillingQuoteRequest = {
2588
+ quantity: number;
2589
+ sandbox_runtime: { timeout?: string; size?: 'standard' };
2590
+ };
2591
+
2592
+ export type BillingQuoteResult = {
2593
+ scope: 'sandbox_session';
2594
+ quantity: number;
2595
+ resources: {
2596
+ timeoutSeconds: number;
2597
+ memoryGiB: number;
2598
+ cpu: number;
2599
+ diskGiB: number;
2600
+ };
2601
+ maximum_credits: number;
2602
+ maximum_billing_seconds: number;
2603
+ total_play_credits: null;
2604
+ total_budget_supported: false;
2605
+ unbounded_components: string[];
2606
+ explanation: string;
2607
+ plan_version_id: string;
2608
+ rate_card_id: string;
2609
+ };
2610
+
2575
2611
  function isRecord(value: unknown): value is Record<string, unknown> {
2576
2612
  return Boolean(value && typeof value === 'object' && !Array.isArray(value));
2577
2613
  }
@@ -2918,6 +2954,7 @@ export class DeeplineClient {
2918
2954
  input: (runId) => this.getRunInput(runId),
2919
2955
  rerun: (runId, options) => this.rerun(runId, options),
2920
2956
  exportDatasetRows: (input) => this.getPlaySheetRows(input),
2957
+ rowHistory: (input) => this.getPlayRunRowHistory(input),
2921
2958
  stop: (runId, options) => this.stopRun(runId, options),
2922
2959
  stopAll: ((options?: StopAllRunsOptions) =>
2923
2960
  this.stopAllRuns(options)) as RunsNamespace['stopAll'],
@@ -2927,6 +2964,8 @@ export class DeeplineClient {
2927
2964
  planQuery: (input) => planCustomerDbQuery(input),
2928
2965
  };
2929
2966
  this.billing = {
2967
+ quote: (input) =>
2968
+ this.http.post<BillingQuoteResult>('/api/v2/billing/quote', input),
2930
2969
  entitlements: () => this.http.get('/api/v2/billing/entitlements'),
2931
2970
  topUp: (options) => this.topUpBillingBalance(options),
2932
2971
  topUpWithReceipt: (options) =>
@@ -3564,15 +3603,85 @@ export class DeeplineClient {
3564
3603
  * });
3565
3604
  * ```
3566
3605
  */
3567
- async startPlayRun(request: StartPlayRunRequest): Promise<PlayRunStart> {
3606
+ async startPlayRun(
3607
+ request: StartPlayRunRequest,
3608
+ options?: {
3609
+ onSubmission?: (intent: {
3610
+ workflowId: string;
3611
+ orgId: string;
3612
+ request: Record<string, unknown>;
3613
+ }) => void | Promise<void>;
3614
+ },
3615
+ ): Promise<PlayRunStart> {
3568
3616
  const resolved = resolveStartPlayRunRequest(request, this.environment);
3569
3617
  return startPlayRun(
3570
3618
  this.http,
3571
3619
  resolved.request,
3572
3620
  runtimeSelectionHeaders(resolved.runtime, this.environment),
3621
+ options?.onSubmission,
3573
3622
  );
3574
3623
  }
3575
3624
 
3625
+ /**
3626
+ * Prepare a tenant-scoped start intent without executing it. Its stream
3627
+ * sender retains the exact body and transport selected during preparation.
3628
+ */
3629
+ async preparePlayRunAdmission(
3630
+ request: StartPlayRunRequest,
3631
+ options?: {
3632
+ onSubmission?: (intent: {
3633
+ workflowId: string;
3634
+ orgId: string;
3635
+ request: Record<string, unknown>;
3636
+ }) => void | Promise<void>;
3637
+ },
3638
+ ) {
3639
+ const resolved = resolveStartPlayRunRequest(request, this.environment);
3640
+ const prepared = await preparePlayRunAdmission(
3641
+ this.http,
3642
+ resolved.request,
3643
+ options?.onSubmission,
3644
+ );
3645
+ const bodyJson = JSON.stringify(prepared.body);
3646
+ const headers = runtimeSelectionHeaders(resolved.runtime, this.environment);
3647
+ const http = this.http;
3648
+ let submitted = false;
3649
+ return {
3650
+ ...prepared,
3651
+ async *startStream(streamOptions?: { signal?: AbortSignal }) {
3652
+ if (submitted && !prepared.supportsCallerIntent) {
3653
+ throw new DeeplineError(
3654
+ 'This server has not enabled caller-owned admission recovery. Do not retry an ambiguous start.',
3655
+ 409,
3656
+ 'PLAY_RUN_ADMISSION_RECOVERY_UNSUPPORTED',
3657
+ );
3658
+ }
3659
+ if (submitted) {
3660
+ // A later transport attempt may reach a rolled-back server or a
3661
+ // different workspace. Re-prove support for the pinned intent,
3662
+ // without rebuilding it or persisting another submission journal.
3663
+ await preparePlayRunAdmission(
3664
+ http,
3665
+ JSON.parse(bodyJson) as ResolvedStartPlayRunRequest,
3666
+ );
3667
+ }
3668
+ submitted = true;
3669
+ for await (const event of http.streamSse<PlayLiveEvent>(
3670
+ PLAY_RUN_START_STREAM_PATH,
3671
+ {
3672
+ method: 'POST',
3673
+ body: JSON.parse(bodyJson),
3674
+ headers,
3675
+ signal: streamOptions?.signal,
3676
+ exactUrlOnly: true,
3677
+ },
3678
+ )) {
3679
+ if (event.scope === 'play') yield event;
3680
+ }
3681
+ },
3682
+ };
3683
+ }
3684
+
3576
3685
  /**
3577
3686
  * Submit a play run through the legacy event response.
3578
3687
  *
@@ -3588,23 +3697,17 @@ export class DeeplineClient {
3588
3697
  */
3589
3698
  async *startPlayRunStream(
3590
3699
  request: StartPlayRunRequest,
3591
- options?: { signal?: AbortSignal },
3700
+ options?: {
3701
+ signal?: AbortSignal;
3702
+ onSubmission?: (intent: {
3703
+ workflowId: string;
3704
+ orgId: string;
3705
+ request: Record<string, unknown>;
3706
+ }) => void | Promise<void>;
3707
+ },
3592
3708
  ): AsyncGenerator<PlayLiveEvent> {
3593
- const resolved = resolveStartPlayRunRequest(request, this.environment);
3594
- const body = buildPlayRunStartBody(resolved.request);
3595
- for await (const event of this.http.streamSse<PlayLiveEvent>(
3596
- PLAY_RUN_START_STREAM_PATH,
3597
- {
3598
- method: 'POST',
3599
- body,
3600
- headers: runtimeSelectionHeaders(resolved.runtime, this.environment),
3601
- signal: options?.signal,
3602
- },
3603
- )) {
3604
- if (event.scope === 'play') {
3605
- yield event;
3606
- }
3607
- }
3709
+ const prepared = await this.preparePlayRunAdmission(request, options);
3710
+ yield* prepared.startStream({ signal: options?.signal });
3608
3711
  }
3609
3712
 
3610
3713
  /**
@@ -5034,6 +5137,24 @@ export class DeeplineClient {
5034
5137
  );
5035
5138
  }
5036
5139
 
5140
+ /**
5141
+ * Read one page of immutable admitted and terminal rows for a Play Run dataset.
5142
+ * Follow nextCursor; coverage explicitly identifies unavailable or incomplete history.
5143
+ */
5144
+ async getPlayRunRowHistory(
5145
+ input: PlayRunRowHistoryOptions,
5146
+ ): Promise<RuntimeSheetRunRowMembershipPage> {
5147
+ const params = new URLSearchParams({
5148
+ runId: input.runId,
5149
+ tableNamespace: input.tableNamespace,
5150
+ });
5151
+ if (input.limit !== undefined) params.set('limit', String(input.limit));
5152
+ if (input.cursor !== undefined) params.set('cursor', input.cursor);
5153
+ return this.http.get(
5154
+ `/api/v2/plays/${encodeURIComponent(input.playName)}/sheet/history?${params}`,
5155
+ );
5156
+ }
5157
+
5037
5158
  /**
5038
5159
  * Export persisted runtime-sheet rows for a play dataset/table namespace.
5039
5160
  *
@@ -5328,6 +5449,17 @@ export class DeeplineClient {
5328
5449
  return this.http.get('/api/v2/settings/notifications');
5329
5450
  }
5330
5451
 
5452
+ /** Save provider-owned credential fields without starting an OAuth browser flow. */
5453
+ async setIntegrationCredentials(
5454
+ provider: string,
5455
+ credentials: Record<string, string>,
5456
+ ): Promise<{ ok: boolean; credential_saved?: boolean }> {
5457
+ return this.http.post('/api/v2/integrations/connect', {
5458
+ provider,
5459
+ credentials,
5460
+ });
5461
+ }
5462
+
5331
5463
  /** Start the Slack OAuth flow required by product notifications. */
5332
5464
  async connectNotificationSlack(options?: {
5333
5465
  successUrl?: string;
@@ -1,4 +1,5 @@
1
1
  import { SDK_API_CONTRACT, SDK_API_MAJOR, SDK_VERSION } from './version.js';
2
+ import { SDK_RELEASE } from './release.js';
2
3
  import { randomUUID } from 'node:crypto';
3
4
  import {
4
5
  existsSync,
@@ -62,6 +63,10 @@ export type SdkCompatibilityResponse = {
62
63
 
63
64
  export type SdkCompatibilitySkillsUpdate = {
64
65
  needs_update: boolean;
66
+ /** Preserve installed skills until this CLI can execute the new guidance. */
67
+ requires_cli_update?: boolean;
68
+ minimum_cli_version?: string;
69
+ required_cli_capability?: number;
65
70
  local: {
66
71
  version: string | null;
67
72
  };
@@ -366,6 +371,10 @@ export async function checkSdkCompatibility(
366
371
  }
367
372
  if (options.skillsVersion !== undefined) {
368
373
  url.searchParams.set('skills_version', options.skillsVersion ?? '');
374
+ url.searchParams.set(
375
+ 'skills_cli_capability',
376
+ String(SDK_RELEASE.packageCapabilities.skillsGuidance),
377
+ );
369
378
  }
370
379
  if (options.catalog) {
371
380
  url.searchParams.set('catalog_tool_id', options.catalog.toolId);
@@ -104,6 +104,7 @@ interface StreamOptions {
104
104
  body?: unknown;
105
105
  headers?: Record<string, string>;
106
106
  signal?: AbortSignal;
107
+ exactUrlOnly?: boolean;
107
108
  }
108
109
 
109
110
  type RequestAbortTaggedError = Error & {
@@ -813,7 +814,10 @@ export class HttpClient {
813
814
  }
814
815
  let lastError: Error | null = null;
815
816
 
816
- for (const candidateUrl of buildCandidateUrls(url)) {
817
+ const candidateUrls = options?.exactUrlOnly
818
+ ? [url]
819
+ : buildCandidateUrls(url);
820
+ for (const candidateUrl of candidateUrls) {
817
821
  try {
818
822
  const response = await fetch(candidateUrl, {
819
823
  method,
@@ -116,6 +116,9 @@ export type {
116
116
  BillingInvoiceEntry,
117
117
  BillingInvoicesResult,
118
118
  BillingNamespace,
119
+ BillingQuoteRequest,
120
+ BillingQuoteResult,
121
+ PlayRunRowHistoryOptions,
119
122
  BillingRecentUsageEntry,
120
123
  DbNamespace,
121
124
  BillingPaymentMethodSummary,
@@ -313,6 +316,8 @@ export type {
313
316
  ResolvedConfig,
314
317
  ToolDefinition,
315
318
  ToolMetadata,
319
+ ToolRequestCondition,
320
+ ToolRequestWarningRule,
316
321
  LiveEventEnvelope,
317
322
  PlayLiveEvent,
318
323
  PlayRunResult,
@@ -17,6 +17,10 @@
17
17
  */
18
18
  import { DeeplineError } from '../../../shared_libs/plays/tool-execution-error';
19
19
  import { isTerminalPlayRunLifecycleStatus } from '../../../shared_libs/play-runtime/run-lifecycle-policy.js';
20
+ import {
21
+ buildCallerPlayWorkflowId,
22
+ callerPlayWorkflowIdMatchesRequest,
23
+ } from '../../../shared_libs/play-runtime/run-identity';
20
24
  import { apiErrorCodeFromResponse, apiErrorMessage } from '../api-error';
21
25
  import type {
22
26
  PlayRunPackage,
@@ -40,6 +44,7 @@ export const PLAY_FILES_STAGE_MINT_PATH = `${PLAY_FILES_STAGE_PATH}/mint`;
40
44
  * responses so the staging fallbacks below classify failures identically.
41
45
  */
42
46
  export interface PlayRunHttp {
47
+ get?<T = unknown>(path: string): Promise<T>;
43
48
  post<T = unknown>(
44
49
  path: string,
45
50
  body: unknown,
@@ -66,6 +71,13 @@ export function buildPlayRunStartBody(
66
71
  request: ResolvedStartPlayRunRequest,
67
72
  ): Record<string, unknown> {
68
73
  return {
74
+ ...(request.admissionOrgId
75
+ ? { admissionOrgId: request.admissionOrgId }
76
+ : {}),
77
+ ...(request.workflowId ? { workflowId: request.workflowId } : {}),
78
+ ...(request.maxTotalCredits !== undefined
79
+ ? { maxTotalCredits: request.maxTotalCredits }
80
+ : {}),
69
81
  ...(request.name ? { name: request.name } : {}),
70
82
  ...(request.revisionId ? { revisionId: request.revisionId } : {}),
71
83
  ...(request.artifactStorageKey
@@ -134,17 +146,180 @@ export function buildPlayRunStartBody(
134
146
  * or times out, and retrying without an idempotency key can create a second
135
147
  * root run, so callers resolve ambiguous failures explicitly.
136
148
  */
149
+ export async function preparePlayRunAdmission(
150
+ http: PlayRunHttp,
151
+ request: ResolvedStartPlayRunRequest,
152
+ onSubmission?: (intent: {
153
+ workflowId: string;
154
+ orgId: string;
155
+ request: Record<string, unknown>;
156
+ }) => void | Promise<void>,
157
+ ): Promise<{
158
+ body: Record<string, unknown>;
159
+ workflowId?: string;
160
+ supportsCallerIntent: boolean;
161
+ }> {
162
+ // The reader ships before the writer. An older route ignores workflowId;
163
+ // that response cannot prove an identity can be reused safely after a timeout.
164
+ let capability: {
165
+ admissionContract?: string;
166
+ strictTotalBudget?: string;
167
+ orgId?: string;
168
+ } | null = null;
169
+ if (http.get) {
170
+ try {
171
+ capability = await http.get(PLAY_RUN_START_PATH);
172
+ } catch (error) {
173
+ if (
174
+ !(error instanceof DeeplineError) ||
175
+ ![404, 405].includes(error.statusCode ?? 0)
176
+ )
177
+ throw error;
178
+ // Only an authoritative absent route proves an older server. A timeout,
179
+ // 503, or authentication denial must never switch to an unkeyed writer.
180
+ }
181
+ if (
182
+ capability &&
183
+ !['caller-intent-v1', 'unsupported'].includes(
184
+ capability.admissionContract ?? '',
185
+ )
186
+ ) {
187
+ throw new DeeplineError(
188
+ 'The server admission capability response is unknown; execution was not submitted.',
189
+ 503,
190
+ 'PLAY_RUN_ADMISSION_CAPABILITY_UNKNOWN',
191
+ );
192
+ }
193
+ }
194
+ const supportsCallerIntent =
195
+ capability?.admissionContract === 'caller-intent-v1';
196
+ if (
197
+ supportsCallerIntent &&
198
+ (!capability?.orgId ||
199
+ (request.admissionOrgId && request.admissionOrgId !== capability.orgId))
200
+ ) {
201
+ throw new DeeplineError(
202
+ 'The admission workspace could not be pinned to this request; execution was not submitted.',
203
+ 409,
204
+ 'PLAY_RUN_ADMISSION_TENANT_CONFLICT',
205
+ );
206
+ }
207
+ if (request.workflowId && !supportsCallerIntent) {
208
+ throw new DeeplineError(
209
+ 'This server has not enabled caller-owned admission recovery. Do not retry an ambiguous start.',
210
+ 409,
211
+ 'PLAY_RUN_ADMISSION_RECOVERY_UNSUPPORTED',
212
+ );
213
+ }
214
+ if (
215
+ request.maxTotalCredits !== undefined &&
216
+ capability?.strictTotalBudget !== 'fail-closed-v1'
217
+ ) {
218
+ throw new DeeplineError(
219
+ 'This server cannot honor a strict total Play budget. Execution was not submitted.',
220
+ 409,
221
+ 'PLAY_TOTAL_BUDGET_UNSUPPORTED',
222
+ );
223
+ }
224
+ // Snapshot the exact JSON representation once. Date/toJSON/undefined and
225
+ // nonfinite values must hash to precisely the bytes the server will parse.
226
+ const wireBody = JSON.parse(
227
+ JSON.stringify(
228
+ buildPlayRunStartBody({
229
+ ...request,
230
+ ...(supportsCallerIntent ? { admissionOrgId: capability!.orgId } : {}),
231
+ }),
232
+ ),
233
+ ) as Record<string, unknown>;
234
+ const workflowId = supportsCallerIntent
235
+ ? (request.workflowId ??
236
+ buildCallerPlayWorkflowId(request.name ?? 'play', wireBody))
237
+ : undefined;
238
+ const submittedBody = workflowId ? { workflowId, ...wireBody } : wireBody;
239
+ if (
240
+ workflowId &&
241
+ !callerPlayWorkflowIdMatchesRequest(workflowId, submittedBody)
242
+ ) {
243
+ throw new DeeplineError(
244
+ 'workflowId must be the caller run ID of this same immutable request.',
245
+ 400,
246
+ 'PLAY_RUN_START_INTENT_CONFLICT',
247
+ );
248
+ }
249
+ if (onSubmission) {
250
+ if (!workflowId || !capability?.orgId) {
251
+ throw new DeeplineError(
252
+ 'This server cannot persist a recoverable submission intent. Execution was not submitted.',
253
+ 409,
254
+ 'PLAY_RUN_ADMISSION_RECOVERY_UNSUPPORTED',
255
+ );
256
+ }
257
+ await onSubmission({
258
+ workflowId,
259
+ orgId: capability.orgId,
260
+ request: submittedBody,
261
+ });
262
+ }
263
+ return { body: submittedBody, workflowId, supportsCallerIntent };
264
+ }
265
+
137
266
  export async function startPlayRun(
138
267
  http: PlayRunHttp,
139
268
  request: ResolvedStartPlayRunRequest,
140
269
  headers?: Record<string, string>,
270
+ onSubmission?: (intent: {
271
+ workflowId: string;
272
+ orgId: string;
273
+ request: Record<string, unknown>;
274
+ }) => void | Promise<void>,
141
275
  ): Promise<PlayRunStart> {
142
- const response = await http.post<Record<string, unknown>>(
143
- PLAY_RUN_START_PATH,
144
- buildPlayRunStartBody(request),
145
- headers,
146
- { maxRetries: 0, exactUrlOnly: true },
147
- );
276
+ const {
277
+ body: submittedBody,
278
+ workflowId,
279
+ supportsCallerIntent,
280
+ } = await preparePlayRunAdmission(http, request, onSubmission);
281
+ let response: Record<string, unknown>;
282
+ try {
283
+ response = await http.post<Record<string, unknown>>(
284
+ PLAY_RUN_START_PATH,
285
+ submittedBody,
286
+ headers,
287
+ { maxRetries: 0, exactUrlOnly: true },
288
+ );
289
+ } catch (error) {
290
+ if (
291
+ (error instanceof DeeplineError &&
292
+ ['NETWORK_TIMEOUT', 'NETWORK_ERROR', 'FETCH_FAILED'].includes(
293
+ error.code ?? '',
294
+ )) ||
295
+ error instanceof TypeError ||
296
+ (error instanceof Error &&
297
+ ['AbortError', 'TimeoutError'].includes(error.name))
298
+ ) {
299
+ const originalMessage =
300
+ error instanceof Error ? error.message : 'Transport failed';
301
+ const failure = new DeeplineError(
302
+ workflowId
303
+ ? `${originalMessage} Admission outcome is unknown for ${workflowId}. Inspect this run before retrying; reuse this workflowId for the same immutable request.`
304
+ : `${originalMessage} Admission outcome is unknown. This server did not prove caller-owned recovery support; inspect existing runs before starting again.`,
305
+ error instanceof DeeplineError ? error.statusCode : undefined,
306
+ error instanceof DeeplineError ? error.code : 'NETWORK_ERROR',
307
+ {
308
+ ...(workflowId ? { runId: workflowId, workflowId } : {}),
309
+ admissionState: 'unknown',
310
+ recoverySupported: supportsCallerIntent,
311
+ next: {
312
+ inspect: workflowId
313
+ ? `deepline runs get ${workflowId} --json`
314
+ : 'deepline runs list --json',
315
+ },
316
+ },
317
+ );
318
+ Object.assign(failure, { cause: error });
319
+ throw failure;
320
+ }
321
+ throw error;
322
+ }
148
323
  return normalizePlayRunStart(response);
149
324
  }
150
325
 
@@ -843,6 +1018,7 @@ export function createSessionPlayRunHttp(
843
1018
  return parsed as T;
844
1019
  };
845
1020
  return {
1021
+ get: (path) => send(path, { method: 'GET' }),
846
1022
  post: (path, body, headers) =>
847
1023
  send(path, {
848
1024
  method: 'POST',
@@ -147,6 +147,8 @@ export type SdkRelease = {
147
147
  /** Capabilities stamped into the published package's `deepline` metadata. */
148
148
  packageCapabilities: {
149
149
  updatePreferences: 1;
150
+ /** Skill guidance/command surface understood by this built package. */
151
+ skillsGuidance: 1;
150
152
  };
151
153
  /** Named compatibility policies. This is the only authored contract policy. */
152
154
  contracts: DeeplineContractPolicy;
@@ -200,11 +202,12 @@ export const SDK_RELEASE = {
200
202
  // getters keep their established compatibility behavior.
201
203
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
204
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
203
- version: '0.3.392',
205
+ version: '0.3.393',
204
206
  updateSummary:
205
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.',
206
208
  packageCapabilities: {
207
209
  updatePreferences: 1,
210
+ skillsGuidance: 1,
208
211
  },
209
212
  contracts: {
210
213
  api: {
@@ -1,4 +1,9 @@
1
1
  import type { PlaySettings } from '../../shared_libs/plays/settings-contract';
2
+ import type { ToolRequestWarningRule } from '../../shared_libs/integration-contracts/request-warnings';
3
+ export type {
4
+ ToolRequestCondition,
5
+ ToolRequestWarningRule,
6
+ } from '../../shared_libs/integration-contracts/request-warnings';
2
7
  import type { PlayCompilerManifest } from '../../shared_libs/plays/compiler-manifest';
3
8
  import type { RunGetStatus, RunLifecycleStatus } from './client';
4
9
  import type { PlayGrepMatch } from '../../shared_libs/plays/play-grep-search';
@@ -376,6 +381,8 @@ export interface ToolDefinition extends ToolExecutionMetadataFields {
376
381
  message: string;
377
382
  execution?: 'terminal' | 'forward';
378
383
  };
384
+ /** Ordered server-authored request warnings. The CLI prints the first match before dispatch. */
385
+ requestWarnings?: readonly ToolRequestWarningRule[];
379
386
  /**
380
387
  * Connection status for discovery: `managed` (Deepline-run credentials),
381
388
  * `connected` (your own credential is connected), or `requires_connection`
@@ -2090,6 +2097,12 @@ export interface PlayCheckToolGetterHint {
2090
2097
  * ```
2091
2098
  */
2092
2099
  export interface StartPlayRunRequest {
2100
+ /** Tenant pin supplied by admission capability discovery; recovery must preserve it. */
2101
+ admissionOrgId?: string;
2102
+ /** Caller-owned canonical run ID. Reuse it to reconcile or replay an ambiguous start. */
2103
+ workflowId?: string;
2104
+ /** Strict total Deepline spend ceiling, including compute. Unbounded workloads are refused before admission. */
2105
+ maxTotalCredits?: number;
2093
2106
  /** Play name for registered revisions. */
2094
2107
  name?: string;
2095
2108
  /** Explicit revision ID when the caller wants a specific saved version. */