deepline 0.3.373 → 0.3.375

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 (101) hide show
  1. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  2. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +1 -53
  3. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +15 -23
  4. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +65 -3
  5. package/dist/cli/auth-B7CLYD7R.js +35 -0
  6. package/dist/cli/{auth-7BMCDCRH.mjs → auth-U3Y7DTIG.mjs} +6 -4
  7. package/dist/cli/{billing-GKI7B4JF.js → billing-P2DNRAND.js} +73 -73
  8. package/dist/cli/{billing-RZEHHMPU.mjs → billing-TKARGBO3.mjs} +4 -4
  9. package/dist/cli/{chunk-IUYKSTWB.mjs → chunk-4GP56LRE.mjs} +12 -12
  10. package/dist/cli/{chunk-JSK6GUY6.js → chunk-4WINCNNH.js} +13 -9
  11. package/dist/cli/{chunk-CLEB5KUZ.js → chunk-ADSZGPYZ.js} +1 -1
  12. package/dist/cli/{chunk-E6BZWURC.mjs → chunk-B2LFDTXZ.mjs} +15 -6
  13. package/dist/cli/{chunk-JP2YA3AV.mjs → chunk-B3TQIJ6L.mjs} +1 -1
  14. package/dist/cli/{chunk-NVZAZGHA.js → chunk-CUIBDSSS.js} +8 -8
  15. package/dist/cli/{chunk-E7MGPPM5.js → chunk-DAG4ZBTJ.js} +1495 -1495
  16. package/dist/cli/{chunk-YPVTQRUM.js → chunk-DHTG5CCI.js} +15 -6
  17. package/dist/cli/{chunk-EYXSAB7O.js → chunk-F5CU5ALX.js} +26 -26
  18. package/dist/cli/{chunk-46JCJ7FT.mjs → chunk-FWF24ULX.mjs} +13 -9
  19. package/dist/cli/{chunk-JHUMUIU6.js → chunk-GN5QM2BB.js} +6 -6
  20. package/dist/cli/{chunk-BM47AKUZ.js → chunk-HEF6UDGA.js} +235 -235
  21. package/dist/cli/{chunk-ORBVXCTL.js → chunk-HP4BE43N.js} +52 -51
  22. package/dist/cli/{chunk-YHHY2YHK.mjs → chunk-HSIVHAZA.mjs} +3 -3
  23. package/dist/cli/{chunk-P5JPGZNI.mjs → chunk-IG3GOO4T.mjs} +1 -1
  24. package/dist/cli/{chunk-ND4BVWWZ.js → chunk-IQTHRG6E.js} +15 -15
  25. package/dist/cli/{chunk-S5OTS6H5.js → chunk-KK4XPUVA.js} +8 -8
  26. package/dist/cli/{chunk-IHQQNWU4.js → chunk-LZUWGLM4.js} +2 -2
  27. package/dist/cli/{chunk-W3H422KP.js → chunk-M2HVNJ47.js} +60 -60
  28. package/dist/cli/{chunk-HNLXC5BP.mjs → chunk-M5QDOHLG.mjs} +1 -1
  29. package/dist/cli/{chunk-XMME4SCK.mjs → chunk-MKS7C3YR.mjs} +3 -2
  30. package/dist/cli/{chunk-ECA6NQYL.mjs → chunk-MPQSBHMA.mjs} +4 -4
  31. package/dist/cli/{chunk-D2CZ4Y5G.js → chunk-MTBQEND4.js} +15 -15
  32. package/dist/cli/{chunk-XJYUQBHY.js → chunk-NVXMPGM4.js} +65 -84
  33. package/dist/cli/{chunk-6JCVL7CE.mjs → chunk-QEEIEHGV.mjs} +2 -2
  34. package/dist/cli/{chunk-TB73PXE3.mjs → chunk-SJVJZOPT.mjs} +2 -2
  35. package/dist/cli/{chunk-QSV76EMO.mjs → chunk-STYH5U6W.mjs} +7 -7
  36. package/dist/cli/{chunk-R6TPSZLN.mjs → chunk-Z4ARN4X3.mjs} +2 -2
  37. package/dist/cli/{chunk-PZ26EKNC.mjs → chunk-ZFWU5V2A.mjs} +13 -32
  38. package/dist/cli/{chunk-Y32GUTEN.mjs → chunk-ZHXPNJQI.mjs} +1467 -1467
  39. package/dist/cli/command-docs.js +2 -2
  40. package/dist/cli/command-docs.mjs +1 -1
  41. package/dist/cli/{csv-3FNCVMWA.mjs → csv-3FTYTEJ3.mjs} +3 -3
  42. package/dist/cli/{csv-NFQYQWWO.js → csv-WAEVGKHF.js} +12 -12
  43. package/dist/cli/{db-VA7HULGR.mjs → db-HUGGFIVS.mjs} +4 -4
  44. package/dist/cli/{db-CTLGRV3X.js → db-UDMDGNKO.js} +29 -29
  45. package/dist/cli/{describe-GXGRMP2M.mjs → describe-EOBOGTB5.mjs} +130 -20
  46. package/dist/cli/{describe-IUHOEPKY.js → describe-SIAKZYRK.js} +144 -34
  47. package/dist/cli/{executions-DSK3HRPU.js → executions-HYYP27MG.js} +6 -6
  48. package/dist/cli/{executions-OZQDZQIK.mjs → executions-O6Z2HSLK.mjs} +4 -4
  49. package/dist/cli/{feedback-KTMLMWKV.js → feedback-3DWSBHKS.js} +7 -7
  50. package/dist/cli/{feedback-ZOY7R4JD.mjs → feedback-RRAMGMQV.mjs} +3 -3
  51. package/dist/cli/{git-FIOI4IA2.mjs → git-KVAK7VOL.mjs} +4 -4
  52. package/dist/cli/git-M36KWCCG.js +23 -0
  53. package/dist/cli/index.js +106 -91
  54. package/dist/cli/index.mjs +63 -48
  55. package/dist/cli/{legacy-noops-KQZWSABN.mjs → legacy-noops-MQNCDMY7.mjs} +4 -4
  56. package/dist/cli/{legacy-noops-WXAYRQMQ.js → legacy-noops-V5GQXXUR.js} +7 -7
  57. package/dist/cli/{monitors-VHNWIF4V.mjs → monitors-6FB63TDM.mjs} +4 -4
  58. package/dist/cli/{monitors-LPUCHRNJ.js → monitors-RFGQILPW.js} +85 -85
  59. package/dist/cli/{org-GWHWBCMD.js → org-L33EPH2E.js} +64 -64
  60. package/dist/cli/{org-UW7NPGEY.mjs → org-TZPQDDVX.mjs} +4 -4
  61. package/dist/cli/{play-FNM2E66T.mjs → play-PU23OETO.mjs} +8 -8
  62. package/dist/cli/play-YR2XQARF.js +155 -0
  63. package/dist/cli/{providers-6D6R3PWX.js → providers-2RHIKO22.js} +7 -7
  64. package/dist/cli/{providers-XAZMYDWS.mjs → providers-QGQR6ZZF.mjs} +4 -4
  65. package/dist/cli/{quickstart-OK65PGZL.mjs → quickstart-24DQYBW7.mjs} +3 -3
  66. package/dist/cli/{quickstart-HBUWBVH6.js → quickstart-BGQVPI7W.js} +5 -5
  67. package/dist/cli/{search-XY6JOTS2.mjs → search-EUN7YFMX.mjs} +5 -5
  68. package/dist/cli/search-OHELMK6E.js +26 -0
  69. package/dist/cli/{secrets-W2LDLU2W.mjs → secrets-OOHN6LNJ.mjs} +4 -4
  70. package/dist/cli/{secrets-6CYCPK7T.js → secrets-XL7GUTQA.js} +13 -13
  71. package/dist/cli/{sessions-GOYEKNTJ.js → sessions-FD5XB7M2.js} +5 -5
  72. package/dist/cli/{sessions-JAX7PGXU.mjs → sessions-SDN4C3YS.mjs} +4 -4
  73. package/dist/cli/{settings-OACUQOCM.mjs → settings-3MXRXYXI.mjs} +7 -7
  74. package/dist/cli/{settings-QMFYFCT7.js → settings-6ZEKVAYL.js} +74 -74
  75. package/dist/cli/{setup-2KA5TZBZ.mjs → setup-DWTR6HNT.mjs} +6 -6
  76. package/dist/cli/{setup-36VOOGVA.js → setup-VKQ5EJZR.js} +41 -41
  77. package/dist/cli/skills-6GFW4GCW.js +28 -0
  78. package/dist/cli/{skills-QY4BX5ZX.mjs → skills-ISG5UUZW.mjs} +4 -4
  79. package/dist/cli/{tools-UCB2QRVC.mjs → tools-JTC3DR6M.mjs} +7 -7
  80. package/dist/cli/tools-LK4L6VCK.js +40 -0
  81. package/dist/cli/{update-327MHUO4.mjs → update-GMTVIHCG.mjs} +6 -6
  82. package/dist/cli/update-PSJLAW4Q.js +28 -0
  83. package/dist/cli/{workflow-G7BU54KW.js → workflow-2765Y3Y5.js} +15 -15
  84. package/dist/cli/{workflow-HJN4GA5A.mjs → workflow-3POT3VFY.mjs} +5 -5
  85. package/dist/index.js +8 -8
  86. package/dist/index.mjs +7 -7
  87. package/dist/install-integrity.json +76 -78
  88. package/dist/release.d.mts +1 -1
  89. package/dist/release.d.ts +1 -1
  90. package/dist/release.js +2 -2
  91. package/dist/release.mjs +1 -1
  92. package/package.json +1 -1
  93. package/dist/cli/auth-BWCNRUG3.js +0 -33
  94. package/dist/cli/client-FO6LMHT4.mjs +0 -20
  95. package/dist/cli/client-KAWK7FJR.js +0 -20
  96. package/dist/cli/git-5P5FLEUC.js +0 -23
  97. package/dist/cli/play-EVBIC7Z5.js +0 -155
  98. package/dist/cli/search-6ZY2XWP2.js +0 -26
  99. package/dist/cli/skills-6GPIEPTP.js +0 -28
  100. package/dist/cli/tools-RTECP4WT.js +0 -40
  101. package/dist/cli/update-WR65EHBN.js +0 -28
@@ -21,7 +21,7 @@ var _chunkLA46MMTLjs = require('./chunk-LA46MMTL.js');
21
21
 
22
22
 
23
23
 
24
- var _chunkND4BVWWZjs = require('./chunk-ND4BVWWZ.js');
24
+ var _chunkIQTHRG6Ejs = require('./chunk-IQTHRG6E.js');
25
25
 
26
26
 
27
27
 
@@ -29,11 +29,6 @@ var _chunkND4BVWWZjs = require('./chunk-ND4BVWWZ.js');
29
29
 
30
30
  var _chunk7P5AA3SNjs = require('./chunk-7P5AA3SN.js');
31
31
 
32
- // ../plays/trigger-config-route.ts
33
- function playTriggerConfigPath(playName) {
34
- return `/api/v2/plays/${encodeURIComponent(playName)}/triggers`;
35
- }
36
-
37
32
  // src/csv-header-matching.ts
38
33
  var CSV_HEADER_MATCHING_NOTE = 'A header matches a column when it equals the column name or its default header, ignoring case, spaces and punctuation: LINKEDIN_URL, linkedin-url and "Linkedin Url" all match linkedin_url. A capital inside a word starts a new word, so "LinkedIn URL" reads as linked_in_url and does not match. Map any other header in the input: {"csv":"<path>","columns":{"<column>":"<your header>"}}.';
39
34
 
@@ -57,31 +52,6 @@ async function* iterateCursorPages(fetchPage) {
57
52
  }
58
53
  }
59
54
 
60
- // src/plays/input-example.ts
61
- function playInputExampleArgs(schema) {
62
- if (!schema) return " --input '@<input.json>'";
63
- if (schema.$ref || schema.allOf) return " --input '@<input.json>'";
64
- const csv = schema.csvInput;
65
- const csvField = typeof _optionalChain([csv, 'optionalAccess', _ => _.inputField]) === "string" ? csv.inputField : null;
66
- const required = Array.isArray(schema.required) ? schema.required : [];
67
- const csvOnlyRequired = required.every((key) => key === csvField);
68
- const alternatives = _nullishCoalesce(schema.oneOf, () => ( schema.anyOf));
69
- const hasCsvAlternative = Array.isArray(alternatives) && alternatives.some((branch) => {
70
- if (!branch || typeof branch !== "object") return false;
71
- const keys = branch.required;
72
- return Array.isArray(keys) && keys.includes(csvField) && keys.every((key) => key === csvField);
73
- });
74
- if (csvField && csvOnlyRequired && (!alternatives || hasCsvAlternative)) {
75
- if (csvField === "csv") return " --csv '<contacts.csv>'";
76
- const value = JSON.stringify({ [csvField]: "<contacts.csv>" });
77
- return ` --input '${value.replace(/'/g, "'\\''")}'`;
78
- }
79
- if (Array.isArray(schema.required) && !required.length && !csv && !alternatives) {
80
- return "";
81
- }
82
- return " --input '@<input.json>'";
83
- }
84
-
85
55
  // src/billing-idempotency.ts
86
56
  function requireBillingIdempotencyKey(value) {
87
57
  const normalized = value.trim();
@@ -164,10 +134,10 @@ async function queryCustomerDatabase(http, input) {
164
134
  }
165
135
  );
