deepline 0.3.258 → 0.3.259

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 (67) hide show
  1. package/dist/bundling-sources/sdk/src/api-error.ts +45 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +98 -459
  3. package/dist/bundling-sources/sdk/src/http.ts +1 -34
  4. package/dist/bundling-sources/sdk/src/index.ts +8 -0
  5. package/dist/bundling-sources/sdk/src/plays/csv-data-input.ts +139 -0
  6. package/dist/bundling-sources/sdk/src/plays/run-request.ts +855 -0
  7. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  8. package/dist/bundling-sources/sdk/src/runs/overview.ts +45 -2
  9. package/dist/bundling-sources/sdk/src/types.ts +5 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +8 -0
  11. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +42 -10
  12. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +3 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +23 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +3 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/play-admission-outcome.ts +23 -5
  16. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +1 -1
  17. package/dist/bundling-sources/shared_libs/play-runtime/run-execution-state.ts +845 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +106 -6
  19. package/dist/bundling-sources/shared_libs/play-runtime/run-observation.ts +440 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +35 -2
  21. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +66 -7
  22. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +0 -29
  23. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -2
  24. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +6 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +475 -36
  26. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +78 -11
  27. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +550 -42
  28. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +181 -8
  29. package/dist/bundling-sources/shared_libs/play-runtime/step-lifecycle-tracker.ts +0 -18
  30. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +80 -7
  31. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +37 -2
  32. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +148 -18
  33. package/dist/bundling-sources/shared_libs/plays/cascade-falloff.ts +86 -0
  34. package/dist/bundling-sources/shared_libs/plays/docflow-unreached-reason.ts +611 -0
  35. package/dist/bundling-sources/shared_libs/plays/docflow.ts +21 -0
  36. package/dist/bundling-sources/shared_libs/plays/play-exports.ts +28 -5
  37. package/dist/bundling-sources/shared_libs/plays/settings-contract.ts +92 -10
  38. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +5 -0
  39. package/dist/bundling-sources/shared_libs/plays/trigger-config-contract.ts +222 -0
  40. package/dist/bundling-sources/shared_libs/plays/trigger-config-route.ts +15 -0
  41. package/dist/cli/index.js +4957 -771
  42. package/dist/cli/index.mjs +4957 -771
  43. package/dist/client-B5XbKrrs.d.mts +6564 -0
  44. package/dist/client-C9Y49yya.d.ts +6564 -0
  45. package/dist/{compiler-manifest-C4mdRJOP.d.mts → compiler-manifest-CUuh8C3b.d.mts} +14 -1
  46. package/dist/{compiler-manifest-C4mdRJOP.d.ts → compiler-manifest-CUuh8C3b.d.ts} +14 -1
  47. package/dist/index.d.mts +7 -6275
  48. package/dist/index.d.ts +7 -6275
  49. package/dist/index.js +360 -326
  50. package/dist/index.mjs +360 -326
  51. package/dist/install-integrity.json +21 -2
  52. package/dist/plays/bundle-play-file.d.mts +2 -2
  53. package/dist/plays/bundle-play-file.d.ts +2 -2
  54. package/dist/plays/bundle-play-file.mjs +117 -18
  55. package/dist/plays/csv-data-input.d.mts +37 -0
  56. package/dist/plays/csv-data-input.d.ts +37 -0
  57. package/dist/plays/csv-data-input.js +3135 -0
  58. package/dist/plays/csv-data-input.mjs +3108 -0
  59. package/dist/plays/run-request.d.mts +6 -0
  60. package/dist/plays/run-request.d.ts +6 -0
  61. package/dist/plays/run-request.js +664 -0
  62. package/dist/plays/run-request.mjs +614 -0
  63. package/dist/release.d.mts +1 -1
  64. package/dist/release.d.ts +1 -1
  65. package/dist/release.js +1 -1
  66. package/dist/release.mjs +1 -1
  67. package/package.json +12 -1
package/dist/index.mjs CHANGED
@@ -1,3 +1,8 @@
1
+ // ../plays/trigger-config-route.ts
2
+ function playTriggerConfigPath(playName) {
3
+ return `/api/v2/plays/${encodeURIComponent(playName)}/triggers`;
4
+ }
5
+
1
6
  // src/pagination.ts