166
136
  } catch (error) {
167
- if (error instanceof _chunk7P5AA3SNjs.DeeplineError && (_optionalChain([error, 'access', _2 => _2.code, 'optionalAccess', _3 => _3.startsWith, 'call', _4 => _4("NETWORK_")]) || // Older API readers return PostgreSQL errors as HTTP 400, including
137
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError && (_optionalChain([error, 'access', _ => _.code, 'optionalAccess', _2 => _2.startsWith, 'call', _3 => _3("NETWORK_")]) || // Older API readers return PostgreSQL errors as HTTP 400, including
168
138
  // lost connections and explicitly unknown transaction resolution.
169
139
  /^08[A-Z0-9]{3}$/.test(_nullishCoalesce(error.code, () => ( ""))) || ["57P01", "57P02", "57P03"].includes(_nullishCoalesce(error.code, () => ( ""))) || error.statusCode === 408 || (_nullishCoalesce(error.statusCode, () => ( 0))) >= 500)) {
170
- throw new (0, _chunkND4BVWWZjs.CustomerDbQueryOutcomeUnknownError)(
140
+ throw new (0, _chunkIQTHRG6Ejs.CustomerDbQueryOutcomeUnknownError)(
171
141
  error,
172
142
  plan.request.body.operation_key
173
143
  );
@@ -175,7 +145,7 @@ async function queryCustomerDatabase(http, input) {
175
145
  throw error;
176
146
  }
177
147
  if (!result || typeof result !== "object" || Array.isArray(result) || typeof result.command !== "string" || !Array.isArray(result.columns) || !Array.isArray(result.rows) || typeof result.truncated !== "boolean" || result.row_count !== null && (!Number.isSafeInteger(result.row_count) || result.row_count < 0) || !Number.isSafeInteger(result.row_count_returned) || result.row_count_returned < 0) {
178
- throw new (0, _chunkND4BVWWZjs.CustomerDbQueryOutcomeUnknownError)(
148
+ throw new (0, _chunkIQTHRG6Ejs.CustomerDbQueryOutcomeUnknownError)(
179
149
  new (0, _chunk7P5AA3SNjs.DeeplineError)(
180
150
  "The SQL response did not contain a valid result.",
181
151
  200,
@@ -186,7 +156,7 @@ async function queryCustomerDatabase(http, input) {
186
156
  }
187
157
  const operation = result.operation;
188
158
  if (input.operationKey !== void 0 && (!operation || operation.operation_key !== input.operationKey || !Number.isSafeInteger(operation.completed_at_ms) || operation.completed_at_ms < 0 || !["executed", "operation_recovery"].includes(operation.source))) {
189
- throw new (0, _chunkND4BVWWZjs.CustomerDbQueryOutcomeUnknownError)(
159
+ throw new (0, _chunkIQTHRG6Ejs.CustomerDbQueryOutcomeUnknownError)(
190
160
  new (0, _chunk7P5AA3SNjs.DeeplineError)(
191
161
  "The server did not confirm the original atomic SQL operation.",
192
162
  200,
@@ -326,7 +296,7 @@ function isRecoverableExecutionAttemptError(error) {
326
296
  if (error instanceof _chunk7P5AA3SNjs.ToolExecutionError) {
327
297
  return error.code === "EXECUTION_IN_PROGRESS" || error.origin === "deepline" && error.category === "network" && error.networkScope === "client_to_deepline";
328
298
  }
329
- return error instanceof _chunk7P5AA3SNjs.DeeplineError && (error.code === "EXECUTION_IN_PROGRESS" || _optionalChain([error, 'access', _5 => _5.code, 'optionalAccess', _6 => _6.startsWith, 'call', _7 => _7("NETWORK_")]) === true && error.statusCode === void 0);
299
+ return error instanceof _chunk7P5AA3SNjs.DeeplineError && (error.code === "EXECUTION_IN_PROGRESS" || _optionalChain([error, 'access', _4 => _4.code, 'optionalAccess', _5 => _5.startsWith, 'call', _6 => _6("NETWORK_")]) === true && error.statusCode === void 0);
330
300
  }
331
301
  function isRecoverableExecutionLookupError(error) {
332
302
  if (isRecoverableExecutionAttemptError(error)) return true;
@@ -435,24 +405,24 @@ var ToolCalls = class {
435
405
  this.configuredRequestTimeoutMs = configuredRequestTimeoutMs;
436
406
  }
437
407
  async call(toolId, input, options) {
438
- if (_optionalChain([options, 'optionalAccess', _8 => _8.cliInvocationId]) !== void 0) {
408
+ if (_optionalChain([options, 'optionalAccess', _7 => _7.cliInvocationId]) !== void 0) {
439
409
  validateCliInvocationId(options.cliInvocationId);
440
410
  }
441
411
  const inputSnapshot = JSON.parse(JSON.stringify(input));
442
- const metadataSnapshot = _optionalChain([options, 'optionalAccess', _9 => _9.metadata]) ? JSON.parse(JSON.stringify(options.metadata)) : void 0;
443
- const idempotencyKey = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _10 => _10.idempotencyKey]), () => ( (_optionalChain([options, 'optionalAccess', _11 => _11.recover]) ? crypto.randomUUID() : void 0)));
412
+ const metadataSnapshot = _optionalChain([options, 'optionalAccess', _8 => _8.metadata]) ? JSON.parse(JSON.stringify(options.metadata)) : void 0;
413
+ const idempotencyKey = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _9 => _9.idempotencyKey]), () => ( (_optionalChain([options, 'optionalAccess', _10 => _10.recover]) ? crypto.randomUUID() : void 0)));
444
414
  if (idempotencyKey !== void 0) {
445
415
  validateExecutionIdempotencyKey(idempotencyKey);
446
- if (_optionalChain([options, 'optionalAccess', _12 => _12.recoveryTimeoutMs]) !== void 0 && (!Number.isFinite(options.recoveryTimeoutMs) || options.recoveryTimeoutMs < 0)) {
416
+ if (_optionalChain([options, 'optionalAccess', _11 => _11.recoveryTimeoutMs]) !== void 0 && (!Number.isFinite(options.recoveryTimeoutMs) || options.recoveryTimeoutMs < 0)) {
447
417
  throw new (0, _chunk7P5AA3SNjs.DeeplineError)(
448
418
  "recoveryTimeoutMs must be a finite, non-negative number.",
449
419
  void 0,
450
420
  "IDEMPOTENCY_KEY_INVALID"
451
421
  );
452
422
  }
453
- await _optionalChain([options, 'optionalAccess', _13 => _13.onExecution, 'optionalCall', _14 => _14({ idempotencyKey })]);
423
+ await _optionalChain([options, 'optionalAccess', _12 => _12.onExecution, 'optionalCall', _13 => _13({ idempotencyKey })]);
454
424
  }
455
- const timeoutMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _15 => _15.timeout]), () => ( resolveToolExecuteTimeoutMs(
425
+ const timeoutMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _14 => _14.timeout]), () => ( resolveToolExecuteTimeoutMs(
456
426
  toolId,
457
427
  inputSnapshot,
458
428
  this.configuredRequestTimeoutMs
@@ -461,7 +431,7 @@ var ToolCalls = class {
461
431
  await this.lookupExecutionByKey(
462
432
  idempotencyKey,
463
433
  timeoutMs,
464
- _optionalChain([options, 'optionalAccess', _16 => _16.cliInvocationId])
434
+ _optionalChain([options, 'optionalAccess', _15 => _15.cliInvocationId])
465
435
  );
466
436
  }
467
437
  const isApifySync = toolId.trim().toLowerCase() === "apify_run_actor_sync";
@@ -471,11 +441,11 @@ var ToolCalls = class {
471
441
  [_chunk7P5AA3SNjs.TOOL_EXECUTION_ERROR_SCHEMA_HEADER]: String(
472
442
  _chunk7P5AA3SNjs.TOOL_EXECUTION_ERROR_SCHEMA_VERSION
473
443
  ),
474
- ..._optionalChain([options, 'optionalAccess', _17 => _17.includeToolMetadata]) ? { [INCLUDE_TOOL_METADATA_HEADER]: "true" } : {},
475
- [EXECUTE_RESPONSE_INTENT_HEADER]: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _18 => _18.responseIntent]), () => ( "raw")),
444
+ ..._optionalChain([options, 'optionalAccess', _16 => _16.includeToolMetadata]) ? { [INCLUDE_TOOL_METADATA_HEADER]: "true" } : {},
445
+ [EXECUTE_RESPONSE_INTENT_HEADER]: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _17 => _17.responseIntent]), () => ( "raw")),
476
446
  ...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {},
477
- ..._optionalChain([options, 'optionalAccess', _19 => _19.searchRef]) ? { "x-deepline-search-ref": options.searchRef } : {},
478
- ..._optionalChain([options, 'optionalAccess', _20 => _20.cliInvocationId]) !== void 0 ? { "x-deepline-cli-invocation-id": options.cliInvocationId } : {}
447
+ ..._optionalChain([options, 'optionalAccess', _18 => _18.searchRef]) ? { "x-deepline-search-ref": options.searchRef } : {},
448
+ ..._optionalChain([options, 'optionalAccess', _19 => _19.cliInvocationId]) !== void 0 ? { "x-deepline-cli-invocation-id": options.cliInvocationId } : {}
479
449
  };
480
450
  let lastResponse = null;
481
451
  const observeTerminal = (failure) => {
@@ -491,7 +461,7 @@ var ToolCalls = class {
491
461
  const state = isRecord(body) ? body.status : null;
492
462
  const terminal = state === "completed" || state === "failed" || state === "cancelled" ? state : state === "canceled" ? "cancelled" : failure ? "failed" : null;
493
463
  if (terminal)
494
- _optionalChain([options, 'optionalAccess', _21 => _21.onResponseReceived, 'optionalCall', _22 => _22({
464
+ _optionalChain([options, 'optionalAccess', _20 => _20.onResponseReceived, 'optionalCall', _21 => _21({
495
465
  receivedAtMs: lastResponse.receivedAtMs,
496
466
  httpStatus: lastResponse.httpStatus,
497
467
  state: terminal
@@ -509,8 +479,8 @@ var ToolCalls = class {
509
479
  headers,
510
480
  {
511
481
  timeout: requestTimeoutMs,
512
- maxRetries: idempotencyKey ? 0 : _nullishCoalesce(_optionalChain([options, 'optionalAccess', _23 => _23.maxRetries]), () => ( 0)),
513
- retryApiErrors: _optionalChain([options, 'optionalAccess', _24 => _24.retryApiErrors]) === true,
482
+ maxRetries: idempotencyKey ? 0 : _nullishCoalesce(_optionalChain([options, 'optionalAccess', _22 => _22.maxRetries]), () => ( 0)),
483
+ retryApiErrors: _optionalChain([options, 'optionalAccess', _23 => _23.retryApiErrors]) === true,
514
484
  exactUrlOnly: true,
515
485
  toolId,
516
486
  idempotencyKey,
@@ -529,7 +499,7 @@ var ToolCalls = class {
529
499
  };
530
500
  let response;
531
501
  let recoveryDeadline = null;
532
- const recoveryTimeoutMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _25 => _25.recoveryTimeoutMs]), () => ( DEFAULT_EXECUTION_RECOVERY_TIMEOUT_MS));
502
+ const recoveryTimeoutMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _24 => _24.recoveryTimeoutMs]), () => ( DEFAULT_EXECUTION_RECOVERY_TIMEOUT_MS));
533
503
  let retryDelayMs = 1e3;
534
504
  const recoveryTimeoutError = () => executionRecoveryError({
535
505
  toolId,
@@ -557,7 +527,7 @@ var ToolCalls = class {
557
527
  this.defaultRequestTimeoutMs,
558
528
  remainingMs
559
529
  ),
560
- _optionalChain([options, 'optionalAccess', _26 => _26.cliInvocationId])
530
+ _optionalChain([options, 'optionalAccess', _25 => _25.cliInvocationId])
561
531
  );
562
532
  } catch (error) {
563
533
  if (!isRecoverableExecutionLookupError(error)) throw error;
@@ -747,302 +717,166 @@ var PRODUCT_NOTIFICATION_DELIVERY_LEASE_MS = 2 * 6e4;
747
717
  var PRODUCT_NOTIFICATION_SUCCESS_TTL_MS = 15 * 6e4;
748
718
  var PRODUCT_NOTIFICATION_FAILURE_TTL_MS = 24 * 60 * 6e4;
749
719
 
750
- // ../product-notifications/configuration.ts
751
- var PRODUCT_NOTIFICATION_EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
752
- function normalizeProductNotificationEmail(value) {
753
- const email = typeof value === "string" ? value.trim().toLowerCase() : "";
754
- return email && email.length <= 320 && PRODUCT_NOTIFICATION_EMAIL_PATTERN.test(email) ? email : null;
755
- }
756
- var DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING = {
757
- mode: "rolling_limit",
758
- windowMs: 36e5
720
+ // ../play-runtime/log-provenance.ts
721
+ var LOG_LEVELS = [
722
+ "debug",
723
+ "info",
724
+ "warn",
725
+ "error"
726
+ ];
727
+ var LOG_LEVEL_RANK = {
728
+ debug: 0,
729
+ info: 1,
730
+ warn: 2,
731
+ error: 3
759
732
  };
760
-
761
- // ../play-runtime/live-events.ts
762
- function projectPlayStepProgressCounters(progress) {
763
- return {
764
- completed: progress.completed,
765
- total: progress.total,
766
- failed: progress.failed,
767
- startedRows: progress.startedRows,
768
- activeRows: progress.activeRows,
769
- waitingRows: progress.waitingRows,
770
- completedRows: progress.completedRows,
771
- supersededRows: progress.supersededRows
772
- };
733
+ var LOG_PROVENANCE_CLASSES = [
734
+ "user",
735
+ "lifecycle",
736
+ "replay",
737
+ "infra",
738
+ "diagnostic",
739
+ "receipt"
740
+ ];
741
+ var LOG_PROVENANCE_POLICY = {
742
+ user: { watch: true, ui: true, debug: true },
743
+ lifecycle: { watch: true, ui: true, debug: true },
744
+ replay: { watch: false, ui: false, debug: true },
745
+ infra: { watch: false, ui: false, debug: true },
746
+ diagnostic: { watch: true, ui: true, debug: true },
747
+ receipt: { watch: false, ui: false, debug: true }
748
+ };
749
+ function logProvenanceReaches(provenance, surface) {
750
+ return LOG_PROVENANCE_POLICY[provenance][surface];
773
751
  }
774
- function resolveTimingWindow(input) {
775
- const startedAt = typeof input.startedAt === "number" && Number.isFinite(input.startedAt) ? input.startedAt : null;
776
- const completedAt = typeof input.completedAt === "number" && Number.isFinite(input.completedAt) ? input.completedAt : null;
777
- const updatedAt = typeof input.updatedAt === "number" && Number.isFinite(input.updatedAt) ? input.updatedAt : null;
752
+ var PROVENANCE_SENTINEL = "";
753
+ var PROVENANCE_PREFIX = `${PROVENANCE_SENTINEL}prov:`;
754
+ function logLevelReaches(level, minimum) {
755
+ return LOG_LEVEL_RANK[level] >= LOG_LEVEL_RANK[minimum];
756
+ }
757
+ function parseLogLevel(value) {
758
+ const normalized = value.trim().toLowerCase();
759
+ return LOG_LEVELS.includes(normalized) ? normalized : null;
760
+ }
761
+ function readProvenanceTag(line) {
762
+ if (!line.startsWith(PROVENANCE_PREFIX)) {
763
+ return { provenance: null, line };
764
+ }
765
+ const end = line.indexOf(PROVENANCE_SENTINEL, PROVENANCE_PREFIX.length);
766
+ if (end === -1) {
767
+ return { provenance: null, line };
768
+ }
769
+ const candidate = line.slice(PROVENANCE_PREFIX.length, end);
770
+ const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
771
+ return { provenance, line: line.slice(end + 1) };
772
+ }
773
+ function classifyLegacyLogLine(line) {
774
+ const message = stripLeadingTimestamp(line);
775
+ if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
776
+ return "replay";
777
+ }
778
+ if (/^\[perf\] runtime receipt\b/i.test(message)) {
779
+ return "receipt";
780
+ }
781
+ if (/^\[perf\]/i.test(message) || /^\[runtime\.(?:phase_summary|logs|log_transport)\]/i.test(message) || /\[worker\] picked up run\b/.test(message) || /\[worker\] heartbeat\b/.test(message) || /\[worker\] progress completedRows=\d+ totalRows=\d+ rowUpdates=\d+/.test(
782
+ message
783
+ ) || /\[worker\] step started\b/.test(message) || /\[worker\] Preparing run files\b/.test(message) || /\[worker\] Run files ready\b/.test(message) || /\[worker\] Runtime ready\b/.test(message) || /\[worker\] Sandbox (?:starting|create start|create done|workspace ready|upload start|runner uploaded)\b/.test(
784
+ message
785
+ ) || /^\[event\] play\.step\.progress\b/.test(message) || /^\[event\] play\.run\.snapshot\b/.test(message) || /^\[event\] play\.sheet\.summary\b/.test(message)) {
786
+ return "infra";
787
+ }
788
+ if (/^\[warn\]/i.test(message) || /^\[error\]/i.test(message) || /^\[runtime\.[a-z_]*(?:failure|error)\]/i.test(message)) {
789
+ return "diagnostic";
790
+ }
791
+ return "user";
792
+ }
793
+ function classifyLogLine(line) {
794
+ const tagged = readProvenanceTag(line);
795
+ const provenance = _nullishCoalesce(tagged.provenance, () => ( classifyLegacyLogLine(tagged.line)));
796
+ if (tagged.provenance !== null) {
797
+ return {
798
+ provenance,
799
+ level: inferLogLevel(provenance, tagged.line),
800
+ line: tagged.line
801
+ };
802
+ }
778
803
  return {
779
- startedAt,
780
- completedAt,
781
- updatedAt
804
+ provenance,
805
+ level: inferLogLevel(provenance, tagged.line),
806
+ line: tagged.line
782
807
  };
783
808
  }
784
-
785
- // ../play-runtime/run-failure.ts
786
- var PUBLIC_FAILURE_TEXT_BYTE_LIMIT = 64 * 1024;
787
-
788
- // ../play-runtime/log-context.ts
789
- var utf8 = new TextEncoder();
790
-
791
- // ../play-runtime/run-log-buffer.ts
792
- var RUNNER_LOG_MAX_BYTES = 5 * 1024 * 1024;
793
- var RUNNER_LOG_CONTEXT_MAX_BYTES = 128 * 1024;
794
- var TERMINAL_RESERVE_BYTES = 64 * 1024;
795
- var encoder = new TextEncoder();
796
-
797
- // ../play-runtime/secret-redaction.ts
798
- var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
799
- var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
800
- var BASIC_CREDENTIAL_RE = /\bBasic\s+[A-Za-z0-9+/]{4,}={0,2}\b/g;
801
- var JWT_RE = /\b[A-Za-z0-9_-]{8,16384}\.[A-Za-z0-9_-]{1,16384}\.[A-Za-z0-9_-]{8,16384}\b/g;
802
- var EMAIL_LOCAL_CHAR_RE = /[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]/;
803
- var EMAIL_DOMAIN_RE = /^[A-Za-z0-9](?:[A-Za-z0-9.-]{0,251}[A-Za-z0-9])?\.[A-Za-z]{2,63}\b/;
804
- function isEmailLocalPart(value, start, end) {
805
- let localStart = start;
806
- while (localStart > 0 && EMAIL_LOCAL_CHAR_RE.test(value[localStart - 1])) {
807
- localStart -= 1;
809
+ function inferLogLevel(provenance, line) {
810
+ const message = stripLeadingTimestamp(line);
811
+ if (/^\[info\]/i.test(message)) {
812
+ return "info";
808
813
  }
809
- let localEnd = end;
810
- while (localEnd < value.length && EMAIL_LOCAL_CHAR_RE.test(value[localEnd])) {
811
- localEnd += 1;
814
+ if (/^\[debug\]/i.test(message)) {
815
+ return "debug";
812
816
  }
813
- return localStart < localEnd && localEnd - localStart <= 64 && value[localEnd] === "@" && EMAIL_DOMAIN_RE.test(value.slice(localEnd + 1));
817
+ if (/^\[console\.error\]/i.test(message) || /^\[error\]/i.test(message)) {
818
+ return "error";
819
+ }
820
+ if (/^\[console\.warn\]/i.test(message) || /^\[warn\]/i.test(message)) {
821
+ return "warn";
822
+ }
823
+ if (/^\[console\.debug\]/i.test(message)) {
824
+ return "debug";
825
+ }
826
+ if (provenance === "replay" || provenance === "infra" || provenance === "receipt") {
827
+ return "debug";
828
+ }
829
+ if (provenance === "diagnostic") {
830
+ return "warn";
831
+ }
832
+ return "info";
814
833
  }
815
- function redactTokenUnlessEmail(match, offset, source) {
816
- return isEmailLocalPart(source, offset, offset + match.length) ? match : SECRET_REDACTION_PLACEHOLDER;
834
+ function stripLeadingTimestamp(line) {
835
+ const match = line.match(/^\[([^\]]+)\]\s*([\s\S]*)$/);
836
+ if (!match) {
837
+ return line;
838
+ }
839
+ const inner = _nullishCoalesce(match[1], () => ( ""));
840
+ const isTimestamp = !Number.isNaN(new Date(inner).getTime());
841
+ return isTimestamp ? _nullishCoalesce(match[2], () => ( line)) : line;
817
842
  }
818
- var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
819
- var SENSITIVE_FIELD_NAME = "authorization|cookie|password|(?:client[_-]?)?secret|(?:access|refresh)[_-]?token|(?:x[_-]?)?api[_-]?key|private[_-]?key|token|credentials";
820
- var COMMON_SECRET_RE = /\b(?:[prs]k_(?:live|test)_|(?:pat|ghp|github_pat)_|xox[baprs]-)[A-Za-z0-9_./+=:-]{12,}\b/gi;
821
- var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
822
- var URL_SECRET_VALUE_RE = /\b(?:[spr]k|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
823
- var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
824
- var HIGH_ENTROPY_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password|authorization|(?:access|refresh)[_-]?token)\b\s*[:=]\s*["']?[^"',\s]{16,}["']?/gi;
825
- var SENSITIVE_URL_PARAM_RE = /[?#&](?:\w*(?:key|token)|secret|password|authorization|credential|signature|sig)(?:=|$)/i;
826
- var SENSITIVE_FIELD_NAME_RE = new RegExp(
827
- `(^|[._-])(?:${SENSITIVE_FIELD_NAME})$`,
828
- "i"
829
- );
830
- var SENSITIVE_FIELD_NAME_CACHE_MAX_ENTRIES = 4096;
831
- var sensitiveFieldNameCache = /* @__PURE__ */ new Map();
832
- function isSensitiveFieldName(key) {
833
- const cached = sensitiveFieldNameCache.get(key);
834
- if (cached !== void 0) return cached;
835
- const sensitive = SENSITIVE_FIELD_NAME_RE.test(key);
836
- if (sensitiveFieldNameCache.size >= SENSITIVE_FIELD_NAME_CACHE_MAX_ENTRIES) {
837
- sensitiveFieldNameCache.clear();
843
+
844
+ // src/runs/read-errors.ts
845
+ function isTransientPlayRunReadError(error) {
846
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
847
+ return true;
838
848
  }
839
- sensitiveFieldNameCache.set(key, sensitive);
840
- return sensitive;
849
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError && typeof error.statusCode === "number") {
850
+ return error.statusCode >= 500 && error.statusCode < 600;
851
+ }
852
+ const text = error instanceof Error ? error.message : String(error);
853
+ return /auth validation backend timed out|coordinator \/submit(?:\?[^ ]*)? 5\d\d|Worker threw exception|Internal Server Error|Service Unavailable|fetch failed|eaddrnotavail|econnreset|etimedout|eai_again|socket hang up/i.test(
854
+ text
855
+ );
841
856
  }
842
- var SERIALIZED_SECRET_FIELD_RE = new RegExp(
843
- `"(${SENSITIVE_FIELD_NAME})"\\s*:\\s*(?:"[^"\\\\]*"|\\{[^{}]*\\})`,
844
- "gi"
845
- );
846
- function escapeRegExp(value) {
847
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
857
+
858
+ // src/runs/log-cursor.ts
859
+ var RUN_LOGS_CURSOR_PREFIX = "before:";
860
+ function encodeRunLogsCursor(beforeSequence) {
861
+ return `${RUN_LOGS_CURSOR_PREFIX}${beforeSequence}`;
848
862
  }
849
- var REDACTION_TRIGGER_RE = new RegExp(
850
- [
851
- // Sensitive field names, in object keys and in `name=`/`"name":` text.
852
- "token",
853
- "secret",
854
- "password",
855
- "authorization",
856
- "cookie",
857
- "credential",
858
- // One `key` branch instead of `api[_-]?key`, `private[_-]?key` and `key_`.
859
- // A regex alternation costs roughly one substring scan per branch, and a
860
- // broader branch can only send more payloads down the exact path.
861
- "key",
862
- // Self-identifying credential prefixes.
863
- "bearer",
864
- "basic",
865
- "-----BEGIN",
866
- "xox[baprs]-",
867
- "[prs]k_",
868
- "pat_",
869
- "ghp_",
870
- // URL credentials: `//user:pass@host` userinfo and sensitive query params.
871
- // The userinfo class excludes `/` exactly as the rule it guards does.
872
- "//[^\\s/]{0,256}@",
873
- "[?#&]sig",
874
- // JWTs carry no keyword at all, so the shape itself is the marker. Anchor
875
- // on the separating dot and drop JWT_RE's leading `{8,}` segment: a dot is
876
- // rare enough for the engine to skip between candidates, which makes this
877
- // gate roughly ten times cheaper than re-running JWT_RE itself, and
878
- // dropping a required segment can only widen what it accepts.
879
- "\\.[A-Za-z0-9_-]{1,16384}\\.[A-Za-z0-9_-]{8}"
880
- ].join("|"),
881
- "i"
882
- );
883
- function mightContainRedactableSecret(value) {
884
- return REDACTION_TRIGGER_RE.test(value);
885
- }
886
- function redactSecretLikeString(value) {
887
- if (!mightContainRedactableSecret(value)) return value;
888
- const serializedRedacted = value.replace(
889
- SERIALIZED_SECRET_FIELD_RE,
890
- `"$1":"${SECRET_REDACTION_PLACEHOLDER}"`
891
- );
892
- const trimmed = serializedRedacted.trim();
893
- if (/^https?:\/\/\S+$/i.test(trimmed)) {
894
- if (/^https?:\/\/[^/?#@]+@/i.test(trimmed) || SENSITIVE_URL_PARAM_RE.test(trimmed)) {
895
- return SECRET_REDACTION_PLACEHOLDER;
896
- }
897
- if (!URL_SECRET_VALUE_RE.test(serializedRedacted)) {
898
- return serializedRedacted;
899
- }
900
- }
901
- return serializedRedacted.replace(PRIVATE_KEY_RE, SECRET_REDACTION_PLACEHOLDER).replace(BEARER_TOKEN_RE, `Bearer ${SECRET_REDACTION_PLACEHOLDER}`).replace(BASIC_CREDENTIAL_RE, `Basic ${SECRET_REDACTION_PLACEHOLDER}`).replace(JWT_RE, redactTokenUnlessEmail).replace(COMMON_SECRET_RE, redactTokenUnlessEmail).replace(GENERIC_PREFIXED_SECRET_RE, redactTokenUnlessEmail).replace(GENERIC_SECRET_ASSIGNMENT_RE, SECRET_REDACTION_PLACEHOLDER).replace(HIGH_ENTROPY_ASSIGNMENT_RE, (match) => {
902
- const separator = match.includes("=") ? "=" : ":";
903
- const [key] = match.split(separator, 1);
904
- return `${key.trim()}${separator}${SECRET_REDACTION_PLACEHOLDER}`;
905
- });
863
+ function isRunLogsCursor(value) {
864
+ return value.startsWith(RUN_LOGS_CURSOR_PREFIX);
906
865
  }
907
- function createSecretRedactionContext(initialValues = []) {
908
- const exactSecrets = /* @__PURE__ */ new Set();
909
- const exactSecretMatchers = /* @__PURE__ */ new Map();
910
- function register(value) {
911
- if (value.length > 0) exactSecrets.add(value);
912
- }
913
- function matchersForSecret(secret) {
914
- const cached = exactSecretMatchers.get(secret);
915
- if (cached) return cached;
916
- const literals = [secret];
917
- try {
918
- const encoded = encodeURIComponent(secret);
919
- if (encoded !== secret) literals.push(encoded);
920
- } catch (e2) {
921
- }
922
- const built = literals.map((literal) => ({
923
- literal,
924
- matcher: new RegExp(escapeRegExp(literal), "g")
925
- }));
926
- exactSecretMatchers.set(secret, built);
927
- return built;
928
- }
929
- for (const value of initialValues) register(value);
930
- function containsRegisteredSecret(value, {
931
- includeEncoded = false,
932
- minimumLength = 1
933
- } = {}) {
934
- for (const secret of exactSecrets) {
935
- if (secret.length < minimumLength) continue;
936
- if (value.includes(secret)) return true;
937
- if (includeEncoded) {
938
- try {
939
- const encoded = encodeURIComponent(secret);
940
- if (encoded !== secret && value.includes(encoded)) return true;
941
- } catch (e3) {
942
- }
943
- }
944
- }
945
- return false;
946
- }
947
- function matchesRegisteredSecret(value) {
948
- return exactSecrets.has(value);
949
- }
950
- function redactRegisteredSecrets(value) {
951
- if (exactSecrets.size === 0) return value;
952
- let output = value;
953
- for (const secret of exactSecrets) {
954
- for (const { literal, matcher } of matchersForSecret(secret)) {
955
- if (!output.includes(literal)) continue;
956
- matcher.lastIndex = 0;
957
- output = output.replace(matcher, SECRET_REDACTION_PLACEHOLDER);
958
- }
959
- }
960
- return output;
961
- }
962
- function redactString(value) {
963
- const output = redactRegisteredSecrets(value);
964
- return redactSecretLikeString(output);
965
- }
966
- function redact(value) {
967
- if (typeof value === "string") return redactString(value);
968
- if (Array.isArray(value)) {
969
- let changed = false;
970
- const next = new Array(value.length);
971
- for (let index = 0; index < value.length; index += 1) {
972
- const entry = value[index];
973
- const redacted = redact(entry);
974
- next[index] = redacted;
975
- if (redacted !== entry) changed = true;
976
- }
977
- return changed ? next : value;
978
- }
979
- if (value && typeof value === "object") {
980
- const prototype = Object.getPrototypeOf(value);
981
- let changed = prototype !== Object.prototype && prototype !== null;
982
- const source = value;
983
- const keys = Object.keys(source);
984
- const redactedValues = new Array(keys.length);
985
- for (let index = 0; index < keys.length; index += 1) {
986
- const key = keys[index];
987
- const entry = source[key];
988
- const redacted = isSensitiveFieldName(key) ? SECRET_REDACTION_PLACEHOLDER : redact(entry);
989
- redactedValues[index] = redacted;
990
- if (redacted !== entry) changed = true;
991
- }
992
- if (!changed) return value;
993
- return Object.fromEntries(
994
- keys.map((key, index) => [key, redactedValues[index]])
995
- );
996
- }
997
- return value;
998
- }
999
- function redactKnownSecrets(value) {
1000
- if (typeof value === "string") return redactRegisteredSecrets(value);
1001
- if (Array.isArray(value)) {
1002
- return value.map((entry) => redactKnownSecrets(entry));
1003
- }
1004
- if (value && typeof value === "object") {
1005
- return Object.fromEntries(
1006
- Object.entries(value).map(([key, entry]) => [
1007
- key,
1008
- redactKnownSecrets(entry)
1009
- ])
1010
- );
1011
- }
1012
- return value;
866
+ function parseRunLogsCursor(value) {
867
+ const raw = isRunLogsCursor(value) ? value.slice(RUN_LOGS_CURSOR_PREFIX.length) : "";
868
+ const parsed = /^[1-9]\d*$/.test(raw) ? Number(raw) : NaN;
869
+ if (!Number.isSafeInteger(parsed)) {
870
+ throw Object.assign(
871
+ new Error(
872
+ `Invalid run log cursor ${JSON.stringify(value)}. Pass the nextCursor value from a previous deepline runs logs result.`
873
+ ),
874
+ { exitCode: 2 }
875
+ );
1013
876
  }
1014
- return {
1015
- register,
1016
- containsRegisteredSecret,
1017
- matchesRegisteredSecret,
1018
- redactRegisteredSecrets,
1019
- redactString,
1020
- redactKnownSecrets,
1021
- redact
1022
- };
877
+ return parsed;
1023
878
  }
1024
879
 
1025
- // ../play-runtime/output-size-limits.ts
1026
- var TERMINAL_RUN_RESULT_MAX_BYTES = 6 * 1024 * 1024;
1027
- var LEDGER_TERMINAL_RESULT_MAX_BYTES = 256 * 1024;
1028
- var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 5 * 1024 * 1024;
1029
- var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 5 * 1024 * 1024;
1030
- var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
1031
- var RUNTIME_RECEIPT_COMPLETION_BUFFER_MAX_BYTES = 32 * 1024 * 1024;
1032
- var RUNTIME_RECEIPT_CONTROL_BUFFER_MAX_BYTES = 2 * 1024 * 1024;
1033
- var RUNNER_TERMINAL_PUSH_MAX_BODY_BYTES = 16 * 1024 * 1024;
1034
- var RUNTIME_RECEIPT_GATEWAY_BATCH_MAX_BYTES = 12 * 1024 * 1024;
1035
- var RUNTIME_RECEIPT_WRITER_TARGET_BATCH_BYTES = 8 * 1024 * 1024;
1036
- var RUNNER_POST_TERMINAL_DIAGNOSTIC_MAX_BYTES = 64 * 1024;
1037
- var JSON_SIZE_LIMIT_REACHED = Symbol("JSON_SIZE_LIMIT_REACHED");
1038
-
1039
- // ../play-runtime/ledger-safe-payload.ts
1040
- var ledgerIngressRedactor = createSecretRedactionContext();
1041
-
1042
- // ../play-runtime/docflow-node-io.ts
1043
- var utf8Encoder = new TextEncoder();
1044
- var PLAY_DATASET_BRAND = Symbol.for("deepline.play.dataset");
1045
-
1046
880
  // ../play-runtime/run-event-catalog.ts
1047
881
  var RUN_EVENT_KIND = {
1048
882
  runCreated: "run.created",
@@ -1458,1254 +1292,1420 @@ var RUN_EVENT_SEARCH_FALLBACK_KIND_SQL_LITERAL = sqlStringLiteral(
1458
1292
  RUN_EVENT_SEARCH_FALLBACK_KIND
1459
1293
  );
1460
1294
 
1461
- // ../play-data-plane/runtime-sheet-orm.ts
1462
- var RUNTIME_SHEET_CELL_META_COLUMN = {
1463
- name: "_cell_meta",
1464
- dataType: "jsonb",
1465
- nullable: "NO",
1466
- defaultSql: "'{}'::jsonb"
1295
+ // ../play-runtime/run-event-query.ts
1296
+ var stringField = { type: "string", nullable: false };
1297
+ var optionalString = { type: "string", nullable: true };
1298
+ var RUN_EVENT_QUERY_FIELD_CATALOG = {
1299
+ eventId: stringField,
1300
+ orgId: stringField,
1301
+ runtimeScope: stringField,
1302
+ runId: stringField,
1303
+ playName: stringField,
1304
+ kind: stringField,
1305
+ source: optionalString,
1306
+ occurredAt: { type: "timestamp", nullable: false },
1307
+ status: optionalString,
1308
+ level: { type: "level", nullable: true },
1309
+ stepId: optionalString,
1310
+ stepKind: optionalString,
1311
+ datasetId: optionalString,
1312
+ phase: optionalString,
1313
+ provider: optionalString,
1314
+ operation: optionalString,
1315
+ producerAttempt: { type: "number", nullable: true }
1467
1316
  };
1468
- var RUNTIME_SHEET_COLUMN_CONTRACTS = [
1469
- {
1470
- name: "_key",
1471
- sqlType: "text",
1472
- dataType: "text",
1473
- nullable: "NO",
1474
- defaultSql: null,
1475
- repairable: false,
1476
- requiresDefault: false
1477
- },
1478
- {
1479
- name: "_status",
1480
- sqlType: "text NOT NULL",
1481
- dataType: "text",
1482
- nullable: "NO",
1483
- defaultSql: null,
1484
- repairable: false,
1485
- requiresDefault: false
1486
- },
1487
- {
1488
- name: "_run_id",
1489
- sqlType: "text",
1490
- dataType: "text",
1491
- nullable: "YES",
1492
- defaultSql: null,
1493
- repairable: true,
1494
- requiresDefault: false
1495
- },
1496
- {
1497
- name: "_error",
1498
- sqlType: "text",
1499
- dataType: "text",
1500
- nullable: "YES",
1501
- defaultSql: null,
1502
- repairable: true,
1503
- requiresDefault: false
1504
- },
1505
- {
1506
- name: "_stage",
1507
- sqlType: "text",
1508
- dataType: "text",
1509
- nullable: "YES",
1510
- defaultSql: null,
1511
- repairable: true,
1512
- requiresDefault: false
1513
- },
1514
- {
1515
- name: "_provider",
1516
- sqlType: "text",
1517
- dataType: "text",
1518
- nullable: "YES",
1519
- defaultSql: null,
1520
- repairable: true,
1521
- requiresDefault: false
1522
- },
1523
- {
1524
- name: "_input_index",
1525
- sqlType: "bigint",
1526
- dataType: "bigint",
1527
- nullable: "YES",
1528
- defaultSql: null,
1529
- repairable: true,
1530
- requiresDefault: false
1531
- },
1532
- {
1533
- name: "_attempt_id",
1534
- sqlType: "text",
1535
- dataType: "text",
1536
- nullable: "YES",
1537
- defaultSql: null,
1538
- repairable: true,
1539
- requiresDefault: false
1540
- },
1541
- {
1542
- name: "_attempt_owner_run_id",
1543
- sqlType: "text",
1544
- dataType: "text",
1545
- nullable: "YES",
1546
- defaultSql: null,
1547
- repairable: true,
1548
- requiresDefault: false
1549
- },
1550
- {
1551
- name: "_attempt_expires_at",
1552
- sqlType: "timestamptz",
1553
- dataType: "timestamp with time zone",
1554
- nullable: "YES",
1555
- defaultSql: null,
1556
- repairable: true,
1557
- requiresDefault: false
1558
- },
1559
- {
1560
- name: "_attempt_seq",
1561
- sqlType: "integer",
1562
- dataType: "integer",
1563
- nullable: "YES",
1564
- defaultSql: null,
1565
- repairable: true,
1566
- requiresDefault: false
1567
- },
1568
- {
1569
- name: "_write_version",
1570
- sqlType: "bigint NOT NULL DEFAULT 0",
1571
- dataType: "bigint",
1572
- nullable: "NO",
1573
- defaultSql: "0",
1574
- repairable: true,
1575
- requiresDefault: true
1576
- },
1577
- {
1578
- name: "_writer_run_id",
1579
- sqlType: "text",
1580
- dataType: "text",
1581
- nullable: "YES",
1582
- defaultSql: null,
1583
- repairable: true,
1584
- requiresDefault: false
1585
- },
1586
- {
1587
- name: "_created_at",
1588
- sqlType: "timestamptz NOT NULL DEFAULT now()",
1589
- dataType: "timestamp with time zone",
1590
- nullable: "NO",
1591
- defaultSql: "now()",
1592
- repairable: true,
1593
- requiresDefault: true
1594
- },
1595
- {
1596
- name: "_updated_at",
1597
- sqlType: "timestamptz NOT NULL DEFAULT now()",
1598
- dataType: "timestamp with time zone",
1599
- nullable: "NO",
1600
- defaultSql: "now()",
1601
- repairable: true,
1602
- requiresDefault: true
1603
- },
1604
- {
1605
- name: "_version",
1606
- sqlType: "bigint NOT NULL",
1607
- dataType: "bigint",
1608
- nullable: "NO",
1609
- defaultSql: null,
1610
- defaultKind: "version_sequence",
1611
- repairable: true,
1612
- requiresDefault: true
1613
- },
1614
- {
1615
- ...RUNTIME_SHEET_CELL_META_COLUMN,
1616
- sqlType: `jsonb NOT NULL DEFAULT ${RUNTIME_SHEET_CELL_META_COLUMN.defaultSql}`,
1617
- repairable: true,
1618
- requiresDefault: true
1619
- }
1620
- ];
1621
- var RUNTIME_SHEET_ATTEMPT_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
1622
- (column) => column.name.startsWith("_attempt_")
1623
- ).map((column) => column.name);
1624
- var RUNTIME_SHEET_WRITE_VERSION_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
1625
- (column) => column.name === "_write_version" || column.name === "_writer_run_id"
1626
- ).map((column) => column.name);
1627
- var RUNTIME_SHEET_TIMESTAMP_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
1628
- (column) => column.name === "_created_at" || column.name === "_updated_at"
1629
- ).map((column) => column.name);
1630
- var RUNTIME_SHEET_SYSTEM_COLUMNS = new Set(
1631
- RUNTIME_SHEET_COLUMN_CONTRACTS.map((column) => column.name)
1632
- );
1633
- var RUNTIME_SHEET_REPAIRABLE_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
1634
- (column) => column.repairable
1635
- );
1636
-
1637
- // ../play-runtime/run-ledger.ts
1638
- var TERMINAL_STATUS_BY_EVENT_TYPE = {
1639
- [RUN_EVENT_KIND.runCompleted]: "completed",
1640
- [RUN_EVENT_KIND.runFailed]: "failed",
1641
- [RUN_EVENT_KIND.runCancelled]: "cancelled"
1642
- };
1643
-
1644
- // ../play-runtime/log-provenance.ts
1645
- var LOG_LEVELS = [
1646
- "debug",
1647
- "info",
1648
- "warn",
1649
- "error"
1650
- ];
1651
- var LOG_LEVEL_RANK = {
1652
- debug: 0,
1653
- info: 1,
1654
- warn: 2,
1655
- error: 3
1656
- };
1657
- var LOG_PROVENANCE_CLASSES = [
1658
- "user",
1659
- "lifecycle",
1660
- "replay",
1661
- "infra",
1662
- "diagnostic",
1663
- "receipt"
1317
+ var RUN_EVENT_QUERY_RETENTION_MS = 7 * 864e5;
1318
+ var RUN_EVENT_QUERY_MAX_LIMIT = 200;
1319
+ var RUN_EVENT_QUERY_MAX_PAYLOAD_LIMIT = 10;
1320
+ var RUN_EVENT_QUERY_MAX_CURSOR_BYTES = 48 * 1024;
1321
+ var RUN_EVENT_QUERY_MAX_REQUEST_BYTES = 64 * 1024;
1322
+ var MAX_BYTES = 8192;
1323
+ var MAX_DEPTH = 8;
1324
+ var MAX_PREDICATES = 64;
1325
+ var OPERATORS = [
1326
+ "eq",
1327
+ "ne",
1328
+ "gt",
1329
+ "gte",
1330
+ "lt",
1331
+ "lte",
1332
+ "exists",
1333
+ "in"
1664
1334
  ];
1665
- var LOG_PROVENANCE_POLICY = {
1666
- user: { watch: true, ui: true, debug: true },
1667
- lifecycle: { watch: true, ui: true, debug: true },
1668
- replay: { watch: false, ui: false, debug: true },
1669
- infra: { watch: false, ui: false, debug: true },
1670
- diagnostic: { watch: true, ui: true, debug: true },
1671
- receipt: { watch: false, ui: false, debug: true }
1335
+ var RunEventQueryInputError = class extends TypeError {
1336
+ constructor(message, code = "invalid_run_event_query") {
1337
+ super(message);
1338
+ this.code = code;
1339
+ this.name = "RunEventQueryInputError";
1340
+ }
1672
1341
  };
1673
- function logProvenanceReaches(provenance, surface) {
1674
- return LOG_PROVENANCE_POLICY[provenance][surface];
1675
- }
1676
- var PROVENANCE_SENTINEL = "";
1677
- var PROVENANCE_PREFIX = `${PROVENANCE_SENTINEL}prov:`;
1678
- function logLevelReaches(level, minimum) {
1679
- return LOG_LEVEL_RANK[level] >= LOG_LEVEL_RANK[minimum];
1680
- }
1681
- function parseLogLevel(value) {
1682
- const normalized = value.trim().toLowerCase();
1683
- return LOG_LEVELS.includes(normalized) ? normalized : null;
1342
+ function fail(message) {
1343
+ throw new RunEventQueryInputError(message);
1684
1344
  }
1685
- function readProvenanceTag(line) {
1686
- if (!line.startsWith(PROVENANCE_PREFIX)) {
1687
- return { provenance: null, line };
1688
- }
1689
- const end = line.indexOf(PROVENANCE_SENTINEL, PROVENANCE_PREFIX.length);
1690
- if (end === -1) {
1691
- return { provenance: null, line };
1692
- }
1693
- const candidate = line.slice(PROVENANCE_PREFIX.length, end);
1694
- const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
1695
- return { provenance, line: line.slice(end + 1) };
1345
+ function object(value) {
1346
+ return value !== null && typeof value === "object" && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
1696
1347
  }
1697
- function classifyLegacyLogLine(line) {
1698
- const message = stripLeadingTimestamp(line);
1699
- if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
1700
- return "replay";
1701
- }
1702
- if (/^\[perf\] runtime receipt\b/i.test(message)) {
1703
- return "receipt";
1704
- }
1705
- if (/^\[perf\]/i.test(message) || /^\[runtime\.(?:phase_summary|logs|log_transport)\]/i.test(message) || /\[worker\] picked up run\b/.test(message) || /\[worker\] heartbeat\b/.test(message) || /\[worker\] progress completedRows=\d+ totalRows=\d+ rowUpdates=\d+/.test(
1706
- message
1707
- ) || /\[worker\] step started\b/.test(message) || /\[worker\] Preparing run files\b/.test(message) || /\[worker\] Run files ready\b/.test(message) || /\[worker\] Runtime ready\b/.test(message) || /\[worker\] Sandbox (?:starting|create start|create done|workspace ready|upload start|runner uploaded)\b/.test(
1708
- message
1709
- ) || /^\[event\] play\.step\.progress\b/.test(message) || /^\[event\] play\.run\.snapshot\b/.test(message) || /^\[event\] play\.sheet\.summary\b/.test(message)) {
1710
- return "infra";
1711
- }
1712
- if (/^\[warn\]/i.test(message) || /^\[error\]/i.test(message) || /^\[runtime\.[a-z_]*(?:failure|error)\]/i.test(message)) {
1713
- return "diagnostic";
1348
+ function bounded(value, maxBytes = MAX_BYTES) {
1349
+ let encoded;
1350
+ try {
1351
+ encoded = JSON.stringify(value);
1352
+ } catch (e2) {
1353
+ fail("Run event query must be bounded JSON without cycles.");
1714
1354
  }
1715
- return "user";
1355
+ if (!encoded || new TextEncoder().encode(encoded).length > maxBytes)
1356
+ fail(`Run event query exceeds ${maxBytes} bytes.`);
1716
1357
  }
1717
- function classifyLogLine(line) {
1718
- const tagged = readProvenanceTag(line);
1719
- const provenance = _nullishCoalesce(tagged.provenance, () => ( classifyLegacyLogLine(tagged.line)));
1720
- if (tagged.provenance !== null) {
1721
- return {
1722
- provenance,
1723
- level: inferLogLevel(provenance, tagged.line),
1724
- line: tagged.line
1725
- };
1726
- }
1727
- return {
1728
- provenance,
1729
- level: inferLogLevel(provenance, tagged.line),
1730
- line: tagged.line
1358
+ function validateRunEventField(value) {
1359
+ if (typeof value !== "string") fail("Run event field must be a string.");
1360
+ const field = value.startsWith("$.") ? value.slice(2) : value;
1361
+ if (Object.prototype.hasOwnProperty.call(RUN_EVENT_QUERY_FIELD_CATALOG, field))
1362
+ return field;
1363
+ if (/^context\.[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(field) && !["__proto__", "prototype", "constructor"].includes(field.slice(8)))
1364
+ return field;
1365
+ const alternatives = {
1366
+ step: "stepId",
1367
+ severity: "level",
1368
+ timestamp: "occurredAt",
1369
+ play: "playName",
1370
+ run: "runId",
1371
+ attempt: "producerAttempt"
1731
1372
  };
1373
+ fail(
1374
+ `Unsupported run event field: ${field}. Use ${_nullishCoalesce(alternatives[field], () => ( "a catalog field or context.<key>"))}; call fields() for supported fields.`
1375
+ );
1732
1376
  }
1733
- function inferLogLevel(provenance, line) {
1734
- const message = stripLeadingTimestamp(line);
1735
- if (/^\[info\]/i.test(message)) {
1736
- return "info";
1737
- }
1738
- if (/^\[debug\]/i.test(message)) {
1739
- return "debug";
1740
- }
1741
- if (/^\[console\.error\]/i.test(message) || /^\[error\]/i.test(message)) {
1742
- return "error";
1743
- }
1744
- if (/^\[console\.warn\]/i.test(message) || /^\[warn\]/i.test(message)) {
1745
- return "warn";
1746
- }
1747
- if (/^\[console\.debug\]/i.test(message)) {
1748
- return "debug";
1749
- }
1750
- if (provenance === "replay" || provenance === "infra" || provenance === "receipt") {
1751
- return "debug";
1752
- }
1753
- if (provenance === "diagnostic") {
1754
- return "warn";
1377
+ function scalar(field, value, op) {
1378
+ if (value !== null && typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean")
1379
+ fail(`Run event ${field} requires a JSON scalar.`);
1380
+ if (typeof value === "number" && !Number.isFinite(value))
1381
+ fail(`Run event ${field} requires a finite number.`);
1382
+ if (typeof value === "string" && new TextEncoder().encode(value).length > 1024)
1383
+ fail(`Run event ${field} value exceeds 1024 bytes.`);
1384
+ const descriptor = RUN_EVENT_QUERY_FIELD_CATALOG[field];
1385
+ if (descriptor) {
1386
+ if (value === null) {
1387
+ if (!descriptor.nullable) fail(`Run event ${field} cannot be null.`);
1388
+ } else if (descriptor.type === "number") {
1389
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
1390
+ fail(`Run event ${field} requires a positive integer.`);
1391
+ } else if (typeof value !== "string")
1392
+ fail(`Run event ${field} requires a string.`);
1393
+ else if (descriptor.type === "level" && !RUN_LOG_LEVELS.includes(value))
1394
+ fail("Run event level requires debug, info, warn or error.");
1395
+ else if (descriptor.type === "timestamp") {
1396
+ value = normalizeRunEventQueryTimestamp(value);
1397
+ }
1755
1398
  }
1756
- return "info";
1399
+ if (["gt", "gte", "lt", "lte"].includes(op) && (value === null || typeof value === "boolean"))
1400
+ fail(`Run event ${op} requires a string or number.`);
1401
+ return value;
1757
1402
  }
1758
- function stripLeadingTimestamp(line) {
1759
- const match = line.match(/^\[([^\]]+)\]\s*([\s\S]*)$/);
1760
- if (!match) {
1761
- return line;
1403
+ function comparison(field, op, value) {
1404
+ if (!OPERATORS.includes(op))
1405
+ fail(`Unsupported run event operator: ${op}. Use ${OPERATORS.join(", ")}.`);
1406
+ if (op === "exists") {
1407
+ if (typeof value !== "boolean")
1408
+ fail("Run event exists requires a boolean.");
1409
+ return { field, op, value };
1410
+ }
1411
+ if (op === "in") {
1412
+ if (!Array.isArray(value) || value.length < 1 || value.length > 32)
1413
+ fail("Run event in requires between 1 and 32 scalars.");
1414
+ return { field, op, value: value.map((item) => scalar(field, item, "eq")) };
1762
1415
  }
1763
- const inner = _nullishCoalesce(match[1], () => ( ""));
1764
- const isTimestamp = !Number.isNaN(new Date(inner).getTime());
1765
- return isTimestamp ? _nullishCoalesce(match[2], () => ( line)) : line;
1766
- }
1767
-
1768
- // ../play-runtime/run-snapshot-stream.ts
1769
- function isTerminalPlayRunLiveStatus(status) {
1770
- return _chunkLA46MMTLjs.isTerminalPlayRunLifecycleStatus.call(void 0, status);
1771
- }
1772
- function makeRunStreamEvent(input) {
1773
1416
  return {
1774
- ...input,
1775
- scope: "play",
1776
- at: _nullishCoalesce(input.at, () => ( (/* @__PURE__ */ new Date()).toISOString()))
1417
+ field,
1418
+ op,
1419
+ value: scalar(field, value, op)
1777
1420
  };
1778
1421
  }
1779
- var EMPTY_PLAY_RUN_STREAM_DIFF_STATE = {
1780
- runSignature: "",
1781
- snapshotSignature: "",
1782
- stepStatusSignature: "",
1783
- stepProgressSignature: "",
1784
- lastLogSeq: 0
1785
- };
1786
- function getSnapshotCursor(snapshot) {
1787
- return String(_nullishCoalesce(snapshot.updatedAt, () => ( Date.now())));
1422
+ function admitObject(input, depth = 0, budget = { count: 0 }) {
1423
+ if (depth > MAX_DEPTH) fail("Run event where exceeds depth 8.");
1424
+ if (!object(input) || !Object.keys(input).length)
1425
+ fail("Run event where requires a nonempty object.");
1426
+ const terms = [];
1427
+ const fieldTerms = (raw, filter) => {
1428
+ const field = validateRunEventField(raw);
1429
+ const operators = object(filter) ? Object.entries(filter) : [["eq", filter]];
1430
+ if (!operators.length)
1431
+ fail(`Run event ${field} has an empty operator object.`);
1432
+ for (const [op, value] of operators) {
1433
+ if (++budget.count > MAX_PREDICATES)
1434
+ fail("Run event where exceeds 64 predicates.");
1435
+ terms.push(comparison(field, op, value));
1436
+ }
1437
+ };
1438
+ for (const [key, filter] of Object.entries(input)) {
1439
+ if (key === "and" || key === "or") {
1440
+ if (!Array.isArray(filter) || filter.length < 1 || filter.length > MAX_PREDICATES)
1441
+ fail(`Run event ${key} requires a nonempty bounded array.`);
1442
+ const children = filter.map(
1443
+ (item) => admitObject(item, depth + 1, budget)
1444
+ );
1445
+ terms.push(key === "and" ? { and: children } : { or: children });
1446
+ } else if (key === "context") {
1447
+ if (!object(filter) || !Object.keys(filter).length)
1448
+ fail("Run event context requires flat scalar fields.");
1449
+ for (const [contextKey, value] of Object.entries(filter))
1450
+ fieldTerms(`context.${contextKey}`, value);
1451
+ } else fieldTerms(key, filter);
1452
+ }
1453
+ return terms.length === 1 ? terms[0] : { and: terms };
1788
1454
  }
1789
- function getRunSignature(snapshot) {
1790
- return [snapshot.runId, snapshot.status, _nullishCoalesce(snapshot.updatedAt, () => ( 0))].join(":");
1455
+ function compact(predicate) {
1456
+ if ("and" in predicate) {
1457
+ const merged = {};
1458
+ for (const term of predicate.and) {
1459
+ const child = compact(term);
1460
+ for (const [key, value] of Object.entries(child)) {
1461
+ if (key === "and") return { and: predicate.and.map(compact) };
1462
+ if (key === "context") {
1463
+ const context = _nullishCoalesce(merged.context, () => ( {}));
1464
+ for (const [name, filter2] of Object.entries(value)) {
1465
+ if (Object.prototype.hasOwnProperty.call(context, name)) {
1466
+ const combined = combineFilters(context[name], filter2);
1467
+ if (!combined) return { and: predicate.and.map(compact) };
1468
+ context[name] = combined;
1469
+ } else context[name] = filter2;
1470
+ }
1471
+ merged.context = context;
1472
+ } else if (Object.prototype.hasOwnProperty.call(merged, key)) {
1473
+ const combined = key === "or" ? void 0 : combineFilters(merged[key], value);
1474
+ if (!combined) return { and: predicate.and.map(compact) };
1475
+ merged[key] = combined;
1476
+ } else merged[key] = value;
1477
+ }
1478
+ }
1479
+ return merged;
1480
+ }
1481
+ if ("or" in predicate) return { or: predicate.or.map(compact) };
1482
+ const filter = predicate.op === "eq" ? predicate.value : { [predicate.op]: predicate.value };
1483
+ if (predicate.field.startsWith("context."))
1484
+ return { context: { [predicate.field.slice(8)]: filter } };
1485
+ return { [predicate.field]: filter };
1791
1486
  }
1792
- function getStepStatusSignature(snapshot) {
1793
- return snapshot.nodeStates.map(
1794
- (state) => [
1795
- state.nodeId,
1796
- state.status,
1797
- _nullishCoalesce(state.artifactTableNamespace, () => ( "")),
1798
- _nullishCoalesce(state.startedAt, () => ( "")),
1799
- _nullishCoalesce(state.completedAt, () => ( "")),
1800
- _nullishCoalesce(_optionalChain([state, 'access', _27 => _27.progress, 'optionalAccess', _28 => _28.startedAt]), () => ( "")),
1801
- _nullishCoalesce(_optionalChain([state, 'access', _29 => _29.progress, 'optionalAccess', _30 => _30.completedAt]), () => ( "")),
1802
- _nullishCoalesce(state.updatedAt, () => ( "")),
1803
- _nullishCoalesce(_optionalChain([state, 'access', _31 => _31.progress, 'optionalAccess', _32 => _32.updatedAt]), () => ( ""))
1804
- ].join(":")
1805
- ).join("|");
1487
+ function combineFilters(left, right) {
1488
+ const first = object(left) ? left : { eq: left };
1489
+ const second = object(right) ? right : { eq: right };
1490
+ if (Object.keys(first).some(
1491
+ (key) => Object.prototype.hasOwnProperty.call(second, key)
1492
+ ))
1493
+ return void 0;
1494
+ return { ...first, ...second };
1806
1495
  }
1807
- function getStepProgressSignature(snapshot) {
1808
- return JSON.stringify(
1809
- snapshot.nodeStates.map((state) => [
1810
- state.nodeId,
1811
- projectPlayStepProgressCounters(_nullishCoalesce(state.progress, () => ( {}))),
1812
- _nullishCoalesce(_optionalChain([state, 'access', _33 => _33.progress, 'optionalAccess', _34 => _34.artifactTableNamespace]), () => ( "")),
1813
- _nullishCoalesce(_optionalChain([state, 'access', _35 => _35.progress, 'optionalAccess', _36 => _36.startedAt]), () => ( "")),
1814
- _nullishCoalesce(_optionalChain([state, 'access', _37 => _37.progress, 'optionalAccess', _38 => _38.completedAt]), () => ( "")),
1815
- _nullishCoalesce(_optionalChain([state, 'access', _39 => _39.progress, 'optionalAccess', _40 => _40.updatedAt]), () => ( "")),
1816
- _nullishCoalesce(_optionalChain([state, 'access', _41 => _41.progress, 'optionalAccess', _42 => _42.message]), () => ( ""))
1817
- ])
1496
+ function canonical(predicate) {
1497
+ if ("field" in predicate) return predicate;
1498
+ const operator = "and" in predicate ? "and" : "or";
1499
+ const source = "and" in predicate ? predicate.and : predicate.or;
1500
+ const terms = source.map(canonical).flatMap((term) => {
1501
+ if (operator === "and" && "and" in term) return term.and;
1502
+ if (operator === "or" && "or" in term) return term.or;
1503
+ return [term];
1504
+ });
1505
+ terms.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
1506
+ const unique = terms.filter(
1507
+ (term, i) => i === 0 || JSON.stringify(term) !== JSON.stringify(terms[i - 1])
1818
1508
  );
1509
+ if (unique.length === 1) return unique[0];
1510
+ return operator === "and" ? { and: unique } : { or: unique };
1819
1511
  }
1820
- function getSnapshotSignature(snapshot) {
1821
- return JSON.stringify(snapshot);
1822
- }
1823
- function resolvePlayRunLogGap(snapshot, lastLogSeq) {
1824
- if (snapshot.totalLogCount <= lastLogSeq) {
1825
- return null;
1826
- }
1827
- const tailFirstSeq = snapshot.totalLogCount - snapshot.logs.length + 1;
1828
- if (lastLogSeq + 1 >= tailFirstSeq) {
1829
- return null;
1830
- }
1831
- return {
1832
- missingCount: tailFirstSeq - 1 - lastLogSeq,
1833
- tailFirstSeq
1512
+ function parseDsl(input) {
1513
+ let position = 0;
1514
+ let count = 0;
1515
+ const skip = () => {
1516
+ while (/\s/.test(_nullishCoalesce(input[position], () => ( ""))) && position < input.length)
1517
+ position++;
1834
1518
  };
1835
- }
1836
- function diffLogLines(input) {
1837
- const { logs, totalLogCount } = input.snapshot;
1838
- if (input.snapshot.logsUnavailable) {
1839
- return {
1840
- lines: [],
1841
- lastLogSeq: input.lastLogSeq,
1842
- firstSeq: null
1843
- };
1844
- }
1845
- if (totalLogCount <= input.lastLogSeq) {
1846
- return { lines: [], lastLogSeq: input.lastLogSeq, firstSeq: null };
1847
- }
1848
- const tailFirstSeq = totalLogCount - logs.length + 1;
1849
- if (input.lastLogSeq + 1 >= tailFirstSeq) {
1850
- return {
1851
- lines: logs.slice(input.lastLogSeq + 1 - tailFirstSeq),
1852
- lastLogSeq: totalLogCount,
1853
- firstSeq: input.lastLogSeq + 1
1854
- };
1855
- }
1856
- const missingCount = tailFirstSeq - 1 - input.lastLogSeq;
1857
- return {
1858
- lines: [
1859
- `[watch] ${missingCount} log lines not retained in the live window; full logs via runs logs`,
1860
- ...logs
1861
- ],
1862
- lastLogSeq: totalLogCount,
1863
- firstSeq: null
1864
- };
1865
- }
1866
- function diffPlayRunStreamEvents(input) {
1867
- const { snapshot, streamId, previous } = input;
1868
- const cursor = getSnapshotCursor(snapshot);
1869
- const logDiff = diffLogLines({
1870
- snapshot,
1871
- lastLogSeq: previous.lastLogSeq
1872
- });
1873
- const next = {
1874
- runSignature: getRunSignature(snapshot),
1875
- stepStatusSignature: getStepStatusSignature(snapshot),
1876
- stepProgressSignature: getStepProgressSignature(snapshot),
1877
- snapshotSignature: getSnapshotSignature(snapshot),
1878
- lastLogSeq: logDiff.lastLogSeq
1519
+ const take = (token) => {
1520
+ skip();
1521
+ if (input.startsWith(token, position)) {
1522
+ position += token.length;
1523
+ return true;
1524
+ }
1525
+ return false;
1879
1526
  };
1880
- const events = [];
1881
- if (next.stepStatusSignature !== previous.stepStatusSignature) {
1882
- for (const state of snapshot.nodeStates) {
1883
- if (state.status === "idle") {
1884
- continue;
1527
+ const json = () => {
1528
+ skip();
1529
+ const start = position;
1530
+ if (input[position] === '"') {
1531
+ position++;
1532
+ let closed = false;
1533
+ while (position < input.length) {
1534
+ const char = input[position++];
1535
+ if (char === "\\") position++;
1536
+ else if (char === '"') {
1537
+ closed = true;
1538
+ break;
1539
+ }
1885
1540
  }
1886
- const persistedStartedAt = _nullishCoalesce(_nullishCoalesce(state.startedAt, () => ( _optionalChain([state, 'access', _43 => _43.progress, 'optionalAccess', _44 => _44.startedAt]))), () => ( null));
1887
- const persistedCompletedAt = _nullishCoalesce(_nullishCoalesce(state.completedAt, () => ( _optionalChain([state, 'access', _45 => _45.progress, 'optionalAccess', _46 => _46.completedAt]))), () => ( null));
1888
- events.push(
1889
- makeRunStreamEvent({
1890
- cursor,
1891
- streamId,
1892
- type: "play.step.status",
1893
- payload: {
1894
- runId: snapshot.runId,
1895
- stepId: state.nodeId,
1896
- status: state.status,
1897
- artifactTableNamespace: _nullishCoalesce(state.artifactTableNamespace, () => ( null)),
1898
- ...resolveTimingWindow({
1899
- startedAt: persistedStartedAt,
1900
- completedAt: persistedCompletedAt,
1901
- updatedAt: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(state.updatedAt, () => ( _optionalChain([state, 'access', _47 => _47.progress, 'optionalAccess', _48 => _48.updatedAt]))), () => ( snapshot.updatedAt)), () => ( null))
1902
- })
1903
- }
1904
- })
1541
+ if (!closed) fail("Run event DSL has an unterminated JSON string.");
1542
+ } else {
1543
+ const match = /^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)/.exec(
1544
+ input.slice(position)
1905
1545
  );
1546
+ if (!match)
1547
+ fail("Run event DSL requires a JSON quoted string or scalar.");
1548
+ position += match[0].length;
1906
1549
  }
1907
- }
1908
- if (next.stepProgressSignature !== previous.stepProgressSignature) {
1909
- for (const state of snapshot.nodeStates) {
1910
- if (!state.progress) {
1911
- continue;
1550
+ try {
1551
+ return JSON.parse(input.slice(start, position));
1552
+ } catch (e3) {
1553
+ fail("Run event DSL requires valid JSON scalars.");
1554
+ }
1555
+ };
1556
+ const term = (depth) => {
1557
+ if (depth > MAX_DEPTH) fail("Run event where exceeds depth 8.");
1558
+ if (take("(")) {
1559
+ const nested = or(depth + 1);
1560
+ if (!take(")")) fail("Run event DSL is missing a closing parenthesis.");
1561
+ return nested;
1562
+ }
1563
+ skip();
1564
+ const match = /^(?:\$\.)?[A-Za-z_][A-Za-z0-9_.]*/.exec(
1565
+ input.slice(position)
1566
+ );
1567
+ if (!match) fail("Run event DSL requires a supported field.");
1568
+ position += match[0].length;
1569
+ const field = validateRunEventField(match[0]);
1570
+ if (++count > MAX_PREDICATES)
1571
+ fail("Run event where exceeds 64 predicates.");
1572
+ skip();
1573
+ const operation = /^(==|!=|>=|<=|>|<|\b(?:eq|ne|gte|gt|lte|lt|in|exists)\b)/.exec(
1574
+ input.slice(position)
1575
+ );
1576
+ if (!operation) {
1577
+ const token = _nullishCoalesce(_nullishCoalesce(_optionalChain([/^(?:[=!<>~]+|[A-Za-z_]+)/, 'access', _26 => _26.exec, 'call', _27 => _27(input.slice(position)), 'optionalAccess', _28 => _28[0]]), () => ( input[position])), () => ( "<end>"));
1578
+ if (token === "=") {
1579
+ const corrected = `${input.slice(0, position)}==${input.slice(position + 1)}`;
1580
+ fail(
1581
+ `Run event DSL does not support "=" at character ${position + 1}. For equality, replace this "=" with "==": ${JSON.stringify(corrected)}.`
1582
+ );
1912
1583
  }
1913
- events.push(
1914
- makeRunStreamEvent({
1915
- cursor: String(
1916
- _nullishCoalesce(_nullishCoalesce(state.progress.updatedAt, () => ( snapshot.updatedAt)), () => ( Date.now()))
1917
- ),
1918
- streamId,
1919
- type: "play.step.progress",
1920
- payload: {
1921
- runId: snapshot.runId,
1922
- stepId: state.nodeId,
1923
- ...projectPlayStepProgressCounters(state.progress),
1924
- message: state.progress.message,
1925
- artifactTableNamespace: _nullishCoalesce(_nullishCoalesce(state.progress.artifactTableNamespace, () => ( state.artifactTableNamespace)), () => ( null)),
1926
- ...resolveTimingWindow({
1927
- startedAt: _nullishCoalesce(_nullishCoalesce(state.startedAt, () => ( state.progress.startedAt)), () => ( null)),
1928
- completedAt: _nullishCoalesce(_nullishCoalesce(state.completedAt, () => ( state.progress.completedAt)), () => ( null)),
1929
- updatedAt: _nullishCoalesce(_nullishCoalesce(state.progress.updatedAt, () => ( snapshot.updatedAt)), () => ( null))
1930
- })
1931
- }
1932
- })
1584
+ fail(
1585
+ `Run event DSL does not support ${JSON.stringify(token)} after ${JSON.stringify(match[0])} at character ${position + 1}. Use ==, !=, >, >=, <, <=, in or exists.`
1933
1586
  );
1934
1587
  }
1935
- }
1936
- if (logDiff.lines.length > 0) {
1937
- events.push(
1938
- makeRunStreamEvent({
1939
- cursor,
1940
- streamId,
1941
- type: "play.run.log",
1942
- payload: {
1943
- runId: snapshot.runId,
1944
- lines: logDiff.lines,
1945
- source: "worker",
1946
- ...logDiff.firstSeq !== null ? { firstSeq: logDiff.firstSeq } : {},
1947
- totalLogCount: snapshot.totalLogCount
1948
- }
1949
- })
1588
+ position += operation[0].length;
1589
+ const symbols = {
1590
+ "==": "eq",
1591
+ "!=": "ne",
1592
+ ">=": "gte",
1593
+ "<=": "lte",
1594
+ ">": "gt",
1595
+ "<": "lt"
1596
+ };
1597
+ const op = _nullishCoalesce(symbols[operation[0]], () => ( operation[0]));
1598
+ if (op === "in") {
1599
+ if (!take("[")) fail("Run event DSL in requires a JSON scalar array.");
1600
+ const values = [];
1601
+ if (!take("]")) {
1602
+ do {
1603
+ values.push(json());
1604
+ if (values.length > 32)
1605
+ fail("Run event in requires between 1 and 32 scalars.");
1606
+ } while (take(","));
1607
+ if (!take("]")) fail("Run event DSL in requires a closing bracket.");
1608
+ }
1609
+ return comparison(field, op, values);
1610
+ }
1611
+ return comparison(field, op, json());
1612
+ };
1613
+ const and = (depth) => {
1614
+ const terms = [term(depth)];
1615
+ while (take("&&")) terms.push(term(depth));
1616
+ return terms.length === 1 ? terms[0] : { and: terms };
1617
+ };
1618
+ const or = (depth) => {
1619
+ const terms = [and(depth)];
1620
+ while (take("||")) terms.push(and(depth));
1621
+ return terms.length === 1 ? terms[0] : { or: terms };
1622
+ };
1623
+ const result = or(0);
1624
+ skip();
1625
+ if (position !== input.length)
1626
+ fail(`Run event DSL has unsupported input at position ${position}.`);
1627
+ return result;
1628
+ }
1629
+ function parseRunEventWhere(input) {
1630
+ bounded(input);
1631
+ const where = compact(
1632
+ canonical(typeof input === "string" ? parseDsl(input) : admitObject(input))
1633
+ );
1634
+ bounded(where);
1635
+ return where;
1636
+ }
1637
+ function normalizeRunEventQueryTimestamp(value) {
1638
+ let extraMicros = "";
1639
+ if (typeof value === "string") {
1640
+ const timestamp = /^[+-]?\d{4,6}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.(\d{1,6}))?(?:Z|[+-]\d{2}:\d{2})$/.exec(
1641
+ value
1950
1642
  );
1643
+ if (!timestamp)
1644
+ fail(
1645
+ "Run event time bounds require an ISO timestamp with a timezone and at most six fractional digits."
1646
+ );
1647
+ extraMicros = (_nullishCoalesce(timestamp[1], () => ( ""))).padEnd(6, "0").slice(3);
1951
1648
  }
1952
- if (next.snapshotSignature !== previous.snapshotSignature) {
1953
- const enrichedNodeStates = snapshot.nodeStates.map((state) => {
1954
- const timing = resolveTimingWindow({
1955
- startedAt: _nullishCoalesce(_nullishCoalesce(state.startedAt, () => ( _optionalChain([state, 'access', _49 => _49.progress, 'optionalAccess', _50 => _50.startedAt]))), () => ( null)),
1956
- completedAt: _nullishCoalesce(_nullishCoalesce(state.completedAt, () => ( _optionalChain([state, 'access', _51 => _51.progress, 'optionalAccess', _52 => _52.completedAt]))), () => ( null)),
1957
- updatedAt: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(state.updatedAt, () => ( _optionalChain([state, 'access', _53 => _53.progress, 'optionalAccess', _54 => _54.updatedAt]))), () => ( snapshot.updatedAt)), () => ( null))
1958
- });
1959
- return {
1960
- ...state,
1961
- ...timing,
1962
- progress: state.progress ? {
1963
- ...state.progress,
1964
- ...resolveTimingWindow({
1965
- startedAt: _nullishCoalesce(_nullishCoalesce(state.progress.startedAt, () => ( state.startedAt)), () => ( null)),
1966
- completedAt: _nullishCoalesce(_nullishCoalesce(state.progress.completedAt, () => ( state.completedAt)), () => ( null)),
1967
- updatedAt: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(state.progress.updatedAt, () => ( state.updatedAt)), () => ( snapshot.updatedAt)), () => ( null))
1968
- })
1969
- } : state.progress
1649
+ const date = new Date(value);
1650
+ if (!Number.isFinite(date.getTime()))
1651
+ fail("Run event time bound is invalid.");
1652
+ const canonical2 = date.toISOString();
1653
+ return /[1-9]/.test(extraMicros) ? canonical2.replace(/Z$/, `${extraMicros}Z`) : canonical2;
1654
+ }
1655
+ function timestampMicros(value) {
1656
+ const fraction = _nullishCoalesce(_optionalChain([/\.(\d+)Z$/, 'access', _29 => _29.exec, 'call', _30 => _30(value), 'optionalAccess', _31 => _31[1]]), () => ( ""));
1657
+ return BigInt(Date.parse(value)) * BigInt(1e3) + BigInt(fraction.padEnd(6, "0").slice(3));
1658
+ }
1659
+ function time(value, nowMs, fallback) {
1660
+ if (value === void 0) value = fallback;
1661
+ let timestamp;
1662
+ if (typeof value === "number") timestamp = value;
1663
+ else if (typeof value === "string") {
1664
+ const relative = /^(\d+(?:\.\d+)?)(ms|s|m|h|d)$/.exec(value);
1665
+ if (relative) {
1666
+ const units = {
1667
+ ms: 1,
1668
+ s: 1e3,
1669
+ m: 6e4,
1670
+ h: 36e5,
1671
+ d: 864e5
1970
1672
  };
1971
- });
1972
- events.push(
1973
- makeRunStreamEvent({
1974
- cursor,
1975
- streamId,
1976
- type: "play.run.snapshot",
1977
- payload: { ...snapshot, nodeStates: enrichedNodeStates }
1978
- })
1673
+ timestamp = nowMs - Number(relative[1]) * units[relative[2]];
1674
+ } else {
1675
+ return normalizeRunEventQueryTimestamp(value);
1676
+ }
1677
+ } else fail("Run event time bounds require a timestamp or duration.");
1678
+ return normalizeRunEventQueryTimestamp(timestamp);
1679
+ }
1680
+ function exact(value, name) {
1681
+ if (typeof value !== "string" || !value.trim() || value.length > 256)
1682
+ fail(
1683
+ `Run event ${name} requires a nonempty string of at most 256 characters.`
1979
1684
  );
1980
- }
1981
- if (next.runSignature !== previous.runSignature) {
1982
- events.push(
1983
- makeRunStreamEvent({
1984
- cursor,
1985
- streamId,
1986
- type: "play.run.status",
1987
- payload: {
1988
- runId: snapshot.runId,
1989
- status: snapshot.status,
1990
- updatedAt: snapshot.updatedAt,
1991
- ...snapshot.activity ? { activity: snapshot.activity } : {}
1992
- }
1993
- })
1994
- );
1995
- }
1996
- return { events, next };
1685
+ return value;
1997
1686
  }
1998
-
1999
- // src/runs/read-errors.ts
2000
- function isTransientPlayRunReadError(error) {
2001
- if (error instanceof _chunk7P5AA3SNjs.DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
2002
- return true;
2003
- }
2004
- if (error instanceof _chunk7P5AA3SNjs.DeeplineError && typeof error.statusCode === "number") {
2005
- return error.statusCode >= 500 && error.statusCode < 600;
1687
+ var CRITERIA_KEYS = [
1688
+ "since",
1689
+ "until",
1690
+ "where",
1691
+ "runId",
1692
+ "stepId",
1693
+ "minLevel",
1694
+ "text",
1695
+ "playName",
1696
+ "kind"
1697
+ ];
1698
+ function normalizeRunEventQuery(criteria, nowMs = Date.now()) {
1699
+ if (!object(criteria)) fail("Run event criteria requires an object.");
1700
+ bounded(criteria, RUN_EVENT_QUERY_MAX_REQUEST_BYTES);
1701
+ for (const key of Object.keys(criteria)) {
1702
+ if (!CRITERIA_KEYS.includes(key))
1703
+ fail(`Unsupported run event criterion: ${key}.`);
2006
1704
  }
2007
- const text = error instanceof Error ? error.message : String(error);
2008
- return /auth validation backend timed out|coordinator \/submit(?:\?[^ ]*)? 5\d\d|Worker threw exception|Internal Server Error|Service Unavailable|fetch failed|eaddrnotavail|econnreset|etimedout|eai_again|socket hang up/i.test(
2009
- text
2010
- );
2011
- }
2012
-
2013
- // src/runs/watch-polling.ts
2014
- var RUN_WATCH_POLL_INTERVAL_MS = 2e3;
2015
- function waitForNextPoll(ms, signal) {
2016
- if (_optionalChain([signal, 'optionalAccess', _55 => _55.aborted])) {
2017
- return Promise.resolve(false);
1705
+ const until = time(criteria.until, nowMs, nowMs);
1706
+ const since = time(criteria.since, nowMs, Date.parse(until) - 36e5);
1707
+ if (timestampMicros(since) >= timestampMicros(until) || timestampMicros(until) - timestampMicros(since) > BigInt(RUN_EVENT_QUERY_RETENTION_MS) * BigInt(1e3))
1708
+ fail("Run event query requires a window of at most seven days.");
1709
+ const query = { since, until };
1710
+ if (criteria.where !== void 0)
1711
+ query.where = parseRunEventWhere(criteria.where);
1712
+ for (const name of ["runId", "stepId", "playName", "kind"]) {
1713
+ if (criteria[name] !== void 0) query[name] = exact(criteria[name], name);
2018
1714
  }
2019
- return new Promise((resolve) => {
2020
- const finish = (elapsed) => {
2021
- clearTimeout(timeout);
2022
- _optionalChain([signal, 'optionalAccess', _56 => _56.removeEventListener, 'call', _57 => _57("abort", onAbort)]);
2023
- resolve(elapsed);
2024
- };
2025
- const onAbort = () => finish(false);
2026
- const timeout = setTimeout(() => finish(true), ms);
2027
- _optionalChain([signal, 'optionalAccess', _58 => _58.addEventListener, 'call', _59 => _59("abort", onAbort, { once: true })]);
2028
- });
2029
- }
2030
- function readSnapshotResponse(response, runId) {
2031
- if (!response || typeof response !== "object" || Array.isArray(response)) {
2032
- throw new Error("Run watch returned an invalid snapshot response.");
1715
+ if (criteria.minLevel !== void 0) {
1716
+ if (!RUN_LOG_LEVELS.includes(criteria.minLevel))
1717
+ fail("Run event minLevel requires debug, info, warn or error.");
1718
+ query.minLevel = criteria.minLevel;
2033
1719
  }
2034
- const record = response;
2035
- const snapshot = record.snapshot;
2036
- if (record.runId !== runId || !snapshot || typeof snapshot !== "object" || Array.isArray(snapshot) || snapshot.runId !== runId || typeof snapshot.status !== "string" || !Array.isArray(snapshot.logs) || !snapshot.logs.every(
2037
- (line) => typeof line === "string"
2038
- ) || typeof snapshot.totalLogCount !== "number" || !Array.isArray(snapshot.nodeStates)) {
2039
- throw new Error(`Run watch returned an invalid snapshot for ${runId}.`);
1720
+ if (criteria.text !== void 0) {
1721
+ if (typeof criteria.text !== "string" || !criteria.text.length || new TextEncoder().encode(criteria.text).length > 1024)
1722
+ fail("Run event text requires between 1 and 1024 bytes.");
1723
+ query.text = criteria.text;
2040
1724
  }
2041
- return { runId, snapshot };
1725
+ return query;
2042
1726
  }
2043
- async function backfillRotatedLogTail(input) {
2044
- if (!input.previous.runSignature || input.snapshot.logsUnavailable) {
2045
- return input.snapshot;
1727
+ function normalizeRunEventOperationRequest(input, nowMs = Date.now()) {
1728
+ bounded(input, RUN_EVENT_QUERY_MAX_REQUEST_BYTES);
1729
+ if (!object(input)) fail("Run event operation requires an object.");
1730
+ const operation = input.operation;
1731
+ if (!["list", "count", "summarize", "fields"].includes(String(operation)))
1732
+ fail("Run event operation requires list, count, summarize or fields.");
1733
+ if (input.resource !== "logs" && input.resource !== "events")
1734
+ fail("Run event resource requires logs or events.");
1735
+ const allowed = [
1736
+ "operation",
1737
+ "resource",
1738
+ "runId",
1739
+ ...operation === "fields" ? [] : CRITERIA_KEYS,
1740
+ ...operation === "list" ? ["limit", "cursor", "includePayloads"] : operation === "summarize" ? ["groupBy", "measures", "limit", "cursor"] : []
1741
+ ];
1742
+ for (const key of Object.keys(input)) {
1743
+ if (!allowed.includes(key))
1744
+ fail(`Run event ${operation} does not support ${key}.`);
2046
1745
  }
2047
- const gap = resolvePlayRunLogGap(input.snapshot, input.previous.lastLogSeq);
2048
- if (!gap) {
2049
- return input.snapshot;
1746
+ const base = {
1747
+ operation,
1748
+ resource: input.resource,
1749
+ ...input.runId === void 0 ? {} : { runId: exact(input.runId, "runId") }
1750
+ };
1751
+ if (operation === "fields") return base;
1752
+ if (input.resource === "logs" && !base.runId)
1753
+ fail("Run event logs require runId.");
1754
+ if (input.cursor !== void 0 && (typeof input.cursor !== "string" || !input.cursor.length || input.cursor.length > RUN_EVENT_QUERY_MAX_CURSOR_BYTES))
1755
+ fail("Run event cursor is invalid.");
1756
+ const rawCriteria = Object.fromEntries(
1757
+ Object.entries(input).filter(
1758
+ ([key]) => CRITERIA_KEYS.includes(key) && (key !== "runId" || input.resource === "events")
1759
+ )
1760
+ );
1761
+ const query = normalizeRunEventQuery(
1762
+ input.cursor === void 0 ? rawCriteria : { ...rawCriteria, since: nowMs - 36e5, until: nowMs },
1763
+ nowMs
1764
+ );
1765
+ const criteria = { ...query };
1766
+ if (input.cursor !== void 0) {
1767
+ if (input.since === void 0) delete criteria.since;
1768
+ else criteria.since = time(input.since, nowMs, nowMs - 36e5);
1769
+ if (input.until === void 0) delete criteria.until;
1770
+ else criteria.until = time(input.until, nowMs, nowMs);
2050
1771
  }
2051
- const lines = [];
2052
- let cursor = input.previous.lastLogSeq;
2053
- const targetSeq = gap.tailFirstSeq - 1;
2054
- while (cursor < targetSeq) {
2055
- const limit = Math.min(1e3, targetSeq - cursor);
2056
- const page = await input.http.get(
2057
- `/api/v2/runs/${encodeURIComponent(input.runId)}/logs?afterSeq=${cursor}&limit=${limit}`,
2058
- { signal: input.signal }
2059
- );
2060
- if (!page || !Array.isArray(page.entries) || page.entries.length === 0) {
2061
- return input.snapshot;
2062
- }
2063
- for (const entry of page.entries) {
2064
- if (!entry || entry.seq !== cursor + 1 || typeof entry.line !== "string") {
2065
- return input.snapshot;
2066
- }
2067
- lines.push(entry.line);
2068
- cursor = entry.seq;
1772
+ if (operation === "count")
1773
+ return { ...base, ...criteria };
1774
+ const limit = _nullishCoalesce(input.limit, () => ( (input.includePayloads === true ? 10 : 50)));
1775
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > RUN_EVENT_QUERY_MAX_LIMIT)
1776
+ fail("Run event limit must be between 1 and 200.");
1777
+ const page = {
1778
+ limit,
1779
+ ...input.cursor === void 0 ? {} : { cursor: input.cursor }
1780
+ };
1781
+ if (operation === "list") {
1782
+ if (input.includePayloads !== void 0 && typeof input.includePayloads !== "boolean")
1783
+ fail("Run event includePayloads requires a boolean.");
1784
+ if (input.includePayloads === true && limit > RUN_EVENT_QUERY_MAX_PAYLOAD_LIMIT)
1785
+ fail("Run event payload pages cannot exceed 10 rows.");
1786
+ return {
1787
+ ...base,
1788
+ ...criteria,
1789
+ ...page,
1790
+ ...input.includePayloads === void 0 ? {} : { includePayloads: input.includePayloads }
1791
+ };
1792
+ }
1793
+ if (!Array.isArray(input.groupBy) || input.groupBy.length > 4)
1794
+ fail("Run event groupBy requires at most four fields.");
1795
+ const groupBy = input.groupBy.map(validateRunEventField);
1796
+ if (new Set(groupBy).size !== groupBy.length)
1797
+ fail("Run event groupBy fields must be distinct.");
1798
+ const rawMeasures = _nullishCoalesce(input.measures, () => ( [{ op: "count" }]));
1799
+ if (!Array.isArray(rawMeasures) || rawMeasures.length < 1 || rawMeasures.length > 8)
1800
+ fail("Run event measures require between 1 and 8 entries.");
1801
+ const names = /* @__PURE__ */ new Set();
1802
+ const measures = rawMeasures.map((measure) => {
1803
+ if (!object(measure) || measure.op !== "count" && measure.op !== "sum")
1804
+ fail("Run event measures support count and sum.");
1805
+ for (const key of Object.keys(measure)) {
1806
+ if (!["op", "as", ...measure.op === "sum" ? ["field"] : []].includes(key))
1807
+ fail(`Unsupported run event measure option: ${key}.`);
2069
1808
  }
1809
+ const field = measure.op === "sum" ? validateRunEventField(measure.field) : void 0;
1810
+ if (field && !field.startsWith("context.") && RUN_EVENT_QUERY_FIELD_CATALOG[field].type !== "number")
1811
+ fail(`Run event sum requires a numeric field: ${field}.`);
1812
+ const name = _nullishCoalesce(measure.as, () => ( (field ? `sum_${field.replaceAll(".", "_")}` : "count")));
1813
+ if (typeof name !== "string" || !/^[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(name) || names.has(name))
1814
+ fail("Run event measure names must be distinct identifiers.");
1815
+ names.add(name);
1816
+ return field ? { op: "sum", field, as: name } : { op: "count", as: name };
1817
+ });
1818
+ return {
1819
+ ...base,
1820
+ ...criteria,
1821
+ ...page,
1822
+ groupBy,
1823
+ measures
1824
+ };
1825
+ }
1826
+
1827
+ // src/types.ts
1828
+ function isStopAllPlayRunsDryRunResult(result) {
1829
+ return "dryRun" in result && result.dryRun === true;
1830
+ }
1831
+
1832
+ // ../plays/trigger-config-route.ts
1833
+ function playTriggerConfigPath(playName) {
1834
+ return `/api/v2/plays/${encodeURIComponent(playName)}/triggers`;
1835
+ }
1836
+
1837
+ // src/plays/input-example.ts
1838
+ function playInputExampleArgs(schema) {
1839
+ if (!schema) return " --input '@<input.json>'";
1840
+ if (schema.$ref || schema.allOf) return " --input '@<input.json>'";
1841
+ const csv = schema.csvInput;
1842
+ const csvField = typeof _optionalChain([csv, 'optionalAccess', _32 => _32.inputField]) === "string" ? csv.inputField : null;
1843
+ const required = Array.isArray(schema.required) ? schema.required : [];
1844
+ const csvOnlyRequired = required.every((key) => key === csvField);
1845
+ const alternatives = _nullishCoalesce(schema.oneOf, () => ( schema.anyOf));
1846
+ const hasCsvAlternative = Array.isArray(alternatives) && alternatives.some((branch) => {
1847
+ if (!branch || typeof branch !== "object") return false;
1848
+ const keys = branch.required;
1849
+ return Array.isArray(keys) && keys.includes(csvField) && keys.every((key) => key === csvField);
1850
+ });
1851
+ if (csvField && csvOnlyRequired && (!alternatives || hasCsvAlternative)) {
1852
+ if (csvField === "csv") return " --csv '<contacts.csv>'";
1853
+ const value = JSON.stringify({ [csvField]: "<contacts.csv>" });
1854
+ return ` --input '${value.replace(/'/g, "'\\''")}'`;
2070
1855
  }
2071
- if (cursor !== targetSeq) {
2072
- return input.snapshot;
2073
- }
2074
- return { ...input.snapshot, logs: [...lines, ...input.snapshot.logs] };
2075
- }
2076
- async function* watchRunEvents(options) {
2077
- const { http, runId, signal } = options;
2078
- const path = `/api/v2/runs/${encodeURIComponent(runId)}?watchSnapshot=true`;
2079
- const streamId = `play-run-watch:${runId}`;
2080
- const pollIntervalMs = _nullishCoalesce(options.pollIntervalMs, () => ( RUN_WATCH_POLL_INTERVAL_MS));
2081
- let previous = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
2082
- let consecutiveFailures = 0;
2083
- let outageNoticeSent = false;
2084
- while (!_optionalChain([signal, 'optionalAccess', _60 => _60.aborted])) {
2085
- const pollStartedAt = Date.now();
2086
- let snapshot;
2087
- try {
2088
- const response = await http.get(path, { signal });
2089
- snapshot = await backfillRotatedLogTail({
2090
- http,
2091
- runId,
2092
- snapshot: readSnapshotResponse(response, runId).snapshot,
2093
- previous,
2094
- signal
2095
- });
2096
- } catch (error) {
2097
- if (_optionalChain([signal, 'optionalAccess', _61 => _61.aborted])) {
2098
- return;
2099
- }
2100
- if (!isTransientPlayRunReadError(error)) {
2101
- throw error;
2102
- }
2103
- consecutiveFailures += 1;
2104
- const reason = error instanceof Error ? error.message : String(error);
2105
- if (!outageNoticeSent) {
2106
- _optionalChain([options, 'access', _62 => _62.onRetry, 'optionalCall', _63 => _63({
2107
- attempt: consecutiveFailures,
2108
- delayMs: pollIntervalMs,
2109
- reason
2110
- })]);
2111
- _optionalChain([options, 'access', _64 => _64.onNotice, 'optionalCall', _65 => _65(
2112
- `[watch] run snapshot request failed; retrying every ${pollIntervalMs / 1e3}s (${reason})`
2113
- )]);
2114
- outageNoticeSent = true;
2115
- }
2116
- const remaining2 = Math.max(
2117
- 0,
2118
- pollIntervalMs - (Date.now() - pollStartedAt)
2119
- );
2120
- if (!await waitForNextPoll(remaining2, signal)) {
2121
- return;
2122
- }
2123
- continue;
2124
- }
2125
- if (outageNoticeSent) {
2126
- _optionalChain([options, 'access', _66 => _66.onNotice, 'optionalCall', _67 => _67("[watch] run snapshot polling recovered")]);
2127
- outageNoticeSent = false;
2128
- }
2129
- consecutiveFailures = 0;
2130
- const diff = diffPlayRunStreamEvents({
2131
- streamId,
2132
- snapshot,
2133
- previous
2134
- });
2135
- previous = diff.next;
2136
- for (const event of diff.events) {
2137
- yield event;
2138
- }
2139
- if (isTerminalPlayRunLiveStatus(snapshot.status)) {
2140
- return;
2141
- }
2142
- const remaining = Math.max(
2143
- 0,
2144
- pollIntervalMs - (Date.now() - pollStartedAt)
2145
- );
2146
- if (!await waitForNextPoll(remaining, signal)) {
2147
- return;
2148
- }
1856
+ if (Array.isArray(schema.required) && !required.length && !csv && !alternatives) {
1857
+ return "";
2149
1858
  }
1859
+ return " --input '@<input.json>'";
2150
1860
  }
2151
1861
 
2152
- // src/runs/log-cursor.ts
2153
- var RUN_LOGS_CURSOR_PREFIX = "before:";
2154
- function encodeRunLogsCursor(beforeSequence) {
2155
- return `${RUN_LOGS_CURSOR_PREFIX}${beforeSequence}`;
1862
+ // ../product-notifications/configuration.ts
1863
+ var PRODUCT_NOTIFICATION_EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1864
+ function normalizeProductNotificationEmail(value) {
1865
+ const email = typeof value === "string" ? value.trim().toLowerCase() : "";
1866
+ return email && email.length <= 320 && PRODUCT_NOTIFICATION_EMAIL_PATTERN.test(email) ? email : null;
2156
1867
  }
2157
- function isRunLogsCursor(value) {
2158
- return value.startsWith(RUN_LOGS_CURSOR_PREFIX);
1868
+ var DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING = {
1869
+ mode: "rolling_limit",
1870
+ windowMs: 36e5
1871
+ };
1872
+
1873
+ // ../play-runtime/live-events.ts
1874
+ function projectPlayStepProgressCounters(progress) {
1875
+ return {
1876
+ completed: progress.completed,
1877
+ total: progress.total,
1878
+ failed: progress.failed,
1879
+ startedRows: progress.startedRows,
1880
+ activeRows: progress.activeRows,
1881
+ waitingRows: progress.waitingRows,
1882
+ completedRows: progress.completedRows,
1883
+ supersededRows: progress.supersededRows
1884
+ };
2159
1885
  }
2160
- function parseRunLogsCursor(value) {
2161
- const raw = isRunLogsCursor(value) ? value.slice(RUN_LOGS_CURSOR_PREFIX.length) : "";
2162
- const parsed = /^[1-9]\d*$/.test(raw) ? Number(raw) : NaN;
2163
- if (!Number.isSafeInteger(parsed)) {
2164
- throw Object.assign(
2165
- new Error(
2166
- `Invalid run log cursor ${JSON.stringify(value)}. Pass the nextCursor value from a previous deepline runs logs result.`
2167
- ),
2168
- { exitCode: 2 }
2169
- );
2170
- }
2171
- return parsed;
1886
+ function resolveTimingWindow(input) {
1887
+ const startedAt = typeof input.startedAt === "number" && Number.isFinite(input.startedAt) ? input.startedAt : null;
1888
+ const completedAt = typeof input.completedAt === "number" && Number.isFinite(input.completedAt) ? input.completedAt : null;
1889
+ const updatedAt = typeof input.updatedAt === "number" && Number.isFinite(input.updatedAt) ? input.updatedAt : null;
1890
+ return {
1891
+ startedAt,
1892
+ completedAt,
1893
+ updatedAt
1894
+ };
2172
1895
  }
2173
1896
 
2174
- // ../play-runtime/run-event-query.ts
2175
- var stringField = { type: "string", nullable: false };
2176
- var optionalString = { type: "string", nullable: true };
2177
- var RUN_EVENT_QUERY_FIELD_CATALOG = {
2178
- eventId: stringField,
2179
- orgId: stringField,
2180
- runtimeScope: stringField,
2181
- runId: stringField,
2182
- playName: stringField,
2183
- kind: stringField,
2184
- source: optionalString,
2185
- occurredAt: { type: "timestamp", nullable: false },
2186
- status: optionalString,
2187
- level: { type: "level", nullable: true },
2188
- stepId: optionalString,
2189
- stepKind: optionalString,
2190
- datasetId: optionalString,
2191
- phase: optionalString,
2192
- provider: optionalString,
2193
- operation: optionalString,
2194
- producerAttempt: { type: "number", nullable: true }
2195
- };
2196
- var RUN_EVENT_QUERY_RETENTION_MS = 7 * 864e5;
2197
- var RUN_EVENT_QUERY_MAX_LIMIT = 200;
2198
- var RUN_EVENT_QUERY_MAX_PAYLOAD_LIMIT = 10;
2199
- var RUN_EVENT_QUERY_MAX_CURSOR_BYTES = 48 * 1024;
2200
- var RUN_EVENT_QUERY_MAX_REQUEST_BYTES = 64 * 1024;
2201
- var MAX_BYTES = 8192;
2202
- var MAX_DEPTH = 8;
2203
- var MAX_PREDICATES = 64;
2204
- var OPERATORS = [
2205
- "eq",
2206
- "ne",
2207
- "gt",
2208
- "gte",
2209
- "lt",
2210
- "lte",
2211
- "exists",
2212
- "in"
2213
- ];
2214
- var RunEventQueryInputError = class extends TypeError {
2215
- constructor(message, code = "invalid_run_event_query") {
2216
- super(message);
2217
- this.code = code;
2218
- this.name = "RunEventQueryInputError";
1897
+ // ../play-runtime/run-failure.ts
1898
+ var PUBLIC_FAILURE_TEXT_BYTE_LIMIT = 64 * 1024;
1899
+
1900
+ // ../play-runtime/log-context.ts
1901
+ var utf8 = new TextEncoder();
1902
+
1903
+ // ../play-runtime/run-log-buffer.ts
1904
+ var RUNNER_LOG_MAX_BYTES = 5 * 1024 * 1024;
1905
+ var RUNNER_LOG_CONTEXT_MAX_BYTES = 128 * 1024;
1906
+ var TERMINAL_RESERVE_BYTES = 64 * 1024;
1907
+ var encoder = new TextEncoder();
1908
+
1909
+ // ../play-runtime/secret-redaction.ts
1910
+ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
1911
+ var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
1912
+ var BASIC_CREDENTIAL_RE = /\bBasic\s+[A-Za-z0-9+/]{4,}={0,2}\b/g;
1913
+ var JWT_RE = /\b[A-Za-z0-9_-]{8,16384}\.[A-Za-z0-9_-]{1,16384}\.[A-Za-z0-9_-]{8,16384}\b/g;
1914
+ var EMAIL_LOCAL_CHAR_RE = /[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]/;
1915
+ var EMAIL_DOMAIN_RE = /^[A-Za-z0-9](?:[A-Za-z0-9.-]{0,251}[A-Za-z0-9])?\.[A-Za-z]{2,63}\b/;
1916
+ function isEmailLocalPart(value, start, end) {
1917
+ let localStart = start;
1918
+ while (localStart > 0 && EMAIL_LOCAL_CHAR_RE.test(value[localStart - 1])) {
1919
+ localStart -= 1;
2219
1920
  }
2220
- };
2221
- function fail(message) {
2222
- throw new RunEventQueryInputError(message);
1921
+ let localEnd = end;
1922
+ while (localEnd < value.length && EMAIL_LOCAL_CHAR_RE.test(value[localEnd])) {
1923
+ localEnd += 1;
1924
+ }
1925
+ return localStart < localEnd && localEnd - localStart <= 64 && value[localEnd] === "@" && EMAIL_DOMAIN_RE.test(value.slice(localEnd + 1));
2223
1926
  }
2224
- function object(value) {
2225
- return value !== null && typeof value === "object" && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
1927
+ function redactTokenUnlessEmail(match, offset, source) {
1928
+ return isEmailLocalPart(source, offset, offset + match.length) ? match : SECRET_REDACTION_PLACEHOLDER;
2226
1929
  }
2227
- function bounded(value, maxBytes = MAX_BYTES) {
2228
- let encoded;
2229
- try {
2230
- encoded = JSON.stringify(value);
2231
- } catch (e4) {
2232
- fail("Run event query must be bounded JSON without cycles.");
1930
+ var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
1931
+ var SENSITIVE_FIELD_NAME = "authorization|cookie|password|(?:client[_-]?)?secret|(?:access|refresh)[_-]?token|(?:x[_-]?)?api[_-]?key|private[_-]?key|token|credentials";
1932
+ var COMMON_SECRET_RE = /\b(?:[prs]k_(?:live|test)_|(?:pat|ghp|github_pat)_|xox[baprs]-)[A-Za-z0-9_./+=:-]{12,}\b/gi;
1933
+ var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
1934
+ var URL_SECRET_VALUE_RE = /\b(?:[spr]k|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
1935
+ var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
1936
+ var HIGH_ENTROPY_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password|authorization|(?:access|refresh)[_-]?token)\b\s*[:=]\s*["']?[^"',\s]{16,}["']?/gi;
1937
+ var SENSITIVE_URL_PARAM_RE = /[?#&](?:\w*(?:key|token)|secret|password|authorization|credential|signature|sig)(?:=|$)/i;
1938
+ var SENSITIVE_FIELD_NAME_RE = new RegExp(
1939
+ `(^|[._-])(?:${SENSITIVE_FIELD_NAME})$`,
1940
+ "i"
1941
+ );
1942
+ var SENSITIVE_FIELD_NAME_CACHE_MAX_ENTRIES = 4096;
1943
+ var sensitiveFieldNameCache = /* @__PURE__ */ new Map();
1944
+ function isSensitiveFieldName(key) {
1945
+ const cached = sensitiveFieldNameCache.get(key);
1946
+ if (cached !== void 0) return cached;
1947
+ const sensitive = SENSITIVE_FIELD_NAME_RE.test(key);
1948
+ if (sensitiveFieldNameCache.size >= SENSITIVE_FIELD_NAME_CACHE_MAX_ENTRIES) {
1949
+ sensitiveFieldNameCache.clear();
2233
1950
  }
2234
- if (!encoded || new TextEncoder().encode(encoded).length > maxBytes)
2235
- fail(`Run event query exceeds ${maxBytes} bytes.`);
1951
+ sensitiveFieldNameCache.set(key, sensitive);
1952
+ return sensitive;
2236
1953
  }
2237
- function validateRunEventField(value) {
2238
- if (typeof value !== "string") fail("Run event field must be a string.");
2239
- const field = value.startsWith("$.") ? value.slice(2) : value;
2240
- if (Object.prototype.hasOwnProperty.call(RUN_EVENT_QUERY_FIELD_CATALOG, field))
2241
- return field;
2242
- if (/^context\.[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(field) && !["__proto__", "prototype", "constructor"].includes(field.slice(8)))
2243
- return field;
2244
- const alternatives = {
2245
- step: "stepId",
2246
- severity: "level",
2247
- timestamp: "occurredAt",
2248
- play: "playName",
2249
- run: "runId",
2250
- attempt: "producerAttempt"
2251
- };
2252
- fail(
2253
- `Unsupported run event field: ${field}. Use ${_nullishCoalesce(alternatives[field], () => ( "a catalog field or context.<key>"))}; call fields() for supported fields.`
2254
- );
1954
+ var SERIALIZED_SECRET_FIELD_RE = new RegExp(
1955
+ `"(${SENSITIVE_FIELD_NAME})"\\s*:\\s*(?:"[^"\\\\]*"|\\{[^{}]*\\})`,
1956
+ "gi"
1957
+ );
1958
+ function escapeRegExp(value) {
1959
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2255
1960
  }
2256
- function scalar(field, value, op) {
2257
- if (value !== null && typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean")
2258
- fail(`Run event ${field} requires a JSON scalar.`);
2259
- if (typeof value === "number" && !Number.isFinite(value))
2260
- fail(`Run event ${field} requires a finite number.`);
2261
- if (typeof value === "string" && new TextEncoder().encode(value).length > 1024)
2262
- fail(`Run event ${field} value exceeds 1024 bytes.`);
2263
- const descriptor = RUN_EVENT_QUERY_FIELD_CATALOG[field];
2264
- if (descriptor) {
2265
- if (value === null) {
2266
- if (!descriptor.nullable) fail(`Run event ${field} cannot be null.`);
2267
- } else if (descriptor.type === "number") {
2268
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
2269
- fail(`Run event ${field} requires a positive integer.`);
2270
- } else if (typeof value !== "string")
2271
- fail(`Run event ${field} requires a string.`);
2272
- else if (descriptor.type === "level" && !RUN_LOG_LEVELS.includes(value))
2273
- fail("Run event level requires debug, info, warn or error.");
2274
- else if (descriptor.type === "timestamp") {
2275
- value = normalizeRunEventQueryTimestamp(value);
2276
- }
2277
- }
2278
- if (["gt", "gte", "lt", "lte"].includes(op) && (value === null || typeof value === "boolean"))
2279
- fail(`Run event ${op} requires a string or number.`);
2280
- return value;
2281
- }
2282
- function comparison(field, op, value) {
2283
- if (!OPERATORS.includes(op))
2284
- fail(`Unsupported run event operator: ${op}. Use ${OPERATORS.join(", ")}.`);
2285
- if (op === "exists") {
2286
- if (typeof value !== "boolean")
2287
- fail("Run event exists requires a boolean.");
2288
- return { field, op, value };
2289
- }
2290
- if (op === "in") {
2291
- if (!Array.isArray(value) || value.length < 1 || value.length > 32)
2292
- fail("Run event in requires between 1 and 32 scalars.");
2293
- return { field, op, value: value.map((item) => scalar(field, item, "eq")) };
2294
- }
2295
- return {
2296
- field,
2297
- op,
2298
- value: scalar(field, value, op)
2299
- };
1961
+ var REDACTION_TRIGGER_RE = new RegExp(
1962
+ [
1963
+ // Sensitive field names, in object keys and in `name=`/`"name":` text.
1964
+ "token",
1965
+ "secret",
1966
+ "password",
1967
+ "authorization",
1968
+ "cookie",
1969
+ "credential",
1970
+ // One `key` branch instead of `api[_-]?key`, `private[_-]?key` and `key_`.
1971
+ // A regex alternation costs roughly one substring scan per branch, and a
1972
+ // broader branch can only send more payloads down the exact path.
1973
+ "key",
1974
+ // Self-identifying credential prefixes.
1975
+ "bearer",
1976
+ "basic",
1977
+ "-----BEGIN",
1978
+ "xox[baprs]-",
1979
+ "[prs]k_",
1980
+ "pat_",
1981
+ "ghp_",
1982
+ // URL credentials: `//user:pass@host` userinfo and sensitive query params.
1983
+ // The userinfo class excludes `/` exactly as the rule it guards does.
1984
+ "//[^\\s/]{0,256}@",
1985
+ "[?#&]sig",
1986
+ // JWTs carry no keyword at all, so the shape itself is the marker. Anchor
1987
+ // on the separating dot and drop JWT_RE's leading `{8,}` segment: a dot is
1988
+ // rare enough for the engine to skip between candidates, which makes this
1989
+ // gate roughly ten times cheaper than re-running JWT_RE itself, and
1990
+ // dropping a required segment can only widen what it accepts.
1991
+ "\\.[A-Za-z0-9_-]{1,16384}\\.[A-Za-z0-9_-]{8}"
1992
+ ].join("|"),
1993
+ "i"
1994
+ );
1995
+ function mightContainRedactableSecret(value) {
1996
+ return REDACTION_TRIGGER_RE.test(value);
2300
1997
  }
2301
- function admitObject(input, depth = 0, budget = { count: 0 }) {
2302
- if (depth > MAX_DEPTH) fail("Run event where exceeds depth 8.");
2303
- if (!object(input) || !Object.keys(input).length)
2304
- fail("Run event where requires a nonempty object.");
2305
- const terms = [];
2306
- const fieldTerms = (raw, filter) => {
2307
- const field = validateRunEventField(raw);
2308
- const operators = object(filter) ? Object.entries(filter) : [["eq", filter]];
2309
- if (!operators.length)
2310
- fail(`Run event ${field} has an empty operator object.`);
2311
- for (const [op, value] of operators) {
2312
- if (++budget.count > MAX_PREDICATES)
2313
- fail("Run event where exceeds 64 predicates.");
2314
- terms.push(comparison(field, op, value));
1998
+ function redactSecretLikeString(value) {
1999
+ if (!mightContainRedactableSecret(value)) return value;
2000
+ const serializedRedacted = value.replace(
2001
+ SERIALIZED_SECRET_FIELD_RE,
2002
+ `"$1":"${SECRET_REDACTION_PLACEHOLDER}"`
2003
+ );
2004
+ const trimmed = serializedRedacted.trim();
2005
+ if (/^https?:\/\/\S+$/i.test(trimmed)) {
2006
+ if (/^https?:\/\/[^/?#@]+@/i.test(trimmed) || SENSITIVE_URL_PARAM_RE.test(trimmed)) {
2007
+ return SECRET_REDACTION_PLACEHOLDER;
2315
2008
  }
2316
- };
2317
- for (const [key, filter] of Object.entries(input)) {
2318
- if (key === "and" || key === "or") {
2319
- if (!Array.isArray(filter) || filter.length < 1 || filter.length > MAX_PREDICATES)
2320
- fail(`Run event ${key} requires a nonempty bounded array.`);
2321
- const children = filter.map(
2322
- (item) => admitObject(item, depth + 1, budget)
2323
- );
2324
- terms.push(key === "and" ? { and: children } : { or: children });
2325
- } else if (key === "context") {
2326
- if (!object(filter) || !Object.keys(filter).length)
2327
- fail("Run event context requires flat scalar fields.");
2328
- for (const [contextKey, value] of Object.entries(filter))
2329
- fieldTerms(`context.${contextKey}`, value);
2330
- } else fieldTerms(key, filter);
2331
- }
2332
- return terms.length === 1 ? terms[0] : { and: terms };
2333
- }
2334
- function compact(predicate) {
2335
- if ("and" in predicate) {
2336
- const merged = {};
2337
- for (const term of predicate.and) {
2338
- const child = compact(term);
2339
- for (const [key, value] of Object.entries(child)) {
2340
- if (key === "and") return { and: predicate.and.map(compact) };
2341
- if (key === "context") {
2342
- const context = _nullishCoalesce(merged.context, () => ( {}));
2343
- for (const [name, filter2] of Object.entries(value)) {
2344
- if (Object.prototype.hasOwnProperty.call(context, name)) {
2345
- const combined = combineFilters(context[name], filter2);
2346
- if (!combined) return { and: predicate.and.map(compact) };
2347
- context[name] = combined;
2348
- } else context[name] = filter2;
2349
- }
2350
- merged.context = context;
2351
- } else if (Object.prototype.hasOwnProperty.call(merged, key)) {
2352
- const combined = key === "or" ? void 0 : combineFilters(merged[key], value);
2353
- if (!combined) return { and: predicate.and.map(compact) };
2354
- merged[key] = combined;
2355
- } else merged[key] = value;
2356
- }
2009
+ if (!URL_SECRET_VALUE_RE.test(serializedRedacted)) {
2010
+ return serializedRedacted;
2357
2011
  }
2358
- return merged;
2359
2012
  }
2360
- if ("or" in predicate) return { or: predicate.or.map(compact) };
2361
- const filter = predicate.op === "eq" ? predicate.value : { [predicate.op]: predicate.value };
2362
- if (predicate.field.startsWith("context."))
2363
- return { context: { [predicate.field.slice(8)]: filter } };
2364
- return { [predicate.field]: filter };
2365
- }
2366
- function combineFilters(left, right) {
2367
- const first = object(left) ? left : { eq: left };
2368
- const second = object(right) ? right : { eq: right };
2369
- if (Object.keys(first).some(
2370
- (key) => Object.prototype.hasOwnProperty.call(second, key)
2371
- ))
2372
- return void 0;
2373
- return { ...first, ...second };
2374
- }
2375
- function canonical(predicate) {
2376
- if ("field" in predicate) return predicate;
2377
- const operator = "and" in predicate ? "and" : "or";
2378
- const source = "and" in predicate ? predicate.and : predicate.or;
2379
- const terms = source.map(canonical).flatMap((term) => {
2380
- if (operator === "and" && "and" in term) return term.and;
2381
- if (operator === "or" && "or" in term) return term.or;
2382
- return [term];
2013
+ return serializedRedacted.replace(PRIVATE_KEY_RE, SECRET_REDACTION_PLACEHOLDER).replace(BEARER_TOKEN_RE, `Bearer ${SECRET_REDACTION_PLACEHOLDER}`).replace(BASIC_CREDENTIAL_RE, `Basic ${SECRET_REDACTION_PLACEHOLDER}`).replace(JWT_RE, redactTokenUnlessEmail).replace(COMMON_SECRET_RE, redactTokenUnlessEmail).replace(GENERIC_PREFIXED_SECRET_RE, redactTokenUnlessEmail).replace(GENERIC_SECRET_ASSIGNMENT_RE, SECRET_REDACTION_PLACEHOLDER).replace(HIGH_ENTROPY_ASSIGNMENT_RE, (match) => {
2014
+ const separator = match.includes("=") ? "=" : ":";
2015
+ const [key] = match.split(separator, 1);
2016
+ return `${key.trim()}${separator}${SECRET_REDACTION_PLACEHOLDER}`;
2383
2017
  });
2384
- terms.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
2385
- const unique = terms.filter(
2386
- (term, i) => i === 0 || JSON.stringify(term) !== JSON.stringify(terms[i - 1])
2387
- );
2388
- if (unique.length === 1) return unique[0];
2389
- return operator === "and" ? { and: unique } : { or: unique };
2390
2018
  }
2391
- function parseDsl(input) {
2392
- let position = 0;
2393
- let count = 0;
2394
- const skip = () => {
2395
- while (/\s/.test(_nullishCoalesce(input[position], () => ( ""))) && position < input.length)
2396
- position++;
2397
- };
2398
- const take = (token) => {
2399
- skip();
2400
- if (input.startsWith(token, position)) {
2401
- position += token.length;
2402
- return true;
2019
+ function createSecretRedactionContext(initialValues = []) {
2020
+ const exactSecrets = /* @__PURE__ */ new Set();
2021
+ const exactSecretMatchers = /* @__PURE__ */ new Map();
2022
+ function register(value) {
2023
+ if (value.length > 0) exactSecrets.add(value);
2024
+ }
2025
+ function matchersForSecret(secret) {
2026
+ const cached = exactSecretMatchers.get(secret);
2027
+ if (cached) return cached;
2028
+ const literals = [secret];
2029
+ try {
2030
+ const encoded = encodeURIComponent(secret);
2031
+ if (encoded !== secret) literals.push(encoded);
2032
+ } catch (e4) {
2403
2033
  }
2404
- return false;
2405
- };
2406
- const json = () => {
2407
- skip();
2408
- const start = position;
2409
- if (input[position] === '"') {
2410
- position++;
2411
- let closed = false;
2412
- while (position < input.length) {
2413
- const char = input[position++];
2414
- if (char === "\\") position++;
2415
- else if (char === '"') {
2416
- closed = true;
2417
- break;
2034
+ const built = literals.map((literal) => ({
2035
+ literal,
2036
+ matcher: new RegExp(escapeRegExp(literal), "g")
2037
+ }));
2038
+ exactSecretMatchers.set(secret, built);
2039
+ return built;
2040
+ }
2041
+ for (const value of initialValues) register(value);
2042
+ function containsRegisteredSecret(value, {
2043
+ includeEncoded = false,
2044
+ minimumLength = 1
2045
+ } = {}) {
2046
+ for (const secret of exactSecrets) {
2047
+ if (secret.length < minimumLength) continue;
2048
+ if (value.includes(secret)) return true;
2049
+ if (includeEncoded) {
2050
+ try {
2051
+ const encoded = encodeURIComponent(secret);
2052
+ if (encoded !== secret && value.includes(encoded)) return true;
2053
+ } catch (e5) {
2418
2054
  }
2419
2055
  }
2420
- if (!closed) fail("Run event DSL has an unterminated JSON string.");
2421
- } else {
2422
- const match = /^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)/.exec(
2423
- input.slice(position)
2424
- );
2425
- if (!match)
2426
- fail("Run event DSL requires a JSON quoted string or scalar.");
2427
- position += match[0].length;
2428
- }
2429
- try {
2430
- return JSON.parse(input.slice(start, position));
2431
- } catch (e5) {
2432
- fail("Run event DSL requires valid JSON scalars.");
2433
2056
  }
2434
- };
2435
- const term = (depth) => {
2436
- if (depth > MAX_DEPTH) fail("Run event where exceeds depth 8.");
2437
- if (take("(")) {
2438
- const nested = or(depth + 1);
2439
- if (!take(")")) fail("Run event DSL is missing a closing parenthesis.");
2440
- return nested;
2057
+ return false;
2058
+ }
2059
+ function matchesRegisteredSecret(value) {
2060
+ return exactSecrets.has(value);
2061
+ }
2062
+ function redactRegisteredSecrets(value) {
2063
+ if (exactSecrets.size === 0) return value;
2064
+ let output = value;
2065
+ for (const secret of exactSecrets) {
2066
+ for (const { literal, matcher } of matchersForSecret(secret)) {
2067
+ if (!output.includes(literal)) continue;
2068
+ matcher.lastIndex = 0;
2069
+ output = output.replace(matcher, SECRET_REDACTION_PLACEHOLDER);
2070
+ }
2441
2071
  }
2442
- skip();
2443
- const match = /^(?:\$\.)?[A-Za-z_][A-Za-z0-9_.]*/.exec(
2444
- input.slice(position)
2445
- );
2446
- if (!match) fail("Run event DSL requires a supported field.");
2447
- position += match[0].length;
2448
- const field = validateRunEventField(match[0]);
2449
- if (++count > MAX_PREDICATES)
2450
- fail("Run event where exceeds 64 predicates.");
2451
- skip();
2452
- const operation = /^(==|!=|>=|<=|>|<|\b(?:eq|ne|gte|gt|lte|lt|in|exists)\b)/.exec(
2453
- input.slice(position)
2454
- );
2455
- if (!operation) {
2456
- const token = _nullishCoalesce(_nullishCoalesce(_optionalChain([/^(?:[=!<>~]+|[A-Za-z_]+)/, 'access', _68 => _68.exec, 'call', _69 => _69(input.slice(position)), 'optionalAccess', _70 => _70[0]]), () => ( input[position])), () => ( "<end>"));
2457
- if (token === "=") {
2458
- const corrected = `${input.slice(0, position)}==${input.slice(position + 1)}`;
2459
- fail(
2460
- `Run event DSL does not support "=" at character ${position + 1}. For equality, replace this "=" with "==": ${JSON.stringify(corrected)}.`
2461
- );
2072
+ return output;
2073
+ }
2074
+ function redactString(value) {
2075
+ const output = redactRegisteredSecrets(value);
2076
+ return redactSecretLikeString(output);
2077
+ }
2078
+ function redact(value) {
2079
+ if (typeof value === "string") return redactString(value);
2080
+ if (Array.isArray(value)) {
2081
+ let changed = false;
2082
+ const next = new Array(value.length);
2083
+ for (let index = 0; index < value.length; index += 1) {
2084
+ const entry = value[index];
2085
+ const redacted = redact(entry);
2086
+ next[index] = redacted;
2087
+ if (redacted !== entry) changed = true;
2462
2088
  }
2463
- fail(
2464
- `Run event DSL does not support ${JSON.stringify(token)} after ${JSON.stringify(match[0])} at character ${position + 1}. Use ==, !=, >, >=, <, <=, in or exists.`
2465
- );
2089
+ return changed ? next : value;
2466
2090
  }
2467
- position += operation[0].length;
2468
- const symbols = {
2469
- "==": "eq",
2470
- "!=": "ne",
2471
- ">=": "gte",
2472
- "<=": "lte",
2473
- ">": "gt",
2474
- "<": "lt"
2475
- };
2476
- const op = _nullishCoalesce(symbols[operation[0]], () => ( operation[0]));
2477
- if (op === "in") {
2478
- if (!take("[")) fail("Run event DSL in requires a JSON scalar array.");
2479
- const values = [];
2480
- if (!take("]")) {
2481
- do {
2482
- values.push(json());
2483
- if (values.length > 32)
2484
- fail("Run event in requires between 1 and 32 scalars.");
2485
- } while (take(","));
2486
- if (!take("]")) fail("Run event DSL in requires a closing bracket.");
2091
+ if (value && typeof value === "object") {
2092
+ const prototype = Object.getPrototypeOf(value);
2093
+ let changed = prototype !== Object.prototype && prototype !== null;
2094
+ const source = value;
2095
+ const keys = Object.keys(source);
2096
+ const redactedValues = new Array(keys.length);
2097
+ for (let index = 0; index < keys.length; index += 1) {
2098
+ const key = keys[index];
2099
+ const entry = source[key];
2100
+ const redacted = isSensitiveFieldName(key) ? SECRET_REDACTION_PLACEHOLDER : redact(entry);
2101
+ redactedValues[index] = redacted;
2102
+ if (redacted !== entry) changed = true;
2487
2103
  }
2488
- return comparison(field, op, values);
2104
+ if (!changed) return value;
2105
+ return Object.fromEntries(
2106
+ keys.map((key, index) => [key, redactedValues[index]])
2107
+ );
2489
2108
  }
2490
- return comparison(field, op, json());
2491
- };
2492
- const and = (depth) => {
2493
- const terms = [term(depth)];
2494
- while (take("&&")) terms.push(term(depth));
2495
- return terms.length === 1 ? terms[0] : { and: terms };
2109
+ return value;
2110
+ }
2111
+ function redactKnownSecrets(value) {
2112
+ if (typeof value === "string") return redactRegisteredSecrets(value);
2113
+ if (Array.isArray(value)) {
2114
+ return value.map((entry) => redactKnownSecrets(entry));
2115
+ }
2116
+ if (value && typeof value === "object") {
2117
+ return Object.fromEntries(
2118
+ Object.entries(value).map(([key, entry]) => [
2119
+ key,
2120
+ redactKnownSecrets(entry)
2121
+ ])
2122
+ );
2123
+ }
2124
+ return value;
2125
+ }
2126
+ return {
2127
+ register,
2128
+ containsRegisteredSecret,
2129
+ matchesRegisteredSecret,
2130
+ redactRegisteredSecrets,
2131
+ redactString,
2132
+ redactKnownSecrets,
2133
+ redact
2496
2134
  };
2497
- const or = (depth) => {
2498
- const terms = [and(depth)];
2499
- while (take("||")) terms.push(and(depth));
2500
- return terms.length === 1 ? terms[0] : { or: terms };
2135
+ }
2136
+
2137
+ // ../play-runtime/output-size-limits.ts
2138
+ var TERMINAL_RUN_RESULT_MAX_BYTES = 6 * 1024 * 1024;
2139
+ var LEDGER_TERMINAL_RESULT_MAX_BYTES = 256 * 1024;
2140
+ var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 5 * 1024 * 1024;
2141
+ var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 5 * 1024 * 1024;
2142
+ var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
2143
+ var RUNTIME_RECEIPT_COMPLETION_BUFFER_MAX_BYTES = 32 * 1024 * 1024;
2144
+ var RUNTIME_RECEIPT_CONTROL_BUFFER_MAX_BYTES = 2 * 1024 * 1024;
2145
+ var RUNNER_TERMINAL_PUSH_MAX_BODY_BYTES = 16 * 1024 * 1024;
2146
+ var RUNTIME_RECEIPT_GATEWAY_BATCH_MAX_BYTES = 12 * 1024 * 1024;
2147
+ var RUNTIME_RECEIPT_WRITER_TARGET_BATCH_BYTES = 8 * 1024 * 1024;
2148
+ var RUNNER_POST_TERMINAL_DIAGNOSTIC_MAX_BYTES = 64 * 1024;
2149
+ var JSON_SIZE_LIMIT_REACHED = Symbol("JSON_SIZE_LIMIT_REACHED");
2150
+
2151
+ // ../play-runtime/ledger-safe-payload.ts
2152
+ var ledgerIngressRedactor = createSecretRedactionContext();
2153
+
2154
+ // ../play-runtime/docflow-node-io.ts
2155
+ var utf8Encoder = new TextEncoder();
2156
+ var PLAY_DATASET_BRAND = Symbol.for("deepline.play.dataset");
2157
+
2158
+ // ../play-data-plane/runtime-sheet-orm.ts
2159
+ var RUNTIME_SHEET_CELL_META_COLUMN = {
2160
+ name: "_cell_meta",
2161
+ dataType: "jsonb",
2162
+ nullable: "NO",
2163
+ defaultSql: "'{}'::jsonb"
2164
+ };
2165
+ var RUNTIME_SHEET_COLUMN_CONTRACTS = [
2166
+ {
2167
+ name: "_key",
2168
+ sqlType: "text",
2169
+ dataType: "text",
2170
+ nullable: "NO",
2171
+ defaultSql: null,
2172
+ repairable: false,
2173
+ requiresDefault: false
2174
+ },
2175
+ {
2176
+ name: "_status",
2177
+ sqlType: "text NOT NULL",
2178
+ dataType: "text",
2179
+ nullable: "NO",
2180
+ defaultSql: null,
2181
+ repairable: false,
2182
+ requiresDefault: false
2183
+ },
2184
+ {
2185
+ name: "_run_id",
2186
+ sqlType: "text",
2187
+ dataType: "text",
2188
+ nullable: "YES",
2189
+ defaultSql: null,
2190
+ repairable: true,
2191
+ requiresDefault: false
2192
+ },
2193
+ {
2194
+ name: "_error",
2195
+ sqlType: "text",
2196
+ dataType: "text",
2197
+ nullable: "YES",
2198
+ defaultSql: null,
2199
+ repairable: true,
2200
+ requiresDefault: false
2201
+ },
2202
+ {
2203
+ name: "_stage",
2204
+ sqlType: "text",
2205
+ dataType: "text",
2206
+ nullable: "YES",
2207
+ defaultSql: null,
2208
+ repairable: true,
2209
+ requiresDefault: false
2210
+ },
2211
+ {
2212
+ name: "_provider",
2213
+ sqlType: "text",
2214
+ dataType: "text",
2215
+ nullable: "YES",
2216
+ defaultSql: null,
2217
+ repairable: true,
2218
+ requiresDefault: false
2219
+ },
2220
+ {
2221
+ name: "_input_index",
2222
+ sqlType: "bigint",
2223
+ dataType: "bigint",
2224
+ nullable: "YES",
2225
+ defaultSql: null,
2226
+ repairable: true,
2227
+ requiresDefault: false
2228
+ },
2229
+ {
2230
+ name: "_attempt_id",
2231
+ sqlType: "text",
2232
+ dataType: "text",
2233
+ nullable: "YES",
2234
+ defaultSql: null,
2235
+ repairable: true,
2236
+ requiresDefault: false
2237
+ },
2238
+ {
2239
+ name: "_attempt_owner_run_id",
2240
+ sqlType: "text",
2241
+ dataType: "text",
2242
+ nullable: "YES",
2243
+ defaultSql: null,
2244
+ repairable: true,
2245
+ requiresDefault: false
2246
+ },
2247
+ {
2248
+ name: "_attempt_expires_at",
2249
+ sqlType: "timestamptz",
2250
+ dataType: "timestamp with time zone",
2251
+ nullable: "YES",
2252
+ defaultSql: null,
2253
+ repairable: true,
2254
+ requiresDefault: false
2255
+ },
2256
+ {
2257
+ name: "_attempt_seq",
2258
+ sqlType: "integer",
2259
+ dataType: "integer",
2260
+ nullable: "YES",
2261
+ defaultSql: null,
2262
+ repairable: true,
2263
+ requiresDefault: false
2264
+ },
2265
+ {
2266
+ name: "_write_version",
2267
+ sqlType: "bigint NOT NULL DEFAULT 0",
2268
+ dataType: "bigint",
2269
+ nullable: "NO",
2270
+ defaultSql: "0",
2271
+ repairable: true,
2272
+ requiresDefault: true
2273
+ },
2274
+ {
2275
+ name: "_writer_run_id",
2276
+ sqlType: "text",
2277
+ dataType: "text",
2278
+ nullable: "YES",
2279
+ defaultSql: null,
2280
+ repairable: true,
2281
+ requiresDefault: false
2282
+ },
2283
+ {
2284
+ name: "_created_at",
2285
+ sqlType: "timestamptz NOT NULL DEFAULT now()",
2286
+ dataType: "timestamp with time zone",
2287
+ nullable: "NO",
2288
+ defaultSql: "now()",
2289
+ repairable: true,
2290
+ requiresDefault: true
2291
+ },
2292
+ {
2293
+ name: "_updated_at",
2294
+ sqlType: "timestamptz NOT NULL DEFAULT now()",
2295
+ dataType: "timestamp with time zone",
2296
+ nullable: "NO",
2297
+ defaultSql: "now()",
2298
+ repairable: true,
2299
+ requiresDefault: true
2300
+ },
2301
+ {
2302
+ name: "_version",
2303
+ sqlType: "bigint NOT NULL",
2304
+ dataType: "bigint",
2305
+ nullable: "NO",
2306
+ defaultSql: null,
2307
+ defaultKind: "version_sequence",
2308
+ repairable: true,
2309
+ requiresDefault: true
2310
+ },
2311
+ {
2312
+ ...RUNTIME_SHEET_CELL_META_COLUMN,
2313
+ sqlType: `jsonb NOT NULL DEFAULT ${RUNTIME_SHEET_CELL_META_COLUMN.defaultSql}`,
2314
+ repairable: true,
2315
+ requiresDefault: true
2316
+ }
2317
+ ];
2318
+ var RUNTIME_SHEET_ATTEMPT_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
2319
+ (column) => column.name.startsWith("_attempt_")
2320
+ ).map((column) => column.name);
2321
+ var RUNTIME_SHEET_WRITE_VERSION_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
2322
+ (column) => column.name === "_write_version" || column.name === "_writer_run_id"
2323
+ ).map((column) => column.name);
2324
+ var RUNTIME_SHEET_TIMESTAMP_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
2325
+ (column) => column.name === "_created_at" || column.name === "_updated_at"
2326
+ ).map((column) => column.name);
2327
+ var RUNTIME_SHEET_SYSTEM_COLUMNS = new Set(
2328
+ RUNTIME_SHEET_COLUMN_CONTRACTS.map((column) => column.name)
2329
+ );
2330
+ var RUNTIME_SHEET_REPAIRABLE_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
2331
+ (column) => column.repairable
2332
+ );
2333
+
2334
+ // ../play-runtime/run-ledger.ts
2335
+ var TERMINAL_STATUS_BY_EVENT_TYPE = {
2336
+ [RUN_EVENT_KIND.runCompleted]: "completed",
2337
+ [RUN_EVENT_KIND.runFailed]: "failed",
2338
+ [RUN_EVENT_KIND.runCancelled]: "cancelled"
2339
+ };
2340
+
2341
+ // ../play-runtime/run-snapshot-stream.ts
2342
+ function isTerminalPlayRunLiveStatus(status) {
2343
+ return _chunkLA46MMTLjs.isTerminalPlayRunLifecycleStatus.call(void 0, status);
2344
+ }
2345
+ function makeRunStreamEvent(input) {
2346
+ return {
2347
+ ...input,
2348
+ scope: "play",
2349
+ at: _nullishCoalesce(input.at, () => ( (/* @__PURE__ */ new Date()).toISOString()))
2501
2350
  };
2502
- const result = or(0);
2503
- skip();
2504
- if (position !== input.length)
2505
- fail(`Run event DSL has unsupported input at position ${position}.`);
2506
- return result;
2507
2351
  }
2508
- function parseRunEventWhere(input) {
2509
- bounded(input);
2510
- const where = compact(
2511
- canonical(typeof input === "string" ? parseDsl(input) : admitObject(input))
2352
+ var EMPTY_PLAY_RUN_STREAM_DIFF_STATE = {
2353
+ runSignature: "",
2354
+ snapshotSignature: "",
2355
+ stepStatusSignature: "",
2356
+ stepProgressSignature: "",
2357
+ lastLogSeq: 0
2358
+ };
2359
+ function getSnapshotCursor(snapshot) {
2360
+ return String(_nullishCoalesce(snapshot.updatedAt, () => ( Date.now())));
2361
+ }
2362
+ function getRunSignature(snapshot) {
2363
+ return [snapshot.runId, snapshot.status, _nullishCoalesce(snapshot.updatedAt, () => ( 0))].join(":");
2364
+ }
2365
+ function getStepStatusSignature(snapshot) {
2366
+ return snapshot.nodeStates.map(
2367
+ (state) => [
2368
+ state.nodeId,
2369
+ state.status,
2370
+ _nullishCoalesce(state.artifactTableNamespace, () => ( "")),
2371
+ _nullishCoalesce(state.startedAt, () => ( "")),
2372
+ _nullishCoalesce(state.completedAt, () => ( "")),
2373
+ _nullishCoalesce(_optionalChain([state, 'access', _33 => _33.progress, 'optionalAccess', _34 => _34.startedAt]), () => ( "")),
2374
+ _nullishCoalesce(_optionalChain([state, 'access', _35 => _35.progress, 'optionalAccess', _36 => _36.completedAt]), () => ( "")),
2375
+ _nullishCoalesce(state.updatedAt, () => ( "")),
2376
+ _nullishCoalesce(_optionalChain([state, 'access', _37 => _37.progress, 'optionalAccess', _38 => _38.updatedAt]), () => ( ""))
2377
+ ].join(":")
2378
+ ).join("|");
2379
+ }
2380
+ function getStepProgressSignature(snapshot) {
2381
+ return JSON.stringify(
2382
+ snapshot.nodeStates.map((state) => [
2383
+ state.nodeId,
2384
+ projectPlayStepProgressCounters(_nullishCoalesce(state.progress, () => ( {}))),
2385
+ _nullishCoalesce(_optionalChain([state, 'access', _39 => _39.progress, 'optionalAccess', _40 => _40.artifactTableNamespace]), () => ( "")),
2386
+ _nullishCoalesce(_optionalChain([state, 'access', _41 => _41.progress, 'optionalAccess', _42 => _42.startedAt]), () => ( "")),
2387
+ _nullishCoalesce(_optionalChain([state, 'access', _43 => _43.progress, 'optionalAccess', _44 => _44.completedAt]), () => ( "")),
2388
+ _nullishCoalesce(_optionalChain([state, 'access', _45 => _45.progress, 'optionalAccess', _46 => _46.updatedAt]), () => ( "")),
2389
+ _nullishCoalesce(_optionalChain([state, 'access', _47 => _47.progress, 'optionalAccess', _48 => _48.message]), () => ( ""))
2390
+ ])
2512
2391
  );
2513
- bounded(where);
2514
- return where;
2515
2392
  }
2516
- function normalizeRunEventQueryTimestamp(value) {
2517
- let extraMicros = "";
2518
- if (typeof value === "string") {
2519
- const timestamp = /^[+-]?\d{4,6}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.(\d{1,6}))?(?:Z|[+-]\d{2}:\d{2})$/.exec(
2520
- value
2521
- );
2522
- if (!timestamp)
2523
- fail(
2524
- "Run event time bounds require an ISO timestamp with a timezone and at most six fractional digits."
2525
- );
2526
- extraMicros = (_nullishCoalesce(timestamp[1], () => ( ""))).padEnd(6, "0").slice(3);
2393
+ function getSnapshotSignature(snapshot) {
2394
+ return JSON.stringify(snapshot);
2395
+ }
2396
+ function resolvePlayRunLogGap(snapshot, lastLogSeq) {
2397
+ if (snapshot.totalLogCount <= lastLogSeq) {
2398
+ return null;
2527
2399
  }
2528
- const date = new Date(value);
2529
- if (!Number.isFinite(date.getTime()))
2530
- fail("Run event time bound is invalid.");
2531
- const canonical2 = date.toISOString();
2532
- return /[1-9]/.test(extraMicros) ? canonical2.replace(/Z$/, `${extraMicros}Z`) : canonical2;
2400
+ const tailFirstSeq = snapshot.totalLogCount - snapshot.logs.length + 1;
2401
+ if (lastLogSeq + 1 >= tailFirstSeq) {
2402
+ return null;
2403
+ }
2404
+ return {
2405
+ missingCount: tailFirstSeq - 1 - lastLogSeq,
2406
+ tailFirstSeq
2407
+ };
2533
2408
  }
2534
- function timestampMicros(value) {
2535
- const fraction = _nullishCoalesce(_optionalChain([/\.(\d+)Z$/, 'access', _71 => _71.exec, 'call', _72 => _72(value), 'optionalAccess', _73 => _73[1]]), () => ( ""));
2536
- return BigInt(Date.parse(value)) * BigInt(1e3) + BigInt(fraction.padEnd(6, "0").slice(3));
2409
+ function diffLogLines(input) {
2410
+ const { logs, totalLogCount } = input.snapshot;
2411
+ if (input.snapshot.logsUnavailable) {
2412
+ return {
2413
+ lines: [],
2414
+ lastLogSeq: input.lastLogSeq,
2415
+ firstSeq: null
2416
+ };
2417
+ }
2418
+ if (totalLogCount <= input.lastLogSeq) {
2419
+ return { lines: [], lastLogSeq: input.lastLogSeq, firstSeq: null };
2420
+ }
2421
+ const tailFirstSeq = totalLogCount - logs.length + 1;
2422
+ if (input.lastLogSeq + 1 >= tailFirstSeq) {
2423
+ return {
2424
+ lines: logs.slice(input.lastLogSeq + 1 - tailFirstSeq),
2425
+ lastLogSeq: totalLogCount,
2426
+ firstSeq: input.lastLogSeq + 1
2427
+ };
2428
+ }
2429
+ const missingCount = tailFirstSeq - 1 - input.lastLogSeq;
2430
+ return {
2431
+ lines: [
2432
+ `[watch] ${missingCount} log lines not retained in the live window; full logs via runs logs`,
2433
+ ...logs
2434
+ ],
2435
+ lastLogSeq: totalLogCount,
2436
+ firstSeq: null
2437
+ };
2537
2438
  }
2538
- function time(value, nowMs, fallback) {
2539
- if (value === void 0) value = fallback;
2540
- let timestamp;
2541
- if (typeof value === "number") timestamp = value;
2542
- else if (typeof value === "string") {
2543
- const relative = /^(\d+(?:\.\d+)?)(ms|s|m|h|d)$/.exec(value);
2544
- if (relative) {
2545
- const units = {
2546
- ms: 1,
2547
- s: 1e3,
2548
- m: 6e4,
2549
- h: 36e5,
2550
- d: 864e5
2551
- };
2552
- timestamp = nowMs - Number(relative[1]) * units[relative[2]];
2553
- } else {
2554
- return normalizeRunEventQueryTimestamp(value);
2439
+ function diffPlayRunStreamEvents(input) {
2440
+ const { snapshot, streamId, previous } = input;
2441
+ const cursor = getSnapshotCursor(snapshot);
2442
+ const logDiff = diffLogLines({
2443
+ snapshot,
2444
+ lastLogSeq: previous.lastLogSeq
2445
+ });
2446
+ const next = {
2447
+ runSignature: getRunSignature(snapshot),
2448
+ stepStatusSignature: getStepStatusSignature(snapshot),
2449
+ stepProgressSignature: getStepProgressSignature(snapshot),
2450
+ snapshotSignature: getSnapshotSignature(snapshot),
2451
+ lastLogSeq: logDiff.lastLogSeq
2452
+ };
2453
+ const events = [];
2454
+ if (next.stepStatusSignature !== previous.stepStatusSignature) {
2455
+ for (const state of snapshot.nodeStates) {
2456
+ if (state.status === "idle") {
2457
+ continue;
2458
+ }
2459
+ const persistedStartedAt = _nullishCoalesce(_nullishCoalesce(state.startedAt, () => ( _optionalChain([state, 'access', _49 => _49.progress, 'optionalAccess', _50 => _50.startedAt]))), () => ( null));
2460
+ const persistedCompletedAt = _nullishCoalesce(_nullishCoalesce(state.completedAt, () => ( _optionalChain([state, 'access', _51 => _51.progress, 'optionalAccess', _52 => _52.completedAt]))), () => ( null));
2461
+ events.push(
2462
+ makeRunStreamEvent({
2463
+ cursor,
2464
+ streamId,
2465
+ type: "play.step.status",
2466
+ payload: {
2467
+ runId: snapshot.runId,
2468
+ stepId: state.nodeId,
2469
+ status: state.status,
2470
+ artifactTableNamespace: _nullishCoalesce(state.artifactTableNamespace, () => ( null)),
2471
+ ...resolveTimingWindow({
2472
+ startedAt: persistedStartedAt,
2473
+ completedAt: persistedCompletedAt,
2474
+ updatedAt: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(state.updatedAt, () => ( _optionalChain([state, 'access', _53 => _53.progress, 'optionalAccess', _54 => _54.updatedAt]))), () => ( snapshot.updatedAt)), () => ( null))
2475
+ })
2476
+ }
2477
+ })
2478
+ );
2555
2479
  }
2556
- } else fail("Run event time bounds require a timestamp or duration.");
2557
- return normalizeRunEventQueryTimestamp(timestamp);
2558
- }
2559
- function exact(value, name) {
2560
- if (typeof value !== "string" || !value.trim() || value.length > 256)
2561
- fail(
2562
- `Run event ${name} requires a nonempty string of at most 256 characters.`
2480
+ }
2481
+ if (next.stepProgressSignature !== previous.stepProgressSignature) {
2482
+ for (const state of snapshot.nodeStates) {
2483
+ if (!state.progress) {
2484
+ continue;
2485
+ }
2486
+ events.push(
2487
+ makeRunStreamEvent({
2488
+ cursor: String(
2489
+ _nullishCoalesce(_nullishCoalesce(state.progress.updatedAt, () => ( snapshot.updatedAt)), () => ( Date.now()))
2490
+ ),
2491
+ streamId,
2492
+ type: "play.step.progress",
2493
+ payload: {
2494
+ runId: snapshot.runId,
2495
+ stepId: state.nodeId,
2496
+ ...projectPlayStepProgressCounters(state.progress),
2497
+ message: state.progress.message,
2498
+ artifactTableNamespace: _nullishCoalesce(_nullishCoalesce(state.progress.artifactTableNamespace, () => ( state.artifactTableNamespace)), () => ( null)),
2499
+ ...resolveTimingWindow({
2500
+ startedAt: _nullishCoalesce(_nullishCoalesce(state.startedAt, () => ( state.progress.startedAt)), () => ( null)),
2501
+ completedAt: _nullishCoalesce(_nullishCoalesce(state.completedAt, () => ( state.progress.completedAt)), () => ( null)),
2502
+ updatedAt: _nullishCoalesce(_nullishCoalesce(state.progress.updatedAt, () => ( snapshot.updatedAt)), () => ( null))
2503
+ })
2504
+ }
2505
+ })
2506
+ );
2507
+ }
2508
+ }
2509
+ if (logDiff.lines.length > 0) {
2510
+ events.push(
2511
+ makeRunStreamEvent({
2512
+ cursor,
2513
+ streamId,
2514
+ type: "play.run.log",
2515
+ payload: {
2516
+ runId: snapshot.runId,
2517
+ lines: logDiff.lines,
2518
+ source: "worker",
2519
+ ...logDiff.firstSeq !== null ? { firstSeq: logDiff.firstSeq } : {},
2520
+ totalLogCount: snapshot.totalLogCount
2521
+ }
2522
+ })
2563
2523
  );
2564
- return value;
2565
- }
2566
- var CRITERIA_KEYS = [
2567
- "since",
2568
- "until",
2569
- "where",
2570
- "runId",
2571
- "stepId",
2572
- "minLevel",
2573
- "text",
2574
- "playName",
2575
- "kind"
2576
- ];
2577
- function normalizeRunEventQuery(criteria, nowMs = Date.now()) {
2578
- if (!object(criteria)) fail("Run event criteria requires an object.");
2579
- bounded(criteria, RUN_EVENT_QUERY_MAX_REQUEST_BYTES);
2580
- for (const key of Object.keys(criteria)) {
2581
- if (!CRITERIA_KEYS.includes(key))
2582
- fail(`Unsupported run event criterion: ${key}.`);
2583
2524
  }
2584
- const until = time(criteria.until, nowMs, nowMs);
2585
- const since = time(criteria.since, nowMs, Date.parse(until) - 36e5);
2586
- if (timestampMicros(since) >= timestampMicros(until) || timestampMicros(until) - timestampMicros(since) > BigInt(RUN_EVENT_QUERY_RETENTION_MS) * BigInt(1e3))
2587
- fail("Run event query requires a window of at most seven days.");
2588
- const query = { since, until };
2589
- if (criteria.where !== void 0)
2590
- query.where = parseRunEventWhere(criteria.where);
2591
- for (const name of ["runId", "stepId", "playName", "kind"]) {
2592
- if (criteria[name] !== void 0) query[name] = exact(criteria[name], name);
2525
+ if (next.snapshotSignature !== previous.snapshotSignature) {
2526
+ const enrichedNodeStates = snapshot.nodeStates.map((state) => {
2527
+ const timing = resolveTimingWindow({
2528
+ startedAt: _nullishCoalesce(_nullishCoalesce(state.startedAt, () => ( _optionalChain([state, 'access', _55 => _55.progress, 'optionalAccess', _56 => _56.startedAt]))), () => ( null)),
2529
+ completedAt: _nullishCoalesce(_nullishCoalesce(state.completedAt, () => ( _optionalChain([state, 'access', _57 => _57.progress, 'optionalAccess', _58 => _58.completedAt]))), () => ( null)),
2530
+ updatedAt: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(state.updatedAt, () => ( _optionalChain([state, 'access', _59 => _59.progress, 'optionalAccess', _60 => _60.updatedAt]))), () => ( snapshot.updatedAt)), () => ( null))
2531
+ });
2532
+ return {
2533
+ ...state,
2534
+ ...timing,
2535
+ progress: state.progress ? {
2536
+ ...state.progress,
2537
+ ...resolveTimingWindow({
2538
+ startedAt: _nullishCoalesce(_nullishCoalesce(state.progress.startedAt, () => ( state.startedAt)), () => ( null)),
2539
+ completedAt: _nullishCoalesce(_nullishCoalesce(state.progress.completedAt, () => ( state.completedAt)), () => ( null)),
2540
+ updatedAt: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(state.progress.updatedAt, () => ( state.updatedAt)), () => ( snapshot.updatedAt)), () => ( null))
2541
+ })
2542
+ } : state.progress
2543
+ };
2544
+ });
2545
+ events.push(
2546
+ makeRunStreamEvent({
2547
+ cursor,
2548
+ streamId,
2549
+ type: "play.run.snapshot",
2550
+ payload: { ...snapshot, nodeStates: enrichedNodeStates }
2551
+ })
2552
+ );
2593
2553
  }
2594
- if (criteria.minLevel !== void 0) {
2595
- if (!RUN_LOG_LEVELS.includes(criteria.minLevel))
2596
- fail("Run event minLevel requires debug, info, warn or error.");
2597
- query.minLevel = criteria.minLevel;
2554
+ if (next.runSignature !== previous.runSignature) {
2555
+ events.push(
2556
+ makeRunStreamEvent({
2557
+ cursor,
2558
+ streamId,
2559
+ type: "play.run.status",
2560
+ payload: {
2561
+ runId: snapshot.runId,
2562
+ status: snapshot.status,
2563
+ updatedAt: snapshot.updatedAt,
2564
+ ...snapshot.activity ? { activity: snapshot.activity } : {}
2565
+ }
2566
+ })
2567
+ );
2598
2568
  }
2599
- if (criteria.text !== void 0) {
2600
- if (typeof criteria.text !== "string" || !criteria.text.length || new TextEncoder().encode(criteria.text).length > 1024)
2601
- fail("Run event text requires between 1 and 1024 bytes.");
2602
- query.text = criteria.text;
2569
+ return { events, next };
2570
+ }
2571
+
2572
+ // src/runs/watch-polling.ts
2573
+ var RUN_WATCH_POLL_INTERVAL_MS = 2e3;
2574
+ function waitForNextPoll(ms, signal) {
2575
+ if (_optionalChain([signal, 'optionalAccess', _61 => _61.aborted])) {
2576
+ return Promise.resolve(false);
2603
2577
  }
2604
- return query;
2578
+ return new Promise((resolve) => {
2579
+ const finish = (elapsed) => {
2580
+ clearTimeout(timeout);
2581
+ _optionalChain([signal, 'optionalAccess', _62 => _62.removeEventListener, 'call', _63 => _63("abort", onAbort)]);
2582
+ resolve(elapsed);
2583
+ };
2584
+ const onAbort = () => finish(false);
2585
+ const timeout = setTimeout(() => finish(true), ms);
2586
+ _optionalChain([signal, 'optionalAccess', _64 => _64.addEventListener, 'call', _65 => _65("abort", onAbort, { once: true })]);
2587
+ });
2605
2588
  }
2606
- function normalizeRunEventOperationRequest(input, nowMs = Date.now()) {
2607
- bounded(input, RUN_EVENT_QUERY_MAX_REQUEST_BYTES);
2608
- if (!object(input)) fail("Run event operation requires an object.");
2609
- const operation = input.operation;
2610
- if (!["list", "count", "summarize", "fields"].includes(String(operation)))
2611
- fail("Run event operation requires list, count, summarize or fields.");
2612
- if (input.resource !== "logs" && input.resource !== "events")
2613
- fail("Run event resource requires logs or events.");
2614
- const allowed = [
2615
- "operation",
2616
- "resource",
2617
- "runId",
2618
- ...operation === "fields" ? [] : CRITERIA_KEYS,
2619
- ...operation === "list" ? ["limit", "cursor", "includePayloads"] : operation === "summarize" ? ["groupBy", "measures", "limit", "cursor"] : []
2620
- ];
2621
- for (const key of Object.keys(input)) {
2622
- if (!allowed.includes(key))
2623
- fail(`Run event ${operation} does not support ${key}.`);
2589
+ function readSnapshotResponse(response, runId) {
2590
+ if (!response || typeof response !== "object" || Array.isArray(response)) {
2591
+ throw new Error("Run watch returned an invalid snapshot response.");
2624
2592
  }
2625
- const base = {
2626
- operation,
2627
- resource: input.resource,
2628
- ...input.runId === void 0 ? {} : { runId: exact(input.runId, "runId") }
2629
- };
2630
- if (operation === "fields") return base;
2631
- if (input.resource === "logs" && !base.runId)
2632
- fail("Run event logs require runId.");
2633
- if (input.cursor !== void 0 && (typeof input.cursor !== "string" || !input.cursor.length || input.cursor.length > RUN_EVENT_QUERY_MAX_CURSOR_BYTES))
2634
- fail("Run event cursor is invalid.");
2635
- const rawCriteria = Object.fromEntries(
2636
- Object.entries(input).filter(
2637
- ([key]) => CRITERIA_KEYS.includes(key) && (key !== "runId" || input.resource === "events")
2638
- )
2639
- );
2640
- const query = normalizeRunEventQuery(
2641
- input.cursor === void 0 ? rawCriteria : { ...rawCriteria, since: nowMs - 36e5, until: nowMs },
2642
- nowMs
2643
- );
2644
- const criteria = { ...query };
2645
- if (input.cursor !== void 0) {
2646
- if (input.since === void 0) delete criteria.since;
2647
- else criteria.since = time(input.since, nowMs, nowMs - 36e5);
2648
- if (input.until === void 0) delete criteria.until;
2649
- else criteria.until = time(input.until, nowMs, nowMs);
2593
+ const record = response;
2594
+ const snapshot = record.snapshot;
2595
+ if (record.runId !== runId || !snapshot || typeof snapshot !== "object" || Array.isArray(snapshot) || snapshot.runId !== runId || typeof snapshot.status !== "string" || !Array.isArray(snapshot.logs) || !snapshot.logs.every(
2596
+ (line) => typeof line === "string"
2597
+ ) || typeof snapshot.totalLogCount !== "number" || !Array.isArray(snapshot.nodeStates)) {
2598
+ throw new Error(`Run watch returned an invalid snapshot for ${runId}.`);
2650
2599
  }
2651
- if (operation === "count")
2652
- return { ...base, ...criteria };
2653
- const limit = _nullishCoalesce(input.limit, () => ( (input.includePayloads === true ? 10 : 50)));
2654
- if (!Number.isSafeInteger(limit) || limit < 1 || limit > RUN_EVENT_QUERY_MAX_LIMIT)
2655
- fail("Run event limit must be between 1 and 200.");
2656
- const page = {
2657
- limit,
2658
- ...input.cursor === void 0 ? {} : { cursor: input.cursor }
2659
- };
2660
- if (operation === "list") {
2661
- if (input.includePayloads !== void 0 && typeof input.includePayloads !== "boolean")
2662
- fail("Run event includePayloads requires a boolean.");
2663
- if (input.includePayloads === true && limit > RUN_EVENT_QUERY_MAX_PAYLOAD_LIMIT)
2664
- fail("Run event payload pages cannot exceed 10 rows.");
2665
- return {
2666
- ...base,
2667
- ...criteria,
2668
- ...page,
2669
- ...input.includePayloads === void 0 ? {} : { includePayloads: input.includePayloads }
2670
- };
2600
+ return { runId, snapshot };
2601
+ }
2602
+ async function backfillRotatedLogTail(input) {
2603
+ if (!input.previous.runSignature || input.snapshot.logsUnavailable) {
2604
+ return input.snapshot;
2671
2605
  }
2672
- if (!Array.isArray(input.groupBy) || input.groupBy.length > 4)
2673
- fail("Run event groupBy requires at most four fields.");
2674
- const groupBy = input.groupBy.map(validateRunEventField);
2675
- if (new Set(groupBy).size !== groupBy.length)
2676
- fail("Run event groupBy fields must be distinct.");
2677
- const rawMeasures = _nullishCoalesce(input.measures, () => ( [{ op: "count" }]));
2678
- if (!Array.isArray(rawMeasures) || rawMeasures.length < 1 || rawMeasures.length > 8)
2679
- fail("Run event measures require between 1 and 8 entries.");
2680
- const names = /* @__PURE__ */ new Set();
2681
- const measures = rawMeasures.map((measure) => {
2682
- if (!object(measure) || measure.op !== "count" && measure.op !== "sum")
2683
- fail("Run event measures support count and sum.");
2684
- for (const key of Object.keys(measure)) {
2685
- if (!["op", "as", ...measure.op === "sum" ? ["field"] : []].includes(key))
2686
- fail(`Unsupported run event measure option: ${key}.`);
2606
+ const gap = resolvePlayRunLogGap(input.snapshot, input.previous.lastLogSeq);
2607
+ if (!gap) {
2608
+ return input.snapshot;
2609
+ }
2610
+ const lines = [];
2611
+ let cursor = input.previous.lastLogSeq;
2612
+ const targetSeq = gap.tailFirstSeq - 1;
2613
+ while (cursor < targetSeq) {
2614
+ const limit = Math.min(1e3, targetSeq - cursor);
2615
+ const page = await input.http.get(
2616
+ `/api/v2/runs/${encodeURIComponent(input.runId)}/logs?afterSeq=${cursor}&limit=${limit}`,
2617
+ { signal: input.signal }
2618
+ );
2619
+ if (!page || !Array.isArray(page.entries) || page.entries.length === 0) {
2620
+ return input.snapshot;
2687
2621
  }
2688
- const field = measure.op === "sum" ? validateRunEventField(measure.field) : void 0;
2689
- if (field && !field.startsWith("context.") && RUN_EVENT_QUERY_FIELD_CATALOG[field].type !== "number")
2690
- fail(`Run event sum requires a numeric field: ${field}.`);
2691
- const name = _nullishCoalesce(measure.as, () => ( (field ? `sum_${field.replaceAll(".", "_")}` : "count")));
2692
- if (typeof name !== "string" || !/^[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(name) || names.has(name))
2693
- fail("Run event measure names must be distinct identifiers.");
2694
- names.add(name);
2695
- return field ? { op: "sum", field, as: name } : { op: "count", as: name };
2696
- });
2697
- return {
2698
- ...base,
2699
- ...criteria,
2700
- ...page,
2701
- groupBy,
2702
- measures
2703
- };
2622
+ for (const entry of page.entries) {
2623
+ if (!entry || entry.seq !== cursor + 1 || typeof entry.line !== "string") {
2624
+ return input.snapshot;
2625
+ }
2626
+ lines.push(entry.line);
2627
+ cursor = entry.seq;
2628
+ }
2629
+ }
2630
+ if (cursor !== targetSeq) {
2631
+ return input.snapshot;
2632
+ }
2633
+ return { ...input.snapshot, logs: [...lines, ...input.snapshot.logs] };
2704
2634
  }
2705
-
2706
- // src/types.ts
2707
- function isStopAllPlayRunsDryRunResult(result) {
2708
- return "dryRun" in result && result.dryRun === true;
2635
+ async function* watchRunEvents(options) {
2636
+ const { http, runId, signal } = options;
2637
+ const path = `/api/v2/runs/${encodeURIComponent(runId)}?watchSnapshot=true`;
2638
+ const streamId = `play-run-watch:${runId}`;
2639
+ const pollIntervalMs = _nullishCoalesce(options.pollIntervalMs, () => ( RUN_WATCH_POLL_INTERVAL_MS));
2640
+ let previous = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
2641
+ let consecutiveFailures = 0;
2642
+ let outageNoticeSent = false;
2643
+ while (!_optionalChain([signal, 'optionalAccess', _66 => _66.aborted])) {
2644
+ const pollStartedAt = Date.now();
2645
+ let snapshot;
2646
+ try {
2647
+ const response = await http.get(path, { signal });
2648
+ snapshot = await backfillRotatedLogTail({
2649
+ http,
2650
+ runId,
2651
+ snapshot: readSnapshotResponse(response, runId).snapshot,
2652
+ previous,
2653
+ signal
2654
+ });
2655
+ } catch (error) {
2656
+ if (_optionalChain([signal, 'optionalAccess', _67 => _67.aborted])) {
2657
+ return;
2658
+ }
2659
+ if (!isTransientPlayRunReadError(error)) {
2660
+ throw error;
2661
+ }
2662
+ consecutiveFailures += 1;
2663
+ const reason = error instanceof Error ? error.message : String(error);
2664
+ if (!outageNoticeSent) {
2665
+ _optionalChain([options, 'access', _68 => _68.onRetry, 'optionalCall', _69 => _69({
2666
+ attempt: consecutiveFailures,
2667
+ delayMs: pollIntervalMs,
2668
+ reason
2669
+ })]);
2670
+ _optionalChain([options, 'access', _70 => _70.onNotice, 'optionalCall', _71 => _71(
2671
+ `[watch] run snapshot request failed; retrying every ${pollIntervalMs / 1e3}s (${reason})`
2672
+ )]);
2673
+ outageNoticeSent = true;
2674
+ }
2675
+ const remaining2 = Math.max(
2676
+ 0,
2677
+ pollIntervalMs - (Date.now() - pollStartedAt)
2678
+ );
2679
+ if (!await waitForNextPoll(remaining2, signal)) {
2680
+ return;
2681
+ }
2682
+ continue;
2683
+ }
2684
+ if (outageNoticeSent) {
2685
+ _optionalChain([options, 'access', _72 => _72.onNotice, 'optionalCall', _73 => _73("[watch] run snapshot polling recovered")]);
2686
+ outageNoticeSent = false;
2687
+ }
2688
+ consecutiveFailures = 0;
2689
+ const diff = diffPlayRunStreamEvents({
2690
+ streamId,
2691
+ snapshot,
2692
+ previous
2693
+ });
2694
+ previous = diff.next;
2695
+ for (const event of diff.events) {
2696
+ yield event;
2697
+ }
2698
+ if (isTerminalPlayRunLiveStatus(snapshot.status)) {
2699
+ return;
2700
+ }
2701
+ const remaining = Math.max(
2702
+ 0,
2703
+ pollIntervalMs - (Date.now() - pollStartedAt)
2704
+ );
2705
+ if (!await waitForNextPoll(remaining, signal)) {
2706
+ return;
2707
+ }
2708
+ }
2709
2709
  }
2710
2710
 
2711
2711
  // ../play-runtime/runtime-environment.ts
@@ -2910,8 +2910,8 @@ function runtimeSelectionHeaders(runtime) {
2910
2910
  }
2911
2911
  const receivers = _optionalChain([process, 'access', _104 => _104.env, 'access', _105 => _105.DEEPLINE_RUNTIME_RETAINED_PIPELINE_RECEIVERS, 'optionalAccess', _106 => _106.trim, 'call', _107 => _107()]);
2912
2912
  return {
2913
- [_chunkND4BVWWZjs.RUNTIME_ENVIRONMENT_TOKEN_HEADER]: token,
2914
- ...receivers ? { [_chunkND4BVWWZjs.RETAINED_PIPELINE_RECEIVERS_HEADER]: receivers } : {}
2913
+ [_chunkIQTHRG6Ejs.RUNTIME_ENVIRONMENT_TOKEN_HEADER]: token,
2914
+ ...receivers ? { [_chunkIQTHRG6Ejs.RETAINED_PIPELINE_RECEIVERS_HEADER]: receivers } : {}
2915
2915
  };
2916
2916
  }
2917
2917
  function isolatedCiRuntimeEventReadHeaders() {
@@ -2927,7 +2927,7 @@ function isolatedCiRuntimeEventReadHeaders() {
2927
2927
  "RUNTIME_EVENT_INTERNAL_TOKEN_REQUIRED"
2928
2928
  );
2929
2929
  }
2930
- return { [_chunkND4BVWWZjs.COORDINATOR_INTERNAL_TOKEN_HEADER]: token };
2930
+ return { [_chunkIQTHRG6Ejs.COORDINATOR_INTERNAL_TOKEN_HEADER]: token };
2931
2931
  }
2932
2932
  function normalizeTestPolicyOverrides(value, source) {
2933
2933
  if (value && typeof value === "object" && !Array.isArray(value)) {
@@ -3217,8 +3217,8 @@ var DeeplineClient = (_class = class _DeeplineClient {
3217
3217
  * @throws {@link ConfigError} if no API key can be resolved from any source.
3218
3218
  */
3219
3219
  constructor(options) {
3220
- this.config = _chunkND4BVWWZjs.resolveConfig.call(void 0, options);
3221
- this.http = new (0, _chunkND4BVWWZjs.HttpClient)(this.config);
3220
+ this.config = _chunkIQTHRG6Ejs.resolveConfig.call(void 0, options);
3221
+ this.http = new (0, _chunkIQTHRG6Ejs.HttpClient)(this.config);
3222
3222
  this.toolCalls = new ToolCalls(
3223
3223
  this.http,
3224
3224
  this.config.timeout,