2
7
  async function* iterateCursorPages(fetchPage) {
3
8
  let cursor = null;
@@ -1224,7 +1229,7 @@ var SDK_RELEASE = {
1224
1229
  // getters keep their established compatibility behavior.
1225
1230
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1226
1231
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
1227
- version: "0.3.258",
1232
+ version: "0.3.259",
1228
1233
  updateSummary: "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.",
1229
1234
  packageCapabilities: {
1230
1235
  updatePreferences: 1
@@ -1360,6 +1365,30 @@ var SDK_VERSION = SDK_RELEASE.version;
1360
1365
  var SDK_API_MAJOR = SDK_RELEASE.contracts.api.currentMajor;
1361
1366
  var SDK_API_CONTRACT = SDK_RELEASE.contracts.api.legacyWireIds[0] ?? `api-v${SDK_API_MAJOR}`;
1362
1367
 
1368
+ // src/api-error.ts
1369
+ function asRecord(value) {
1370
+ return typeof value === "object" && value !== null ? value : null;
1371
+ }
1372
+ function apiErrorCodeFromResponse(parsed) {
1373
+ const response = asRecord(parsed);
1374
+ const error = asRecord(response?.error);
1375
+ const code = error?.code ?? response?.code;
1376
+ return typeof code === "string" ? code : "API_ERROR";
1377
+ }
1378
+ function apiErrorMessage(parsed, status) {
1379
+ const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
1380
+ if (typeof errorValue === "string") {
1381
+ return errorValue;
1382
+ }
1383
+ if (errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string") {
1384
+ return errorValue.message;
1385
+ }
1386
+ if (typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string") {
1387
+ return parsed.message;
1388
+ }
1389
+ return `HTTP ${status}`;
1390
+ }
1391
+
1363
1392
  // src/agent-runtime.ts
1364
1393
  import { homedir as homedir2 } from "os";
1365
1394
  var EXPLICIT_AGENT_RUNTIMES = /* @__PURE__ */ new Set([
@@ -2379,24 +2408,18 @@ function parseResponseBody(body) {
2379
2408
  }
2380
2409
  }
2381
2410
  function isProviderOriginatedHttpError(parsed) {
2382
- const response = asRecord(parsed);
2383
- const error = asRecord(response?.error);
2411
+ const response = asRecord2(parsed);
2412
+ const error = asRecord2(response?.error);
2384
2413
  const failureOrigin = error?.failure_origin ?? response?.failure_origin;
2385
2414
  const code = error?.code ?? response?.code;
2386
2415
  return failureOrigin === "provider" || code === "UPSTREAM_BLOCKED";
2387
2416
  }
2388
2417
  function isMonitorRateLimitEnvelope(parsed) {
2389
- const response = asRecord(parsed);
2390
- const error = asRecord(response?.error);
2418
+ const response = asRecord2(parsed);
2419
+ const error = asRecord2(response?.error);
2391
2420
  return error?.code === "monitor_upstream_rate_limited" && typeof error.message === "string";
2392
2421
  }
2393
- function apiErrorCodeFromResponse(parsed) {
2394
- const response = asRecord(parsed);
2395
- const error = asRecord(response?.error);
2396
- const code = error?.code ?? response?.code;
2397
- return typeof code === "string" ? code : "API_ERROR";
2398
- }
2399
- function asRecord(value) {
2422
+ function asRecord2(value) {
2400
2423
  return typeof value === "object" && value !== null ? value : null;
2401
2424
  }
2402
2425
  function isRetryableApiErrorResponse(status) {
@@ -2427,19 +2450,6 @@ function detectHtmlErrorBody(body, contentType) {
2427
2450
  }
2428
2451
  };
2429
2452
  }
2430
- function apiErrorMessage(parsed, status) {
2431
- const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
2432
- if (typeof errorValue === "string") {
2433
- return errorValue;
2434
- }
2435
- if (errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string") {
2436
- return errorValue.message;
2437
- }
2438
- if (typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string") {
2439
- return parsed.message;
2440
- }
2441
- return `HTTP ${status}`;
2442
- }
2443
2453
  function parseRetryAfter(response) {
2444
2454
  return parseOptionalRetryAfter(response) ?? 5e3;
2445
2455
  }
@@ -3326,6 +3336,278 @@ function isStopAllPlayRunsDryRunResult(result) {
3326
3336
  return "dryRun" in result && result.dryRun === true;
3327
3337
  }
3328
3338
 
3339
+ // src/plays/run-request.ts
3340
+ var PLAY_RUN_START_PATH = "/api/v2/plays/run";
3341
+ var PLAY_RUN_START_STREAM_PATH = `${PLAY_RUN_START_PATH}?stream=true`;
3342
+ var PLAY_FILES_STAGE_PATH = "/api/v2/plays/files/stage";
3343
+ var PLAY_FILES_STAGE_MINT_PATH = `${PLAY_FILES_STAGE_PATH}/mint`;
3344
+ function buildPlayRunStartBody(request) {
3345
+ return {
3346
+ ...request.name ? { name: request.name } : {},
3347
+ ...request.revisionId ? { revisionId: request.revisionId } : {},
3348
+ ...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
3349
+ ...request.sourceCode ? { sourceCode: request.sourceCode } : {},
3350
+ ...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
3351
+ ...request.description ? { description: request.description } : {},
3352
+ ..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
3353
+ ...request.artifactHash ? { artifactHash: request.artifactHash } : {},
3354
+ ...request.graphHash ? { graphHash: request.graphHash } : {},
3355
+ ...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
3356
+ ...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
3357
+ ...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
3358
+ ...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
3359
+ ...request.input ? { input: request.input } : {},
3360
+ ...request.inputFile ? { inputFile: request.inputFile } : {},
3361
+ ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
3362
+ ...request.force ? { force: true } : {},
3363
+ ...request.forceToolRefresh === true ? { forceToolRefresh: true } : {},
3364
+ ...typeof request.maxConcurrentExternalCalls === "number" ? { maxConcurrentExternalCalls: request.maxConcurrentExternalCalls } : {},
3365
+ ...typeof request.maxConcurrentRows === "number" ? { maxConcurrentRows: request.maxConcurrentRows } : {},
3366
+ ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
3367
+ // Profile selection is the API's job, not the caller's. The server
3368
+ // defaults to absurd; callers normally omit this field.
3369
+ ...request.profile ? { profile: request.profile } : {},
3370
+ ...request.integrationMode ? { integrationMode: request.integrationMode } : {},
3371
+ ...request.fixtureBehavior ? { fixtureBehavior: request.fixtureBehavior } : {},
3372
+ ...request.runtime ? { runtime: request.runtime } : {},
3373
+ ...request.testPolicyOverrides ? { testPolicyOverrides: request.testPolicyOverrides } : {}
3374
+ };
3375
+ }
3376
+ async function startPlayRun(http, request, headers) {
3377
+ const response = await http.post(
3378
+ PLAY_RUN_START_PATH,
3379
+ buildPlayRunStartBody(request),
3380
+ headers,
3381
+ { maxRetries: 0, exactUrlOnly: true }
3382
+ );
3383
+ return normalizePlayRunStart(response);
3384
+ }
3385
+ function isPlayRunPackage(value) {
3386
+ return Boolean(
3387
+ value && typeof value === "object" && !Array.isArray(value) && value.kind === "play_run" && value.run && typeof value.run?.id === "string"
3388
+ );
3389
+ }
3390
+ function normalizePlayRunStart(raw) {
3391
+ const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
3392
+ if (!runPackage) {
3393
+ const workflowId = typeof raw.workflowId === "string" && raw.workflowId ? raw.workflowId : typeof raw.runId === "string" ? raw.runId : "";
3394
+ return {
3395
+ ...raw,
3396
+ workflowId
3397
+ };
3398
+ }
3399
+ const status = typeof runPackage.run.status === "string" ? runPackage.run.status : "running";
3400
+ return {
3401
+ workflowId: runPackage.run.id,
3402
+ name: runPackage.run.playName,
3403
+ status,
3404
+ ...runPackage.run.dashboardUrl ? { dashboardUrl: runPackage.run.dashboardUrl } : {},
3405
+ ...isTerminalPlayRunLifecycleStatus(status) ? { finalStatus: runPackage } : {},
3406
+ package: runPackage
3407
+ };
3408
+ }
3409
+ var STAGE_LEGACY_MULTIPART_MAX_BYTES = 4e6;
3410
+ var STAGE_DIRECT_UPLOAD_MAX_ATTEMPTS = 3;
3411
+ function sleep2(ms) {
3412
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
3413
+ }
3414
+ function stagedUploadIdentity(logicalPath, contentHash) {
3415
+ return `${contentHash}:${logicalPath}`;
3416
+ }
3417
+ function isStagedUploadMintUnsupported(error) {
3418
+ return error instanceof DeeplineError && error.statusCode === 404;
3419
+ }
3420
+ function isStagedUploadDirectEgressDenied(error) {
3421
+ return error instanceof DeeplineError && error.code === "STAGED_FILE_UPLOAD_EGRESS_DENIED";
3422
+ }
3423
+ function formatMegabytes(bytes) {
3424
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3425
+ }
3426
+ function decodeBase64Bytes(value) {
3427
+ const binary = atob(value);
3428
+ const bytes = new Uint8Array(binary.length);
3429
+ for (let index = 0; index < binary.length; index += 1) {
3430
+ bytes[index] = binary.charCodeAt(index);
3431
+ }
3432
+ return bytes;
3433
+ }
3434
+ async function uploadStagedFileToPresignedUrl(input) {
3435
+ const arrayBuffer = input.body.buffer.slice(
3436
+ input.body.byteOffset,
3437
+ input.body.byteOffset + input.body.byteLength
3438
+ );
3439
+ let lastError;
3440
+ for (let attempt = 1; attempt <= STAGE_DIRECT_UPLOAD_MAX_ATTEMPTS; attempt += 1) {
3441
+ try {
3442
+ const response = await fetch(input.url, {
3443
+ method: "PUT",
3444
+ headers: input.headers,
3445
+ body: new Blob([arrayBuffer])
3446
+ });
3447
+ if (response.ok) {
3448
+ return;
3449
+ }
3450
+ const text = await response.text().catch(() => "");
3451
+ const egressDenied = response.status === 403 && response.headers.get("x-deny-reason")?.trim().toLowerCase() === "host_not_allowed";
3452
+ lastError = new DeeplineError(
3453
+ `Direct storage upload of ${input.logicalPath} failed: ${response.status} ${text.slice(0, 200)}`,
3454
+ response.status,
3455
+ egressDenied ? "STAGED_FILE_UPLOAD_EGRESS_DENIED" : "STAGED_FILE_UPLOAD_FAILED",
3456
+ { logicalPath: input.logicalPath }
3457
+ );
3458
+ if (response.status < 500 && response.status !== 429) {
3459
+ break;
3460
+ }
3461
+ } catch (error) {
3462
+ lastError = error instanceof TypeError ? new DeeplineError(
3463
+ `Direct storage upload of ${input.logicalPath} could not reach the storage endpoint: ${error.message}`,
3464
+ void 0,
3465
+ "STAGED_FILE_UPLOAD_EGRESS_DENIED",
3466
+ { logicalPath: input.logicalPath }
3467
+ ) : error;
3468
+ }
3469
+ if (attempt < STAGE_DIRECT_UPLOAD_MAX_ATTEMPTS) {
3470
+ await sleep2(250 * attempt);
3471
+ }
3472
+ }
3473
+ throw lastError instanceof Error ? lastError : new DeeplineError(
3474
+ `Direct storage upload of ${input.logicalPath} failed.`,
3475
+ void 0,
3476
+ "STAGED_FILE_UPLOAD_FAILED",
3477
+ { logicalPath: input.logicalPath }
3478
+ );
3479
+ }
3480
+ async function mintStagedPlayFileUploads(http, files) {
3481
+ const response = await http.post(PLAY_FILES_STAGE_MINT_PATH, { files });
3482
+ return response.uploads ?? [];
3483
+ }
3484
+ async function stagePlayFilesViaMultipart(http, files, reason = "mint-unsupported") {
3485
+ for (const file of files) {
3486
+ if (file.bytes > STAGE_LEGACY_MULTIPART_MAX_BYTES) {
3487
+ const reasonMessage = reason === "direct-egress-denied" ? "direct storage is blocked by this environment's network egress policy" : "the connected Deepline server does not support direct-to-storage uploads";
3488
+ throw new DeeplineError(
3489
+ `Cannot stage ${file.logicalPath} (${formatMegabytes(file.bytes)}): ${reasonMessage}, and this file exceeds the ~4.5MB request-body limit the legacy upload path is subject to.`,
3490
+ 413,
3491
+ "STAGED_FILE_TOO_LARGE_FOR_LEGACY_UPLOAD",
3492
+ {
3493
+ logicalPath: file.logicalPath,
3494
+ bytes: file.bytes,
3495
+ maxBytes: STAGE_LEGACY_MULTIPART_MAX_BYTES
3496
+ }
3497
+ );
3498
+ }
3499
+ }
3500
+ const buildFormData = () => {
3501
+ const formData = new FormData();
3502
+ formData.set(
3503
+ "metadata",
3504
+ JSON.stringify({
3505
+ files: files.map((file, index) => ({
3506
+ index,
3507
+ logicalPath: file.logicalPath,
3508
+ contentHash: file.contentHash,
3509
+ contentType: file.contentType,
3510
+ bytes: file.bytes
3511
+ }))
3512
+ })
3513
+ );
3514
+ for (const [index, file] of files.entries()) {
3515
+ const bytes = decodeBase64Bytes(file.contentBase64);
3516
+ const body = bytes.buffer.slice(
3517
+ bytes.byteOffset,
3518
+ bytes.byteOffset + bytes.byteLength
3519
+ );
3520
+ formData.set(
3521
+ `file:${index}`,
3522
+ new Blob([body], { type: file.contentType }),
3523
+ file.logicalPath
3524
+ );
3525
+ }
3526
+ return formData;
3527
+ };
3528
+ const response = await http.postFormData(PLAY_FILES_STAGE_PATH, buildFormData);
3529
+ return response.files;
3530
+ }
3531
+ async function stagePlayFiles(http, files) {
3532
+ let uploads;
3533
+ try {
3534
+ uploads = await mintStagedPlayFileUploads(
3535
+ http,
3536
+ files.map((file) => ({
3537
+ logicalPath: file.logicalPath,
3538
+ contentHash: file.contentHash,
3539
+ contentType: file.contentType,
3540
+ bytes: file.bytes
3541
+ }))
3542
+ );
3543
+ } catch (error) {
3544
+ if (isStagedUploadMintUnsupported(error)) {
3545
+ return stagePlayFilesViaMultipart(http, files);
3546
+ }
3547
+ throw error;
3548
+ }
3549
+ const uploadByIdentity = /* @__PURE__ */ new Map();
3550
+ for (const upload of uploads) {
3551
+ uploadByIdentity.set(
3552
+ stagedUploadIdentity(upload.logicalPath, upload.contentHash),
3553
+ upload
3554
+ );
3555
+ }
3556
+ const directResults = await Promise.all(
3557
+ files.map(async (file) => {
3558
+ const upload = uploadByIdentity.get(
3559
+ stagedUploadIdentity(file.logicalPath, file.contentHash)
3560
+ );
3561
+ if (!upload) {
3562
+ throw new DeeplineError(
3563
+ `The staging server did not return an upload target for ${file.logicalPath}.`,
3564
+ void 0,
3565
+ "STAGED_FILE_MINT_INCOMPLETE"
3566
+ );
3567
+ }
3568
+ if (upload.alreadyStaged || !upload.uploadUrl) {
3569
+ return { ref: upload.ref };
3570
+ }
3571
+ try {
3572
+ await uploadStagedFileToPresignedUrl({
3573
+ url: upload.uploadUrl,
3574
+ headers: upload.uploadHeaders ?? {
3575
+ "content-type": file.contentType
3576
+ },
3577
+ body: decodeBase64Bytes(file.contentBase64),
3578
+ logicalPath: file.logicalPath
3579
+ });
3580
+ return { ref: upload.ref };
3581
+ } catch (error) {
3582
+ if (isStagedUploadDirectEgressDenied(error)) {
3583
+ return { fallbackFile: file };
3584
+ }
3585
+ throw error;
3586
+ }
3587
+ })
3588
+ );
3589
+ return await Promise.all(
3590
+ directResults.map(async (result) => {
3591
+ if ("fallbackFile" in result) {
3592
+ const [ref] = await stagePlayFilesViaMultipart(
3593
+ http,
3594
+ [result.fallbackFile],
3595
+ "direct-egress-denied"
3596
+ );
3597
+ if (!ref) {
3598
+ throw new DeeplineError(
3599
+ `The staging server did not return an upload target for ${result.fallbackFile.logicalPath}.`,
3600
+ void 0,
3601
+ "STAGED_FILE_MINT_INCOMPLETE"
3602
+ );
3603
+ }
3604
+ return ref;
3605
+ }
3606
+ return result.ref;
3607
+ })
3608
+ );
3609
+ }
3610
+
3329
3611
  // ../plays/artifact-types.ts
3330
3612
  var PLAY_ARTIFACT_KINDS = {
3331
3613
  cjsNode20: "cjs_node20"
@@ -3532,6 +3814,19 @@ function resolvePlayRunRuntimeSelection(request) {
3532
3814
  ...configuredPlacementPolicy ? { sandboxPlacementPolicy: configuredPlacementPolicy } : {}
3533
3815
  };
3534
3816
  }
3817
+ function resolveStartPlayRunRequest(request) {
3818
+ const integrationMode = resolvePlayRunIntegrationMode(request);
3819
+ const testPolicyOverrides = request.testPolicyOverrides ?? parseEnvTestPolicyOverrides();
3820
+ const runtime = resolvePlayRunRuntimeSelection(request);
3821
+ const resolved = { ...request };
3822
+ delete resolved.integrationMode;
3823
+ delete resolved.runtime;
3824
+ delete resolved.testPolicyOverrides;
3825
+ if (integrationMode) resolved.integrationMode = integrationMode;
3826
+ if (runtime) resolved.runtime = runtime;
3827
+ if (testPolicyOverrides) resolved.testPolicyOverrides = testPolicyOverrides;
3828
+ return { request: resolved, runtime };
3829
+ }
3535
3830
  function runtimeSelectionHeaders(runtime) {
3536
3831
  if (!runtime) return void 0;
3537
3832
  const token = process.env.DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN?.trim();
@@ -3590,7 +3885,7 @@ function parseEnvTestPolicyOverrides() {
3590
3885
  }
3591
3886
  return normalizeTestPolicyOverrides(parsed, "DEEPLINE_TEST_POLICY_OVERRIDES");
3592
3887
  }
3593
- function sleep2(ms) {
3888
+ function sleep3(ms) {
3594
3889
  return new Promise((resolve2) => setTimeout(resolve2, ms));
3595
3890
  }
3596
3891
  function isTransientCompileManifestError(error) {
@@ -3698,11 +3993,6 @@ function preferPrebuiltPlayDescriptions(plays) {
3698
3993
  (left, right) => Number(right.play.pinned) - Number(left.play.pinned) || Number(isPrebuiltPlayDescription(right.play)) - Number(isPrebuiltPlayDescription(left.play)) || left.index - right.index
3699
3994
  ).map(({ play }) => play);
3700
3995
  }
3701
- function isPlayRunPackage(value) {
3702
- return Boolean(
3703
- value && typeof value === "object" && !Array.isArray(value) && value.kind === "play_run" && value.run && typeof value.run?.id === "string"
3704
- );
3705
- }
3706
3996
  function normalizePlayStatus(raw) {
3707
3997
  const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
3708
3998
  const packageRun = runPackage?.run;
@@ -3730,93 +4020,6 @@ function normalizePlayStatus(raw) {
3730
4020
  status
3731
4021
  };
3732
4022
  }
3733
- function normalizePlayRunStart(raw) {
3734
- const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
3735
- if (!runPackage) {
3736
- const workflowId = typeof raw.workflowId === "string" && raw.workflowId ? raw.workflowId : typeof raw.runId === "string" ? raw.runId : "";
3737
- return {
3738
- ...raw,
3739
- workflowId
3740
- };
3741
- }
3742
- const status = typeof runPackage.run.status === "string" ? runPackage.run.status : "running";
3743
- return {
3744
- workflowId: runPackage.run.id,
3745
- name: runPackage.run.playName,
3746
- status,
3747
- ...runPackage.run.dashboardUrl ? { dashboardUrl: runPackage.run.dashboardUrl } : {},
3748
- ...isTerminalPlayRunLifecycleStatus(status) ? { finalStatus: runPackage } : {},
3749
- package: runPackage
3750
- };
3751
- }
3752
- function decodeBase64Bytes(value) {
3753
- const binary = atob(value);
3754
- const bytes = new Uint8Array(binary.length);
3755
- for (let index = 0; index < binary.length; index += 1) {
3756
- bytes[index] = binary.charCodeAt(index);
3757
- }
3758
- return bytes;
3759
- }
3760
- var STAGE_LEGACY_MULTIPART_MAX_BYTES = 4e6;
3761
- var STAGE_DIRECT_UPLOAD_MAX_ATTEMPTS = 3;
3762
- function stagedUploadIdentity(logicalPath, contentHash) {
3763
- return `${contentHash}:${logicalPath}`;
3764
- }
3765
- function isStagedUploadMintUnsupported(error) {
3766
- return error instanceof DeeplineError && error.statusCode === 404;
3767
- }
3768
- function isStagedUploadDirectEgressDenied(error) {
3769
- return error instanceof DeeplineError && error.code === "STAGED_FILE_UPLOAD_EGRESS_DENIED";
3770
- }
3771
- function formatMegabytes(bytes) {
3772
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3773
- }
3774
- async function uploadStagedFileToPresignedUrl(input) {
3775
- const arrayBuffer = input.body.buffer.slice(
3776
- input.body.byteOffset,
3777
- input.body.byteOffset + input.body.byteLength
3778
- );
3779
- let lastError;
3780
- for (let attempt = 1; attempt <= STAGE_DIRECT_UPLOAD_MAX_ATTEMPTS; attempt += 1) {
3781
- try {
3782
- const response = await fetch(input.url, {
3783
- method: "PUT",
3784
- headers: input.headers,
3785
- body: new Blob([arrayBuffer])
3786
- });
3787
- if (response.ok) {
3788
- return;
3789
- }
3790
- const text = await response.text().catch(() => "");
3791
- const egressDenied = response.status === 403 && response.headers.get("x-deny-reason")?.trim().toLowerCase() === "host_not_allowed";
3792
- lastError = new DeeplineError(
3793
- `Direct storage upload of ${input.logicalPath} failed: ${response.status} ${text.slice(0, 200)}`,
3794
- response.status,
3795
- egressDenied ? "STAGED_FILE_UPLOAD_EGRESS_DENIED" : "STAGED_FILE_UPLOAD_FAILED",
3796
- { logicalPath: input.logicalPath }
3797
- );
3798
- if (response.status < 500 && response.status !== 429) {
3799
- break;
3800
- }
3801
- } catch (error) {
3802
- lastError = error instanceof TypeError ? new DeeplineError(
3803
- `Direct storage upload of ${input.logicalPath} could not reach the storage endpoint: ${error.message}`,
3804
- void 0,
3805
- "STAGED_FILE_UPLOAD_EGRESS_DENIED",
3806
- { logicalPath: input.logicalPath }
3807
- ) : error;
3808
- }
3809
- if (attempt < STAGE_DIRECT_UPLOAD_MAX_ATTEMPTS) {
3810
- await sleep2(250 * attempt);
3811
- }
3812
- }
3813
- throw lastError instanceof Error ? lastError : new DeeplineError(
3814
- `Direct storage upload of ${input.logicalPath} failed.`,
3815
- void 0,
3816
- "STAGED_FILE_UPLOAD_FAILED",
3817
- { logicalPath: input.logicalPath }
3818
- );
3819
- }
3820
4023
  function readStringArray(value) {
3821
4024
  return Array.isArray(value) ? value.filter((line) => typeof line === "string") : [];
3822
4025
  }
@@ -4436,51 +4639,12 @@ var DeeplineClient = class _DeeplineClient {
4436
4639
  * ```
4437
4640
  */
4438
4641
  async startPlayRun(request) {
4439
- const integrationMode = resolvePlayRunIntegrationMode(request);
4440
- const testPolicyOverrides = request.testPolicyOverrides ?? parseEnvTestPolicyOverrides();
4441
- const forceToolRefresh = request.forceToolRefresh === true;
4442
- const runtime = resolvePlayRunRuntimeSelection(request);
4443
- const response = await this.http.post(
4444
- "/api/v2/plays/run",
4445
- {
4446
- ...request.name ? { name: request.name } : {},
4447
- ...request.revisionId ? { revisionId: request.revisionId } : {},
4448
- ...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
4449
- ...request.sourceCode ? { sourceCode: request.sourceCode } : {},
4450
- ...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
4451
- ...request.description ? { description: request.description } : {},
4452
- ..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
4453
- ...request.artifactHash ? { artifactHash: request.artifactHash } : {},
4454
- ...request.graphHash ? { graphHash: request.graphHash } : {},
4455
- ...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
4456
- ...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
4457
- ...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
4458
- ...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
4459
- ...request.input ? { input: request.input } : {},
4460
- ...request.inputFile ? { inputFile: request.inputFile } : {},
4461
- ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
4462
- ...request.force ? { force: true } : {},
4463
- ...forceToolRefresh ? { forceToolRefresh: true } : {},
4464
- ...typeof request.maxConcurrentExternalCalls === "number" ? {
4465
- maxConcurrentExternalCalls: request.maxConcurrentExternalCalls
4466
- } : {},
4467
- ...typeof request.maxConcurrentRows === "number" ? { maxConcurrentRows: request.maxConcurrentRows } : {},
4468
- ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
4469
- // Profile selection is the API's job, not the CLI's. The server
4470
- // defaults to absurd; callers normally omit this field.
4471
- ...request.profile ? { profile: request.profile } : {},
4472
- ...integrationMode ? { integrationMode } : {},
4473
- ...request.fixtureBehavior ? { fixtureBehavior: request.fixtureBehavior } : {},
4474
- ...runtime ? { runtime } : {},
4475
- ...testPolicyOverrides ? { testPolicyOverrides } : {}
4476
- },
4477
- runtimeSelectionHeaders(runtime),
4478
- // A start can reach the server even when its response is lost or times
4479
- // out. Retrying this mutation without an idempotency key can create a
4480
- // second root run, so callers must resolve ambiguous failures explicitly.
4481
- { maxRetries: 0, exactUrlOnly: true }
4642
+ const resolved = resolveStartPlayRunRequest(request);
4643
+ return startPlayRun(
4644
+ this.http,
4645
+ resolved.request,
4646
+ runtimeSelectionHeaders(resolved.runtime)
4482
4647
  );
4483
- return normalizePlayRunStart(response);
4484
4648
  }
4485
4649
  /**
4486
4650
  * Submit a play run through the legacy event response.
@@ -4496,44 +4660,14 @@ var DeeplineClient = class _DeeplineClient {
4496
4660
  * @returns Async generator of play-scoped live events.
4497
4661
  */
4498
4662
  async *startPlayRunStream(request, options) {
4499
- const integrationMode = resolvePlayRunIntegrationMode(request);
4500
- const testPolicyOverrides = request.testPolicyOverrides ?? parseEnvTestPolicyOverrides();
4501
- const forceToolRefresh = request.forceToolRefresh === true;
4502
- const runtime = resolvePlayRunRuntimeSelection(request);
4503
- const body = {
4504
- ...request.name ? { name: request.name } : {},
4505
- ...request.revisionId ? { revisionId: request.revisionId } : {},
4506
- ...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
4507
- ...request.sourceCode ? { sourceCode: request.sourceCode } : {},
4508
- ...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
4509
- ...request.description ? { description: request.description } : {},
4510
- ..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
4511
- ...request.artifactHash ? { artifactHash: request.artifactHash } : {},
4512
- ...request.graphHash ? { graphHash: request.graphHash } : {},
4513
- ...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
4514
- ...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
4515
- ...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
4516
- ...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
4517
- ...request.input ? { input: request.input } : {},
4518
- ...request.inputFile ? { inputFile: request.inputFile } : {},
4519
- ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
4520
- ...request.force ? { force: true } : {},
4521
- ...forceToolRefresh ? { forceToolRefresh: true } : {},
4522
- ...typeof request.maxConcurrentExternalCalls === "number" ? { maxConcurrentExternalCalls: request.maxConcurrentExternalCalls } : {},
4523
- ...typeof request.maxConcurrentRows === "number" ? { maxConcurrentRows: request.maxConcurrentRows } : {},
4524
- ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
4525
- ...request.profile ? { profile: request.profile } : {},
4526
- ...integrationMode ? { integrationMode } : {},
4527
- ...request.fixtureBehavior ? { fixtureBehavior: request.fixtureBehavior } : {},
4528
- ...runtime ? { runtime } : {},
4529
- ...testPolicyOverrides ? { testPolicyOverrides } : {}
4530
- };
4663
+ const resolved = resolveStartPlayRunRequest(request);
4664
+ const body = buildPlayRunStartBody(resolved.request);
4531
4665
  for await (const event of this.http.streamSse(
4532
- "/api/v2/plays/run?stream=true",
4666
+ PLAY_RUN_START_STREAM_PATH,
4533
4667
  {
4534
4668
  method: "POST",
4535
4669
  body,
4536
- headers: runtimeSelectionHeaders(runtime),
4670
+ headers: runtimeSelectionHeaders(resolved.runtime),
4537
4671
  signal: options?.signal
4538
4672
  }
4539
4673
  )) {
@@ -4632,7 +4766,7 @@ var DeeplineClient = class _DeeplineClient {
4632
4766
  if (delayMs === void 0 || !isTransientCompileManifestError(error)) {
4633
4767
  throw error;
4634
4768
  }
4635
- await sleep2(delayMs);
4769
+ await sleep3(delayMs);
4636
4770
  }
4637
4771
  }
4638
4772
  }
@@ -4799,81 +4933,7 @@ var DeeplineClient = class _DeeplineClient {
4799
4933
  * ```
4800
4934
  */
4801
4935
  async stagePlayFiles(files) {
4802
- let uploads;
4803
- try {
4804
- uploads = await this.mintStagedPlayFileUploads(
4805
- files.map((file) => ({
4806
- logicalPath: file.logicalPath,
4807
- contentHash: file.contentHash,
4808
- contentType: file.contentType,
4809
- bytes: file.bytes
4810
- }))
4811
- );
4812
- } catch (error) {
4813
- if (isStagedUploadMintUnsupported(error)) {
4814
- return this.stagePlayFilesViaMultipart(files);
4815
- }
4816
- throw error;
4817
- }
4818
- const uploadByIdentity = /* @__PURE__ */ new Map();
4819
- for (const upload of uploads) {
4820
- uploadByIdentity.set(
4821
- stagedUploadIdentity(upload.logicalPath, upload.contentHash),
4822
- upload
4823
- );
4824
- }
4825
- const directResults = await Promise.all(
4826
- files.map(async (file) => {
4827
- const upload = uploadByIdentity.get(
4828
- stagedUploadIdentity(file.logicalPath, file.contentHash)
4829
- );
4830
- if (!upload) {
4831
- throw new DeeplineError(
4832
- `The staging server did not return an upload target for ${file.logicalPath}.`,
4833
- void 0,
4834
- "STAGED_FILE_MINT_INCOMPLETE"
4835
- );
4836
- }
4837
- if (upload.alreadyStaged || !upload.uploadUrl) {
4838
- return { ref: upload.ref };
4839
- }
4840
- try {
4841
- await uploadStagedFileToPresignedUrl({
4842
- url: upload.uploadUrl,
4843
- headers: upload.uploadHeaders ?? {
4844
- "content-type": file.contentType
4845
- },
4846
- body: decodeBase64Bytes(file.contentBase64),
4847
- logicalPath: file.logicalPath
4848
- });
4849
- return { ref: upload.ref };
4850
- } catch (error) {
4851
- if (isStagedUploadDirectEgressDenied(error)) {
4852
- return { fallbackFile: file };
4853
- }
4854
- throw error;
4855
- }
4856
- })
4857
- );
4858
- return await Promise.all(
4859
- directResults.map(async (result) => {
4860
- if ("fallbackFile" in result) {
4861
- const [ref] = await this.stagePlayFilesViaMultipart(
4862
- [result.fallbackFile],
4863
- "direct-egress-denied"
4864
- );
4865
- if (!ref) {
4866
- throw new DeeplineError(
4867
- `The staging server did not return an upload target for ${result.fallbackFile.logicalPath}.`,
4868
- void 0,
4869
- "STAGED_FILE_MINT_INCOMPLETE"
4870
- );
4871
- }
4872
- return ref;
4873
- }
4874
- return result.ref;
4875
- })
4876
- );
4936
+ return stagePlayFiles(this.http, files);
4877
4937
  }
4878
4938
  /**
4879
4939
  * Mint short-lived presigned upload targets for staged play files.
@@ -4883,55 +4943,7 @@ var DeeplineClient = class _DeeplineClient {
4883
4943
  * already holds, or a presigned PUT URL the caller uploads the body to.
4884
4944
  */
4885
4945
  async mintStagedPlayFileUploads(files) {
4886
- const response = await this.http.post("/api/v2/plays/files/stage/mint", { files });
4887
- return response.uploads ?? [];
4888
- }
4889
- async stagePlayFilesViaMultipart(files, reason = "mint-unsupported") {
4890
- for (const file of files) {
4891
- if (file.bytes > STAGE_LEGACY_MULTIPART_MAX_BYTES) {
4892
- const reasonMessage = reason === "direct-egress-denied" ? "direct storage is blocked by this environment's network egress policy" : "the connected Deepline server does not support direct-to-storage uploads";
4893
- throw new DeeplineError(
4894
- `Cannot stage ${file.logicalPath} (${formatMegabytes(file.bytes)}): ${reasonMessage}, and this file exceeds the ~4.5MB request-body limit the legacy upload path is subject to.`,
4895
- 413,
4896
- "STAGED_FILE_TOO_LARGE_FOR_LEGACY_UPLOAD",
4897
- {
4898
- logicalPath: file.logicalPath,
4899
- bytes: file.bytes,
4900
- maxBytes: STAGE_LEGACY_MULTIPART_MAX_BYTES
4901
- }
4902
- );
4903
- }
4904
- }
4905
- const buildFormData = () => {
4906
- const formData = new FormData();
4907
- formData.set(
4908
- "metadata",
4909
- JSON.stringify({
4910
- files: files.map((file, index) => ({
4911
- index,
4912
- logicalPath: file.logicalPath,
4913
- contentHash: file.contentHash,
4914
- contentType: file.contentType,
4915
- bytes: file.bytes
4916
- }))
4917
- })
4918
- );
4919
- for (const [index, file] of files.entries()) {
4920
- const bytes = decodeBase64Bytes(file.contentBase64);
4921
- const body = bytes.buffer.slice(
4922
- bytes.byteOffset,
4923
- bytes.byteOffset + bytes.byteLength
4924
- );
4925
- formData.set(
4926
- `file:${index}`,
4927
- new Blob([body], { type: file.contentType }),
4928
- file.logicalPath
4929
- );
4930
- }
4931
- return formData;
4932
- };
4933
- const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
4934
- return response.files;
4946
+ return mintStagedPlayFileUploads(this.http, files);
4935
4947
  }
4936
4948
  /**
4937
4949
  * Resolve staged play files by content hash without uploading bytes.
@@ -5367,7 +5379,7 @@ var DeeplineClient = class _DeeplineClient {
5367
5379
  }
5368
5380
  return this.http.post(
5369
5381
  `/api/v2/runs/${encodeURIComponent(runId)}/rerun`,
5370
- {},
5382
+ options?.inputOverrides ? { inputOverrides: options.inputOverrides } : {},
5371
5383
  { "Idempotency-Key": idempotencyKey || globalThis.crypto.randomUUID() }
5372
5384
  );
5373
5385
  }
@@ -5502,8 +5514,8 @@ var DeeplineClient = class _DeeplineClient {
5502
5514
  if (input.runId?.trim()) {
5503
5515
  params.set("runId", input.runId.trim());
5504
5516
  }
5505
- if (input.rowMode === "all") {
5506
- params.set("rowMode", "all");
5517
+ if (input.rowMode === "all" || input.rowMode === "live") {
5518
+ params.set("rowMode", input.rowMode);
5507
5519
  }
5508
5520
  const result = await this.http.get(
5509
5521
  `/api/v2/plays/${encodeURIComponent(input.playName)}/sheet?${params.toString()}`,
@@ -5667,6 +5679,18 @@ var DeeplineClient = class _DeeplineClient {
5667
5679
  patch
5668
5680
  );
5669
5681
  }
5682
+ /** Read a Play's cron and webhook triggers and their scheduler state. */
5683
+ async getPlayTriggerConfig(playName) {
5684
+ return this.http.get(playTriggerConfigPath(playName));
5685
+ }
5686
+ /**
5687
+ * Declare a Play's cron and/or webhook trigger (null removes it) and publish
5688
+ * the rewritten source as a new live revision. Retry-safe: a request the
5689
+ * live revision already satisfies returns `changed: false`.
5690
+ */
5691
+ async updatePlayTriggerConfig(playName, update) {
5692
+ return this.http.put(playTriggerConfigPath(playName), update);
5693
+ }
5670
5694
  /** List one bounded page of existing Play locations; continue with cursor. */
5671
5695
  async listPlaySettingsPaths(options = {}) {
5672
5696
  const query = new URLSearchParams();
@@ -6329,6 +6353,16 @@ var DeeplineClient = class _DeeplineClient {
6329
6353
  }
6330
6354
  return event;
6331
6355
  }
6356
+ /**
6357
+ * What Deepline has billed each run so far (customer-visible credits, never
6358
+ * provider spend) and whether any of its charges is still settling — the
6359
+ * same read the dashboard's runs grid shows. `GET /api/v2/runs/billing`.
6360
+ */
6361
+ async getRunBilling(runIds) {
6362
+ const params = new URLSearchParams();
6363
+ for (const runId of runIds) params.append("runId", runId);
6364
+ return this.http.get(`/api/v2/runs/billing?${params}`);
6365
+ }
6332
6366
  /**
6333
6367
  * Read workspace usage and recent customer-facing Deepline charges. Pass
6334
6368
  * the `job_id` from `executeTool` as `requestId` to retrieve one exact call,
@@ -7044,7 +7078,7 @@ var DeeplineClient = class _DeeplineClient {
7044
7078
  const state = typeof job?.state === "string" ? job.state : void 0;
7045
7079
  if (state && terminal.has(state)) return latest;
7046
7080
  if (Date.now() - startedAt >= timeoutMs) return latest;
7047
- await sleep2(pollIntervalMs);
7081
+ await sleep3(pollIntervalMs);
7048
7082
  latest = await this.getMonitorJob(jobId);
7049
7083
  }
7050
7084
  }
@@ -7157,7 +7191,7 @@ var DeeplineClient = class _DeeplineClient {
7157
7191
  const status = typeof latest.status === "string" ? latest.status : void 0;
7158
7192
  if (status && terminal.has(status)) return latest;
7159
7193
  if (Date.now() - startedAt >= timeoutMs) return latest;
7160
- await sleep2(pollIntervalMs);
7194
+ await sleep3(pollIntervalMs);
7161
7195
  latest = await this.getMonitorFleet(fleetId);
7162
7196
  }
7163
7197
  }