deepline 0.3.236 → 0.3.238

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.
@@ -3449,7 +3449,7 @@ var SDK_RELEASE = {
3449
3449
  // getters keep their established compatibility behavior.
3450
3450
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3451
3451
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3452
- version: "0.3.236",
3452
+ version: "0.3.238",
3453
3453
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3454
3454
  packageCapabilities: {
3455
3455
  updatePreferences: 1
@@ -4098,19 +4098,19 @@ function withErrorCause(error, cause) {
4098
4098
  }
4099
4099
  return error;
4100
4100
  }
4101
- function mapNetworkError(baseUrl, error, targetLabel2) {
4101
+ function mapNetworkError(baseUrl, error, targetLabel) {
4102
4102
  const tagged = error;
4103
4103
  const timeoutMs = tagged?.[REQUEST_TIMEOUT_MARKER];
4104
4104
  if (typeof timeoutMs === "number") {
4105
4105
  return {
4106
- message: `Request to ${targetLabel2} timed out after ${timeoutMs}ms while waiting for a response.`,
4106
+ message: `Request to ${targetLabel} timed out after ${timeoutMs}ms while waiting for a response.`,
4107
4107
  code: "NETWORK_TIMEOUT",
4108
- details: { timeoutMs, target: targetLabel2 }
4108
+ details: { timeoutMs, target: targetLabel }
4109
4109
  };
4110
4110
  }
4111
4111
  if (tagged?.[REQUEST_ABORT_MARKER]) {
4112
4112
  return {
4113
- message: `Request to ${targetLabel2} was aborted before it completed.`,
4113
+ message: `Request to ${targetLabel} was aborted before it completed.`,
4114
4114
  code: "NETWORK_ABORTED"
4115
4115
  };
4116
4116
  }
@@ -4873,30 +4873,6 @@ var DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING = {
4873
4873
  windowMs: 36e5
4874
4874
  };
4875
4875
 
4876
- // src/stream-reconnect.ts
4877
- var STREAM_RECONNECT_BASE_DELAY_MS = 500;
4878
- var STREAM_RECONNECT_MAX_DELAY_MS = 15e3;
4879
- var STREAM_HEALTHY_CONNECTION_MS = 3e4;
4880
- function streamReconnectDelayMs(attempt) {
4881
- const cappedExponentialMs = Math.min(
4882
- STREAM_RECONNECT_MAX_DELAY_MS,
4883
- STREAM_RECONNECT_BASE_DELAY_MS * 2 ** Math.max(0, attempt)
4884
- );
4885
- return Math.max(1, Math.floor(Math.random() * (cappedExponentialMs + 1)));
4886
- }
4887
- function isTransientPlayStreamError(error) {
4888
- if (error instanceof DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
4889
- return true;
4890
- }
4891
- if (error instanceof DeeplineError && typeof error.statusCode === "number") {
4892
- return error.statusCode >= 500 && error.statusCode < 600;
4893
- }
4894
- const text = error instanceof Error ? error.message : String(error);
4895
- 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(
4896
- text
4897
- );
4898
- }
4899
-
4900
4876
  // ../play-runtime/live-events.ts
4901
4877
  function resolveTimingWindow(input2) {
4902
4878
  const startedAt = typeof input2.startedAt === "number" && Number.isFinite(input2.startedAt) ? input2.startedAt : null;
@@ -4912,19 +4888,6 @@ function resolveTimingWindow(input2) {
4912
4888
  // ../play-runtime/run-failure.ts
4913
4889
  var PUBLIC_FAILURE_TEXT_BYTE_LIMIT = 64 * 1024;
4914
4890
 
4915
- // ../play-runtime/run-terminal-source.ts
4916
- var PLAY_RUN_LEDGER_EVENT_SOURCES = [
4917
- "worker",
4918
- "convex",
4919
- "coordinator",
4920
- "system"
4921
- ];
4922
- function normalizePlayRunLedgerTerminalSource(value) {
4923
- return PLAY_RUN_LEDGER_EVENT_SOURCES.includes(
4924
- value
4925
- ) ? value : null;
4926
- }
4927
-
4928
4891
  // ../play-runtime/run-log-buffer.ts
4929
4892
  var RUNNER_LOG_MAX_BYTES = 5 * 1024 * 1024;
4930
4893
  var TERMINAL_RESERVE_BYTES = 64 * 1024;
@@ -5095,12 +5058,12 @@ function createSecretRedactionContext(initialValues = []) {
5095
5058
  }
5096
5059
  return output2;
5097
5060
  }
5098
- function redactString2(value) {
5061
+ function redactString(value) {
5099
5062
  const output2 = redactRegisteredSecrets(value);
5100
5063
  return redactSecretLikeString(output2);
5101
5064
  }
5102
5065
  function redact(value) {
5103
- if (typeof value === "string") return redactString2(value);
5066
+ if (typeof value === "string") return redactString(value);
5104
5067
  if (Array.isArray(value)) {
5105
5068
  let changed = false;
5106
5069
  const next = new Array(value.length);
@@ -5133,7 +5096,7 @@ function createSecretRedactionContext(initialValues = []) {
5133
5096
  return value;
5134
5097
  }
5135
5098
  function redactKnownSecrets(value) {
5136
- if (typeof value === "string") return redactString2(value);
5099
+ if (typeof value === "string") return redactString(value);
5137
5100
  if (Array.isArray(value)) {
5138
5101
  return value.map((entry) => redactKnownSecrets(entry));
5139
5102
  }
@@ -5152,7 +5115,7 @@ function createSecretRedactionContext(initialValues = []) {
5152
5115
  containsRegisteredSecret,
5153
5116
  matchesRegisteredSecret,
5154
5117
  redactRegisteredSecrets,
5155
- redactString: redactString2,
5118
+ redactString,
5156
5119
  redactKnownSecrets,
5157
5120
  redact
5158
5121
  };
@@ -5176,981 +5139,8 @@ var JSON_SIZE_LIMIT_REACHED = Symbol("JSON_SIZE_LIMIT_REACHED");
5176
5139
  var ledgerIngressRedactor = createSecretRedactionContext();
5177
5140
 
5178
5141
  // ../play-runtime/docflow-node-io.ts
5179
- var DOCFLOW_NODE_IO_LIMITS = {
5180
- maxPaths: 16,
5181
- maxDepth: 3,
5182
- maxObjectFields: 12,
5183
- maxArrayItems: 3,
5184
- maxStringBytes: 256,
5185
- maxPhaseBytes: 2e3,
5186
- maxErrorBytes: 512
5187
- };
5188
5142
  var utf8Encoder = new TextEncoder();
5189
5143
  var PLAY_DATASET_BRAND = Symbol.for("deepline.play.dataset");
5190
- var MAX_CONVEX_PREVIEW_KEY_LENGTH = 1024;
5191
- function ledgerSafeDocflowPreviewKey(key) {
5192
- const source = key.startsWith("$") ? key.replace(/^\$+/, "") || "output" : key || "output";
5193
- let encoded = "";
5194
- for (const character of source) {
5195
- const code = character.charCodeAt(0);
5196
- if (code >= 32 && code < 127) {
5197
- encoded += character;
5198
- continue;
5199
- }
5200
- for (const byte of utf8Encoder.encode(character)) {
5201
- encoded += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
5202
- }
5203
- }
5204
- if (encoded.length <= MAX_CONVEX_PREVIEW_KEY_LENGTH) return encoded;
5205
- let hashA = 2166136261;
5206
- let hashB = 2654435769;
5207
- for (let index = 0; index < encoded.length; index += 1) {
5208
- const code = encoded.charCodeAt(index);
5209
- hashA = Math.imul(hashA ^ code, 16777619);
5210
- hashB = Math.imul(hashB ^ code, 16777619);
5211
- }
5212
- const suffix = `~${(hashA >>> 0).toString(16).padStart(8, "0")}${(hashB >>> 0).toString(16).padStart(8, "0")}`;
5213
- return `${encoded.slice(0, MAX_CONVEX_PREVIEW_KEY_LENGTH - suffix.length)}${suffix}`;
5214
- }
5215
- function utf8Bytes(value) {
5216
- return utf8Encoder.encode(value).byteLength;
5217
- }
5218
- function truncateUtf8(value, maxBytes) {
5219
- if (utf8Bytes(value) <= maxBytes) return value;
5220
- let output2 = "";
5221
- for (const character of value) {
5222
- if (utf8Bytes(`${output2}${character}\u2026`) > maxBytes) break;
5223
- output2 += character;
5224
- }
5225
- return `${output2}\u2026`;
5226
- }
5227
- function redactString(redactor, value, key) {
5228
- if (!key) return redactor.redactString(value);
5229
- const wrapped = redactor.redact({ [key]: value });
5230
- return typeof wrapped[key] === "string" ? wrapped[key] : redactor.redactString(value);
5231
- }
5232
- function safeString(value, redactor, key) {
5233
- if (typeof value !== "string") return void 0;
5234
- return truncateUtf8(
5235
- redactString(redactor, value, key),
5236
- DOCFLOW_NODE_IO_LIMITS.maxStringBytes
5237
- );
5238
- }
5239
- function previewValue(value, input2) {
5240
- if (value === null) return { kind: "null" };
5241
- if (value === void 0) return { kind: "unavailable", reason: "undefined" };
5242
- if (typeof value === "string") {
5243
- return {
5244
- kind: "scalar",
5245
- value: safeString(value, input2.redactor, input2.key) ?? ""
5246
- };
5247
- }
5248
- if (typeof value === "number") {
5249
- return Number.isFinite(value) ? { kind: "scalar", value } : { kind: "unavailable", reason: "unsupported" };
5250
- }
5251
- if (typeof value === "boolean") return { kind: "scalar", value };
5252
- if (typeof value === "bigint") {
5253
- return { kind: "unavailable", reason: "bigint" };
5254
- }
5255
- if (typeof value === "function") {
5256
- return { kind: "unavailable", reason: "function" };
5257
- }
5258
- if (typeof value === "symbol") {
5259
- return { kind: "unavailable", reason: "symbol" };
5260
- }
5261
- if (typeof value !== "object") {
5262
- return { kind: "unavailable", reason: "unsupported" };
5263
- }
5264
- try {
5265
- const brand = readDataProperty(value, PLAY_DATASET_BRAND);
5266
- const datasetKind = readDataProperty(value, "datasetKind");
5267
- const datasetId = readDataProperty(value, "datasetId");
5268
- const tableNamespace = readDataProperty(value, "tableNamespace");
5269
- if (brand.ok && brand.value === true && datasetKind.ok && (datasetKind.value === "csv" || datasetKind.value === "map") && datasetId.ok && typeof datasetId.value === "string") {
5270
- return {
5271
- kind: "dataset",
5272
- datasetId: safeString(datasetId.value, input2.redactor, "datasetId") ?? "dataset",
5273
- datasetKind: datasetKind.value,
5274
- tableNamespace: tableNamespace.ok && tableNamespace.value === null ? null : tableNamespace.ok ? safeString(
5275
- tableNamespace.value,
5276
- input2.redactor,
5277
- "tableNamespace"
5278
- ) : void 0
5279
- };
5280
- }
5281
- const kind = readDataProperty(value, "kind");
5282
- const count = readDataProperty(value, "count");
5283
- const preview = readDataProperty(value, "preview");
5284
- if (kind.ok && kind.value === "dataset" && datasetKind.ok && (datasetKind.value === "csv" || datasetKind.value === "map") && datasetId.ok && typeof datasetId.value === "string" && count.ok && typeof count.value === "number" && preview.ok && Array.isArray(preview.value)) {
5285
- return {
5286
- kind: "dataset",
5287
- datasetId: safeString(datasetId.value, input2.redactor, "datasetId") ?? "dataset",
5288
- datasetKind: datasetKind.value,
5289
- tableNamespace: tableNamespace.ok && tableNamespace.value === null ? null : tableNamespace.ok ? safeString(
5290
- tableNamespace.value,
5291
- input2.redactor,
5292
- "tableNamespace"
5293
- ) : void 0,
5294
- rowCount: Math.max(0, Math.floor(count.value))
5295
- };
5296
- }
5297
- } catch {
5298
- return { kind: "unavailable", reason: "access_error" };
5299
- }
5300
- if (input2.ancestors.has(value)) {
5301
- return { kind: "unavailable", reason: "cycle" };
5302
- }
5303
- if (input2.depth >= DOCFLOW_NODE_IO_LIMITS.maxDepth) {
5304
- return { kind: "unavailable", reason: "depth" };
5305
- }
5306
- input2.ancestors.add(value);
5307
- try {
5308
- if (Array.isArray(value)) {
5309
- const items = [];
5310
- for (let index = 0; index < Math.min(value.length, DOCFLOW_NODE_IO_LIMITS.maxArrayItems); index += 1) {
5311
- const descriptor = Object.getOwnPropertyDescriptor(
5312
- value,
5313
- String(index)
5314
- );
5315
- items.push(
5316
- descriptor && "value" in descriptor ? previewValue(descriptor.value, {
5317
- ...input2,
5318
- depth: input2.depth + 1
5319
- }) : { kind: "unavailable", reason: "access_error" }
5320
- );
5321
- }
5322
- return {
5323
- kind: "array",
5324
- items,
5325
- totalItems: value.length,
5326
- ...value.length > items.length ? { truncated: true } : {}
5327
- };
5328
- }
5329
- let descriptors;
5330
- try {
5331
- descriptors = Object.getOwnPropertyDescriptors(value);
5332
- } catch {
5333
- return { kind: "unavailable", reason: "access_error" };
5334
- }
5335
- const entries = Object.entries(descriptors).filter(
5336
- ([, descriptor]) => descriptor.enumerable
5337
- );
5338
- const selected = entries.slice(0, DOCFLOW_NODE_IO_LIMITS.maxObjectFields);
5339
- const fields2 = {};
5340
- for (const [key, descriptor] of selected) {
5341
- const safeKey = truncateUtf8(
5342
- ledgerSafeDocflowPreviewKey(input2.redactor.redactString(key)),
5343
- DOCFLOW_NODE_IO_LIMITS.maxStringBytes
5344
- );
5345
- fields2[safeKey] = "value" in descriptor ? previewValue(descriptor.value, {
5346
- ...input2,
5347
- depth: input2.depth + 1,
5348
- key
5349
- }) : { kind: "unavailable", reason: "access_error" };
5350
- }
5351
- return {
5352
- kind: "object",
5353
- fields: fields2,
5354
- totalFields: entries.length,
5355
- ...entries.length > selected.length ? { truncated: true } : {}
5356
- };
5357
- } catch {
5358
- return { kind: "unavailable", reason: "access_error" };
5359
- } finally {
5360
- input2.ancestors.delete(value);
5361
- }
5362
- }
5363
- function readDataProperty(value, property) {
5364
- if ((typeof value !== "object" || value === null) && typeof value !== "function") {
5365
- return { ok: false };
5366
- }
5367
- try {
5368
- let owner = value;
5369
- while (owner) {
5370
- const descriptor = Object.getOwnPropertyDescriptor(owner, property);
5371
- if (descriptor) {
5372
- return "value" in descriptor ? { ok: true, value: descriptor.value } : { ok: false };
5373
- }
5374
- owner = Object.getPrototypeOf(owner);
5375
- }
5376
- } catch {
5377
- return { ok: false };
5378
- }
5379
- return { ok: false };
5380
- }
5381
- function buildPlayDocflowNodeErrorPreview(error, redactor = createSecretRedactionContext()) {
5382
- try {
5383
- const message = error instanceof Error ? error.message : String(error);
5384
- return truncateUtf8(
5385
- redactor.redactString(message),
5386
- DOCFLOW_NODE_IO_LIMITS.maxErrorBytes
5387
- );
5388
- } catch {
5389
- return "Non-Error value thrown (message unavailable)";
5390
- }
5391
- }
5392
- function isRecord4(value) {
5393
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
5394
- }
5395
- function normalizePreview(value, depth) {
5396
- if (!isRecord4(value) || typeof value.kind !== "string") return null;
5397
- if (value.kind === "null") return { kind: "null" };
5398
- if (value.kind === "scalar") {
5399
- if (typeof value.value === "string" || typeof value.value === "boolean" || typeof value.value === "number" && Number.isFinite(value.value)) {
5400
- return previewValue(value.value, {
5401
- depth: 0,
5402
- ancestors: /* @__PURE__ */ new WeakSet(),
5403
- redactor: createSecretRedactionContext()
5404
- });
5405
- }
5406
- return null;
5407
- }
5408
- if (value.kind === "unavailable") {
5409
- const reason = value.reason;
5410
- return typeof reason === "string" && [
5411
- "undefined",
5412
- "function",
5413
- "symbol",
5414
- "bigint",
5415
- "cycle",
5416
- "depth",
5417
- "access_error",
5418
- "limit",
5419
- "unsupported"
5420
- ].includes(reason) ? {
5421
- kind: "unavailable",
5422
- reason
5423
- } : null;
5424
- }
5425
- if (value.kind === "dataset") {
5426
- const datasetId = safeString(
5427
- value.datasetId,
5428
- createSecretRedactionContext(),
5429
- "datasetId"
5430
- );
5431
- if (!datasetId || value.datasetKind !== "csv" && value.datasetKind !== "map") {
5432
- return null;
5433
- }
5434
- return {
5435
- kind: "dataset",
5436
- datasetId,
5437
- datasetKind: value.datasetKind,
5438
- ...value.tableNamespace === null ? { tableNamespace: null } : typeof value.tableNamespace === "string" ? {
5439
- tableNamespace: safeString(
5440
- value.tableNamespace,
5441
- createSecretRedactionContext(),
5442
- "tableNamespace"
5443
- )
5444
- } : {},
5445
- ...typeof value.rowCount === "number" && Number.isFinite(value.rowCount) ? { rowCount: Math.max(0, Math.floor(value.rowCount)) } : {}
5446
- };
5447
- }
5448
- if (depth >= DOCFLOW_NODE_IO_LIMITS.maxDepth) {
5449
- return { kind: "unavailable", reason: "depth" };
5450
- }
5451
- if (value.kind === "array" && Array.isArray(value.items)) {
5452
- const items = value.items.slice(0, DOCFLOW_NODE_IO_LIMITS.maxArrayItems).map((item) => normalizePreview(item, depth + 1)).filter((item) => item !== null);
5453
- const totalItems = typeof value.totalItems === "number" && Number.isFinite(value.totalItems) ? Math.max(items.length, Math.floor(value.totalItems)) : items.length;
5454
- return {
5455
- kind: "array",
5456
- items,
5457
- totalItems,
5458
- ...value.truncated === true || totalItems > items.length ? { truncated: true } : {}
5459
- };
5460
- }
5461
- if (value.kind === "object" && isRecord4(value.fields)) {
5462
- const fields2 = {};
5463
- for (const [key, field] of Object.entries(value.fields).slice(
5464
- 0,
5465
- DOCFLOW_NODE_IO_LIMITS.maxObjectFields
5466
- )) {
5467
- const normalized = normalizePreview(field, depth + 1);
5468
- if (normalized) fields2[ledgerSafeDocflowPreviewKey(key)] = normalized;
5469
- }
5470
- const totalFields = typeof value.totalFields === "number" && Number.isFinite(value.totalFields) ? Math.max(Object.keys(fields2).length, Math.floor(value.totalFields)) : Object.keys(fields2).length;
5471
- return {
5472
- kind: "object",
5473
- fields: fields2,
5474
- totalFields,
5475
- ...value.truncated === true || totalFields > Object.keys(fields2).length ? { truncated: true } : {}
5476
- };
5477
- }
5478
- return null;
5479
- }
5480
- function normalizePlayDocflowNodeIoState(value) {
5481
- if (!isRecord4(value)) return void 0;
5482
- const attempt = typeof value.attempt === "number" && Number.isFinite(value.attempt) ? Math.max(0, Math.floor(value.attempt)) : 0;
5483
- const normalizeMap = (raw) => {
5484
- if (!isRecord4(raw)) return void 0;
5485
- const output2 = {};
5486
- for (const [path, preview] of Object.entries(raw).slice(
5487
- 0,
5488
- DOCFLOW_NODE_IO_LIMITS.maxPaths
5489
- )) {
5490
- const normalized = normalizePreview(preview, 0);
5491
- if (!normalized) continue;
5492
- const safePath = ledgerSafeDocflowPreviewKey(path);
5493
- const candidate = { ...output2, [safePath]: normalized };
5494
- if (utf8Bytes(JSON.stringify(candidate)) > DOCFLOW_NODE_IO_LIMITS.maxPhaseBytes) {
5495
- break;
5496
- }
5497
- output2[safePath] = normalized;
5498
- }
5499
- return output2;
5500
- };
5501
- const inputs = normalizeMap(value.inputs);
5502
- const outputs = normalizeMap(value.outputs);
5503
- const error = typeof value.error === "string" ? buildPlayDocflowNodeErrorPreview(value.error) : value.error === null ? null : void 0;
5504
- return {
5505
- attempt,
5506
- ...typeof value.invocationId === "string" && value.invocationId.trim() ? {
5507
- invocationId: truncateUtf8(
5508
- value.invocationId.trim(),
5509
- DOCFLOW_NODE_IO_LIMITS.maxStringBytes
5510
- )
5511
- } : {},
5512
- ...inputs ? { inputs } : {},
5513
- ...outputs ? { outputs } : {},
5514
- ...value.inputsTruncated === true ? { inputsTruncated: true } : {},
5515
- ...value.outputsTruncated === true ? { outputsTruncated: true } : {},
5516
- ...error !== void 0 ? { error } : {}
5517
- };
5518
- }
5519
-
5520
- // ../play-runtime/activity-observation.ts
5521
- function isRecord5(value) {
5522
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
5523
- }
5524
- function isPlayActivityObservation(value) {
5525
- if (!isRecord5(value) || value.schemaVersion !== void 0 && value.schemaVersion !== 1 || typeof value.activityId !== "string" || !value.activityId.trim() || typeof value.observedAt !== "number" || !Number.isFinite(value.observedAt) || !isRecord5(value.target) || !isRecord5(value.state)) {
5526
- return false;
5527
- }
5528
- const targetKinds = /* @__PURE__ */ new Set([
5529
- "provider",
5530
- "dataset",
5531
- "lease",
5532
- "runner",
5533
- "step",
5534
- "capacity"
5535
- ]);
5536
- const stateKinds = /* @__PURE__ */ new Set([
5537
- "active",
5538
- "queued",
5539
- "waiting",
5540
- "retrying",
5541
- "scheduled",
5542
- "completed",
5543
- "failed"
5544
- ]);
5545
- return typeof value.target.kind === "string" && targetKinds.has(value.target.kind) && typeof value.state.kind === "string" && stateKinds.has(value.state.kind);
5546
- }
5547
- function derivePlayActivityVisibility(input2) {
5548
- const { state } = input2.observation;
5549
- if (state.kind === "failed") return "action";
5550
- if (state.kind === "waiting") {
5551
- return state.reason.kind === "external_event" ? "action" : "headline";
5552
- }
5553
- if (state.kind === "queued" || state.kind === "scheduled") return "headline";
5554
- if (state.kind === "retrying") {
5555
- if (state.reason === "rate_limit" && input2.observation.target.kind === "capacity") {
5556
- return "headline";
5557
- }
5558
- if (state.retryAt - input2.now <= 3e4) return "hidden";
5559
- return state.reason === "rate_limit" ? "headline" : "timeline";
5560
- }
5561
- if (state.kind === "active") return "headline";
5562
- return "timeline";
5563
- }
5564
- function targetLabel(target) {
5565
- switch (target.kind) {
5566
- case "provider":
5567
- return target.label ?? `${target.provider} ${target.operation}`;
5568
- case "dataset":
5569
- return target.label ?? `dataset ${target.tableNamespace}`;
5570
- case "lease":
5571
- return `${target.resourceKind} ${target.resourceLabel}`;
5572
- case "runner":
5573
- return target.label ?? `${target.backend} runner`;
5574
- case "step":
5575
- return target.label ?? target.stepId;
5576
- case "capacity":
5577
- return target.label ?? `${target.pool} capacity`;
5578
- }
5579
- }
5580
- function summarizePlayActivity(observation) {
5581
- const label = targetLabel(observation.target);
5582
- const { state } = observation;
5583
- switch (state.kind) {
5584
- case "active": {
5585
- const progress = state.progress;
5586
- const counts = typeof progress?.completed === "number" && typeof progress.total === "number" ? ` (${progress.completed}/${progress.total})` : "";
5587
- return `Active: ${label}${counts}.`;
5588
- }
5589
- case "queued":
5590
- return `Queued: waiting for ${label}.`;
5591
- case "waiting":
5592
- if (state.reason.kind === "external_event") {
5593
- const provider = state.reason.provider ? ` from ${state.reason.provider}` : "";
5594
- return `Blocked: waiting for an external event${provider}.`;
5595
- }
5596
- if (state.reason.kind === "dataset") {
5597
- return `Blocked: waiting for dataset ${state.reason.tableNamespace} to become ${state.reason.requiredPhase}.`;
5598
- }
5599
- if (state.reason.kind === "lease") {
5600
- return `Contended: waiting for ${state.reason.resourceKind} lease ${state.reason.resourceLabel}.`;
5601
- }
5602
- return `Paused: ${label}; the legacy producer did not report a typed reason.`;
5603
- case "retrying":
5604
- if (state.reason === "rate_limit") {
5605
- return `Waiting for ${label} request capacity; the run will retry automatically.`;
5606
- }
5607
- return `Delayed: ${label} will retry automatically.`;
5608
- case "scheduled":
5609
- return `Scheduled: ${label} will resume automatically.`;
5610
- case "completed":
5611
- return `Completed: ${label}.`;
5612
- case "failed":
5613
- return `Failed: ${label}.`;
5614
- }
5615
- }
5616
- function isTerminalActivityState(state) {
5617
- return state.kind === "completed" || state.kind === "failed";
5618
- }
5619
- function projection(observation, now, classified = true) {
5620
- return {
5621
- observation,
5622
- summary: summarizePlayActivity(observation),
5623
- visibility: derivePlayActivityVisibility({ observation, now }),
5624
- classified
5625
- };
5626
- }
5627
- function projectPlayRunActivity(input2) {
5628
- const now = input2.now ?? Date.now();
5629
- const observedAt = input2.updatedAt ?? now;
5630
- const normalizedStatus = input2.status.trim().toLowerCase();
5631
- if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
5632
- return null;
5633
- }
5634
- const latestExplicit = [...input2.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
5635
- const explicit = latestExplicit?.target.kind === "capacity" && latestExplicit.target.pool === "provider" && latestExplicit.state.kind === "retrying" && latestExplicit.state.retryAt < now ? null : latestExplicit;
5636
- if (explicit) return projection(explicit, now);
5637
- if (input2.waitKind === "detached_runner") {
5638
- return projection(
5639
- {
5640
- activityId: "runner:managed",
5641
- target: {
5642
- kind: "runner",
5643
- backend: input2.runtimeBackend ?? "managed",
5644
- label: "managed play runner"
5645
- },
5646
- state: { kind: "active" },
5647
- observedAt
5648
- },
5649
- now
5650
- );
5651
- }
5652
- if (input2.waitKind === "sleep") {
5653
- return projection(
5654
- {
5655
- activityId: "run:sleep",
5656
- target: {
5657
- kind: "step",
5658
- stepId: input2.activeNodeId ?? "run",
5659
- label: input2.playName ?? "play"
5660
- },
5661
- state: {
5662
- kind: "scheduled",
5663
- reason: "sleep",
5664
- resumeAt: input2.waitUntil ?? observedAt
5665
- },
5666
- observedAt
5667
- },
5668
- now
5669
- );
5670
- }
5671
- if (input2.waitKind === "integration_event" || input2.waitKind === "integration_event_batch") {
5672
- return projection(
5673
- {
5674
- activityId: `event:${input2.activeNodeId ?? "run"}`,
5675
- stepId: input2.activeNodeId ?? void 0,
5676
- target: {
5677
- kind: "step",
5678
- stepId: input2.activeNodeId ?? "run",
5679
- label: input2.playName ?? "play"
5680
- },
5681
- state: {
5682
- kind: "waiting",
5683
- reason: {
5684
- kind: "external_event",
5685
- eventKey: input2.eventKey ?? void 0,
5686
- deadlineAt: input2.waitUntil ?? void 0
5687
- }
5688
- },
5689
- observedAt
5690
- },
5691
- now
5692
- );
5693
- }
5694
- if (normalizedStatus === "waiting") {
5695
- return projection(
5696
- {
5697
- activityId: "run:legacy-wait",
5698
- target: {
5699
- kind: "step",
5700
- stepId: input2.activeNodeId ?? "run",
5701
- label: input2.playName ?? "play"
5702
- },
5703
- state: { kind: "waiting", reason: { kind: "unknown" } },
5704
- observedAt
5705
- },
5706
- now,
5707
- false
5708
- );
5709
- }
5710
- const pendingDataset = [...input2.datasets ?? []].filter(
5711
- (dataset) => dataset.phase === "registered" || dataset.complete !== true && dataset.phase !== "failed"
5712
- ).sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))[0];
5713
- if (pendingDataset) {
5714
- const activeDatasetStep = input2.nodeStates?.find(
5715
- (candidate) => candidate.nodeId === input2.activeNodeId && candidate.status === "running" && candidate.artifactTableNamespace === pendingDataset.tableNamespace
5716
- );
5717
- const datasetStep = activeDatasetStep ?? input2.nodeStates?.find(
5718
- (candidate) => candidate.artifactTableNamespace === pendingDataset.tableNamespace
5719
- );
5720
- const datasetProgress = datasetStep?.progress ?? null;
5721
- return projection(
5722
- {
5723
- activityId: `dataset:${pendingDataset.datasetId ?? pendingDataset.tableNamespace}`,
5724
- target: {
5725
- kind: "dataset",
5726
- tableNamespace: pendingDataset.tableNamespace,
5727
- operation: "materializing"
5728
- },
5729
- state: {
5730
- kind: "active",
5731
- progress: {
5732
- completed: datasetProgress?.completed ?? pendingDataset.persistedRows,
5733
- total: datasetProgress?.total ?? (typeof pendingDataset.succeededRows === "number" || typeof pendingDataset.failedRows === "number" ? (pendingDataset.succeededRows ?? 0) + (pendingDataset.failedRows ?? 0) : void 0),
5734
- failed: datasetProgress?.failed ?? pendingDataset.failedRows
5735
- }
5736
- },
5737
- observedAt: datasetStep?.updatedAt ?? pendingDataset.updatedAt ?? observedAt
5738
- },
5739
- now
5740
- );
5741
- }
5742
- const activeStep = input2.nodeStates?.find(
5743
- (candidate) => candidate.nodeId === input2.activeNodeId
5744
- ) ?? input2.nodeStates?.find((candidate) => candidate.status === "running") ?? null;
5745
- if (activeStep) {
5746
- const toolId = activeStep.nodeId.startsWith("tool:") ? activeStep.nodeId.split(":").at(-1)?.trim() || null : null;
5747
- const provider = toolId?.split(/[._]/)[0]?.trim() || null;
5748
- return projection(
5749
- {
5750
- activityId: `step:${activeStep.nodeId}`,
5751
- stepId: activeStep.nodeId,
5752
- target: toolId && provider ? {
5753
- kind: "provider",
5754
- provider,
5755
- operation: toolId,
5756
- label: activeStep.label ?? toolId
5757
- } : {
5758
- kind: "step",
5759
- stepId: activeStep.nodeId,
5760
- label: activeStep.label
5761
- },
5762
- state: {
5763
- kind: "active",
5764
- progress: activeStep.progress ?? void 0
5765
- },
5766
- observedAt: activeStep.updatedAt ?? observedAt
5767
- },
5768
- now
5769
- );
5770
- }
5771
- if (normalizedStatus === "queued") {
5772
- return projection(
5773
- {
5774
- activityId: "capacity:worker",
5775
- target: { kind: "capacity", pool: "worker" },
5776
- state: { kind: "queued", reason: "capacity" },
5777
- observedAt
5778
- },
5779
- now
5780
- );
5781
- }
5782
- const fallback = {
5783
- activityId: "run:legacy",
5784
- target: {
5785
- kind: "step",
5786
- stepId: input2.activeNodeId ?? "run",
5787
- label: input2.playName ?? "play"
5788
- },
5789
- state: normalizedStatus === "waiting" ? { kind: "waiting", reason: { kind: "unknown" } } : { kind: "active" },
5790
- observedAt
5791
- };
5792
- return projection(fallback, now, normalizedStatus !== "waiting");
5793
- }
5794
-
5795
- // ../play-runtime/cell-provenance.ts
5796
- function finiteNonNegativeInteger2(value) {
5797
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
5798
- return null;
5799
- }
5800
- return Math.trunc(value);
5801
- }
5802
- function nonEmptyString(value) {
5803
- if (typeof value !== "string") return null;
5804
- const trimmed = value.trim();
5805
- return trimmed ? trimmed : null;
5806
- }
5807
- function normalizeDatasetBornFrom(value) {
5808
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
5809
- const record3 = value;
5810
- const table = nonEmptyString(record3.table);
5811
- const rowCountIn = finiteNonNegativeInteger2(record3.rowCountIn);
5812
- if (!table || rowCountIn === null) return null;
5813
- return { table, rowCountIn };
5814
- }
5815
-
5816
- // ../play-runtime/run-ledger.ts
5817
- var LOG_TAIL_LIMIT = 100;
5818
- var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
5819
- "completed",
5820
- "failed",
5821
- "cancelled",
5822
- "terminated",
5823
- "timed_out"
5824
- ]);
5825
- function isRecord6(value) {
5826
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
5827
- }
5828
- function finiteNumber(value) {
5829
- return typeof value === "number" && Number.isFinite(value) ? value : null;
5830
- }
5831
- function nonnegativeSafeInteger(value) {
5832
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
5833
- }
5834
- function isWorkCounterSegmentId(value) {
5835
- return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
5836
- value
5837
- );
5838
- }
5839
- function normalizePlayRunLedgerTerminalWorkCounterSegment(value) {
5840
- if (!isRecord6(value)) return void 0;
5841
- if (!nonnegativeSafeInteger(value.attempt) || !nonnegativeSafeInteger(value.invocationSeq) || value.invocationSeq === 0 || !isWorkCounterSegmentId(value.segmentId)) {
5842
- return void 0;
5843
- }
5844
- return {
5845
- attempt: value.attempt,
5846
- invocationSeq: value.invocationSeq,
5847
- segmentId: value.segmentId
5848
- };
5849
- }
5850
- function hasConfirmedPlayRunLedgerWorkCounters(snapshot) {
5851
- const counters = snapshot.workCounters;
5852
- const terminal = snapshot.terminalWorkCounterSegment;
5853
- return Boolean(
5854
- isTerminalPlayRunLedgerStatus(snapshot.status) && (snapshot.terminalSource === "worker" || snapshot.terminalSource === "system") && counters?.final && counters.completeThroughAttempt && counters.consistent && terminal && counters.attempt === terminal.attempt && counters.invocationSeq === terminal.invocationSeq && counters.segmentId === terminal.segmentId && Number.isSafeInteger(
5855
- counters.completedLogicalCalls + counters.logicalCalls
5856
- ) && Number.isSafeInteger(
5857
- counters.completedProviderRequests + counters.providerRequests
5858
- ) && Number.isSafeInteger(
5859
- counters.completedProvider429s + counters.provider429s
5860
- )
5861
- );
5862
- }
5863
- function normalizeWorkCounters(value) {
5864
- if (!isRecord6(value)) return void 0;
5865
- for (const field of [
5866
- "attempt",
5867
- "invocationSeq",
5868
- "logicalCalls",
5869
- "providerRequests",
5870
- "provider429s",
5871
- "completedLogicalCalls",
5872
- "completedProviderRequests",
5873
- "completedProvider429s"
5874
- ]) {
5875
- if (!nonnegativeSafeInteger(value[field])) return void 0;
5876
- }
5877
- if (value.invocationSeq === 0 || !isWorkCounterSegmentId(value.segmentId) || typeof value.final !== "boolean" || typeof value.completeThroughAttempt !== "boolean" || typeof value.consistent !== "boolean") {
5878
- return void 0;
5879
- }
5880
- return {
5881
- ...value,
5882
- attempt: value.attempt,
5883
- invocationSeq: value.invocationSeq,
5884
- segmentId: value.segmentId,
5885
- logicalCalls: value.logicalCalls,
5886
- providerRequests: value.providerRequests,
5887
- provider429s: value.provider429s,
5888
- final: value.final,
5889
- completedLogicalCalls: value.completedLogicalCalls,
5890
- completedProviderRequests: value.completedProviderRequests,
5891
- completedProvider429s: value.completedProvider429s,
5892
- completeThroughAttempt: value.completeThroughAttempt,
5893
- consistent: value.consistent
5894
- };
5895
- }
5896
- function optionalFiniteNumber(value) {
5897
- const normalized = finiteNumber(value);
5898
- return normalized === null ? void 0 : normalized;
5899
- }
5900
- function optionalString(value) {
5901
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
5902
- }
5903
- function optionalNullableString(value) {
5904
- if (value === null) return null;
5905
- return optionalString(value);
5906
- }
5907
- function normalizePlayRunLedgerStatus(value) {
5908
- const normalized = String(value ?? "").trim().toLowerCase();
5909
- switch (normalized) {
5910
- case "queued":
5911
- case "pending":
5912
- return "queued";
5913
- case "running":
5914
- case "started":
5915
- return "running";
5916
- case "waiting":
5917
- return "waiting";
5918
- case "completed":
5919
- case "complete":
5920
- case "succeeded":
5921
- return "completed";
5922
- case "failed":
5923
- case "error":
5924
- return "failed";
5925
- case "cancelled":
5926
- case "canceled":
5927
- return "cancelled";
5928
- case "terminated":
5929
- return "terminated";
5930
- case "timed_out":
5931
- case "timeout":
5932
- return "timed_out";
5933
- default:
5934
- return "unknown";
5935
- }
5936
- }
5937
- function isTerminalPlayRunLedgerStatus(status) {
5938
- return TERMINAL_STATUSES.has(status);
5939
- }
5940
- function summarizeRunRowOutcomes(snapshot) {
5941
- let completedRows = 0;
5942
- let failedRows = 0;
5943
- let totalRows = 0;
5944
- let supersededRows = 0;
5945
- for (const step of Object.values(snapshot.stepsById)) {
5946
- const progress = step.progress;
5947
- if (!progress) continue;
5948
- completedRows += Math.max(0, finiteNumber(progress.completed) ?? 0);
5949
- failedRows += Math.max(0, finiteNumber(progress.failed) ?? 0);
5950
- supersededRows += Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
5951
- const stepTotal = finiteNumber(progress.total);
5952
- totalRows += stepTotal !== null && stepTotal >= 0 ? stepTotal : Math.max(0, finiteNumber(progress.completed) ?? 0) + Math.max(0, finiteNumber(progress.failed) ?? 0) + Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
5953
- }
5954
- const resultSummary = isRecord6(snapshot.resultSummary) ? snapshot.resultSummary : null;
5955
- const resultRowOutcomes = isRecord6(resultSummary?.rowOutcomes) ? resultSummary.rowOutcomes : null;
5956
- const terminalCompletedRows = finiteNumber(resultRowOutcomes?.completedRows);
5957
- const terminalFailedRows = finiteNumber(resultRowOutcomes?.failedRows);
5958
- const terminalTotalRows = finiteNumber(resultRowOutcomes?.totalRows);
5959
- const terminalSupersededRows = finiteNumber(
5960
- resultRowOutcomes?.supersededRows
5961
- );
5962
- const settledCompletedRows = terminalCompletedRows ?? completedRows;
5963
- const settledFailedRows = terminalFailedRows ?? failedRows;
5964
- return {
5965
- completedRows: settledCompletedRows,
5966
- failedRows: settledFailedRows,
5967
- totalRows: terminalTotalRows ?? totalRows,
5968
- hasRowFailures: settledFailedRows > 0,
5969
- ...(terminalSupersededRows ?? supersededRows) > 0 ? { supersededRows: terminalSupersededRows ?? supersededRows } : {}
5970
- };
5971
- }
5972
- function createEmptyPlayRunLedgerSnapshot(input2) {
5973
- const status = normalizePlayRunLedgerStatus(input2.status ?? "unknown");
5974
- const startedAt = finiteNumber(input2.startedAt) ?? null;
5975
- const finishedAt = finiteNumber(input2.finishedAt) ?? null;
5976
- return {
5977
- runId: input2.runId,
5978
- playName: input2.playName ?? null,
5979
- status,
5980
- waitKind: null,
5981
- waitUntil: null,
5982
- error: optionalNullableString(input2.error) ?? null,
5983
- createdAt: finiteNumber(input2.createdAt) ?? null,
5984
- startedAt,
5985
- updatedAt: finiteNumber(input2.updatedAt) ?? finishedAt ?? startedAt ?? finiteNumber(input2.createdAt) ?? null,
5986
- finishedAt,
5987
- durationMs: startedAt !== null && finishedAt !== null ? Math.max(0, finishedAt - startedAt) : null,
5988
- orderedStepIds: [],
5989
- stepsById: {},
5990
- orderedDatasetIds: [],
5991
- datasetsById: {},
5992
- orderedActivityIds: [],
5993
- activitiesById: {},
5994
- logTail: [],
5995
- totalLogCount: 0,
5996
- logsTruncated: false,
5997
- activeStepId: null,
5998
- activeActivityId: null,
5999
- activeArtifactTableNamespace: null,
6000
- resultTableNamespace: null
6001
- };
6002
- }
6003
- function normalizePlayRunLedgerSnapshot(value, fallback) {
6004
- if (!isRecord6(value)) {
6005
- return createEmptyPlayRunLedgerSnapshot(fallback);
6006
- }
6007
- const orderedStepIds = Array.isArray(value.orderedStepIds) ? value.orderedStepIds.filter(
6008
- (entry) => typeof entry === "string" && Boolean(entry.trim())
6009
- ) : [];
6010
- const rawSteps = isRecord6(value.stepsById) ? value.stepsById : {};
6011
- const stepsById = {};
6012
- for (const [stepId, rawStep] of Object.entries(rawSteps)) {
6013
- if (!stepId.trim() || !isRecord6(rawStep)) continue;
6014
- const rawStatus = normalizeStepStatus(rawStep.status);
6015
- if (!rawStatus) continue;
6016
- const completedAt = finiteNumber(rawStep.completedAt);
6017
- const status = rawStatus === "running" && completedAt !== null ? "completed" : rawStatus;
6018
- const rawProgress = isRecord6(rawStep.progress) ? rawStep.progress : null;
6019
- stepsById[stepId] = {
6020
- stepId,
6021
- label: optionalString(rawStep.label),
6022
- kind: optionalString(rawStep.kind),
6023
- status,
6024
- error: optionalNullableString(rawStep.error),
6025
- artifactTableNamespace: optionalNullableString(
6026
- rawStep.artifactTableNamespace
6027
- ),
6028
- startedAt: finiteNumber(rawStep.startedAt),
6029
- completedAt,
6030
- updatedAt: finiteNumber(rawStep.updatedAt),
6031
- progress: rawProgress ? normalizeStepProgress(rawProgress) : null
6032
- };
6033
- }
6034
- const rawDatasets = isRecord6(value.datasetsById) ? value.datasetsById : {};
6035
- const datasetsById = {};
6036
- for (const [datasetId, rawDataset] of Object.entries(rawDatasets)) {
6037
- if (!datasetId.trim() || !isRecord6(rawDataset)) continue;
6038
- const phase = rawDataset.phase === "available" || rawDataset.phase === "failed" ? rawDataset.phase : "registered";
6039
- const datasetBornFrom = normalizeDatasetBornFrom(rawDataset.bornFrom);
6040
- datasetsById[datasetId] = {
6041
- datasetId,
6042
- path: optionalString(rawDataset.path) ?? `datasets.${datasetId}`,
6043
- tableNamespace: optionalString(rawDataset.tableNamespace) ?? datasetId,
6044
- phase,
6045
- persistedRows: Math.max(0, finiteNumber(rawDataset.persistedRows) ?? 0),
6046
- persistedRowsObserved: rawDataset.persistedRowsObserved === true,
6047
- succeededRows: Math.max(0, finiteNumber(rawDataset.succeededRows) ?? 0),
6048
- succeededRowsObserved: rawDataset.succeededRowsObserved === true,
6049
- failedRows: Math.max(0, finiteNumber(rawDataset.failedRows) ?? 0),
6050
- failedRowsObserved: rawDataset.failedRowsObserved === true,
6051
- complete: rawDataset.complete === true,
6052
- completeObserved: rawDataset.completeObserved === true,
6053
- // ADR 0019 birth survives the snapshot round trip. A partial record is
6054
- // dropped rather than half-admitted, so a dataset either states where its
6055
- // rows came from or says nothing.
6056
- ...datasetBornFrom ? { bornFrom: datasetBornFrom } : {},
6057
- updatedAt: finiteNumber(rawDataset.updatedAt) ?? 0
6058
- };
6059
- }
6060
- const rawActivities = isRecord6(value.activitiesById) ? value.activitiesById : {};
6061
- const activitiesById = {};
6062
- for (const [activityId, rawActivity] of Object.entries(rawActivities)) {
6063
- if (activityId.trim() && isPlayActivityObservation(rawActivity) && rawActivity.activityId === activityId) {
6064
- activitiesById[activityId] = rawActivity;
6065
- }
6066
- }
6067
- const createdAt = finiteNumber(value.createdAt) ?? fallback.createdAt ?? null;
6068
- const startedAt = finiteNumber(value.startedAt) ?? fallback.startedAt ?? null;
6069
- const finishedAt = finiteNumber(value.finishedAt) ?? fallback.finishedAt ?? null;
6070
- const updatedAt = finiteNumber(value.updatedAt) ?? fallback.updatedAt ?? finishedAt ?? startedAt ?? createdAt ?? null;
6071
- const error = Object.prototype.hasOwnProperty.call(value, "error") ? optionalNullableString(value.error) ?? null : fallback.error ?? null;
6072
- const rawTail = Array.isArray(value.logTail) ? value.logTail : value.logs;
6073
- const logTail = Array.isArray(rawTail) ? rawTail.filter((line) => typeof line === "string") : [];
6074
- const workCounters = normalizeWorkCounters(value.workCounters);
6075
- const terminalWorkCounterSegment = normalizePlayRunLedgerTerminalWorkCounterSegment(
6076
- value.terminalWorkCounterSegment
6077
- );
6078
- return {
6079
- runId: optionalString(value.runId) ?? fallback.runId,
6080
- playName: optionalNullableString(value.playName) ?? fallback.playName ?? null,
6081
- status: normalizePlayRunLedgerStatus(value.status ?? fallback.status),
6082
- waitKind: optionalNullableString(value.waitKind),
6083
- waitUntil: finiteNumber(value.waitUntil),
6084
- error,
6085
- createdAt,
6086
- startedAt,
6087
- updatedAt,
6088
- finishedAt,
6089
- durationMs: startedAt !== null && finishedAt !== null ? Math.max(0, finishedAt - startedAt) : finiteNumber(value.durationMs),
6090
- orderedStepIds: orderedStepIds.filter((stepId) => stepsById[stepId]),
6091
- stepsById,
6092
- orderedDatasetIds: (Array.isArray(value.orderedDatasetIds) ? value.orderedDatasetIds : Object.keys(datasetsById)).filter(
6093
- (datasetId) => typeof datasetId === "string" && Boolean(datasetsById[datasetId])
6094
- ),
6095
- datasetsById,
6096
- orderedActivityIds: (Array.isArray(value.orderedActivityIds) ? value.orderedActivityIds : Object.keys(activitiesById)).filter(
6097
- (activityId) => typeof activityId === "string" && Boolean(activitiesById[activityId])
6098
- ),
6099
- activitiesById,
6100
- ...workCounters ? { workCounters } : {},
6101
- ...terminalWorkCounterSegment ? { terminalWorkCounterSegment } : {},
6102
- logTail: logTail.slice(-LOG_TAIL_LIMIT),
6103
- // Snapshots persisted before totalLogCount existed only know the retained
6104
- // tail, so the best lower bound for the cumulative count is the tail size.
6105
- totalLogCount: Math.max(
6106
- finiteNumber(value.totalLogCount) ?? logTail.length,
6107
- logTail.length
6108
- ),
6109
- // A persisted snapshot carrying more lines than the tail keeps is
6110
- // truncated here, whatever the stored flag says. Reporting `false` while
6111
- // dropping lines is silent loss: a reader would take the tail for the
6112
- // whole log.
6113
- logsTruncated: value.logsTruncated === true || logTail.length > LOG_TAIL_LIMIT,
6114
- activeStepId: optionalNullableString(value.activeStepId),
6115
- activeActivityId: optionalNullableString(value.activeActivityId),
6116
- activeArtifactTableNamespace: optionalNullableString(
6117
- value.activeArtifactTableNamespace
6118
- ),
6119
- resultTableNamespace: optionalNullableString(value.resultTableNamespace),
6120
- resultSummary: value.resultSummary,
6121
- result: value.result,
6122
- terminalSource: normalizePlayRunLedgerTerminalSource(value.terminalSource)
6123
- };
6124
- }
6125
- function normalizeStepStatus(value) {
6126
- const normalized = String(value ?? "").trim().toLowerCase();
6127
- if (normalized === "running" || normalized === "completed" || normalized === "failed" || normalized === "skipped") {
6128
- return normalized;
6129
- }
6130
- return null;
6131
- }
6132
- function normalizeStepProgress(value) {
6133
- return {
6134
- ...optionalFiniteNumber(value.completed) !== void 0 ? { completed: optionalFiniteNumber(value.completed) } : {},
6135
- ...optionalFiniteNumber(value.total) !== void 0 ? { total: optionalFiniteNumber(value.total) } : {},
6136
- ...optionalFiniteNumber(value.failed) !== void 0 ? { failed: optionalFiniteNumber(value.failed) } : {},
6137
- ...optionalFiniteNumber(value.startedRows) !== void 0 ? { startedRows: optionalFiniteNumber(value.startedRows) } : {},
6138
- ...optionalFiniteNumber(value.activeRows) !== void 0 ? { activeRows: optionalFiniteNumber(value.activeRows) } : {},
6139
- ...optionalFiniteNumber(value.waitingRows) !== void 0 ? { waitingRows: optionalFiniteNumber(value.waitingRows) } : {},
6140
- ...optionalFiniteNumber(value.completedRows) !== void 0 ? { completedRows: optionalFiniteNumber(value.completedRows) } : {},
6141
- ...optionalFiniteNumber(value.supersededRows) !== void 0 ? { supersededRows: optionalFiniteNumber(value.supersededRows) } : {},
6142
- ...optionalString(value.message) ? { message: optionalString(value.message) } : {},
6143
- ...optionalNullableString(value.artifactTableNamespace) !== void 0 ? {
6144
- artifactTableNamespace: optionalNullableString(
6145
- value.artifactTableNamespace
6146
- )
6147
- } : {},
6148
- ...finiteNumber(value.startedAt) !== null ? { startedAt: finiteNumber(value.startedAt) } : {},
6149
- ...finiteNumber(value.completedAt) !== null ? { completedAt: finiteNumber(value.completedAt) } : {},
6150
- ...finiteNumber(value.updatedAt) !== null ? { updatedAt: finiteNumber(value.updatedAt) } : {},
6151
- ...normalizePlayDocflowNodeIoState(value.nodeIo) ? { nodeIo: normalizePlayDocflowNodeIoState(value.nodeIo) } : {}
6152
- };
6153
- }
6154
5144
 
6155
5145
  // ../play-runtime/run-lifecycle-policy.ts
6156
5146
  var TERMINAL_PLAY_RUN_STATUSES = /* @__PURE__ */ new Set([
@@ -6266,9 +5256,6 @@ function readProvenanceTag(line) {
6266
5256
  const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
6267
5257
  return { provenance, line: line.slice(end + 1) };
6268
5258
  }
6269
- function stripProvenanceTag(line) {
6270
- return readProvenanceTag(line).line;
6271
- }
6272
5259
  function classifyLegacyLogLine(line) {
6273
5260
  const message = stripLeadingTimestamp(line);
6274
5261
  if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
@@ -6341,143 +5328,9 @@ function stripLeadingTimestamp(line) {
6341
5328
  }
6342
5329
 
6343
5330
  // ../play-runtime/run-snapshot-stream.ts
6344
- function normalizePlayRunLiveStatus(value) {
6345
- return normalizePlayRunLifecycleStatus(value);
6346
- }
6347
5331
  function isTerminalPlayRunLiveStatus(status) {
6348
5332
  return isTerminalPlayRunLifecycleStatus(status);
6349
5333
  }
6350
- function isRecord7(value) {
6351
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
6352
- }
6353
- function finiteNumber2(value) {
6354
- return typeof value === "number" && Number.isFinite(value) ? value : null;
6355
- }
6356
- function extractTerminalRunLogTail(result) {
6357
- if (!isRecord7(result) || !isRecord7(result._metadata)) {
6358
- return null;
6359
- }
6360
- const runLogTail = result._metadata.runLogTail;
6361
- if (!isRecord7(runLogTail) || !Array.isArray(runLogTail.tail)) {
6362
- return null;
6363
- }
6364
- const logTail = runLogTail.tail.filter(
6365
- (line) => typeof line === "string" && line.trim().length > 0
6366
- );
6367
- if (logTail.length === 0) {
6368
- return null;
6369
- }
6370
- const totalLogCount = Math.max(
6371
- finiteNumber2(runLogTail.totalLogCount) ?? logTail.length,
6372
- logTail.length
6373
- );
6374
- return {
6375
- logTail: logTail.slice(-LOG_TAIL_LIMIT),
6376
- totalLogCount
6377
- };
6378
- }
6379
- function buildSnapshotFromLedger(snapshot) {
6380
- const nodeStates = snapshot.orderedStepIds.map((stepId) => snapshot.stepsById[stepId]).filter((step) => Boolean(step)).map((step) => ({
6381
- nodeId: step.stepId,
6382
- status: step.status,
6383
- error: step.error ?? null,
6384
- artifactTableNamespace: step.artifactTableNamespace ?? null,
6385
- progress: step.progress ? {
6386
- completed: step.progress.completed,
6387
- total: step.progress.total,
6388
- failed: step.progress.failed,
6389
- startedRows: step.progress.startedRows,
6390
- activeRows: step.progress.activeRows,
6391
- waitingRows: step.progress.waitingRows,
6392
- completedRows: step.progress.completedRows,
6393
- supersededRows: step.progress.supersededRows,
6394
- message: step.progress.message,
6395
- artifactTableNamespace: step.progress.artifactTableNamespace ?? step.artifactTableNamespace ?? null,
6396
- startedAt: step.startedAt ?? null,
6397
- completedAt: step.completedAt ?? null,
6398
- updatedAt: step.progress.updatedAt ?? step.updatedAt ?? null,
6399
- nodeIo: step.progress.nodeIo
6400
- } : null,
6401
- startedAt: step.startedAt ?? null,
6402
- completedAt: step.completedAt ?? null,
6403
- updatedAt: step.updatedAt ?? null,
6404
- ...step.progress?.nodeIo ? { nodeIo: step.progress.nodeIo } : {}
6405
- }));
6406
- const liveStatus = normalizePlayRunLiveStatus(snapshot.status);
6407
- const terminalRowOutcomes = isTerminalPlayRunLiveStatus(liveStatus) ? summarizeRunRowOutcomes(snapshot) : null;
6408
- const rowOutcomes = terminalRowOutcomes && (Object.keys(snapshot.stepsById).length > 0 || terminalRowOutcomes.totalRows > 0 || (terminalRowOutcomes.supersededRows ?? 0) > 0) ? terminalRowOutcomes : null;
6409
- const workCounters = snapshot.workCounters;
6410
- const calls = workCounters ? {
6411
- logicalCalls: workCounters.completedLogicalCalls + workCounters.logicalCalls,
6412
- providerRequests: workCounters.completedProviderRequests + workCounters.providerRequests,
6413
- provider429s: workCounters.completedProvider429s + workCounters.provider429s,
6414
- confirmed: isTerminalPlayRunLiveStatus(liveStatus) && hasConfirmedPlayRunLedgerWorkCounters(snapshot)
6415
- } : null;
6416
- return {
6417
- runId: snapshot.runId,
6418
- status: liveStatus,
6419
- createdAt: snapshot.createdAt ?? null,
6420
- startedAt: snapshot.startedAt ?? null,
6421
- finishedAt: snapshot.finishedAt ?? null,
6422
- durationMs: snapshot.durationMs ?? null,
6423
- updatedAt: snapshot.updatedAt ?? snapshot.finishedAt ?? snapshot.startedAt ?? null,
6424
- // This snapshot is public SDK/API transport. Keep the historical plain
6425
- // timestamp-prefixed text while provenance remains runtime metadata.
6426
- logs: snapshot.logTail.map(stripProvenanceTag),
6427
- totalLogCount: snapshot.totalLogCount,
6428
- ...snapshot.logsTruncated ? { logsTruncated: true } : {},
6429
- activeArtifactTableNamespace: snapshot.activeArtifactTableNamespace ?? null,
6430
- resultTableNamespace: snapshot.resultTableNamespace ?? null,
6431
- datasets: snapshot.orderedDatasetIds.map((datasetId) => snapshot.datasetsById[datasetId]).filter(
6432
- (dataset) => Boolean(dataset)
6433
- ),
6434
- activities: snapshot.orderedActivityIds.map((activityId) => snapshot.activitiesById[activityId]).filter(
6435
- (activity) => Boolean(activity)
6436
- ),
6437
- activeActivity: snapshot.activeActivityId ? snapshot.activitiesById[snapshot.activeActivityId] ?? null : null,
6438
- nodeStates,
6439
- activeNodeId: snapshot.activeStepId ?? null,
6440
- ...rowOutcomes ? { rowOutcomes } : {},
6441
- ...calls && Object.values(calls).every(
6442
- (value) => typeof value === "boolean" || Number.isSafeInteger(value)
6443
- ) ? { calls } : {}
6444
- };
6445
- }
6446
- function buildPlayRunStatusSnapshot(input2) {
6447
- const ledgerSnapshot = normalizePlayRunLedgerSnapshot(input2.run.runSnapshot, {
6448
- runId: input2.run.workflowId,
6449
- playName: input2.run.name ?? null,
6450
- status: input2.run.status,
6451
- createdAt: input2.run.createdAt ?? null,
6452
- startedAt: input2.run.startedAt ?? null,
6453
- updatedAt: input2.run.updatedAt ?? null,
6454
- finishedAt: input2.run.finishedAt ?? null
6455
- });
6456
- const terminalRunLogTail = extractTerminalRunLogTail(input2.run.result);
6457
- const projectedSnapshot = terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount ? buildSnapshotFromLedger({
6458
- ...ledgerSnapshot,
6459
- logTail: terminalRunLogTail.logTail,
6460
- totalLogCount: terminalRunLogTail.totalLogCount
6461
- }) : buildSnapshotFromLedger(ledgerSnapshot);
6462
- const activity = projectPlayRunActivity({
6463
- runId: input2.run.workflowId,
6464
- playName: input2.run.name,
6465
- status: projectedSnapshot.status,
6466
- updatedAt: projectedSnapshot.updatedAt,
6467
- waitKind: input2.run.waitKind ?? input2.run.wait?.kind ?? null,
6468
- waitUntil: input2.run.waitUntil,
6469
- eventKey: input2.run.wait?.eventKey ?? null,
6470
- runtimeBackend: input2.run.runtimeBackend,
6471
- activeNodeId: input2.run.activeBoundaryId ?? projectedSnapshot.activeNodeId,
6472
- nodeStates: projectedSnapshot.nodeStates,
6473
- datasets: projectedSnapshot.datasets,
6474
- explicit: projectedSnapshot.activities
6475
- });
6476
- return {
6477
- ...projectedSnapshot,
6478
- activity
6479
- };
6480
- }
6481
5334
  function makeRunStreamEvent(input2) {
6482
5335
  return {
6483
5336
  ...input2,
@@ -6560,7 +5413,7 @@ function diffLogLines(input2) {
6560
5413
  const missingCount = tailFirstSeq - 1 - input2.lastLogSeq;
6561
5414
  return {
6562
5415
  lines: [
6563
- `[stream] ${missingCount} log lines not retained in the live window; full logs via runs logs`,
5416
+ `[watch] ${missingCount} log lines not retained in the live window; full logs via runs logs`,
6564
5417
  ...logs
6565
5418
  ],
6566
5419
  lastLogSeq: totalLogCount,
@@ -6706,310 +5559,156 @@ function diffPlayRunStreamEvents(input2) {
6706
5559
  return { events, next };
6707
5560
  }
6708
5561
 
6709
- // src/runs/observe-transport.ts
6710
- var RunObserveTransportUnavailableError = class extends Error {
6711
- constructor(message, reason) {
6712
- super(message);
6713
- this.reason = reason;
6714
- this.name = "RunObserveTransportUnavailableError";
5562
+ // src/stream-reconnect.ts
5563
+ function isTransientPlayRunReadError(error) {
5564
+ if (error instanceof DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
5565
+ return true;
6715
5566
  }
6716
- };
6717
- var OBSERVE_BOOTSTRAP_TIMEOUT_MS = 1e4;
6718
- var OBSERVE_RECONNECT_NOTICE_MS = 1e4;
6719
- var OBSERVE_STALE_WARNING_MS = 12e4;
6720
- var OBSERVE_WATCHDOG_TICK_MS = 5e3;
6721
- var GRANT_REFRESH_MARGIN_MS = 5 * 6e4;
6722
- var BACKFILL_PAGE_LIMIT = 1e3;
6723
- var BACKFILL_MAX_PAGES = 30;
6724
- var OBSERVER_SNAPSHOT_QUERY = "runObservers:getPlayRunSnapshotForObserver";
6725
- var OBSERVER_LOG_PAGE_QUERY = "runObservers:getRunLogPageForObserver";
6726
- function errorText(error) {
6727
- return error instanceof Error ? error.message : String(error);
5567
+ if (error instanceof DeeplineError && typeof error.statusCode === "number") {
5568
+ return error.statusCode >= 500 && error.statusCode < 600;
5569
+ }
5570
+ const text = error instanceof Error ? error.message : String(error);
5571
+ 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(
5572
+ text
5573
+ );
6728
5574
  }
6729
- async function mintRunObserveGrant(http, runId) {
6730
- let response;
6731
- try {
6732
- response = await http.post(
6733
- `/api/v2/runs/${encodeURIComponent(runId)}/observe-grant`,
6734
- {}
6735
- );
6736
- } catch (error) {
6737
- if (error instanceof DeeplineError) {
6738
- if (error.statusCode === 401 || error.statusCode === 403) {
6739
- throw error;
6740
- }
6741
- throw new RunObserveTransportUnavailableError(
6742
- `observe-grant endpoint unavailable (${error.statusCode ?? "network"}): ${error.message}`,
6743
- "grant_endpoint_unavailable"
6744
- );
6745
- }
6746
- throw new RunObserveTransportUnavailableError(
6747
- `observe-grant request failed: ${errorText(error)}`,
6748
- "grant_request_failed"
6749
- );
5575
+
5576
+ // src/runs/watch-polling.ts
5577
+ var RUN_WATCH_POLL_INTERVAL_MS = 2e3;
5578
+ function waitForNextPoll(ms, signal) {
5579
+ if (signal?.aborted) {
5580
+ return Promise.resolve(false);
6750
5581
  }
6751
- const grant = response;
6752
- if (!grant || typeof grant.convexUrl !== "string" || !grant.convexUrl.trim() || typeof grant.token !== "string" || !grant.token.trim() || typeof grant.expiresAt !== "number") {
6753
- throw new RunObserveTransportUnavailableError(
6754
- "observe-grant endpoint returned an invalid grant payload.",
6755
- "grant_payload_invalid"
6756
- );
5582
+ return new Promise((resolve22) => {
5583
+ const finish = (elapsed) => {
5584
+ clearTimeout(timeout);
5585
+ signal?.removeEventListener("abort", onAbort);
5586
+ resolve22(elapsed);
5587
+ };
5588
+ const onAbort = () => finish(false);
5589
+ const timeout = setTimeout(() => finish(true), ms);
5590
+ signal?.addEventListener("abort", onAbort, { once: true });
5591
+ });
5592
+ }
5593
+ function readSnapshotResponse(response, runId) {
5594
+ if (!response || typeof response !== "object" || Array.isArray(response)) {
5595
+ throw new Error("Run watch returned an invalid snapshot response.");
5596
+ }
5597
+ const record3 = response;
5598
+ const snapshot = record3.snapshot;
5599
+ if (record3.runId !== runId || !snapshot || typeof snapshot !== "object" || Array.isArray(snapshot) || snapshot.runId !== runId || typeof snapshot.status !== "string" || !Array.isArray(snapshot.logs) || !snapshot.logs.every(
5600
+ (line) => typeof line === "string"
5601
+ ) || typeof snapshot.totalLogCount !== "number" || !Array.isArray(snapshot.nodeStates)) {
5602
+ throw new Error(`Run watch returned an invalid snapshot for ${runId}.`);
6757
5603
  }
6758
- return grant;
5604
+ return { runId, snapshot };
6759
5605
  }
6760
- async function backfillLogGap(input2) {
5606
+ async function backfillRotatedLogTail(input2) {
5607
+ if (!input2.previous.runSignature) {
5608
+ return input2.snapshot;
5609
+ }
5610
+ const gap = resolvePlayRunLogGap(input2.snapshot, input2.previous.lastLogSeq);
5611
+ if (!gap) {
5612
+ return input2.snapshot;
5613
+ }
6761
5614
  const lines = [];
6762
- let cursor = input2.lastLogSeq;
6763
- for (let page = 0; page < BACKFILL_MAX_PAGES; page += 1) {
6764
- if (cursor >= input2.tailFirstSeq - 1) {
6765
- break;
6766
- }
6767
- let logPage;
6768
- try {
6769
- logPage = await input2.queryLogPage(
6770
- cursor,
6771
- Math.min(BACKFILL_PAGE_LIMIT, input2.tailFirstSeq - 1 - cursor)
6772
- );
6773
- } catch {
6774
- return null;
6775
- }
6776
- const entries = (logPage?.entries ?? []).filter(
6777
- (entry) => entry.seq > cursor && entry.seq < input2.tailFirstSeq
5615
+ let cursor = input2.previous.lastLogSeq;
5616
+ const targetSeq = gap.tailFirstSeq - 1;
5617
+ while (cursor < targetSeq) {
5618
+ const limit = Math.min(1e3, targetSeq - cursor);
5619
+ const page = await input2.http.get(
5620
+ `/api/v2/runs/${encodeURIComponent(input2.runId)}/logs?afterSeq=${cursor}&limit=${limit}`,
5621
+ { signal: input2.signal }
6778
5622
  );
6779
- if (entries.length === 0) {
6780
- break;
5623
+ if (!page || !Array.isArray(page.entries) || page.entries.length === 0) {
5624
+ return input2.snapshot;
6781
5625
  }
6782
- for (const entry of entries) {
6783
- if (entry.seq !== cursor + 1) {
6784
- return null;
5626
+ for (const entry of page.entries) {
5627
+ if (!entry || entry.seq !== cursor + 1 || typeof entry.line !== "string") {
5628
+ return input2.snapshot;
6785
5629
  }
6786
5630
  lines.push(entry.line);
6787
5631
  cursor = entry.seq;
6788
5632
  }
6789
5633
  }
6790
- if (cursor < input2.tailFirstSeq - 1) {
6791
- return null;
5634
+ if (cursor !== targetSeq) {
5635
+ return input2.snapshot;
6792
5636
  }
6793
- return lines;
5637
+ return { ...input2.snapshot, logs: [...lines, ...input2.snapshot.logs] };
6794
5638
  }
6795
- async function* observeRunEvents(options) {
6796
- const { http, runId } = options;
6797
- let grant = await mintRunObserveGrant(http, runId);
6798
- let convexBrowser;
6799
- let convexServer;
6800
- try {
6801
- convexBrowser = await import("convex/browser");
6802
- convexServer = await import("convex/server");
6803
- } catch (error) {
6804
- throw new RunObserveTransportUnavailableError(
6805
- `convex client module unavailable: ${errorText(error)}`,
6806
- "convex_module_unavailable"
6807
- );
6808
- }
6809
- let webSocketConstructor;
6810
- if (typeof WebSocket === "undefined") {
5639
+ async function* watchRunEvents(options) {
5640
+ const { http, runId, signal } = options;
5641
+ const path = `/api/v2/runs/${encodeURIComponent(runId)}?watchSnapshot=true`;
5642
+ const streamId = `play-run-watch:${runId}`;
5643
+ const pollIntervalMs = options.pollIntervalMs ?? RUN_WATCH_POLL_INTERVAL_MS;
5644
+ let previous = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
5645
+ let consecutiveFailures = 0;
5646
+ let outageNoticeSent = false;
5647
+ while (!signal?.aborted) {
5648
+ const pollStartedAt = Date.now();
5649
+ let snapshot;
6811
5650
  try {
6812
- const wsModuleName = "ws";
6813
- const ws = await import(wsModuleName);
6814
- webSocketConstructor = ws.default;
6815
- } catch (error) {
6816
- throw new RunObserveTransportUnavailableError(
6817
- `no WebSocket implementation available: ${errorText(error)}`,
6818
- "websocket_unavailable"
6819
- );
6820
- }
6821
- }
6822
- const snapshotQuery = convexServer.makeFunctionReference(
6823
- OBSERVER_SNAPSHOT_QUERY
6824
- );
6825
- const logPageQuery = convexServer.makeFunctionReference(
6826
- OBSERVER_LOG_PAGE_QUERY
6827
- );
6828
- const client2 = new convexBrowser.ConvexClient(grant.convexUrl, {
6829
- ...webSocketConstructor ? { webSocketConstructor } : {},
6830
- unsavedChangesWarning: false
6831
- });
6832
- const queue = [];
6833
- let wake = null;
6834
- const push = (item) => {
6835
- queue.push(item);
6836
- wake?.();
6837
- wake = null;
6838
- };
6839
- let lastForcedRefreshAt = 0;
6840
- client2.setAuth(async ({ forceRefreshToken }) => {
6841
- const now = Date.now();
6842
- if (!forceRefreshToken && grant.expiresAt - now > GRANT_REFRESH_MARGIN_MS) {
6843
- return grant.token;
6844
- }
6845
- if (forceRefreshToken && now - lastForcedRefreshAt < 5e3) {
6846
- push({
6847
- kind: "error",
6848
- error: new DeeplineError(
6849
- `Run observe grant for ${runId} was rejected after a re-mint. The server and Convex deployment disagree on the grant issuer/JWKS.`,
6850
- 401,
6851
- "RUN_OBSERVE_GRANT_REJECTED"
6852
- )
5651
+ const response = await http.get(path, { signal });
5652
+ snapshot = await backfillRotatedLogTail({
5653
+ http,
5654
+ runId,
5655
+ snapshot: readSnapshotResponse(response, runId).snapshot,
5656
+ previous,
5657
+ signal
6853
5658
  });
6854
- return null;
6855
- }
6856
- if (forceRefreshToken) {
6857
- lastForcedRefreshAt = now;
6858
- }
6859
- try {
6860
- grant = await mintRunObserveGrant(http, runId);
6861
- return grant.token;
6862
5659
  } catch (error) {
6863
- push({ kind: "error", error });
6864
- return null;
6865
- }
6866
- });
6867
- const unsubscribe = client2.onUpdate(
6868
- snapshotQuery,
6869
- { workflowId: runId },
6870
- (run) => push({ kind: "run", run: run ?? null }),
6871
- (error) => push({ kind: "error", error })
6872
- );
6873
- let lastUpdateAt = Date.now();
6874
- let lastStatusTerminal = false;
6875
- let disconnectedSince = null;
6876
- let warnedReconnecting = false;
6877
- let warnedStale = false;
6878
- const watchdog = setInterval(() => {
6879
- const now = Date.now();
6880
- try {
6881
- const connectionState = client2.connectionState();
6882
- if (connectionState.isWebSocketConnected) {
6883
- disconnectedSince = null;
6884
- warnedReconnecting = false;
6885
- } else {
6886
- disconnectedSince ??= now;
6887
- if (!warnedReconnecting && now - disconnectedSince >= OBSERVE_RECONNECT_NOTICE_MS) {
6888
- warnedReconnecting = true;
6889
- options.onNotice?.(
6890
- `[observe] connection lost; reconnecting to live run ${runId}\u2026`
6891
- );
6892
- }
6893
- }
6894
- } catch {
6895
- }
6896
- if (!lastStatusTerminal && !warnedStale && now - lastUpdateAt >= OBSERVE_STALE_WARNING_MS) {
6897
- warnedStale = true;
6898
- options.onNotice?.(
6899
- `[observe] no live updates for ${Math.round((now - lastUpdateAt) / 1e3)}s; run ${runId} may be stalled (status checks continue)`
6900
- );
6901
- }
6902
- }, OBSERVE_WATCHDOG_TICK_MS);
6903
- watchdog.unref?.();
6904
- const abortListener = () => push({
6905
- kind: "error",
6906
- error: new DeeplineError(
6907
- "Run observation aborted.",
6908
- void 0,
6909
- "ABORTED"
6910
- )
6911
- });
6912
- options.signal?.addEventListener("abort", abortListener, { once: true });
6913
- let diffState = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
6914
- const streamId = ["observe", runId].join(":");
6915
- let sawFirstSnapshot = false;
6916
- try {
6917
- for (; ; ) {
6918
- if (queue.length === 0) {
6919
- const waitForItem = new Promise((resolve22) => {
6920
- wake = resolve22;
6921
- });
6922
- if (!sawFirstSnapshot) {
6923
- const timedOut = await Promise.race([
6924
- waitForItem.then(() => false),
6925
- new Promise(
6926
- (resolve22) => setTimeout(() => resolve22(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
6927
- )
6928
- ]);
6929
- if (timedOut && queue.length === 0) {
6930
- throw new RunObserveTransportUnavailableError(
6931
- `no snapshot from Convex at ${grant.convexUrl} within ${OBSERVE_BOOTSTRAP_TIMEOUT_MS}ms`,
6932
- "convex_unreachable"
6933
- );
6934
- }
6935
- } else {
6936
- await waitForItem;
6937
- }
6938
- continue;
6939
- }
6940
- const item = queue.shift();
6941
- if (item.kind === "error") {
6942
- if (options.signal?.aborted) {
6943
- return;
6944
- }
6945
- throw item.error;
5660
+ if (signal?.aborted) {
5661
+ return;
6946
5662
  }
6947
- sawFirstSnapshot = true;
6948
- lastUpdateAt = Date.now();
6949
- warnedStale = false;
6950
- if (item.run === null) {
6951
- throw new DeeplineError(
6952
- `Run ${runId} was not found (or is not visible to this grant).`,
6953
- 404,
6954
- "RUN_NOT_FOUND"
6955
- );
5663
+ if (!isTransientPlayRunReadError(error)) {
5664
+ throw error;
6956
5665
  }
6957
- const snapshot = buildPlayRunStatusSnapshot({ run: item.run });
6958
- lastStatusTerminal = isTerminalPlayRunLiveStatus(snapshot.status);
6959
- const gap = resolvePlayRunLogGap(snapshot, diffState.lastLogSeq);
6960
- if (gap && diffState.lastLogSeq > 0) {
6961
- const backfilled = await backfillLogGap({
6962
- queryLogPage: (afterSeq, limit) => client2.query(logPageQuery, {
6963
- workflowId: runId,
6964
- afterSeq,
6965
- limit
6966
- }),
6967
- lastLogSeq: diffState.lastLogSeq,
6968
- tailFirstSeq: gap.tailFirstSeq
5666
+ consecutiveFailures += 1;
5667
+ const reason = error instanceof Error ? error.message : String(error);
5668
+ if (!outageNoticeSent) {
5669
+ options.onRetry?.({
5670
+ attempt: consecutiveFailures,
5671
+ delayMs: pollIntervalMs,
5672
+ reason
6969
5673
  });
6970
- if (backfilled && backfilled.length > 0) {
6971
- yield {
6972
- cursor: String(snapshot.updatedAt ?? Date.now()),
6973
- streamId,
6974
- scope: "play",
6975
- type: "play.run.log",
6976
- at: (/* @__PURE__ */ new Date()).toISOString(),
6977
- payload: {
6978
- runId: snapshot.runId,
6979
- lines: backfilled,
6980
- source: "worker",
6981
- firstSeq: diffState.lastLogSeq + 1,
6982
- totalLogCount: snapshot.totalLogCount
6983
- }
6984
- };
6985
- diffState = { ...diffState, lastLogSeq: gap.tailFirstSeq - 1 };
6986
- }
6987
- }
6988
- const { events, next } = diffPlayRunStreamEvents({
6989
- streamId,
6990
- snapshot,
6991
- previous: diffState
6992
- });
6993
- diffState = next;
6994
- const ordered = [
6995
- ...events.filter((event) => event.type === "play.run.snapshot"),
6996
- ...events.filter((event) => event.type !== "play.run.snapshot")
6997
- ];
6998
- for (const event of ordered) {
6999
- yield event;
5674
+ options.onNotice?.(
5675
+ `[watch] run snapshot request failed; retrying every ${pollIntervalMs / 1e3}s (${reason})`
5676
+ );
5677
+ outageNoticeSent = true;
7000
5678
  }
7001
- if (lastStatusTerminal) {
5679
+ const remaining2 = Math.max(
5680
+ 0,
5681
+ pollIntervalMs - (Date.now() - pollStartedAt)
5682
+ );
5683
+ if (!await waitForNextPoll(remaining2, signal)) {
7002
5684
  return;
7003
5685
  }
5686
+ continue;
7004
5687
  }
7005
- } finally {
7006
- clearInterval(watchdog);
7007
- options.signal?.removeEventListener("abort", abortListener);
7008
- try {
7009
- unsubscribe();
7010
- } catch {
5688
+ if (outageNoticeSent) {
5689
+ options.onNotice?.("[watch] run snapshot polling recovered");
5690
+ outageNoticeSent = false;
5691
+ }
5692
+ consecutiveFailures = 0;
5693
+ const diff = diffPlayRunStreamEvents({
5694
+ streamId,
5695
+ snapshot,
5696
+ previous
5697
+ });
5698
+ previous = diff.next;
5699
+ for (const event of diff.events) {
5700
+ yield event;
5701
+ }
5702
+ if (isTerminalPlayRunLiveStatus(snapshot.status)) {
5703
+ return;
5704
+ }
5705
+ const remaining = Math.max(
5706
+ 0,
5707
+ pollIntervalMs - (Date.now() - pollStartedAt)
5708
+ );
5709
+ if (!await waitForNextPoll(remaining, signal)) {
5710
+ return;
7011
5711
  }
7012
- await client2.close().catch(() => void 0);
7013
5712
  }
7014
5713
  }
7015
5714
 
@@ -7340,7 +6039,7 @@ function requireTargetBillingIdempotencyKey(value) {
7340
6039
  }
7341
6040
  return normalized;
7342
6041
  }
7343
- function isRecord8(value) {
6042
+ function isRecord4(value) {
7344
6043
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
7345
6044
  }
7346
6045
  function isPrebuiltPlayDescription(play) {
@@ -7372,10 +6071,10 @@ function normalizePlayStatus(raw) {
7372
6071
  return {
7373
6072
  ...raw,
7374
6073
  runId,
7375
- ...isRecord8(legacyOverview) ? {
6074
+ ...isRecord4(legacyOverview) ? {
7376
6075
  overview: legacyOverview
7377
6076
  } : {},
7378
- ...isRecord8(runStatus) ? { runStatus } : {},
6077
+ ...isRecord4(runStatus) ? { runStatus } : {},
7379
6078
  ...runPackage ? {
7380
6079
  package: runPackage,
7381
6080
  outputs: runPackage.outputs
@@ -7514,7 +6213,7 @@ function updatePlayLiveStatusState(state, event) {
7514
6213
  }
7515
6214
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
7516
6215
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
7517
- const progressPayload = isRecord8(payload.progress) ? payload.progress : {};
6216
+ const progressPayload = isRecord4(payload.progress) ? payload.progress : {};
7518
6217
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
7519
6218
  const payloadLogs = readStringArray(payload.logs);
7520
6219
  const progressLogs = readStringArray(progressPayload.logs);
@@ -7593,6 +6292,7 @@ var DeeplineClient = class _DeeplineClient {
7593
6292
  status: (runId) => this.getRunLifecycleStatus(runId),
7594
6293
  list: (options2) => this.listRuns(options2),
7595
6294
  listPage: (options2) => this.listRunsPage(options2),
6295
+ watch: (runId, options2) => this.watchRunToTerminal(runId, options2),
7596
6296
  tail: (runId, options2) => this.tailRun(runId, options2),
7597
6297
  logs: (runId, options2) => this.getRunLogs(runId, options2),
7598
6298
  input: (runId) => this.getRunInput(runId),
@@ -7715,9 +6415,9 @@ var DeeplineClient = class _DeeplineClient {
7715
6415
  return fields2.length > 0 ? { fields: fields2 } : schema;
7716
6416
  }
7717
6417
  schemaMetadata(schema, key) {
7718
- if (!isRecord8(schema)) return null;
6418
+ if (!isRecord4(schema)) return null;
7719
6419
  const value = schema[key];
7720
- return isRecord8(value) ? value : null;
6420
+ return isRecord4(value) ? value : null;
7721
6421
  }
7722
6422
  playRunCommand(play, options) {
7723
6423
  const target = play.reference || play.name;
@@ -7772,7 +6472,7 @@ var DeeplineClient = class _DeeplineClient {
7772
6472
  aliases,
7773
6473
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
7774
6474
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
7775
- staticPipeline: isRecord8(play.staticPipeline) ? play.staticPipeline : isRecord8(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord8(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
6475
+ staticPipeline: isRecord4(play.staticPipeline) ? play.staticPipeline : isRecord4(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord4(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
7776
6476
  ...csvInput ? { csvInput } : {},
7777
6477
  ...rowOutputSchema ? { rowOutputSchema } : {},
7778
6478
  runCommand: runCommand2,
@@ -8132,15 +6832,17 @@ var DeeplineClient = class _DeeplineClient {
8132
6832
  return normalizePlayRunStart(response);
8133
6833
  }
8134
6834
  /**
8135
- * Start a play run and stream live runtime events from the same request.
6835
+ * Submit a play run through the legacy event response.
8136
6836
  *
8137
- * Use this when a caller wants low-level event handling instead of submitting
8138
- * first and then connecting to `streamPlayRunEvents(runId)`.
6837
+ * This reports admission from the start request; it does not watch an
6838
+ * existing run. Use `startPlayRun()` and `watchRunEvents(runId)` separately.
6839
+ *
6840
+ * @deprecated Use the separate start and watch methods.
8139
6841
  *
8140
6842
  * @param request - Play run configuration.
8141
- * @param options - Optional streaming options.
8142
- * @param options.signal - Optional abort signal for the streaming request.
8143
- * @returns Async stream of play-scoped live events.
6843
+ * @param options - Optional compatibility response options.
6844
+ * @param options.signal - Abort the start response.
6845
+ * @returns Async generator of play-scoped live events.
8144
6846
  */
8145
6847
  async *startPlayRunStream(request, options) {
8146
6848
  const integrationMode = resolvePlayRunIntegrationMode(request);
@@ -8622,11 +7324,23 @@ var DeeplineClient = class _DeeplineClient {
8622
7324
  );
8623
7325
  return normalizePlayStatus(response);
8624
7326
  }
7327
+ /** Poll authenticated run snapshots every two seconds and emit changed events. */
7328
+ async *watchRunEvents(workflowId, options) {
7329
+ for await (const event of watchRunEvents({
7330
+ http: this.http,
7331
+ runId: workflowId,
7332
+ signal: options?.signal,
7333
+ onNotice: options?.onNotice,
7334
+ onRetry: options?.onRetry
7335
+ })) {
7336
+ yield event;
7337
+ }
7338
+ }
8625
7339
  /**
8626
- * Stream semantic play-run events using the same SSE feed as the dashboard.
7340
+ * Read raw legacy SSE events for callers that explicitly require that
7341
+ * compatibility endpoint. Ordinary run watching uses REST snapshot polling.
8627
7342
  *
8628
- * The server emits a canonical `play.run.snapshot` event first for every
8629
- * connection, then incremental live events until terminal state or reconnect.
7343
+ * @deprecated Use `watchRunEvents` for ordinary run watching.
8630
7344
  */
8631
7345
  async *streamPlayRunEvents(workflowId, options) {
8632
7346
  const headers = options?.lastEventId && options.lastEventId.trim() ? { "Last-Event-ID": options.lastEventId.trim() } : void 0;
@@ -8641,6 +7355,68 @@ var DeeplineClient = class _DeeplineClient {
8641
7355
  }
8642
7356
  }
8643
7357
  }
7358
+ /**
7359
+ * Compatibility alias for polling canonical run snapshots and emitting
7360
+ * their changed events.
7361
+ *
7362
+ * @deprecated Use `watchRunEvents`; kept as a source-compatible alias.
7363
+ * The `fallback` option is ignored because watching uses REST polling.
7364
+ */
7365
+ async *observeRunEvents(runId, options) {
7366
+ yield* this.watchRunEvents(runId, {
7367
+ signal: options?.signal,
7368
+ onNotice: options?.onNotice
7369
+ });
7370
+ }
7371
+ /** Poll snapshots to terminal status and return the durable package. */
7372
+ async watchRunToTerminal(runId, options) {
7373
+ const state = {
7374
+ runId,
7375
+ status: "running",
7376
+ logs: [],
7377
+ lastLogSeq: 0,
7378
+ latest: null
7379
+ };
7380
+ let terminalObserved = false;
7381
+ for await (const event of this.watchRunEvents(runId, {
7382
+ signal: options?.signal,
7383
+ onNotice: options?.onNotice,
7384
+ onRetry: options?.onRetry ?? options?.onReconnect
7385
+ })) {
7386
+ options?.onEvent?.(event);
7387
+ const status = updatePlayLiveStatusState(state, event);
7388
+ if (status && TERMINAL_PLAY_STATUSES.has(status.status)) {
7389
+ terminalObserved = true;
7390
+ }
7391
+ }
7392
+ if (options?.signal?.aborted) {
7393
+ throw new DeeplineError("Run watch aborted.", void 0, "ABORTED");
7394
+ }
7395
+ if (terminalObserved) {
7396
+ return await this.getRunStatus(runId);
7397
+ }
7398
+ const refreshed = await this.getRunStatus(runId);
7399
+ if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) return refreshed;
7400
+ throw new DeeplineError(
7401
+ `Run watch for ${runId} ended before a terminal status.`,
7402
+ void 0,
7403
+ "PLAY_WATCH_ENDED"
7404
+ );
7405
+ }
7406
+ /**
7407
+ * Wait for a run and return its terminal status.
7408
+ *
7409
+ * This source-compatible alias uses the same authenticated two-second REST
7410
+ * snapshot polling as `client.runs.watch`.
7411
+ *
7412
+ * @deprecated Use `client.runs.watch`; retained for SDK compatibility.
7413
+ * @param runId - Public Deepline play-run id.
7414
+ * @param options - Optional callbacks and cancellation signal.
7415
+ * @returns The final durable run status.
7416
+ */
7417
+ async tailRun(runId, options) {
7418
+ return this.watchRunToTerminal(runId, options);
7419
+ }
8644
7420
  /**
8645
7421
  * Cancel a running play execution.
8646
7422
  *
@@ -8804,10 +7580,10 @@ var DeeplineClient = class _DeeplineClient {
8804
7580
  const responseRunStatus = isPlayRunPackage(response) ? response.runStatus : isPlayRunPackage(response.package) ? response.package.runStatus : response.runStatus;
8805
7581
  const responseOverview = isPlayRunPackage(response) ? response.overview : isPlayRunPackage(response.package) ? response.package.overview : response.overview;
8806
7582
  const status = normalizePlayStatus(response);
8807
- if (isRecord8(responseRunStatus)) {
7583
+ if (isRecord4(responseRunStatus)) {
8808
7584
  status.runStatus = responseRunStatus;
8809
7585
  }
8810
- if (isRecord8(responseOverview)) {
7586
+ if (isRecord4(responseOverview)) {
8811
7587
  status.overview = responseOverview;
8812
7588
  }
8813
7589
  if (options?.failedLogs !== true || status.status !== "failed") {
@@ -8906,222 +7682,6 @@ var DeeplineClient = class _DeeplineClient {
8906
7682
  );
8907
7683
  return { ...response, runs: response.runs ?? [] };
8908
7684
  }
8909
- /**
8910
- * Observe one run's live events. Uses the Convex Run Snapshot subscription
8911
- * transport first (ADR-0008), then falls back to the canonical SSE stream
8912
- * when the subscription transport or its optional client modules are not
8913
- * available. Pass `fallback: 'none'` to receive
8914
- * {@link RunObserveTransportUnavailableError} instead.
8915
- */
8916
- async *observeRunEvents(runId, options) {
8917
- let yieldedObserveEvent = false;
8918
- try {
8919
- for await (const event of observeRunEvents({
8920
- http: this.http,
8921
- runId,
8922
- signal: options?.signal,
8923
- onNotice: options?.onNotice
8924
- })) {
8925
- yieldedObserveEvent = true;
8926
- yield event;
8927
- }
8928
- } catch (error) {
8929
- if (!(error instanceof RunObserveTransportUnavailableError) || yieldedObserveEvent || options?.fallback === "none") {
8930
- throw error;
8931
- }
8932
- options?.onNotice?.(
8933
- `[observe] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
8934
- );
8935
- yield* this.streamPlayRunEventsUntilTerminal(runId, options);
8936
- }
8937
- }
8938
- async *streamPlayRunEventsUntilTerminal(runId, options) {
8939
- const state = {
8940
- runId,
8941
- status: "running",
8942
- logs: [],
8943
- lastLogSeq: 0,
8944
- latest: null
8945
- };
8946
- let lastEventId;
8947
- let reconnectAttempt = 0;
8948
- for (; ; ) {
8949
- if (options?.signal?.aborted) {
8950
- return;
8951
- }
8952
- const connectedAt = Date.now();
8953
- let sawEvent = false;
8954
- let endedReason = "stream window ended before a terminal event";
8955
- try {
8956
- for await (const event of this.streamPlayRunEvents(runId, {
8957
- mode: "cli",
8958
- signal: options?.signal,
8959
- ...lastEventId ? { lastEventId } : {}
8960
- })) {
8961
- sawEvent = true;
8962
- if (event.cursor?.trim()) {
8963
- lastEventId = event.cursor;
8964
- }
8965
- yield event;
8966
- const status = updatePlayLiveStatusState(state, event);
8967
- if (status && TERMINAL_PLAY_STATUSES.has(status.status)) {
8968
- return;
8969
- }
8970
- }
8971
- } catch (error) {
8972
- if (options?.signal?.aborted) {
8973
- return;
8974
- }
8975
- if (!isTransientPlayStreamError(error)) {
8976
- throw error;
8977
- }
8978
- endedReason = error instanceof Error ? error.message : String(error);
8979
- }
8980
- let refreshed = null;
8981
- try {
8982
- refreshed = await this.getRunStatus(runId);
8983
- } catch (error) {
8984
- if (!isTransientPlayStreamError(error)) {
8985
- throw error;
8986
- }
8987
- }
8988
- if (refreshed && TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
8989
- yield {
8990
- cursor: String(Date.now()),
8991
- streamId: `sse-fallback:${runId}`,
8992
- scope: "play",
8993
- type: "play.run.status",
8994
- at: (/* @__PURE__ */ new Date()).toISOString(),
8995
- payload: refreshed
8996
- };
8997
- return;
8998
- }
8999
- if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
9000
- reconnectAttempt = 0;
9001
- }
9002
- const delayMs = streamReconnectDelayMs(reconnectAttempt);
9003
- reconnectAttempt += 1;
9004
- options?.onNotice?.(
9005
- `[observe] SSE tail window ended before terminal status (${endedReason}); reconnecting to run ${runId}`
9006
- );
9007
- await sleep2(delayMs);
9008
- }
9009
- }
9010
- /**
9011
- * Tail one run through the subscription transport until terminal, then
9012
- * return one durable REST status read (the final Run Response Package).
9013
- */
9014
- async tailRunViaObserveTransport(runId, options) {
9015
- const state = {
9016
- runId,
9017
- status: "running",
9018
- logs: [],
9019
- lastLogSeq: 0,
9020
- latest: null
9021
- };
9022
- for await (const event of this.observeRunEvents(runId, {
9023
- signal: options?.signal,
9024
- onNotice: options?.onNotice,
9025
- fallback: "none"
9026
- })) {
9027
- options?.onEvent?.(event);
9028
- const status = updatePlayLiveStatusState(state, event);
9029
- if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
9030
- continue;
9031
- }
9032
- return await this.getRunStatus(status.runId || runId);
9033
- }
9034
- if (options?.signal?.aborted) {
9035
- throw new DeeplineError("Run observation aborted.", void 0, "ABORTED");
9036
- }
9037
- const refreshed = await this.getRunStatus(runId);
9038
- if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
9039
- return refreshed;
9040
- }
9041
- throw new DeeplineError(
9042
- `Run observation for ${runId} ended before a terminal status.`,
9043
- void 0,
9044
- "PLAY_LIVE_STREAM_ENDED"
9045
- );
9046
- }
9047
- /**
9048
- * Read the canonical run stream until a terminal run status is observed.
9049
- *
9050
- * Tries the Convex Run Snapshot subscription transport first (ADR-0008);
9051
- * when the server cannot serve it (grant endpoint missing/unconfigured or
9052
- * Convex unreachable) it falls back — with one `onNotice` message — to the
9053
- * support-window SSE stream below.
9054
- *
9055
- * Server stream windows are finite: they end cleanly at the function
9056
- * ceiling even while the run keeps executing. A window that ends (cleanly
9057
- * or via transient network error) without a terminal event triggers one
9058
- * durable-status re-check followed by a backed-off reconnect, so long runs
9059
- * tail to completion. Abort via `options.signal` to stop waiting.
9060
- */
9061
- async tailRun(runId, options) {
9062
- try {
9063
- return await this.tailRunViaObserveTransport(runId, options);
9064
- } catch (error) {
9065
- if (!(error instanceof RunObserveTransportUnavailableError)) {
9066
- throw error;
9067
- }
9068
- options?.onNotice?.(
9069
- `[observe] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
9070
- );
9071
- }
9072
- const state = {
9073
- runId,
9074
- status: "running",
9075
- logs: [],
9076
- lastLogSeq: 0,
9077
- latest: null
9078
- };
9079
- let reconnectAttempt = 0;
9080
- for (; ; ) {
9081
- const connectedAt = Date.now();
9082
- let sawEvent = false;
9083
- let terminalRunId = null;
9084
- let endedReason = "stream window ended before a terminal event";
9085
- try {
9086
- for await (const event of this.streamPlayRunEvents(runId, {
9087
- mode: "cli",
9088
- signal: options?.signal
9089
- })) {
9090
- options?.onEvent?.(event);
9091
- sawEvent = true;
9092
- const status = updatePlayLiveStatusState(state, event);
9093
- if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
9094
- continue;
9095
- }
9096
- terminalRunId = status.runId || runId;
9097
- break;
9098
- }
9099
- } catch (error) {
9100
- if (options?.signal?.aborted || !isTransientPlayStreamError(error)) {
9101
- throw error;
9102
- }
9103
- endedReason = error instanceof Error ? error.message : String(error);
9104
- }
9105
- if (terminalRunId) {
9106
- return await this.getRunStatus(terminalRunId);
9107
- }
9108
- const refreshed = await this.getRunStatus(runId);
9109
- if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
9110
- return refreshed;
9111
- }
9112
- if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
9113
- reconnectAttempt = 0;
9114
- }
9115
- const delayMs = streamReconnectDelayMs(reconnectAttempt);
9116
- reconnectAttempt += 1;
9117
- options?.onReconnect?.({
9118
- attempt: reconnectAttempt,
9119
- delayMs,
9120
- reason: endedReason
9121
- });
9122
- await sleep2(delayMs);
9123
- }
9124
- }
9125
7685
  /** Get the exact original input retained for a run. This is intentionally separate from status. */
9126
7686
  async getRunInput(runId) {
9127
7687
  return this.http.get(`/api/v2/runs/${encodeURIComponent(runId)}/input`);
@@ -9912,10 +8472,10 @@ var DeeplineClient = class _DeeplineClient {
9912
8472
  // Plays — high-level orchestration
9913
8473
  // ——————————————————————————————————————————————————————————
9914
8474
  /**
9915
- * Run a play end-to-end: submit, stream until terminal, return result.
8475
+ * Run a play end-to-end: submit, poll progress until terminal, return result.
9916
8476
  *
9917
8477
  * This is the highest-level play execution method. It submits the play,
9918
- * reads the canonical run stream for status updates, and returns a structured
8478
+ * reads the canonical run snapshot for status updates, and returns a structured
9919
8479
  * result with logs and timing. Supports cancellation via `AbortSignal`.
9920
8480
  *
9921
8481
  * @param code - Source string fallback; pass the bundled artifact in `options.artifact`
@@ -9971,6 +8531,7 @@ var DeeplineClient = class _DeeplineClient {
9971
8531
  lastLogSeq: 0,
9972
8532
  latest: null
9973
8533
  };
8534
+ let terminalObserved = null;
9974
8535
  if (options?.signal?.aborted) {
9975
8536
  await this.cancelPlay(workflowId);
9976
8537
  return {
@@ -9981,8 +8542,7 @@ var DeeplineClient = class _DeeplineClient {
9981
8542
  error: "Cancelled by user"
9982
8543
  };
9983
8544
  }
9984
- for await (const event of this.streamPlayRunEvents(workflowId, {
9985
- mode: "cli",
8545
+ for await (const event of this.watchRunEvents(workflowId, {
9986
8546
  signal: options?.signal
9987
8547
  })) {
9988
8548
  if (options?.signal?.aborted) {
@@ -9995,20 +8555,36 @@ var DeeplineClient = class _DeeplineClient {
9995
8555
  error: "Cancelled by user"
9996
8556
  };
9997
8557
  }
8558
+ const previousStatus = state.latest?.status;
9998
8559
  const status = updatePlayLiveStatusState(state, event);
9999
8560
  if (!status) {
10000
8561
  continue;
10001
8562
  }
10002
- options?.onProgress?.(status);
8563
+ if (event.type !== "play.run.status" || status.status !== previousStatus) {
8564
+ options?.onProgress?.(status);
8565
+ }
10003
8566
  if (TERMINAL_PLAY_STATUSES.has(status.status)) {
10004
- const finalStatus = await this.getPlayStatus(
10005
- status.runId || workflowId
10006
- ).catch(() => status);
10007
- return playRunResultFromStatus(finalStatus, start, workflowId);
8567
+ terminalObserved = status;
10008
8568
  }
10009
8569
  }
8570
+ if (options?.signal?.aborted) {
8571
+ await this.cancelPlay(workflowId);
8572
+ return {
8573
+ success: false,
8574
+ runId: workflowId,
8575
+ logs: state.logs,
8576
+ durationMs: Date.now() - start,
8577
+ error: "Cancelled by user"
8578
+ };
8579
+ }
8580
+ if (terminalObserved) {
8581
+ const finalStatus = await this.getPlayStatus(
8582
+ terminalObserved.runId || workflowId
8583
+ ).catch(() => terminalObserved);
8584
+ return playRunResultFromStatus(finalStatus, start, workflowId);
8585
+ }
10010
8586
  throw new DeeplineError(
10011
- `Run stream for ${workflowId} ended before the run reached a terminal state.`,
8587
+ `Run watch for ${workflowId} ended before the run reached a terminal state.`,
10012
8588
  void 0,
10013
8589
  "PLAY_RUN_STREAM_ENDED",
10014
8590
  { runId: workflowId, workflowId }
@@ -12906,9 +11482,13 @@ function recentUsageLines(entries) {
12906
11482
  for (const entry of entries) {
12907
11483
  const op = `${humanize(entry.provider)} ${humanize(entry.operation)}`.trim();
12908
11484
  const roughUsd = Number(entry.rough_usd_cost);
12909
- const usdText = entry.charge_state !== "pending" && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
12910
- const charge = entry.billing_mode === "no_bill" ? "free" : entry.charge_state === "temporary_hold" ? `${entry.credits ?? 0} cr held${usdText}, not final` : entry.charge_state === "pending" ? "final Deepline charge pending" : `${entry.credits ?? 0} cr${usdText}`;
12911
- const state = entry.charge_state === "temporary_hold" ? "temporary hold, final charge pending" : entry.charge_state === "pending" ? "no final charge recorded yet" : entry.status || "completed";
11485
+ const credits = entry.credits !== null && entry.credits !== void 0 && String(entry.credits).trim().length > 0 && Number.isFinite(Number(entry.credits)) ? Number(entry.credits) : null;
11486
+ const temporaryHold = entry.charge_state === "temporary_hold";
11487
+ const pending = entry.charge_state === "pending" || entry.charge_finality === "pending";
11488
+ const unknown = entry.charge_finality === "unknown" || credits === null;
11489
+ const usdText = !pending && !unknown && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
11490
+ const charge = temporaryHold ? `${credits === null ? "unknown amount" : `${credits} cr`} held${usdText}, not final` : pending ? "final Deepline charge pending" : unknown ? "charge unknown" : entry.billing_mode === "no_bill" ? "free" : credits === 0 && (entry.charge_finality === "final" || entry.charge_state === "hold_release") ? "0 cr, final" : `${credits} cr${usdText}`;
11491
+ const state = temporaryHold ? "temporary hold, final charge pending" : pending ? "no final charge recorded yet" : entry.status || "unknown";
12912
11492
  const auditBits = [
12913
11493
  entry.outcome ? `outcome=${entry.outcome}` : null,
12914
11494
  entry.pricing_basis ? `priced_by=${entry.pricing_basis}` : null,
@@ -13105,6 +11685,7 @@ async function handleUsage(options) {
13105
11685
  const recentLines = recentUsageLines(
13106
11686
  Array.isArray(recent.entries) ? recent.entries : []
13107
11687
  );
11688
+ const matchingActivity = typeof recent.total === "number" && Number.isFinite(recent.total) && recent.total >= 0 && typeof recent.total_is_exact === "boolean" ? recent.total_is_exact ? `Matching activity: ${recent.total}` : typeof recent.total_lower_bound === "number" && Number.isFinite(recent.total_lower_bound) && recent.total_lower_bound >= 0 ? `Matching activity: at least ${recent.total_lower_bound}` : `Matching activity: count not exact (reported ${recent.total})` : null;
13108
11689
  const lines = options.requestId ? [`Charge lookup: ${options.requestId}`, ...recentLines] : [
13109
11690
  `Balance: ${payload.balance ?? "(unknown)"}`,
13110
11691
  `Last 30 days usage: ${last30Usage ?? "(unknown)"}`,
@@ -13113,8 +11694,10 @@ async function handleUsage(options) {
13113
11694
  ...options.runId && recent.run_id ? [
13114
11695
  `Run spend: ${(payload.run ?? {}).spent_credits ?? "(unknown)"} Deepline Credits`
13115
11696
  ] : [],
11697
+ ...matchingActivity ? [matchingActivity] : [],
13116
11698
  ...recentLines,
13117
- ...recent.has_more === true || recent.incomplete === true ? ["List truncated \u2014 more recent calls match this query."] : [],
11699
+ ...recent.has_more === true ? ["More activity pages are available."] : [],
11700
+ ...recent.incomplete === true ? ["Recent activity is incomplete; the matching count may be higher."] : [],
13118
11701
  ...nextPage ? [`Next page: ${nextPage}`] : [],
13119
11702
  ...!nextPage && (recent.has_more === true || recent.incomplete === true) ? [
13120
11703
  "No continuation is available for this view. Use deepline billing ledger export all --json for the full ledger."
@@ -13194,7 +11777,13 @@ async function handleLimitOff(options) {
13194
11777
  async function exportLedger(http, outputPath, options) {
13195
11778
  let summary = { row_count: 0, net_delta_credits: 0 };
13196
11779
  let initialized = false;
11780
+ let pageNumber = 0;
11781
+ console.error(`Exporting billing ledger to ${outputPath}`);
13197
11782
  for await (const entries of iterateCursorPages(async (cursor) => {
11783
+ pageNumber += 1;
11784
+ console.error(
11785
+ `Fetching page ${pageNumber}; ${summary.row_count} rows written.`
11786
+ );
13198
11787
  const params = new URLSearchParams({ limit: "5000" });
13199
11788
  if (cursor) params.set("cursor", cursor);
13200
11789
  if (options.sinceAt !== null)
@@ -13221,7 +11810,11 @@ async function exportLedger(http, outputPath, options) {
13221
11810
  const rows = entries.map(ledgerApiEntryToRow);
13222
11811
  await appendFile(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
13223
11812
  summary = summarizeLedgerRows(summary, rows);
11813
+ console.error(
11814
+ `Wrote page ${pageNumber}; ${summary.row_count} rows written.`
11815
+ );
13224
11816
  }
11817
+ console.error(`Export complete: ${summary.row_count} rows written.`);
13225
11818
  return summary;
13226
11819
  }
13227
11820
  async function handleHistory(options) {
@@ -14021,6 +12614,8 @@ function registerBillingCommands(program) {
14021
12614
  `
14022
12615
  Concepts:
14023
12616
  Billing commands show Deepline credits, not raw provider spend.
12617
+ Balance is shared by the workspace; concurrent work changes it. Use a job_id
12618
+ charge lookup to attribute one tool command instead of comparing balances.
14024
12619
  checkout/subscribe/redeem-code can open a browser unless --no-open is set.
14025
12620
 
14026
12621
  Examples:
@@ -14030,6 +12625,10 @@ Examples:
14030
12625
  deepline billing plans --json
14031
12626
  deepline billing subscription status --json
14032
12627
 
12628
+ # Price a tool before execution; look up its exact charge afterward
12629
+ deepline tools describe <tool-id> --pricing-only
12630
+ deepline billing usage --request-id <job_id> --json
12631
+
14033
12632
  # Buy credits or a plan
14034
12633
  deepline billing top-up 1000 --json
14035
12634
  deepline billing checkout --credits 1000 --no-open --json
@@ -14051,6 +12650,8 @@ Examples:
14051
12650
  `
14052
12651
  Notes:
14053
12652
  Read-only. Shows the current Deepline credit balance for the active workspace.
12653
+ The balance includes concurrent workspace activity, so a before/after difference
12654
+ cannot isolate one command. Use billing usage --request-id <job_id> --json.
14054
12655
 
14055
12656
  Examples:
14056
12657
  deepline billing balance
@@ -14063,6 +12664,9 @@ Examples:
14063
12664
  Notes:
14064
12665
  Read-only. Shows last-30-day Deepline credit usage plus a bounded recent-call
14065
12666
  page. Use --limit/--cursor to paginate the recent-call section.
12667
+ For one tool command, use the job_id returned by tools execute, or its next.billing
12668
+ command. Pending charges and temporary holds are not final spend; unknown means
12669
+ final charge evidence is unavailable. Workspace balance changes include other work.
14066
12670
 
14067
12671
  Examples:
14068
12672
  deepline billing usage
@@ -14632,24 +13236,24 @@ function sanitizeCsvProjectionInfo(input2) {
14632
13236
  const rows = input2.rows.map(stripCsvProjectionFields);
14633
13237
  return { rows, columns };
14634
13238
  }
14635
- function isRecord9(value) {
13239
+ function isRecord5(value) {
14636
13240
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
14637
13241
  }
14638
13242
  function isSerializedDataset(value) {
14639
- return isRecord9(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
13243
+ return isRecord5(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
14640
13244
  }
14641
13245
  function isPackagedDatasetOutput(value) {
14642
- return isRecord9(value) && value.kind === "dataset" && isRecord9(value.preview) && Array.isArray(value.preview.rows);
13246
+ return isRecord5(value) && value.kind === "dataset" && isRecord5(value.preview) && Array.isArray(value.preview.rows);
14643
13247
  }
14644
13248
  function hasCurrentTableExport(value) {
14645
- if (!isRecord9(value) || !isRecord9(value.actions)) return false;
13249
+ if (!isRecord5(value) || !isRecord5(value.actions)) return false;
14646
13250
  const exportCsv = value.actions.exportCsv;
14647
- return isRecord9(exportCsv) && isRecord9(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
13251
+ return isRecord5(exportCsv) && isRecord5(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
14648
13252
  }
14649
13253
  function currentTableQueryCommand(value) {
14650
- if (!isRecord9(value) || !isRecord9(value.actions)) return void 0;
13254
+ if (!isRecord5(value) || !isRecord5(value.actions)) return void 0;
14651
13255
  const query = value.actions.queryCurrentTable;
14652
- const command = isRecord9(query) ? query.command : void 0;
13256
+ const command = isRecord5(query) ? query.command : void 0;
14653
13257
  return typeof command === "string" && command.trim() ? command.trim() : void 0;
14654
13258
  }
14655
13259
  function recoveredReturnPaths(value) {
@@ -14668,7 +13272,7 @@ function pathParts(path) {
14668
13272
  function valueAtPath(root, path) {
14669
13273
  let cursor = root;
14670
13274
  for (const part of pathParts(path)) {
14671
- if (!isRecord9(cursor)) {
13275
+ if (!isRecord5(cursor)) {
14672
13276
  return void 0;
14673
13277
  }
14674
13278
  cursor = cursor[part];
@@ -14676,17 +13280,17 @@ function valueAtPath(root, path) {
14676
13280
  return cursor;
14677
13281
  }
14678
13282
  function totalRowsForDataset(result, datasetPath) {
14679
- const metadata = isRecord9(result._metadata) ? result._metadata : null;
13283
+ const metadata = isRecord5(result._metadata) ? result._metadata : null;
14680
13284
  const parentPath = datasetPath.split(".").slice(0, -1).join(".");
14681
13285
  const parent = parentPath ? valueAtPath({ result }, parentPath) : result;
14682
- return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord9(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
13286
+ return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord5(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
14683
13287
  }
14684
13288
  function rowArray(value) {
14685
13289
  if (!Array.isArray(value)) {
14686
13290
  return null;
14687
13291
  }
14688
13292
  const rows = value.filter(
14689
- (row) => isRecord9(row)
13293
+ (row) => isRecord5(row)
14690
13294
  );
14691
13295
  return rows.length === value.length ? rows : null;
14692
13296
  }
@@ -14710,7 +13314,7 @@ function inferColumns(rows) {
14710
13314
  return columns;
14711
13315
  }
14712
13316
  function columnsFromDatasetSummary(summary) {
14713
- if (!isRecord9(summary) || !isRecord9(summary.columnStats)) {
13317
+ if (!isRecord5(summary) || !isRecord5(summary.columnStats)) {
14714
13318
  return [];
14715
13319
  }
14716
13320
  return Object.keys(summary.columnStats).filter((column) => column);
@@ -14767,7 +13371,7 @@ function canonicalRowsInfoFromCandidate(input2) {
14767
13371
  candidate.value.recoveredReturnPaths
14768
13372
  )
14769
13373
  } : {},
14770
- ...isRecord9(candidate.value.exportUnavailable) && (candidate.value.exportUnavailable.reason === "empty_dataset" || candidate.value.exportUnavailable.reason === "shared_table_namespace" || candidate.value.exportUnavailable.reason === "returned_dataset_not_persisted") ? {
13374
+ ...isRecord5(candidate.value.exportUnavailable) && (candidate.value.exportUnavailable.reason === "empty_dataset" || candidate.value.exportUnavailable.reason === "shared_table_namespace" || candidate.value.exportUnavailable.reason === "returned_dataset_not_persisted") ? {
14771
13375
  exportUnavailableReason: candidate.value.exportUnavailable.reason,
14772
13376
  ...typeof candidate.value.exportUnavailable.message === "string" ? {
14773
13377
  exportUnavailableMessage: candidate.value.exportUnavailable.message
@@ -14815,7 +13419,7 @@ function collectDatasetCandidates(input2) {
14815
13419
  });
14816
13420
  return;
14817
13421
  }
14818
- if (!isRecord9(input2.value)) {
13422
+ if (!isRecord5(input2.value)) {
14819
13423
  return;
14820
13424
  }
14821
13425
  for (const [key, child] of Object.entries(input2.value)) {
@@ -14832,12 +13436,12 @@ function collectDatasetCandidates(input2) {
14832
13436
  }
14833
13437
  }
14834
13438
  function collectCanonicalRowsInfos(statusOrResult) {
14835
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
14836
- const result = isRecord9(root?.result) ? root.result : root;
13439
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
13440
+ const result = isRecord5(root?.result) ? root.result : root;
14837
13441
  if (!result) {
14838
13442
  return [];
14839
13443
  }
14840
- const metadata = isRecord9(result._metadata) ? result._metadata : null;
13444
+ const metadata = isRecord5(result._metadata) ? result._metadata : null;
14841
13445
  const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
14842
13446
  const candidates = [
14843
13447
  {
@@ -14861,8 +13465,8 @@ function collectCanonicalRowsInfos(statusOrResult) {
14861
13465
  total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
14862
13466
  }
14863
13467
  ];
14864
- if (isRecord9(result.output)) {
14865
- const outputMetadata = isRecord9(result.output._metadata) ? result.output._metadata : null;
13468
+ if (isRecord5(result.output)) {
13469
+ const outputMetadata = isRecord5(result.output._metadata) ? result.output._metadata : null;
14866
13470
  const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
14867
13471
  candidates.push(
14868
13472
  {
@@ -14889,14 +13493,14 @@ function collectCanonicalRowsInfos(statusOrResult) {
14889
13493
  }
14890
13494
  if (Array.isArray(result.steps)) {
14891
13495
  result.steps.forEach((step, index) => {
14892
- if (!isRecord9(step) || !isRecord9(step.output)) {
13496
+ if (!isRecord5(step) || !isRecord5(step.output)) {
14893
13497
  return;
14894
13498
  }
14895
13499
  const source = typeof step.output.path === "string" ? step.output.path : typeof step.id === "string" ? `steps.${step.id}.output` : `steps.${index}.output`;
14896
13500
  candidates.push({
14897
13501
  source,
14898
13502
  value: step.output,
14899
- total: step.output.rowCount ?? (isRecord9(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord9(step.progress) ? step.progress.total : void 0)
13503
+ total: step.output.rowCount ?? (isRecord5(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord5(step.progress) ? step.progress.total : void 0)
14900
13504
  });
14901
13505
  });
14902
13506
  }
@@ -14924,15 +13528,15 @@ function collectCanonicalRowsInfos(statusOrResult) {
14924
13528
  return infos;
14925
13529
  }
14926
13530
  function collectPackagedDatasetCandidates(statusOrResult) {
14927
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
13531
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
14928
13532
  if (!root) {
14929
13533
  return [];
14930
13534
  }
14931
- const pkg = isRecord9(root.package) ? root.package : root;
13535
+ const pkg = isRecord5(root.package) ? root.package : root;
14932
13536
  const datasets = Array.isArray(pkg.datasets) ? pkg.datasets : [];
14933
13537
  const candidates = [];
14934
13538
  for (const output2 of datasets) {
14935
- if (!isRecord9(output2) || !isPackagedDatasetOutput(output2)) {
13539
+ if (!isRecord5(output2) || !isPackagedDatasetOutput(output2)) {
14936
13540
  continue;
14937
13541
  }
14938
13542
  const source = typeof output2.path === "string" && output2.path.trim() ? output2.path.trim() : null;
@@ -14942,18 +13546,18 @@ function collectPackagedDatasetCandidates(statusOrResult) {
14942
13546
  candidates.push({
14943
13547
  source,
14944
13548
  value: output2,
14945
- total: output2.rowCount ?? (isRecord9(output2.preview) ? output2.preview.totalRows : void 0)
13549
+ total: output2.rowCount ?? (isRecord5(output2.preview) ? output2.preview.totalRows : void 0)
14946
13550
  });
14947
13551
  }
14948
13552
  return candidates;
14949
13553
  }
14950
13554
  function collectPackagedStepDatasetCandidates(statusOrResult) {
14951
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
13555
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
14952
13556
  if (!root) return [];
14953
- const pkg = isRecord9(root.package) ? root.package : root;
13557
+ const pkg = isRecord5(root.package) ? root.package : root;
14954
13558
  const steps = Array.isArray(pkg.steps) ? pkg.steps : [];
14955
13559
  return steps.flatMap((step) => {
14956
- if (!isRecord9(step) || !isPackagedDatasetOutput(step.output)) return [];
13560
+ if (!isRecord5(step) || !isPackagedDatasetOutput(step.output)) return [];
14957
13561
  const source = typeof step.output.path === "string" && step.output.path.trim() ? step.output.path.trim() : null;
14958
13562
  return source ? [
14959
13563
  {
@@ -14965,8 +13569,8 @@ function collectPackagedStepDatasetCandidates(statusOrResult) {
14965
13569
  });
14966
13570
  }
14967
13571
  function collectSerializedDatasetRowsInfos(statusOrResult) {
14968
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
14969
- const result = isRecord9(root?.result) ? root.result : root;
13572
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
13573
+ const result = isRecord5(root?.result) ? root.result : root;
14970
13574
  const candidates = [];
14971
13575
  if (result) {
14972
13576
  collectDatasetCandidates({
@@ -14974,7 +13578,7 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
14974
13578
  path: "result",
14975
13579
  output: candidates
14976
13580
  });
14977
- if (isRecord9(result.output)) {
13581
+ if (isRecord5(result.output)) {
14978
13582
  collectDatasetCandidates({
14979
13583
  value: result.output,
14980
13584
  path: "result",
@@ -15057,13 +13661,13 @@ function summarizeSampleValue(value, depth = 0) {
15057
13661
  if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
15058
13662
  if (depth >= 3) {
15059
13663
  if (Array.isArray(parsed)) return [];
15060
- if (isRecord9(parsed)) return {};
13664
+ if (isRecord5(parsed)) return {};
15061
13665
  return compactScalar(parsed);
15062
13666
  }
15063
13667
  if (Array.isArray(parsed)) {
15064
13668
  return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
15065
13669
  }
15066
- if (isRecord9(parsed)) {
13670
+ if (isRecord5(parsed)) {
15067
13671
  const out = {};
15068
13672
  for (const [key, nested] of Object.entries(parsed)) {
15069
13673
  if (["__dl", "meta", "metadata"].includes(key)) {
@@ -15094,7 +13698,7 @@ function compactCell(value) {
15094
13698
  }
15095
13699
  return `[${parsed.length} items]`;
15096
13700
  }
15097
- if (isRecord9(parsed)) {
13701
+ if (isRecord5(parsed)) {
15098
13702
  for (const key of ["matched_result", "output"]) {
15099
13703
  if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
15100
13704
  return compactCell(parsed[key]);
@@ -16528,17 +15132,17 @@ function parsePositiveInteger2(value, flagName) {
16528
15132
  }
16529
15133
  return parsed;
16530
15134
  }
16531
- function isRecord10(value) {
15135
+ function isRecord6(value) {
16532
15136
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
16533
15137
  }
16534
15138
  function stringValue(value) {
16535
15139
  return typeof value === "string" ? value.trim() : "";
16536
15140
  }
16537
15141
  function extractionEntries(value) {
16538
- if (Array.isArray(value)) return value.filter(isRecord10);
16539
- if (!isRecord10(value)) return [];
15142
+ if (Array.isArray(value)) return value.filter(isRecord6);
15143
+ if (!isRecord6(value)) return [];
16540
15144
  return Object.entries(value).map(
16541
- ([name, entry]) => isRecord10(entry) ? { name, ...entry } : { name }
15145
+ ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
16542
15146
  );
16543
15147
  }
16544
15148
  var PlayBootstrapError = class extends Error {
@@ -17099,7 +15703,7 @@ function readCsvSampleRows(sample) {
17099
15703
  relax_column_count: true,
17100
15704
  trim: true
17101
15705
  });
17102
- return Array.isArray(parsedRows) ? parsedRows.filter(isRecord10) : [];
15706
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord6) : [];
17103
15707
  }
17104
15708
  function readSourceCsvColumnSpecs(csvPath) {
17105
15709
  const sample = readCsvSample(csvPath);
@@ -17132,16 +15736,16 @@ function packagedCsvPathForPlay(csvPath) {
17132
15736
  return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
17133
15737
  }
17134
15738
  function getterNamesFromTool(tool, kind) {
17135
- const usageGuidance = isRecord10(tool?.usageGuidance) ? tool.usageGuidance : {};
17136
- const resultGuidance = isRecord10(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord10(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
15739
+ const usageGuidance = isRecord6(tool?.usageGuidance) ? tool.usageGuidance : {};
15740
+ const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
17137
15741
  const key = kind === "list" ? "extractedLists" : "extractedValues";
17138
15742
  const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
17139
15743
  return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
17140
15744
  }
17141
15745
  function targetGettersFromTool(tool) {
17142
- const record3 = isRecord10(tool) ? tool : {};
15746
+ const record3 = isRecord6(tool) ? tool : {};
17143
15747
  const raw = record3.targetGetters ?? record3.target_getters;
17144
- if (!isRecord10(raw)) return {};
15748
+ if (!isRecord6(raw)) return {};
17145
15749
  const entries = [];
17146
15750
  for (const [target, value] of Object.entries(raw)) {
17147
15751
  const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
@@ -17162,10 +15766,10 @@ function listRowCandidateKeysFromTool(tool) {
17162
15766
  return [...keys].sort();
17163
15767
  }
17164
15768
  function inputPropertyNames(schema) {
17165
- if (!isRecord10(schema)) return [];
17166
- if (isRecord10(schema.properties)) return Object.keys(schema.properties);
15769
+ if (!isRecord6(schema)) return [];
15770
+ if (isRecord6(schema.properties)) return Object.keys(schema.properties);
17167
15771
  if (Array.isArray(schema.fields)) {
17168
- return schema.fields.filter(isRecord10).map((field) => stringValue(field.name)).filter(Boolean);
15772
+ return schema.fields.filter(isRecord6).map((field) => stringValue(field.name)).filter(Boolean);
17169
15773
  }
17170
15774
  return [];
17171
15775
  }
@@ -17179,7 +15783,7 @@ function schemaFieldDetails(schema) {
17179
15783
  return { required, optional };
17180
15784
  }
17181
15785
  function jsonSchemaTypeExpression(schema) {
17182
- if (!isRecord10(schema)) return "unknown";
15786
+ if (!isRecord6(schema)) return "unknown";
17183
15787
  const type = schema.type;
17184
15788
  if (Array.isArray(type)) {
17185
15789
  return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
@@ -17209,7 +15813,7 @@ function jsonSchemaTypeExpression(schema) {
17209
15813
  }
17210
15814
  }
17211
15815
  function objectPropertySchema(schema, property) {
17212
- return isRecord10(schema) && isRecord10(schema.properties) ? schema.properties[property] : null;
15816
+ return isRecord6(schema) && isRecord6(schema.properties) ? schema.properties[property] : null;
17213
15817
  }
17214
15818
  function playOutputHasField(schema, field) {
17215
15819
  return objectPropertySchema(schema, field) != null;
@@ -17385,14 +15989,14 @@ ${indent2.slice(2)}}`;
17385
15989
  }
17386
15990
  function requiredPlayInputFields(play) {
17387
15991
  const schema = play?.inputSchema;
17388
- if (!isRecord10(schema)) return [];
15992
+ if (!isRecord6(schema)) return [];
17389
15993
  if (Array.isArray(schema.required)) {
17390
15994
  return schema.required.filter(
17391
15995
  (value) => typeof value === "string"
17392
15996
  );
17393
15997
  }
17394
15998
  if (Array.isArray(schema.fields)) {
17395
- return schema.fields.filter(isRecord10).filter(
15999
+ return schema.fields.filter(isRecord6).filter(
17396
16000
  (field) => field.required === true && typeof field.name === "string"
17397
16001
  ).map((field) => String(field.name));
17398
16002
  }
@@ -17573,7 +16177,7 @@ function validateBootstrapRoutes(input2) {
17573
16177
  }
17574
16178
  }
17575
16179
  function staticPipelineSubsteps(pipeline) {
17576
- if (!isRecord10(pipeline)) return [];
16180
+ if (!isRecord6(pipeline)) return [];
17577
16181
  return [
17578
16182
  ...extractionEntries(pipeline.stages),
17579
16183
  ...extractionEntries(pipeline.substeps)
@@ -17581,7 +16185,7 @@ function staticPipelineSubsteps(pipeline) {
17581
16185
  }
17582
16186
  function playUsesMapBackedRuntime(play) {
17583
16187
  const pipeline = play?.staticPipeline;
17584
- if (!isRecord10(pipeline)) return false;
16188
+ if (!isRecord6(pipeline)) return false;
17585
16189
  if (stringValue(pipeline.tableNamespace)) return true;
17586
16190
  return staticPipelineSubsteps(pipeline).some((substep) => {
17587
16191
  if (stringValue(substep.type) === "map") return true;
@@ -17590,7 +16194,7 @@ function playUsesMapBackedRuntime(play) {
17590
16194
  aliases: [],
17591
16195
  runCommand: "",
17592
16196
  examples: [],
17593
- staticPipeline: isRecord10(substep.pipeline) ? substep.pipeline : null
16197
+ staticPipeline: isRecord6(substep.pipeline) ? substep.pipeline : null
17594
16198
  });
17595
16199
  });
17596
16200
  }
@@ -22938,35 +21542,35 @@ async function runDeployment(params, hooks) {
22938
21542
  } catch (error) {
22939
21543
  if (revokedFinalStatus(error)) throw error;
22940
21544
  const body = error instanceof DeployApiError ? error.body : null;
22941
- const errorText2 = body?.error ?? (error instanceof Error ? error.message : String(error));
22942
- if (/PLAY_DEPLOYMENT_NOT_ACTIVE/.test(errorText2)) {
21545
+ const errorText = body?.error ?? (error instanceof Error ? error.message : String(error));
21546
+ if (/PLAY_DEPLOYMENT_NOT_ACTIVE/.test(errorText)) {
22943
21547
  console.info("[deploy-worker] cancelled at promote", {
22944
21548
  deploymentId: params.deploymentId
22945
21549
  });
22946
21550
  return { finalStatus: "cancelled", outcomes: [] };
22947
21551
  }
22948
- if (/PLAY_DEPLOYMENT_STALE/.test(errorText2)) {
21552
+ if (/PLAY_DEPLOYMENT_STALE/.test(errorText)) {
22949
21553
  console.info("[deploy-worker] superseded at promote", {
22950
21554
  deploymentId: params.deploymentId
22951
21555
  });
22952
21556
  await setStatus({
22953
21557
  status: "superseded",
22954
- error: errorText2.slice(0, 2e3),
21558
+ error: errorText.slice(0, 2e3),
22955
21559
  buildSeconds: buildSeconds()
22956
21560
  });
22957
21561
  return { finalStatus: "superseded", outcomes: [] };
22958
21562
  }
22959
21563
  return await failWithCheck({
22960
21564
  title: "Deploy failed during promotion",
22961
- summary: errorText2,
22962
- error: errorText2,
21565
+ summary: errorText,
21566
+ error: errorText,
22963
21567
  outcomes: [
22964
21568
  ...outcomes,
22965
21569
  ...(body?.outcomes ?? toPromote).map((entry) => ({
22966
21570
  name: entry.name,
22967
21571
  file: playByName.get(entry.name)?.file ?? entry.name,
22968
21572
  status: "failed",
22969
- error: ("error" in entry ? entry.error : void 0) ?? errorText2
21573
+ error: ("error" in entry ? entry.error : void 0) ?? errorText
22970
21574
  }))
22971
21575
  ]
22972
21576
  });
@@ -24841,7 +23445,7 @@ function playStatusErrorText(status) {
24841
23445
  function isRetryablePendingStartFailure(status) {
24842
23446
  if (status.status !== "failed") return false;
24843
23447
  if (status.runId && status.runId !== "pending") return false;
24844
- return isTransientPlayStreamError(new Error(playStatusErrorText(status)));
23448
+ return isTransientPlayRunReadError(new Error(playStatusErrorText(status)));
24845
23449
  }
24846
23450
  function pendingStartFailureStatus(input2) {
24847
23451
  const message = input2.error instanceof Error ? input2.error.message : String(input2.error);
@@ -25376,7 +23980,7 @@ function assertPlayWaitNotTimedOut(input2) {
25376
23980
  if (input2.waitTimeoutMs !== null && Date.now() - input2.startedAt >= input2.waitTimeoutMs) {
25377
23981
  const hasRealRunId = input2.workflowId.length > 0 && input2.workflowId !== "pending";
25378
23982
  const phaseSuffix = input2.lastPhase && input2.lastPhase.trim() ? ` (last observed phase: ${input2.lastPhase.trim()})` : "";
25379
- const tailHint = hasRealRunId ? ` The CLI stopped waiting; it did not cancel the run. Check its current state with 'deepline runs get ${input2.workflowId} --json', or reattach with 'deepline runs tail ${input2.workflowId} --json'. Do not start another run just to retrieve results.` : ` No run id was received, so acceptance is unknown. Check recent runs with 'deepline runs list --play <play-name> --json' before submitting again.`;
23983
+ const tailHint = hasRealRunId ? ` The CLI stopped waiting; it did not cancel the run. Check its current state with 'deepline runs get ${input2.workflowId} --json', or reattach with 'deepline runs watch ${input2.workflowId} --json'. Do not start another run just to retrieve results.` : ` No run id was received, so acceptance is unknown. Check recent runs with 'deepline runs list --play <play-name> --json' before submitting again.`;
25380
23984
  throw new DeeplineError(
25381
23985
  `Timed out waiting for play ${hasRealRunId ? input2.workflowId : "<no run id>"} after ${Math.ceil(input2.waitTimeoutMs / 1e3)}s${phaseSuffix}.${tailHint}`,
25382
23986
  void 0,
@@ -25389,63 +23993,54 @@ function assertPlayWaitNotTimedOut(input2) {
25389
23993
  );
25390
23994
  }
25391
23995
  }
25392
- var PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS = 15e3;
23996
+ var RUN_WATCH_RETRY_INTERVAL_MS = 2e3;
25393
23997
  function isAdmittedRunVisibilityDelay(error) {
25394
23998
  return error instanceof DeeplineError && error.statusCode === 404 && error.message.trim() === "Workflow run not found.";
25395
23999
  }
25396
- async function waitForPlayCompletionByStream(input2) {
24000
+ async function waitForPlayCompletionByWatch(input2) {
25397
24001
  let lastPhase = null;
25398
- let reconnectAttempt = 0;
25399
- const durableStatusProbeIntervalMs = input2.durableStatusProbeIntervalMs ?? PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS;
25400
- let nextDurableProbeAt = Date.now() + durableStatusProbeIntervalMs;
25401
- let durableStatusProbe = null;
25402
24002
  let admissionConfirmed = false;
24003
+ let visibilityNoticeSent = false;
24004
+ let terminalStatusRead = null;
24005
+ const controller = new AbortController();
24006
+ let timedOut = false;
24007
+ const remainingWaitMs = () => input2.waitTimeoutMs === null ? null : input2.waitTimeoutMs - (Date.now() - input2.startedAt);
24008
+ const remaining = remainingWaitMs();
24009
+ const timeout = remaining === null ? null : setTimeout(
24010
+ () => {
24011
+ timedOut = true;
24012
+ controller.abort();
24013
+ },
24014
+ Math.max(1, remaining)
24015
+ );
25403
24016
  const confirmAdmission = async () => {
25404
24017
  if (admissionConfirmed) return;
25405
24018
  admissionConfirmed = true;
25406
24019
  await input2.onRunAdmitted?.(input2.workflowId);
25407
24020
  };
25408
24021
  const withDashboardUrl = (status) => input2.dashboardUrl ? { ...status, dashboardUrl: input2.dashboardUrl } : status;
25409
- const remainingWaitMs = () => input2.waitTimeoutMs === null ? null : input2.waitTimeoutMs - (Date.now() - input2.startedAt);
25410
24022
  const fetchTerminalStatus = async () => {
25411
- if (durableStatusProbe) return durableStatusProbe;
25412
- const probe = (async () => {
25413
- let refreshed;
25414
- try {
25415
- refreshed = await input2.client.getPlayStatus(input2.workflowId, {
25416
- billing: false
25417
- });
25418
- } catch (error) {
25419
- if (isTransientPlayStreamError(error) || isAdmittedRunVisibilityDelay(error)) {
25420
- return null;
25421
- }
25422
- throw error;
25423
- }
25424
- if (refreshed.runId === input2.workflowId && statusProvesPlayRunExecution(refreshed.status)) {
25425
- await confirmAdmission();
25426
- }
25427
- return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? withDashboardUrl(refreshed) : null;
25428
- })();
25429
- durableStatusProbe = probe;
24023
+ let refreshed;
25430
24024
  try {
25431
- return await probe;
25432
- } finally {
25433
- if (durableStatusProbe === probe) durableStatusProbe = null;
24025
+ refreshed = await input2.client.getPlayStatus(input2.workflowId, {
24026
+ billing: false
24027
+ });
24028
+ } catch (error) {
24029
+ if (isTransientPlayRunReadError(error) || isAdmittedRunVisibilityDelay(error)) {
24030
+ return null;
24031
+ }
24032
+ throw error;
24033
+ }
24034
+ if (refreshed.runId === input2.workflowId && statusProvesPlayRunExecution(refreshed.status)) {
24035
+ await confirmAdmission();
25434
24036
  }
24037
+ return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? withDashboardUrl(refreshed) : null;
25435
24038
  };
25436
- const handleLiveEvent = async (event, probeDurableStatus) => {
24039
+ const handleLiveEvent = async (event) => {
25437
24040
  assertPlayWaitNotTimedOut({ ...input2, lastPhase });
25438
24041
  if (getRunIdFromLiveEvent(event) === input2.workflowId && (eventConfirmsPlayRunLaunch(event) || eventProvesPlayRunExecution(event))) {
25439
24042
  await confirmAdmission();
25440
24043
  }
25441
- const now = Date.now();
25442
- if (now >= nextDurableProbeAt) {
25443
- nextDurableProbeAt = now + durableStatusProbeIntervalMs;
25444
- const durableTerminal = await probeDurableStatus();
25445
- if (durableTerminal) {
25446
- return durableTerminal;
25447
- }
25448
- }
25449
24044
  const phase = describeLiveEventPhase(event);
25450
24045
  if (phase) {
25451
24046
  lastPhase = phase;
@@ -25496,144 +24091,57 @@ async function waitForPlayCompletionByStream(input2) {
25496
24091
  }
25497
24092
  }
25498
24093
  const finalStatus = getFinalStatusFromLiveEvent(event);
25499
- if (finalStatus) {
24094
+ if (event.type === "play.run.final_status" && finalStatus) {
25500
24095
  return withDashboardUrl(finalStatus);
25501
24096
  }
25502
24097
  const status = getStatusFromLiveEvent(event);
25503
24098
  if (status && TERMINAL_PLAY_STATUSES2.has(status)) {
25504
- const refreshedStatus = await probeDurableStatus();
25505
- if (refreshedStatus) return refreshedStatus;
24099
+ terminalStatusRead ??= fetchTerminalStatus();
24100
+ return await terminalStatusRead;
25506
24101
  }
25507
24102
  return null;
25508
24103
  };
25509
- const streamOneWindow = async () => {
25510
- const controller = new AbortController();
25511
- let timedOut = false;
25512
- let sawEvent = false;
25513
- let durableTerminal = null;
25514
- let durableProbeError = null;
25515
- let durableProbeTimer = null;
25516
- const remaining = remainingWaitMs();
25517
- const timeout = remaining === null ? null : setTimeout(
25518
- () => {
25519
- timedOut = true;
25520
- controller.abort();
25521
- },
25522
- Math.max(1, remaining)
25523
- );
25524
- const scheduleDurableStatusProbe = () => {
25525
- durableProbeTimer = setTimeout(() => {
25526
- durableProbeTimer = null;
25527
- if (controller.signal.aborted) return;
25528
- nextDurableProbeAt = Date.now() + durableStatusProbeIntervalMs;
25529
- void fetchTerminalStatus().then((status) => {
25530
- if (controller.signal.aborted) return;
25531
- if (status) {
25532
- durableTerminal = status;
25533
- controller.abort();
25534
- return;
25535
- }
25536
- scheduleDurableStatusProbe();
25537
- }).catch((error) => {
25538
- if (controller.signal.aborted) return;
25539
- durableProbeError = error;
25540
- controller.abort();
25541
- });
25542
- }, durableStatusProbeIntervalMs);
25543
- };
25544
- try {
25545
- scheduleDurableStatusProbe();
25546
- for await (const event of input2.client.streamPlayRunEvents(
25547
- input2.workflowId,
25548
- { signal: controller.signal }
25549
- )) {
25550
- sawEvent = true;
25551
- if (durableTerminal) {
25552
- return { kind: "terminal", status: durableTerminal };
24104
+ try {
24105
+ for (; ; ) {
24106
+ try {
24107
+ let terminalFromWatch = null;
24108
+ for await (const event of input2.client.watchRunEvents(
24109
+ input2.workflowId,
24110
+ { signal: controller.signal }
24111
+ )) {
24112
+ const terminal3 = await handleLiveEvent(event);
24113
+ if (terminal3) terminalFromWatch = terminal3;
25553
24114
  }
25554
- const terminal = await handleLiveEvent(event, fetchTerminalStatus);
25555
- if (terminal) {
25556
- return { kind: "terminal", status: terminal };
24115
+ if (terminalFromWatch) return terminalFromWatch;
24116
+ } catch (error) {
24117
+ if (timedOut || controller.signal.aborted) break;
24118
+ if (!isAdmittedRunVisibilityDelay(error)) throw error;
24119
+ if (!visibilityNoticeSent && !input2.jsonOutput) {
24120
+ input2.progress.writeLine(
24121
+ `[play watch] run is accepted and waiting for its snapshot; checking again in ${RUN_WATCH_RETRY_INTERVAL_MS / 1e3}s`
24122
+ );
24123
+ visibilityNoticeSent = true;
25557
24124
  }
25558
24125
  }
25559
- } catch (error) {
25560
- if (timedOut) {
25561
- return { kind: "timed_out", sawEvent };
25562
- }
25563
- if (durableTerminal) {
25564
- return { kind: "terminal", status: durableTerminal };
25565
- }
25566
- if (durableProbeError) {
25567
- throw durableProbeError;
25568
- }
25569
- if (!isTransientPlayStreamError(error) && !isAdmittedRunVisibilityDelay(error)) {
25570
- throw error;
25571
- }
25572
- return {
25573
- kind: "ended",
25574
- sawEvent,
25575
- reason: error instanceof Error ? error.message : String(error)
25576
- };
25577
- } finally {
25578
- if (timeout) {
25579
- clearTimeout(timeout);
25580
- }
25581
- if (durableProbeTimer) {
25582
- clearTimeout(durableProbeTimer);
25583
- }
25584
- controller.abort();
25585
- }
25586
- if (timedOut) {
25587
- return { kind: "timed_out", sawEvent };
25588
- }
25589
- if (durableTerminal) {
25590
- return { kind: "terminal", status: durableTerminal };
25591
- }
25592
- if (durableProbeError) {
25593
- throw durableProbeError;
25594
- }
25595
- return {
25596
- kind: "ended",
25597
- sawEvent,
25598
- reason: "stream window ended before a terminal event"
25599
- };
25600
- };
25601
- for (; ; ) {
25602
- const connectedAt = Date.now();
25603
- const window = await streamOneWindow();
25604
- if (window.kind === "terminal") {
25605
- return window.status;
24126
+ const terminal2 = await fetchTerminalStatus();
24127
+ if (terminal2) return terminal2;
24128
+ assertPlayWaitNotTimedOut({ ...input2, lastPhase });
24129
+ const nextWait = remainingWaitMs();
24130
+ await sleep5(
24131
+ nextWait === null ? RUN_WATCH_RETRY_INTERVAL_MS : Math.min(RUN_WATCH_RETRY_INTERVAL_MS, Math.max(1, nextWait))
24132
+ );
25606
24133
  }
25607
24134
  const terminal = await fetchTerminalStatus();
25608
- if (terminal) {
25609
- return terminal;
25610
- }
24135
+ if (terminal) return terminal;
25611
24136
  assertPlayWaitNotTimedOut({ ...input2, lastPhase });
25612
- if (window.sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
25613
- reconnectAttempt = 0;
25614
- }
25615
- const delayMs = streamReconnectDelayMs(reconnectAttempt);
25616
- reconnectAttempt += 1;
25617
- const reason = window.kind === "ended" ? window.reason : "wait timeout raced the stream";
25618
- if (!input2.jsonOutput) {
25619
- input2.progress.writeLine(
25620
- `[play watch] stream ended without a terminal status; reconnecting to run ${input2.workflowId} (${reason})`
25621
- );
25622
- }
25623
- recordCliTrace({
25624
- phase: "cli.play_tail_stream_reconnect",
25625
- ms: Date.now() - input2.startedAt,
25626
- ok: true,
25627
- playName: input2.playName,
25628
- workflowId: input2.workflowId,
25629
- attempt: reconnectAttempt,
25630
- delayMs,
25631
- reason
25632
- });
25633
- const remainingBeforeSleep = remainingWaitMs();
25634
- await sleep5(
25635
- remainingBeforeSleep === null ? delayMs : Math.min(delayMs, Math.max(1, remainingBeforeSleep))
24137
+ throw new DeeplineError(
24138
+ `Run watch for ${input2.workflowId} ended before a terminal status.`,
24139
+ void 0,
24140
+ "PLAY_WATCH_ENDED"
25636
24141
  );
24142
+ } finally {
24143
+ if (timeout) clearTimeout(timeout);
24144
+ controller.abort();
25637
24145
  }
25638
24146
  }
25639
24147
  async function startAndWaitForPlayCompletionByStream(input2) {
@@ -25710,7 +24218,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25710
24218
  billing: false
25711
24219
  });
25712
24220
  } catch (error) {
25713
- if (isTransientPlayStreamError(error)) {
24221
+ if (isTransientPlayRunReadError(error)) {
25714
24222
  return null;
25715
24223
  }
25716
24224
  throw error;
@@ -25881,7 +24389,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25881
24389
  firstRunIdMs,
25882
24390
  lastPhase
25883
24391
  });
25884
- return waitForPlayCompletionByStream({
24392
+ return waitForPlayCompletionByWatch({
25885
24393
  client: input2.client,
25886
24394
  playName: input2.playName,
25887
24395
  workflowId: lastKnownWorkflowId,
@@ -25920,7 +24428,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25920
24428
  lastPhase
25921
24429
  });
25922
24430
  }
25923
- if (lastKnownWorkflowId && isTransientPlayStreamError(error)) {
24431
+ if (lastKnownWorkflowId && isTransientPlayRunReadError(error)) {
25924
24432
  if (timeout) {
25925
24433
  clearTimeout(timeout);
25926
24434
  }
@@ -25942,7 +24450,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25942
24450
  lastPhase,
25943
24451
  reason
25944
24452
  });
25945
- return waitForPlayCompletionByStream({
24453
+ return waitForPlayCompletionByWatch({
25946
24454
  client: input2.client,
25947
24455
  playName: input2.playName,
25948
24456
  workflowId: lastKnownWorkflowId,
@@ -25956,7 +24464,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25956
24464
  onRunAdmitted: confirmAdmission
25957
24465
  });
25958
24466
  }
25959
- if (!lastKnownWorkflowId && isTransientPlayStreamError(error)) {
24467
+ if (!lastKnownWorkflowId && isTransientPlayRunReadError(error)) {
25960
24468
  recordCliTrace({
25961
24469
  phase: "cli.play_start_stream_transient_failure",
25962
24470
  ms: Date.now() - startedAt,
@@ -25996,7 +24504,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25996
24504
  lastPhase,
25997
24505
  reason: "stream ended before terminal event"
25998
24506
  });
25999
- return waitForPlayCompletionByStream({
24507
+ return waitForPlayCompletionByWatch({
26000
24508
  client: input2.client,
26001
24509
  playName: input2.playName,
26002
24510
  workflowId: lastKnownWorkflowId,
@@ -26013,7 +24521,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
26013
24521
  const phaseSuffix = lastPhase && lastPhase.trim() ? ` (last observed phase: ${lastPhase.trim()})` : "";
26014
24522
  const idSuffix = lastKnownWorkflowId ? ` runId=${lastKnownWorkflowId}` : "";
26015
24523
  throw new DeeplineError(
26016
- `Play start stream ended before a terminal status was observed${idSuffix}${phaseSuffix}. If a run id was printed, inspect it with 'deepline runs get <run-id> --full --json' or continue watching with 'deepline runs tail <run-id>'.`,
24524
+ `Play start request ended before terminal status was observed${idSuffix}${phaseSuffix}. If a run id was printed, inspect it with 'deepline runs get <run-id> --full --json' or continue watching with 'deepline runs watch <run-id>'.`,
26017
24525
  void 0,
26018
24526
  "PLAY_START_STREAM_ENDED",
26019
24527
  {
@@ -28126,7 +26634,7 @@ function extractPlayValidationErrors(value) {
28126
26634
  if (value instanceof DeeplineError) {
28127
26635
  return extractPlayValidationErrors(value.details);
28128
26636
  }
28129
- if (!isRecord11(value)) {
26637
+ if (!isRecord7(value)) {
28130
26638
  return [];
28131
26639
  }
28132
26640
  const directErrors = stringArrayField(value, "errors");
@@ -28522,7 +27030,7 @@ function parsePlayRunOptions(args) {
28522
27030
  }
28523
27031
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
28524
27032
  throw new Error(
28525
- `${arg} was removed. --watch uses the canonical run stream directly.`
27033
+ `${arg} was removed. --watch polls the canonical run snapshot.`
28526
27034
  );
28527
27035
  }
28528
27036
  if ((arg === "--tail-timeout-ms" || arg === "--timeout-ms") && args[index + 1]) {
@@ -28790,7 +27298,7 @@ function formatPlayRuntimeLimit(runtimeLimit) {
28790
27298
  if (seconds % 60 === 0) return `${seconds / 60} min`;
28791
27299
  return `${seconds} sec`;
28792
27300
  }
28793
- function isRecord11(value) {
27301
+ function isRecord7(value) {
28794
27302
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
28795
27303
  }
28796
27304
  function stringValue3(value) {
@@ -28800,14 +27308,14 @@ function asArray(value) {
28800
27308
  return Array.isArray(value) ? value : [];
28801
27309
  }
28802
27310
  function extractionEntries2(value) {
28803
- if (Array.isArray(value)) return value.filter(isRecord11);
28804
- if (!isRecord11(value)) return [];
27311
+ if (Array.isArray(value)) return value.filter(isRecord7);
27312
+ if (!isRecord7(value)) return [];
28805
27313
  return Object.entries(value).map(
28806
- ([name, entry]) => isRecord11(entry) ? { name, ...entry } : { name }
27314
+ ([name, entry]) => isRecord7(entry) ? { name, ...entry } : { name }
28807
27315
  );
28808
27316
  }
28809
27317
  function firstRawPath(entry) {
28810
- const details = isRecord11(entry.details) ? entry.details : {};
27318
+ const details = isRecord7(entry.details) ? entry.details : {};
28811
27319
  const paths = [
28812
27320
  ...asArray(details.rawToolOutputPaths),
28813
27321
  ...asArray(details.raw_tool_output_paths),
@@ -28825,12 +27333,12 @@ function checkHintRawPath(value) {
28825
27333
  function collectStaticPipelineToolIds(staticPipeline) {
28826
27334
  const seen = /* @__PURE__ */ new Set();
28827
27335
  const visitPipeline = (pipeline) => {
28828
- if (!isRecord11(pipeline)) return;
27336
+ if (!isRecord7(pipeline)) return;
28829
27337
  for (const step of [
28830
27338
  ...asArray(pipeline.stages),
28831
27339
  ...asArray(pipeline.substeps)
28832
27340
  ]) {
28833
- if (!isRecord11(step)) continue;
27341
+ if (!isRecord7(step)) continue;
28834
27342
  if (step.type === "tool") {
28835
27343
  const toolId = stringValue3(step.toolId) || stringValue3(step.tool);
28836
27344
  if (toolId) seen.add(toolId);
@@ -28844,9 +27352,9 @@ function collectStaticPipelineToolIds(staticPipeline) {
28844
27352
  return [...seen].sort();
28845
27353
  }
28846
27354
  function toolGetterHintFromMetadata(toolId, tool) {
28847
- const usageGuidance = isRecord11(tool.usageGuidance) ? tool.usageGuidance : {};
28848
- const resultGuidance = isRecord11(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord11(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
28849
- const toolResponse = isRecord11(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord11(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
27355
+ const usageGuidance = isRecord7(tool.usageGuidance) ? tool.usageGuidance : {};
27356
+ const resultGuidance = isRecord7(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord7(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
27357
+ const toolResponse = isRecord7(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord7(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
28850
27358
  const lists = extractionEntries2(
28851
27359
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
28852
27360
  ).map((entry) => ({
@@ -29209,7 +27717,7 @@ function artifactForProductionCompatibilityCheck(artifact) {
29209
27717
  "DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
29210
27718
  );
29211
27719
  }
29212
- const compatibility = isRecord11(artifact.compatibility) ? artifact.compatibility : {};
27720
+ const compatibility = isRecord7(artifact.compatibility) ? artifact.compatibility : {};
29213
27721
  return {
29214
27722
  ...artifact,
29215
27723
  compatibility: {
@@ -30014,7 +28522,23 @@ async function handleRunsList(args) {
30014
28522
  }
30015
28523
  }
30016
28524
  if (!playName && !statusFilter) {
30017
- console.error(usage);
28525
+ const message = "runs list requires --play or --status.";
28526
+ const next = {
28527
+ discover: "deepline plays list --json",
28528
+ running: "deepline runs list --status running --json"
28529
+ };
28530
+ console.error(
28531
+ `${message}
28532
+ ${usage}
28533
+ Discover Plays: ${next.discover}
28534
+ Active runs: ${next.running}`
28535
+ );
28536
+ if (argsWantJson(args)) {
28537
+ printCommandEnvelope(
28538
+ { ok: false, exitCode: 1, code: "RUN_FILTER_REQUIRED", message, next },
28539
+ { json: true }
28540
+ );
28541
+ }
30018
28542
  return 1;
30019
28543
  }
30020
28544
  if ((offset ?? 0) > 0 && !playName) {
@@ -30093,7 +28617,7 @@ async function handleRunsList(args) {
30093
28617
  return 0;
30094
28618
  }
30095
28619
  async function handleRunTail(args) {
30096
- const usage = "Usage: deepline runs tail <run-id> [--json | --jsonl] [--compact] [--log-level debug|info|warn|error]";
28620
+ const usage = "Usage: deepline runs watch <run-id> [--json | --jsonl] [--compact] [--log-level debug|info|warn|error]";
30097
28621
  let runId;
30098
28622
  try {
30099
28623
  runId = parseRunIdPositional(args, usage);
@@ -30108,7 +28632,7 @@ async function handleRunTail(args) {
30108
28632
  const arg = args[index];
30109
28633
  if (arg === "--cursor") {
30110
28634
  console.error(
30111
- "--cursor was removed. deepline runs tail reads the canonical run stream."
28635
+ "--cursor was removed. deepline runs watch polls the canonical run snapshot."
30112
28636
  );
30113
28637
  return 1;
30114
28638
  }
@@ -30134,7 +28658,7 @@ async function handleRunTail(args) {
30134
28658
  continue;
30135
28659
  }
30136
28660
  if (arg.startsWith("--") && arg !== "--json" && arg !== "--jsonl" && arg !== "--compact") {
30137
- console.error(`${arg} is not supported by deepline runs tail.`);
28661
+ console.error(`${arg} is not supported by deepline runs watch.`);
30138
28662
  return 1;
30139
28663
  }
30140
28664
  }
@@ -30170,7 +28694,7 @@ async function handleRunTail(args) {
30170
28694
  verbose: debug,
30171
28695
  logLevel
30172
28696
  };
30173
- const status = await client2.runs.tail(runId, {
28697
+ const status = await client2.runs.watch(runId, {
30174
28698
  onEvent: jsonLines ? (event) => {
30175
28699
  process.stdout.write(
30176
28700
  `${JSON.stringify({
@@ -30216,9 +28740,9 @@ async function handleRunTail(args) {
30216
28740
  }
30217
28741
  } : void 0,
30218
28742
  // Human mode only: in --json mode emit nothing non-protocol.
30219
- onReconnect: jsonOutput && !debug && !hasExplicitLogLevel ? void 0 : ({ reason }) => {
28743
+ onRetry: jsonOutput && !debug && !hasExplicitLogLevel ? void 0 : ({ reason }) => {
30220
28744
  process.stderr.write(
30221
- `[runs tail] stream ended without a terminal status; reconnecting to run ${runId} (${reason})
28745
+ `[runs watch] snapshot polling failed; retrying for run ${runId} (${reason})
30222
28746
  `
30223
28747
  );
30224
28748
  }
@@ -31885,7 +30409,10 @@ Examples:
31885
30409
  ).option(
31886
30410
  "--log-level <level>",
31887
30411
  "Minimum live log severity: debug, info (default), warn, or error"
31888
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
30412
+ ).option(
30413
+ "--tail-timeout-ms <ms>",
30414
+ "Timeout while waiting for terminal run status"
30415
+ ).option("--force", "Start a fresh run graph").option(
31889
30416
  "--force-tool-refresh",
31890
30417
  "Refresh completed tool receipts; may repeat billed provider calls"
31891
30418
  ).option(
@@ -32355,13 +30882,13 @@ Concepts:
32355
30882
  stop mutates cloud state by requesting cancellation.
32356
30883
 
32357
30884
  Debug a run:
32358
- Active: deepline runs tail <run-id> --log-level debug
30885
+ Active: deepline runs watch <run-id> --log-level debug
32359
30886
  Historical: deepline runs logs <run-id> --out run.log --log-level debug --json
32360
30887
  Full state: deepline runs get <run-id> --full --json
32361
30888
 
32362
30889
  Examples:
32363
30890
  deepline runs get play/my-play/run/20260501t000000-000 --json
32364
- deepline runs tail play/my-play/run/20260501t000000-000
30891
+ deepline runs watch play/my-play/run/20260501t000000-000
32365
30892
  deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --log-level debug --json
32366
30893
  deepline runs list --play my-play --status failed --json
32367
30894
  deepline runs list --status running --json
@@ -32447,11 +30974,15 @@ Examples:
32447
30974
  "after",
32448
30975
  `
32449
30976
  Notes:
30977
+ Requires --play or --status. Discover Play references with deepline plays list --json.
32450
30978
  Bounded inventory for a play's recent runs. Use --compact for agent loops.
30979
+ Use the exact qualified Play reference, such as workspace/my-play or prebuilt/my-play.
30980
+ --offset requires --play; narrow status-only lists with a Play reference to paginate.
32451
30981
  Common statuses include running, completed, failed, and stopped.
32452
30982
 
32453
30983
  Examples:
32454
30984
  deepline runs list --play my-play
30985
+ deepline runs list --play workspace/my-play --json
32455
30986
  deepline runs list --play my-play --status failed --compact --json
32456
30987
  deepline runs list --status running --compact --json
32457
30988
  `
@@ -32491,29 +31022,30 @@ Examples:
32491
31022
  ...options.json ? ["--json"] : []
32492
31023
  ]);
32493
31024
  });
32494
- runs.command("tail <runId>").description("Read the canonical live stream for a play run.").addHelpText(
31025
+ runs.command("watch <runId>").alias("tail").description("Poll the canonical run snapshot until terminal status.").addHelpText(
32495
31026
  "after",
32496
31027
  `
32497
31028
  Notes:
32498
- Streams live run events until the stream ends. Human output shows info and
32499
- warning logs as they arrive. Use get for current status and logs for persisted
32500
- log history. In human output, --compact prints deduplicated
32501
- step transitions and progress instead of the full event stream. --json emits
32502
- one terminal package. --jsonl emits canonical live events as JSON Lines and
32503
- ends with the same compact package shape as runs get --json. --log-level
31029
+ Polls the authenticated run snapshot every two seconds. Human output shows
31030
+ info and warning logs as snapshots change. Use get for current status and
31031
+ logs for persisted log history. In human output, --compact prints
31032
+ deduplicated step transitions and progress. --json emits one terminal
31033
+ package. --jsonl emits canonical watched events as JSON Lines and ends with
31034
+ the same compact package shape as runs get --json. The tail command remains
31035
+ an alias. --log-level
32504
31036
  filters the rendered customer-safe runtime log lines; debug includes runtime
32505
31037
  and receipt diagnostics and writes them to stderr alongside JSON output.
32506
31038
 
32507
31039
  Examples:
32508
- deepline runs tail play/my-play/run/20260501t000000-000
32509
- deepline runs tail play/my-play/run/20260501t000000-000 --compact
32510
- deepline runs tail play/my-play/run/20260501t000000-000 --log-level debug
32511
- deepline runs tail play/my-play/run/20260501t000000-000 --log-level error
32512
- deepline runs tail play/my-play/run/20260501t000000-000 --jsonl
31040
+ deepline runs watch play/my-play/run/20260501t000000-000
31041
+ deepline runs watch play/my-play/run/20260501t000000-000 --compact
31042
+ deepline runs watch play/my-play/run/20260501t000000-000 --log-level debug
31043
+ deepline runs watch play/my-play/run/20260501t000000-000 --log-level error
31044
+ deepline runs watch play/my-play/run/20260501t000000-000 --jsonl
32513
31045
  `
32514
31046
  ).option("--json", "Emit one terminal JSON package after the run completes").option(
32515
31047
  "--jsonl",
32516
- "Stream live events as JSON Lines, then the terminal package"
31048
+ "Emit watched events as JSON Lines, then the terminal package"
32517
31049
  ).option(
32518
31050
  "--compact",
32519
31051
  "Show deduplicated human step transitions and progress"
@@ -34431,7 +32963,7 @@ function isMarkedTestAiInferenceCommand(command) {
34431
32963
  if (normalizeEnrichPlayRef(command.tool) !== "run_javascript") {
34432
32964
  return false;
34433
32965
  }
34434
- return isRecord12(command.payload) && command.payload[ENRICH_TEST_AI_INFERENCE_PAYLOAD_MARKER] === true;
32966
+ return isRecord8(command.payload) && command.payload[ENRICH_TEST_AI_INFERENCE_PAYLOAD_MARKER] === true;
34435
32967
  }
34436
32968
  function enrichDebugEnabled(env = process.env) {
34437
32969
  const raw = String(env.DEEPLINE_DEBUG_ENRICH ?? "").trim().toLowerCase();
@@ -34695,7 +33227,7 @@ function rewriteGeneratedPlayRerunForEnrich(status, enrichCommand) {
34695
33227
  if (Array.isArray(value)) {
34696
33228
  return value.map(rewrite);
34697
33229
  }
34698
- if (!isRecord12(value)) {
33230
+ if (!isRecord8(value)) {
34699
33231
  return value;
34700
33232
  }
34701
33233
  const next = Object.fromEntries(
@@ -34704,7 +33236,7 @@ function rewriteGeneratedPlayRerunForEnrich(status, enrichCommand) {
34704
33236
  key === "rerunCommand" && typeof entry === "string" ? enrichCommand : rewrite(entry)
34705
33237
  ])
34706
33238
  );
34707
- if (isRecord12(next.next) && typeof next.next.run === "string") {
33239
+ if (isRecord8(next.next) && typeof next.next.run === "string") {
34708
33240
  next.next = { ...next.next, run: enrichCommand };
34709
33241
  }
34710
33242
  return next;
@@ -35186,7 +33718,7 @@ async function resolveWatchedGeneratedPlayStatus(input2) {
35186
33718
  }
35187
33719
  return input2.client.runs.get(runId, { full: true });
35188
33720
  }
35189
- function isRecord12(value) {
33721
+ function isRecord8(value) {
35190
33722
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
35191
33723
  }
35192
33724
  async function captureStdout(run, options = {}) {
@@ -35438,15 +33970,15 @@ function readFirstEnrichDatasetActions(value) {
35438
33970
  return null;
35439
33971
  }
35440
33972
  const record3 = candidate;
35441
- const actions = isRecord12(record3.actions) ? record3.actions : null;
35442
- const currentQuery = isRecord12(actions?.queryCurrentTable) ? actions.queryCurrentTable : null;
35443
- const legacyQuery = isRecord12(actions?.query) ? actions.query : null;
33973
+ const actions = isRecord8(record3.actions) ? record3.actions : null;
33974
+ const currentQuery = isRecord8(actions?.queryCurrentTable) ? actions.queryCurrentTable : null;
33975
+ const legacyQuery = isRecord8(actions?.query) ? actions.query : null;
35444
33976
  const query = currentQuery?.kind === "deepline_db_query" ? currentQuery : legacyQuery?.kind === "deepline_db_query" ? legacyQuery : null;
35445
33977
  if (query?.kind === "deepline_db_query") {
35446
33978
  return {
35447
33979
  dataset: record3,
35448
33980
  query,
35449
- ...isRecord12(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
33981
+ ...isRecord8(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
35450
33982
  };
35451
33983
  }
35452
33984
  if (options.allowLegacy && record3.kind === "dataset" && typeof record3.queryDatasetCommand === "string" && record3.queryDatasetCommand.trim()) {
@@ -35499,7 +34031,7 @@ function enrichCustomerDbJson(input2) {
35499
34031
  const dataset = actions.dataset;
35500
34032
  const sql = actionStringField(query, "sql") ?? parseSqlFromDbQueryCommand(actions.queryDatasetCommand);
35501
34033
  const datasetPath = actionStringField(query, "datasetPath") ?? actionStringField(dataset, "path") ?? actionStringField(dataset, "tableNamespace");
35502
- const api = isRecord12(query.api) ? query.api : null;
34034
+ const api = isRecord8(query.api) ? query.api : null;
35503
34035
  const apiPath = actionStringField(api ?? {}, "path") ?? "/api/v2/db/query";
35504
34036
  const apiMethod = actionStringField(api ?? {}, "method") ?? "POST";
35505
34037
  if (!datasetPath) {
@@ -35568,11 +34100,11 @@ function sqlStringLiteral(value) {
35568
34100
  return `'${value.replace(/'/g, "''")}'`;
35569
34101
  }
35570
34102
  function failureAliasFromCellMeta(cellMeta) {
35571
- if (!isRecord12(cellMeta)) {
34103
+ if (!isRecord8(cellMeta)) {
35572
34104
  return null;
35573
34105
  }
35574
34106
  for (const [alias, meta] of Object.entries(cellMeta)) {
35575
- if (!isRecord12(meta)) {
34107
+ if (!isRecord8(meta)) {
35576
34108
  continue;
35577
34109
  }
35578
34110
  const failure = failureCellFromMeta(meta, {});
@@ -36066,7 +34598,7 @@ function exportableSheetRow2(row, sourceRowStart = 0) {
36066
34598
  return fallback;
36067
34599
  }
36068
34600
  function failureCellFromMeta(meta, fallback) {
36069
- if (!isRecord12(meta)) {
34601
+ if (!isRecord8(meta)) {
36070
34602
  return null;
36071
34603
  }
36072
34604
  const status = typeof meta.status === "string" ? meta.status.trim().toLowerCase() : "";
@@ -36086,7 +34618,7 @@ function failureCellFromMeta(meta, fallback) {
36086
34618
  };
36087
34619
  }
36088
34620
  function applyFailureCellMeta(row, cellMeta, fallback) {
36089
- if (!isRecord12(cellMeta)) {
34621
+ if (!isRecord8(cellMeta)) {
36090
34622
  return;
36091
34623
  }
36092
34624
  for (const [field, meta] of Object.entries(cellMeta)) {
@@ -36314,7 +34846,7 @@ function stableRowSnapshot(value) {
36314
34846
  }
36315
34847
  function cellFailureError(value) {
36316
34848
  const parsed = parseMaybeJsonObject(value);
36317
- if (!isRecord12(parsed)) {
34849
+ if (!isRecord8(parsed)) {
36318
34850
  const text = typeof parsed === "string" ? parsed.trim() : "";
36319
34851
  if (/^(?:[A-Za-z0-9_:-]+:\s*)?(?:Error|TypeError|ReferenceError|SyntaxError|RangeError):\s+/.test(
36320
34852
  text
@@ -36322,12 +34854,12 @@ function cellFailureError(value) {
36322
34854
  return { message: text };
36323
34855
  }
36324
34856
  }
36325
- if (!isRecord12(parsed)) {
34857
+ if (!isRecord8(parsed)) {
36326
34858
  return null;
36327
34859
  }
36328
34860
  const status = typeof parsed.status === "string" ? parsed.status.trim().toLowerCase() : "";
36329
34861
  const directError = typeof parsed.error === "string" ? parsed.error.trim() : typeof parsed.last_error === "string" ? parsed.last_error.trim() : "";
36330
- const result = isRecord12(parsed.result) ? parsed.result : null;
34862
+ const result = isRecord8(parsed.result) ? parsed.result : null;
36331
34863
  const resultError = typeof result?.error === "string" ? result.error.trim() : typeof result?.message === "string" ? result.message.trim() : "";
36332
34864
  if (!directError && !resultError && status !== "error" && status !== "failed") {
36333
34865
  return null;
@@ -36397,7 +34929,7 @@ function assignFlattenedFailurePath(target, field, value) {
36397
34929
  let cursor = target;
36398
34930
  for (const part of normalized.slice(0, -1)) {
36399
34931
  const existing = cursor[part];
36400
- if (!isRecord12(existing)) {
34932
+ if (!isRecord8(existing)) {
36401
34933
  const next = {};
36402
34934
  cursor[part] = next;
36403
34935
  cursor = next;
@@ -36561,10 +35093,10 @@ function waterfallExecutionSignal(status, spec) {
36561
35093
  let everyChildStatOnlyConditionSkipped = true;
36562
35094
  const childAliasesWithStats = /* @__PURE__ */ new Set();
36563
35095
  for (const childAlias of childAliases) {
36564
- for (const stat5 of summaries.map((summary) => summary[childAlias]).filter(isRecord12)) {
35096
+ for (const stat5 of summaries.map((summary) => summary[childAlias]).filter(isRecord8)) {
36565
35097
  sawChildStats = true;
36566
35098
  childAliasesWithStats.add(childAlias);
36567
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35099
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36568
35100
  const executedSummary = parseExecutionSummary(
36569
35101
  execution?.["completed:executed"]
36570
35102
  );
@@ -36594,7 +35126,7 @@ function waterfallExecutionSignal(status, spec) {
36594
35126
  }
36595
35127
  function emptyWaterfallStatsEvidence(status, spec) {
36596
35128
  const summaries = collectColumnStats(status);
36597
- const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord12);
35129
+ const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord8);
36598
35130
  for (const stat5 of parentStats) {
36599
35131
  const nonEmpty = parseExecutionSummary(stat5.non_empty);
36600
35132
  if (nonEmpty?.total && nonEmpty.count === 0) {
@@ -36608,7 +35140,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
36608
35140
  let selectedRows = 0;
36609
35141
  let sawStatsForEveryChild = true;
36610
35142
  for (const childAlias of childAliases) {
36611
- const stat5 = summaries.map((summary) => summary[childAlias]).find(isRecord12);
35143
+ const stat5 = summaries.map((summary) => summary[childAlias]).find(isRecord8);
36612
35144
  if (!stat5) {
36613
35145
  sawStatsForEveryChild = false;
36614
35146
  break;
@@ -36617,7 +35149,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
36617
35149
  if ((nonEmpty?.count ?? 0) > 0) {
36618
35150
  return null;
36619
35151
  }
36620
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35152
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36621
35153
  const executed = parseExecutionSummary(execution?.["completed:executed"]);
36622
35154
  const reused = parseExecutionSummary(execution?.["completed:reused"]);
36623
35155
  const skipped = parseExecutionSummary(execution?.["skipped:condition"]);
@@ -36659,11 +35191,11 @@ function collectStatusFailureJobs(input2) {
36659
35191
  const jobs = [];
36660
35192
  aliases.forEach((spec, aliasIndex) => {
36661
35193
  const { alias } = spec;
36662
- const stat5 = summaries.map((summary) => summary[alias]).find(isRecord12);
35194
+ const stat5 = summaries.map((summary) => summary[alias]).find(isRecord8);
36663
35195
  if (!stat5) {
36664
35196
  return;
36665
35197
  }
36666
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35198
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36667
35199
  const failedCount = Math.min(
36668
35200
  selectedRows,
36669
35201
  Math.max(
@@ -36770,10 +35302,10 @@ function collectColumnStats(status) {
36770
35302
  value.forEach(visit);
36771
35303
  return;
36772
35304
  }
36773
- if (!isRecord12(value)) {
35305
+ if (!isRecord8(value)) {
36774
35306
  return;
36775
35307
  }
36776
- if (isRecord12(value.columnStats)) {
35308
+ if (isRecord8(value.columnStats)) {
36777
35309
  summaries.push(value.columnStats);
36778
35310
  }
36779
35311
  Object.values(value).forEach(visit);
@@ -36785,12 +35317,12 @@ function firstAliasExecutionCounts(input2) {
36785
35317
  const aliases = collectConfigScalarAliasOrder(input2.config);
36786
35318
  const summaries = collectColumnStats(input2.status);
36787
35319
  for (const alias of aliases) {
36788
- const stat5 = summaries.map((summary) => summary[alias]).find(isRecord12);
35320
+ const stat5 = summaries.map((summary) => summary[alias]).find(isRecord8);
36789
35321
  if (!stat5) continue;
36790
35322
  if (input2.forceAliases.has(normalizeAlias2(alias))) {
36791
35323
  return { executed: input2.selectedRows, reused: 0 };
36792
35324
  }
36793
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35325
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36794
35326
  if (!execution) continue;
36795
35327
  return {
36796
35328
  executed: parseExecutionCount(execution["completed:executed"]),
@@ -36817,14 +35349,14 @@ function rewriteEnrichJsonStatus(input2) {
36817
35349
  if (Array.isArray(value)) {
36818
35350
  return value.map(rewrite);
36819
35351
  }
36820
- if (!isRecord12(value)) {
35352
+ if (!isRecord8(value)) {
36821
35353
  return value;
36822
35354
  }
36823
35355
  const next = {};
36824
35356
  for (const [key, entry] of Object.entries(value)) {
36825
35357
  next[key] = rewrite(entry);
36826
35358
  }
36827
- if (isRecord12(next.progress)) {
35359
+ if (isRecord8(next.progress)) {
36828
35360
  next.progress = {
36829
35361
  ...next.progress,
36830
35362
  ...selectedRows > 0 ? { total: selectedRows } : {},
@@ -36833,8 +35365,8 @@ function rewriteEnrichJsonStatus(input2) {
36833
35365
  ...failedRows > 0 ? { failed: failedRows, pending: 0 } : {}
36834
35366
  };
36835
35367
  }
36836
- if (isRecord12(next.summary)) {
36837
- const rowCounts = isRecord12(next.summary.rowCounts) ? next.summary.rowCounts : null;
35368
+ if (isRecord8(next.summary)) {
35369
+ const rowCounts = isRecord8(next.summary.rowCounts) ? next.summary.rowCounts : null;
36838
35370
  if (failedRows > 0) {
36839
35371
  next.summary = {
36840
35372
  ...next.summary,
@@ -36847,11 +35379,11 @@ function rewriteEnrichJsonStatus(input2) {
36847
35379
  };
36848
35380
  }
36849
35381
  }
36850
- if (isRecord12(next.columnStats) && selectedRows > 0) {
35382
+ if (isRecord8(next.columnStats) && selectedRows > 0) {
36851
35383
  const columnStats = { ...next.columnStats };
36852
35384
  for (const alias of forcedAliases) {
36853
- const stat5 = isRecord12(columnStats[alias]) ? columnStats[alias] : null;
36854
- const execution = isRecord12(stat5?.execution) ? stat5.execution : null;
35385
+ const stat5 = isRecord8(columnStats[alias]) ? columnStats[alias] : null;
35386
+ const execution = isRecord8(stat5?.execution) ? stat5.execution : null;
36855
35387
  if (!stat5 || !execution) continue;
36856
35388
  columnStats[alias] = {
36857
35389
  ...stat5,
@@ -36870,14 +35402,14 @@ function rewriteEnrichJsonStatus(input2) {
36870
35402
  return next;
36871
35403
  };
36872
35404
  const rewritten = rewrite(input2.status);
36873
- if (failedRows === 0 || !isRecord12(rewritten)) {
35405
+ if (failedRows === 0 || !isRecord8(rewritten)) {
36874
35406
  return rewritten;
36875
35407
  }
36876
35408
  const partialStatus = selectedRows > 0 && failedRows < selectedRows ? "partial_success" : "failed";
36877
35409
  return {
36878
35410
  ...rewritten,
36879
35411
  ...rewritten.status === "completed" || rewritten.status === "failed" ? { status: partialStatus } : {},
36880
- ...isRecord12(rewritten.run) && (rewritten.run.status === "completed" || rewritten.run.status === "failed") ? { run: { ...rewritten.run, status: partialStatus } } : {}
35412
+ ...isRecord8(rewritten.run) && (rewritten.run.status === "completed" || rewritten.run.status === "failed") ? { run: { ...rewritten.run, status: partialStatus } } : {}
36881
35413
  };
36882
35414
  }
36883
35415
  function summarizeFailedJobError(value) {
@@ -37501,7 +36033,7 @@ function materializeCsvCellValue(value) {
37501
36033
  return value;
37502
36034
  }
37503
36035
  function compactArrayEnvelopeCompleteValue(value) {
37504
- if (!isRecord12(value) || value.kind !== "array") {
36036
+ if (!isRecord8(value) || value.kind !== "array") {
37505
36037
  return null;
37506
36038
  }
37507
36039
  if (!Array.isArray(value.preview)) {
@@ -37515,7 +36047,7 @@ function compactArrayEnvelopeCompleteValue(value) {
37515
36047
  }
37516
36048
  function disambiguateCompactAiInferencePayload(value) {
37517
36049
  const parsed = parseMaybeJsonObject(value);
37518
- if (!isRecord12(parsed) || !cellFailureError(parsed)) {
36050
+ if (!isRecord8(parsed) || !cellFailureError(parsed)) {
37519
36051
  return value;
37520
36052
  }
37521
36053
  return {
@@ -37524,14 +36056,14 @@ function disambiguateCompactAiInferencePayload(value) {
37524
36056
  };
37525
36057
  }
37526
36058
  function compactAiInferenceCellForCsv(value) {
37527
- if (!isRecord12(value)) {
36059
+ if (!isRecord8(value)) {
37528
36060
  return value;
37529
36061
  }
37530
36062
  const extractedJson = value.extracted_json;
37531
36063
  if (extractedJson !== null && extractedJson !== void 0) {
37532
36064
  return disambiguateCompactAiInferencePayload(extractedJson);
37533
36065
  }
37534
- const result = isRecord12(value.result) ? value.result : null;
36066
+ const result = isRecord8(value.result) ? value.result : null;
37535
36067
  const object = result?.object;
37536
36068
  if (object !== null && object !== void 0) {
37537
36069
  return disambiguateCompactAiInferencePayload(object);
@@ -37548,12 +36080,12 @@ function compactAiInferenceCellForCsv(value) {
37548
36080
  }
37549
36081
  function materializeEnrichAliasCellForCsv(row, alias, options) {
37550
36082
  const direct = row[alias];
37551
- if (isRecord12(direct)) {
36083
+ if (isRecord8(direct)) {
37552
36084
  const completeArray = compactArrayEnvelopeCompleteValue(direct);
37553
36085
  if (completeArray) {
37554
36086
  return materializeCsvCellValue(completeArray);
37555
36087
  }
37556
- if (options?.compactAiCell && direct.status === "completed" && (isRecord12(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
36088
+ if (options?.compactAiCell && direct.status === "completed" && (isRecord8(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
37557
36089
  return materializeCsvCellValue(compactAiInferenceCellForCsv(direct));
37558
36090
  }
37559
36091
  if (Object.prototype.hasOwnProperty.call(direct, "matched_result") || Object.prototype.hasOwnProperty.call(direct, "matchedResult") || Object.prototype.hasOwnProperty.call(direct, "result")) {
@@ -37694,11 +36226,11 @@ function normalizeEnrichRowsForCsvExport(rows, config, options) {
37694
36226
  }
37695
36227
  function legacyMetadataFromRow(row) {
37696
36228
  const direct = parseLegacyMetadataCell(row._metadata);
37697
- if (direct && isRecord12(direct.columns)) {
36229
+ if (direct && isRecord8(direct.columns)) {
37698
36230
  return direct;
37699
36231
  }
37700
36232
  const relocated = parseLegacyMetadataCell(row.metadata);
37701
- if (relocated && isRecord12(relocated.columns)) {
36233
+ if (relocated && isRecord8(relocated.columns)) {
37702
36234
  return relocated;
37703
36235
  }
37704
36236
  const flattenedColumns = parseLegacyMetadataCell(row["metadata.columns"]);
@@ -37715,7 +36247,7 @@ function legacyMetadataFromRow(row) {
37715
36247
  }
37716
36248
  function parseLegacyMetadataCell(value) {
37717
36249
  const parsed = parseMaybeJsonObject(value);
37718
- if (isRecord12(parsed)) {
36250
+ if (isRecord8(parsed)) {
37719
36251
  return parsed;
37720
36252
  }
37721
36253
  if (typeof value !== "string") {
@@ -37732,12 +36264,12 @@ function parseLegacyMetadataCell(value) {
37732
36264
  for (const candidate of candidates) {
37733
36265
  try {
37734
36266
  const decoded = JSON.parse(candidate);
37735
- if (isRecord12(decoded)) {
36267
+ if (isRecord8(decoded)) {
37736
36268
  return decoded;
37737
36269
  }
37738
36270
  if (typeof decoded === "string") {
37739
36271
  const nested = JSON.parse(decoded);
37740
- if (isRecord12(nested)) {
36272
+ if (isRecord8(nested)) {
37741
36273
  return nested;
37742
36274
  }
37743
36275
  }
@@ -37747,8 +36279,8 @@ function parseLegacyMetadataCell(value) {
37747
36279
  return null;
37748
36280
  }
37749
36281
  function mergeLegacyMetadataRecords(base, enriched) {
37750
- const baseColumns = isRecord12(base.columns) ? base.columns : null;
37751
- const enrichedColumns = isRecord12(enriched.columns) ? enriched.columns : null;
36282
+ const baseColumns = isRecord8(base.columns) ? base.columns : null;
36283
+ const enrichedColumns = isRecord8(enriched.columns) ? enriched.columns : null;
37752
36284
  const merged = {
37753
36285
  ...base,
37754
36286
  ...enriched
@@ -50009,11 +48541,17 @@ var CapabilityDescription = class _CapabilityDescription {
50009
48541
  legacyCost.pricingModel ?? legacyCost.pricing_model
50010
48542
  );
50011
48543
  const pricingModel = unit === "call" ? "fixed" : unit === "result" || unit === "page" ? `per_${unit}` : unit === "usage" ? "provider_usage" : legacyPricingModel;
50012
- const canonicalCredits = numberValue(
50013
- pricing.creditsPerUnit ?? pricing.credits_per_unit
50014
- );
50015
- const canonicalUsd = numberValue(
50016
- pricing.usdPerUnit ?? pricing.usd_per_unit
48544
+ const canonicalCredits = pricingNumber(
48545
+ pricing,
48546
+ "creditsPerUnit",
48547
+ "credits_per_unit",
48548
+ this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
48549
+ );
48550
+ const canonicalUsd = pricingNumber(
48551
+ pricing,
48552
+ "usdPerUnit",
48553
+ "usd_per_unit",
48554
+ this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
50017
48555
  );
50018
48556
  const billingSource = stringValue4(
50019
48557
  this.#catalogEntry.billingSource ?? this.#catalogEntry.billing_source
@@ -50032,12 +48570,8 @@ var CapabilityDescription = class _CapabilityDescription {
50032
48570
  ),
50033
48571
  billingSource,
50034
48572
  billingSourceLabel,
50035
- deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits ?? numberValue(
50036
- this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
50037
- ),
50038
- deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd ?? numberValue(
50039
- this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
50040
- )
48573
+ deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits,
48574
+ deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd
50041
48575
  };
50042
48576
  }
50043
48577
  };
@@ -50050,6 +48584,13 @@ function stringValue4(value) {
50050
48584
  function numberValue(value) {
50051
48585
  return typeof value === "number" && Number.isFinite(value) ? value : null;
50052
48586
  }
48587
+ function pricingNumber(pricing, canonicalKey, aliasKey, legacyValue) {
48588
+ for (const key of [canonicalKey, aliasKey]) {
48589
+ if (Object.prototype.hasOwnProperty.call(pricing, key))
48590
+ return numberValue(pricing[key]);
48591
+ }
48592
+ return numberValue(legacyValue);
48593
+ }
50053
48594
 
50054
48595
  // src/cli/tool-connection-status.ts
50055
48596
  function toolConnectionStatusMessage(input2) {
@@ -50643,11 +49184,15 @@ Concepts:
50643
49184
  Common commands:
50644
49185
  deepline tools search email --json
50645
49186
  deepline tools describe hunter_email_verifier --json
49187
+ deepline tools describe hunter_email_verifier --pricing-only --json
50646
49188
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
49189
+ deepline billing usage --request-id <job_id> --json
50647
49190
 
50648
49191
  Output:
50649
49192
  Use describe for tool contracts.
50650
49193
  Use execute to run a tool.
49194
+ Read pricing before execution; use the returned next.billing command for its
49195
+ exact charge. Workspace balance changes also include other callers' activity.
50651
49196
  `
50652
49197
  );
50653
49198
  tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
@@ -50773,6 +49318,7 @@ Notes:
50773
49318
  Examples:
50774
49319
  deepline tools describe hunter_email_verifier
50775
49320
  deepline tools describe hunter_email_verifier --pricing-only
49321
+ deepline tools describe hunter_email_verifier --pricing-only --json
50776
49322
  deepline tools describe hunter_email_verifier --schema-only
50777
49323
  deepline tools describe hunter_email_verifier --examples-only
50778
49324
  deepline tools describe hunter_email_verifier --json
@@ -50822,10 +49368,15 @@ Notes:
50822
49368
  waterfalls, row maps, checkpoints, and retries.
50823
49369
  Calling a provider-backed tool can spend Deepline credits. Use --json for the
50824
49370
  stable result payload plus output preview and debugging helpers.
49371
+ Read pricing first with tools describe <toolId> --pricing-only --json.
49372
+ Use the returned next.billing command to look up this execution's exact charge;
49373
+ workspace balance changes also include other callers' activity.
50825
49374
  --timeout sets this CLI request's HTTP deadline; it does not cancel provider work.
50826
49375
 
50827
49376
  Examples:
50828
49377
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
49378
+ deepline tools describe hunter_email_verifier --pricing-only --json
49379
+ deepline billing usage --request-id <job_id> --json
50829
49380
  deepline tools execute bounceban_verify_bulk --input @batch.json --timeout 10m --json
50830
49381
  deepline tools execute hunter_email_verifier -p email=a@b.com
50831
49382
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
@@ -50929,6 +49480,38 @@ async function getTool(toolId, options = {}) {
50929
49480
  );
50930
49481
  return 2;
50931
49482
  }
49483
+ const onlyModes = [
49484
+ options.pricingOnly,
49485
+ options.schemaOnly,
49486
+ options.examplesOnly,
49487
+ options.gettersOnly
49488
+ ].filter(Boolean).length;
49489
+ if (onlyModes > 1) {
49490
+ console.error(
49491
+ "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
49492
+ );
49493
+ return 2;
49494
+ }
49495
+ if (options.pricingOnly) {
49496
+ const lines = toolPricingOnlyLines(tool, toolId);
49497
+ if (inferenceQuote)
49498
+ lines.push(...inferenceQuoteSummaryLines(inferenceQuote));
49499
+ printCommandEnvelope(
49500
+ {
49501
+ toolId: String(tool.toolId || toolId),
49502
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
49503
+ ...modelDescription ? { modelOptions: modelDescription } : {},
49504
+ ...isMonitorTypeTool(tool) ? { pricing: recordField2(tool, "pricing") } : {},
49505
+ ...inferenceQuote ? { inferenceQuote } : {}
49506
+ },
49507
+ {
49508
+ json: Boolean(options.json || options.contractJson),
49509
+ text: `${lines.join("\n")}
49510
+ `
49511
+ }
49512
+ );
49513
+ return 0;
49514
+ }
50932
49515
  if (options.contractJson) {
50933
49516
  printCompactJson({
50934
49517
  ...toolContractJsonForDescribe(tool, toolId),
@@ -50946,23 +49529,6 @@ async function getTool(toolId, options = {}) {
50946
49529
  });
50947
49530
  return 0;
50948
49531
  }
50949
- const onlyModes = [
50950
- options.pricingOnly,
50951
- options.schemaOnly,
50952
- options.examplesOnly,
50953
- options.gettersOnly
50954
- ].filter(Boolean).length;
50955
- if (onlyModes > 1) {
50956
- console.error(
50957
- "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
50958
- );
50959
- return 2;
50960
- }
50961
- if (options.pricingOnly) {
50962
- printToolPricingOnly(tool, toolId);
50963
- if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50964
- return 0;
50965
- }
50966
49532
  if (options.schemaOnly) {
50967
49533
  printToolSchemaOnly(tool, toolId);
50968
49534
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
@@ -51003,11 +49569,16 @@ ${formatModelDescription(modelDescription)}`);
51003
49569
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
51004
49570
  return 0;
51005
49571
  }
51006
- function printInferenceQuoteSummary(_quote) {
51007
- console.log("");
51008
- console.log("Inference quote:");
51009
- console.log("- Temporary hold: priced estimate (minimum 0.02 credits)");
51010
- console.log("- Final charge: actual usage");
49572
+ function inferenceQuoteSummaryLines(_quote) {
49573
+ return [
49574
+ "",
49575
+ "Inference quote:",
49576
+ "- Temporary hold: priced estimate (minimum 0.02 credits)",
49577
+ "- Final charge: actual usage"
49578
+ ];
49579
+ }
49580
+ function printInferenceQuoteSummary(quote) {
49581
+ for (const line of inferenceQuoteSummaryLines(quote)) console.log(line);
51011
49582
  }
51012
49583
  function toolContractJsonForDescribe(tool, requestedToolId) {
51013
49584
  const toolId = String(tool.toolId || requestedToolId);
@@ -51066,6 +49637,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
51066
49637
  toolId,
51067
49638
  provider: tool.provider,
51068
49639
  displayName: tool.displayName,
49640
+ cost: pricing,
51069
49641
  description: tool.description,
51070
49642
  categories: tool.categories,
51071
49643
  ...deprecated ? {
@@ -51085,7 +49657,6 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
51085
49657
  } : {},
51086
49658
  ...executionMetadata ? { executionMetadata } : {},
51087
49659
  ...batchCapability ? { batchCapability } : {},
51088
- cost: pricing,
51089
49660
  getters: {
51090
49661
  extractedLists,
51091
49662
  extractedValues
@@ -51096,7 +49667,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
51096
49667
  }
51097
49668
  function extractionContractEntries(entries) {
51098
49669
  return entries.flatMap((entry) => {
51099
- if (!isRecord13(entry)) return [];
49670
+ if (!isRecord9(entry)) return [];
51100
49671
  const name = stringField2(entry, "name");
51101
49672
  const expression = stringField2(entry, "expression");
51102
49673
  return name && expression ? [{ name, expression }] : [];
@@ -51117,7 +49688,7 @@ function printMonitorTypeFilters(tool) {
51117
49688
  }
51118
49689
  console.log("Deploy filters (set in the monitor payload):");
51119
49690
  for (const name of names) {
51120
- const field = isRecord13(properties[name]) ? properties[name] : {};
49691
+ const field = isRecord9(properties[name]) ? properties[name] : {};
51121
49692
  const star = required.has(name) ? "*" : "";
51122
49693
  const enumVals = arrayField2(field, "enum").filter(
51123
49694
  (v) => typeof v === "string"
@@ -51131,7 +49702,7 @@ function printMonitorTypeFilterExamples(tool) {
51131
49702
  const documentation = recordField2(tool, "documentation");
51132
49703
  const fields2 = recordField2(documentation, "fields");
51133
49704
  const examples = Object.entries(fields2).flatMap(([name, rawField]) => {
51134
- const grammar = recordField2(isRecord13(rawField) ? rawField : {}, "grammar");
49705
+ const grammar = recordField2(isRecord9(rawField) ? rawField : {}, "grammar");
51135
49706
  const example = stringField2(grammar, "example");
51136
49707
  const values = [
51137
49708
  ...arrayField2(grammar, "examples").filter(
@@ -51150,18 +49721,18 @@ function printMonitorTypeFilterExamples(tool) {
51150
49721
  }
51151
49722
  function printMonitorTypeStreams(tool) {
51152
49723
  const streams = arrayField2(tool, "streams", "output_streams").filter(
51153
- isRecord13
49724
+ isRecord9
51154
49725
  );
51155
49726
  if (!streams.length) return;
51156
49727
  console.log("");
51157
49728
  console.log("Filter columns (a play's sqlListeners.where, per stream):");
51158
49729
  for (const stream of streams) {
51159
49730
  const name = stringField2(stream, "stream");
51160
- const cols = arrayField2(stream, "columns").filter(isRecord13).map((col) => stringField2(col, "name")).filter(Boolean);
49731
+ const cols = arrayField2(stream, "columns").filter(isRecord9).map((col) => stringField2(col, "name")).filter(Boolean);
51161
49732
  console.log(`- ${name}: ${cols.join(", ")}`);
51162
49733
  }
51163
49734
  }
51164
- function printMonitorTypePricing(tool) {
49735
+ function monitorTypePricingLines(tool) {
51165
49736
  const pricing = recordField2(tool, "pricing");
51166
49737
  const byType = recordField2(
51167
49738
  pricing,
@@ -51170,17 +49741,20 @@ function printMonitorTypePricing(tool) {
51170
49741
  );
51171
49742
  const keys = Object.keys(byType);
51172
49743
  if (!keys.length) {
51173
- console.log("Pricing: Deepline credits per accepted event (see --json)");
51174
- return;
49744
+ return ["Pricing: Deepline credits per accepted event (see --json)"];
51175
49745
  }
51176
- console.log("Pricing (Deepline credits per accepted event):");
49746
+ const lines = ["Pricing (Deepline credits per accepted event):"];
51177
49747
  for (const key of keys) {
51178
- const entry = isRecord13(byType[key]) ? byType[key] : {};
49748
+ const entry = isRecord9(byType[key]) ? byType[key] : {};
51179
49749
  const credits = numberField2(entry, "deepline_credits", "deeplineCredits");
51180
49750
  const display = stringField2(entry, "display");
51181
49751
  const shown = display || (credits !== null ? `${formatDecimal(credits)} credits/event` : "see --json");
51182
- console.log(`- ${key}: ${shown}`);
49752
+ lines.push(`- ${key}: ${shown}`);
51183
49753
  }
49754
+ return lines;
49755
+ }
49756
+ function printMonitorTypePricing(tool) {
49757
+ for (const line of monitorTypePricingLines(tool)) console.log(line);
51184
49758
  }
51185
49759
  function printMonitorTypeDeploy(tool) {
51186
49760
  const deploy = recordField2(tool, "deploy");
@@ -51221,8 +49795,8 @@ function printCompactToolContract(tool, requestedToolId) {
51221
49795
  return;
51222
49796
  }
51223
49797
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
51224
- const cost = isRecord13(contract.cost) ? contract.cost : {};
51225
- const getters = isRecord13(contract.getters) ? contract.getters : {};
49798
+ const cost = isRecord9(contract.cost) ? contract.cost : {};
49799
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
51226
49800
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
51227
49801
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
51228
49802
  const inputFields = recursiveToolInputFieldsForDisplay(
@@ -51239,7 +49813,7 @@ function printCompactToolContract(tool, requestedToolId) {
51239
49813
  printToolOutputArrayShape(contract);
51240
49814
  printToolExecutionHints(contract);
51241
49815
  if (contract.deprecated === true) {
51242
- const deprecation = isRecord13(contract.deprecation) ? contract.deprecation : {};
49816
+ const deprecation = isRecord9(contract.deprecation) ? contract.deprecation : {};
51243
49817
  const message = stringField2(deprecation, "message");
51244
49818
  const replacementToolId = stringField2(
51245
49819
  deprecation,
@@ -51266,7 +49840,7 @@ function printCompactToolContract(tool, requestedToolId) {
51266
49840
  console.log("");
51267
49841
  console.log("Inputs:");
51268
49842
  for (const field of inputFields) {
51269
- if (!isRecord13(field)) continue;
49843
+ if (!isRecord9(field)) continue;
51270
49844
  const name = stringField2(field, "name");
51271
49845
  if (!name) continue;
51272
49846
  const required = field.required ? "*" : "";
@@ -51286,7 +49860,7 @@ function printCompactToolContract(tool, requestedToolId) {
51286
49860
  }
51287
49861
  console.log("");
51288
49862
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
51289
- const starterScript = isRecord13(contract.starterScript) ? contract.starterScript : {};
49863
+ const starterScript = isRecord9(contract.starterScript) ? contract.starterScript : {};
51290
49864
  const starterPath = stringField2(starterScript, "path");
51291
49865
  if (starterPath) {
51292
49866
  console.log("");
@@ -51300,14 +49874,14 @@ function printCompactToolContract(tool, requestedToolId) {
51300
49874
  console.log("Getters:");
51301
49875
  if (listGetters.length) console.log("Lists:");
51302
49876
  for (const entry of listGetters) {
51303
- if (isRecord13(entry))
49877
+ if (isRecord9(entry))
51304
49878
  console.log(
51305
49879
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51306
49880
  );
51307
49881
  }
51308
49882
  if (valueGetters.length) console.log("Values:");
51309
49883
  for (const entry of valueGetters) {
51310
- if (isRecord13(entry))
49884
+ if (isRecord9(entry))
51311
49885
  console.log(
51312
49886
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51313
49887
  );
@@ -51318,13 +49892,12 @@ function printCompactToolContract(tool, requestedToolId) {
51318
49892
  `More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`
51319
49893
  );
51320
49894
  }
51321
- function printToolPricingOnly(tool, requestedToolId, options = {}) {
49895
+ function toolPricingOnlyLines(tool, requestedToolId, options = {}) {
51322
49896
  if (isMonitorTypeTool(tool)) {
51323
- printMonitorTypePricing(tool);
51324
- return;
49897
+ return monitorTypePricingLines(tool);
51325
49898
  }
51326
- const contract = toolContractJsonForDescribe(tool, requestedToolId);
51327
- const cost = isRecord13(contract.cost) ? contract.cost : {};
49899
+ const toolId = String(tool.toolId || requestedToolId);
49900
+ const cost = Capability.fromCatalogEntry(tool).describe().customerCost();
51328
49901
  const pricingModel = stringField2(cost, "pricingModel") || "unknown";
51329
49902
  const billing = stringField2(cost, "billingSourceLabel") || stringField2(cost, "billingSource") || stringField2(cost, "billingMode") || "unknown";
51330
49903
  const explicitUnit = stringField2(cost, "unit");
@@ -51334,8 +49907,14 @@ function printToolPricingOnly(tool, requestedToolId, options = {}) {
51334
49907
  const displayText = stringField2(cost, "displayText");
51335
49908
  const summary = stringField2(cost, "summary");
51336
49909
  const price = displayText || summary || (credits !== null ? `${formatDecimal(credits)} Deepline credits${usd !== null ? ` / ${formatUsd(usd)}` : ""} per ${unit}` : "pricing unavailable");
51337
- console.log(`${options.heading ?? `Pricing: ${contract.toolId}`}: ${price}`);
51338
- console.log(`Billing: ${billing}`);
49910
+ return [
49911
+ `${options.heading ?? `Pricing: ${toolId}`}: ${price}`,
49912
+ `Billing: ${billing}`
49913
+ ];
49914
+ }
49915
+ function printToolPricingOnly(tool, requestedToolId, options = {}) {
49916
+ for (const line of toolPricingOnlyLines(tool, requestedToolId, options))
49917
+ console.log(line);
51339
49918
  }
51340
49919
  function printToolSchemaOnly(tool, requestedToolId) {
51341
49920
  if (isMonitorTypeTool(tool)) {
@@ -51401,10 +49980,10 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
51401
49980
  ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
51402
49981
  );
51403
49982
  console.log("});");
51404
- const getters = isRecord13(contract.getters) ? contract.getters : {};
49983
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
51405
49984
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
51406
49985
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
51407
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord13);
49986
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord9);
51408
49987
  if (firstGetter) {
51409
49988
  const name = stringField2(firstGetter, "name") || "value";
51410
49989
  const expression = stringField2(firstGetter, "expression");
@@ -51440,7 +50019,7 @@ function printPlayLikeToolUsage(tool, requestedToolId) {
51440
50019
  }
51441
50020
  function printToolGettersOnly(tool, requestedToolId) {
51442
50021
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
51443
- const getters = isRecord13(contract.getters) ? contract.getters : {};
50022
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
51444
50023
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
51445
50024
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
51446
50025
  console.log(`Getters: ${contract.toolId}`);
@@ -51453,7 +50032,7 @@ function printToolGettersOnly(tool, requestedToolId) {
51453
50032
  if (listGetters.length) {
51454
50033
  console.log("Lists:");
51455
50034
  for (const entry of listGetters) {
51456
- if (isRecord13(entry))
50035
+ if (isRecord9(entry))
51457
50036
  console.log(
51458
50037
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51459
50038
  );
@@ -51462,7 +50041,7 @@ function printToolGettersOnly(tool, requestedToolId) {
51462
50041
  if (valueGetters.length) {
51463
50042
  console.log("Values:");
51464
50043
  for (const entry of valueGetters) {
51465
- if (isRecord13(entry))
50044
+ if (isRecord9(entry))
51466
50045
  console.log(
51467
50046
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51468
50047
  );
@@ -51488,7 +50067,7 @@ function sampleValueForField(field) {
51488
50067
  function samplePayloadForInputFields(fields2) {
51489
50068
  return Object.fromEntries(
51490
50069
  fields2.slice(0, 4).flatMap((field) => {
51491
- if (!isRecord13(field)) return [];
50070
+ if (!isRecord9(field)) return [];
51492
50071
  const name = stringField2(field, "name");
51493
50072
  if (!name) return [];
51494
50073
  return [[name, sampleValueForField(field)]];
@@ -51548,6 +50127,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51548
50127
  } = tool;
51549
50128
  const outputSchemaRecord = recordField2(tool, "outputSchema", "output_schema");
51550
50129
  return {
50130
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51551
50131
  ...publicTool,
51552
50132
  toolId,
51553
50133
  provider: tool.provider,
@@ -51559,7 +50139,6 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51559
50139
  )
51560
50140
  } : {},
51561
50141
  inputFields: inputFields.map(inputFieldJsonForDescribe),
51562
- cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51563
50142
  usageGuidance,
51564
50143
  runtimeOutputHelp: {
51565
50144
  contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
@@ -51618,8 +50197,8 @@ function formatListedToolCost(tool) {
51618
50197
  }
51619
50198
  function toolInputFieldsForDisplay(inputSchema) {
51620
50199
  if (Array.isArray(inputSchema.fields)) {
51621
- const fields2 = inputSchema.fields.filter(isRecord13);
51622
- if (!isRecord13(inputSchema.jsonSchema)) return fields2;
50200
+ const fields2 = inputSchema.fields.filter(isRecord9);
50201
+ if (!isRecord9(inputSchema.jsonSchema)) return fields2;
51623
50202
  const jsonSchemaFields = new Map(
51624
50203
  recursiveToolInputFieldsForDisplay({
51625
50204
  jsonSchema: inputSchema.jsonSchema
@@ -51631,26 +50210,26 @@ function toolInputFieldsForDisplay(inputSchema) {
51631
50210
  const jsonSchemaField = typeof field.name === "string" ? jsonSchemaFields.get(field.name) : void 0;
51632
50211
  const minItems = typeof field.minItems === "number" ? field.minItems : jsonSchemaField?.minItems;
51633
50212
  const maxItems = typeof field.maxItems === "number" ? field.maxItems : jsonSchemaField?.maxItems;
51634
- const items = isRecord13(field.items) ? field.items : jsonSchemaField?.items;
50213
+ const items = isRecord9(field.items) ? field.items : jsonSchemaField?.items;
51635
50214
  return {
51636
50215
  ...field,
51637
- ...isRecord13(items) ? { items } : {},
50216
+ ...isRecord9(items) ? { items } : {},
51638
50217
  ...typeof minItems === "number" ? { minItems } : {},
51639
50218
  ...typeof maxItems === "number" ? { maxItems } : {}
51640
50219
  };
51641
50220
  });
51642
50221
  }
51643
- const jsonSchema = isRecord13(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
51644
- const properties = isRecord13(jsonSchema.properties) ? jsonSchema.properties : {};
50222
+ const jsonSchema = isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
50223
+ const properties = isRecord9(jsonSchema.properties) ? jsonSchema.properties : {};
51645
50224
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
51646
50225
  return Object.entries(properties).map(([name, value]) => {
51647
- const property = isRecord13(value) ? value : {};
50226
+ const property = isRecord9(value) ? value : {};
51648
50227
  return {
51649
50228
  name,
51650
50229
  type: typeof property.type === "string" ? property.type : "unknown",
51651
50230
  required: required.has(name),
51652
50231
  description: property.description,
51653
- ...isRecord13(property.items) ? { items: property.items } : {},
50232
+ ...isRecord9(property.items) ? { items: property.items } : {},
51654
50233
  ...typeof property.minItems === "number" ? { minItems: property.minItems } : {},
51655
50234
  ...typeof property.maxItems === "number" ? { maxItems: property.maxItems } : {},
51656
50235
  ...Object.prototype.hasOwnProperty.call(property, "default") ? { default: property.default } : {}
@@ -51667,7 +50246,7 @@ function toolOutputFieldsForDisplay(outputSchema) {
51667
50246
  }
51668
50247
  function printToolOutputArrayShape(tool) {
51669
50248
  const outputFields = toolOutputFieldsForDisplay(
51670
- recordField2(isRecord13(tool) ? tool : {}, "outputSchema", "output_schema")
50249
+ recordField2(isRecord9(tool) ? tool : {}, "outputSchema", "output_schema")
51671
50250
  );
51672
50251
  if (outputFields.length === 0) return;
51673
50252
  console.log(" Output array shape (declared schema):");
@@ -51682,10 +50261,10 @@ function printToolOutputArrayShape(tool) {
51682
50261
  }
51683
50262
  }
51684
50263
  function canonicalToolJsonSchema(inputSchema) {
51685
- return isRecord13(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
50264
+ return isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
51686
50265
  }
51687
50266
  function declaredToolJsonSchema(inputSchema) {
51688
- if (isRecord13(inputSchema.jsonSchema)) {
50267
+ if (isRecord9(inputSchema.jsonSchema)) {
51689
50268
  return inputSchema.jsonSchema;
51690
50269
  }
51691
50270
  return Array.isArray(inputSchema.fields) ? null : inputSchema;
@@ -51710,7 +50289,7 @@ function publicToolInputSchemaForDescribe(inputSchema) {
51710
50289
  };
51711
50290
  const stripDescriptions = (value) => {
51712
50291
  if (Array.isArray(value)) return value.map(stripDescriptions);
51713
- if (!isRecord13(value)) return value;
50292
+ if (!isRecord9(value)) return value;
51714
50293
  return Object.fromEntries(
51715
50294
  Object.entries(value).flatMap(([key, nested]) => {
51716
50295
  if (key === "description" && typeof nested === "string" && exposesProviderSpend(nested)) {
@@ -51731,7 +50310,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51731
50310
  for (const item of value) collectSchemaIds(item);
51732
50311
  return;
51733
50312
  }
51734
- if (!isRecord13(value)) return;
50313
+ if (!isRecord9(value)) return;
51735
50314
  if (typeof value.$id === "string" && value.$id.trim()) {
51736
50315
  schemasById.set(value.$id.trim(), value);
51737
50316
  }
@@ -51744,10 +50323,10 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51744
50323
  let current = root;
51745
50324
  for (const rawSegment of ref.slice(2).split("/")) {
51746
50325
  const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
51747
- if (!isRecord13(current)) return schema;
50326
+ if (!isRecord9(current)) return schema;
51748
50327
  current = current[segment];
51749
50328
  }
51750
- return isRecord13(current) ? current : schema;
50329
+ return isRecord9(current) ? current : schema;
51751
50330
  };
51752
50331
  const addField = (field) => {
51753
50332
  const name = typeof field.name === "string" ? field.name : "";
@@ -51762,7 +50341,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51762
50341
  if (ref && activeRefs.has(ref)) return;
51763
50342
  const schema = resolveRef(unresolvedSchema);
51764
50343
  const nextActiveRefs = ref ? /* @__PURE__ */ new Set([...activeRefs, ref]) : activeRefs;
51765
- const type = Array.isArray(schema.type) ? schema.type.map(String).join("|") : typeof schema.type === "string" ? schema.type : isRecord13(schema.properties) ? "object" : schema.items ? "array" : "unknown";
50344
+ const type = Array.isArray(schema.type) ? schema.type.map(String).join("|") : typeof schema.type === "string" ? schema.type : isRecord9(schema.properties) ? "object" : schema.items ? "array" : "unknown";
51766
50345
  if (path) {
51767
50346
  addField({
51768
50347
  name: path,
@@ -51770,18 +50349,18 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51770
50349
  required,
51771
50350
  description: schema.description,
51772
50351
  ...Array.isArray(schema.enum) ? { enum: schema.enum } : {},
51773
- ...isRecord13(schema.items) ? { items: schema.items } : {},
50352
+ ...isRecord9(schema.items) ? { items: schema.items } : {},
51774
50353
  ...typeof schema.minItems === "number" ? { minItems: schema.minItems } : {},
51775
50354
  ...typeof schema.maxItems === "number" ? { maxItems: schema.maxItems } : {},
51776
50355
  ...Object.prototype.hasOwnProperty.call(schema, "default") ? { default: schema.default } : {}
51777
50356
  });
51778
50357
  }
51779
- const properties = isRecord13(schema.properties) ? schema.properties : {};
50358
+ const properties = isRecord9(schema.properties) ? schema.properties : {};
51780
50359
  const requiredNames = new Set(
51781
50360
  Array.isArray(schema.required) ? schema.required.map(String) : []
51782
50361
  );
51783
50362
  for (const [name, value] of Object.entries(properties)) {
51784
- if (!isRecord13(value)) continue;
50363
+ if (!isRecord9(value)) continue;
51785
50364
  visit(
51786
50365
  value,
51787
50366
  path ? `${path}.${name}` : name,
@@ -51789,13 +50368,13 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51789
50368
  nextActiveRefs
51790
50369
  );
51791
50370
  }
51792
- if (isRecord13(schema.items)) {
50371
+ if (isRecord9(schema.items)) {
51793
50372
  visit(schema.items, `${path}[]`, false, nextActiveRefs);
51794
50373
  }
51795
50374
  for (const keyword of ["anyOf", "oneOf", "allOf"]) {
51796
50375
  const branches = Array.isArray(schema[keyword]) ? schema[keyword] : [];
51797
50376
  for (const branch of branches) {
51798
- if (isRecord13(branch)) {
50377
+ if (isRecord9(branch)) {
51799
50378
  visit(branch, path, required, nextActiveRefs);
51800
50379
  }
51801
50380
  }
@@ -51805,21 +50384,21 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51805
50384
  return fields2.size ? [...fields2.values()] : toolInputFieldsForDisplay(inputSchema);
51806
50385
  }
51807
50386
  function inputFieldJsonForDescribe(field) {
51808
- const publicItems = isRecord13(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;
50387
+ const publicItems = isRecord9(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;
51809
50388
  return {
51810
50389
  name: field.name,
51811
50390
  type: field.type ?? "unknown",
51812
50391
  required: Boolean(field.required),
51813
50392
  ...field.description ? { description: field.description } : {},
51814
- ...isRecord13(publicItems) ? { items: publicItems } : {},
50393
+ ...isRecord9(publicItems) ? { items: publicItems } : {},
51815
50394
  ...typeof field.minItems === "number" ? { minItems: field.minItems } : {},
51816
50395
  ...typeof field.maxItems === "number" ? { maxItems: field.maxItems } : {},
51817
50396
  ...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
51818
50397
  };
51819
50398
  }
51820
50399
  function arrayItemBoundsSuffix(field) {
51821
- const itemSchema = isRecord13(field.items) ? field.items : null;
51822
- const itemType = itemSchema ? typeof itemSchema.type === "string" ? itemSchema.type : isRecord13(itemSchema.properties) ? "object" : "unknown" : null;
50400
+ const itemSchema = isRecord9(field.items) ? field.items : null;
50401
+ const itemType = itemSchema ? typeof itemSchema.type === "string" ? itemSchema.type : isRecord9(itemSchema.properties) ? "object" : "unknown" : null;
51823
50402
  const itemEnum = Array.isArray(itemSchema?.enum) ? ` enum=${itemSchema.enum.map(String).join("|")}` : "";
51824
50403
  const itemTypeSuffix = itemType && itemType !== "unknown" ? ` items=${itemType}${itemEnum}` : "";
51825
50404
  const minItems = typeof field.minItems === "number" && Number.isFinite(field.minItems) ? field.minItems : null;
@@ -51833,13 +50412,13 @@ function arrayItemBoundsSuffix(field) {
51833
50412
  }
51834
50413
  function printToolExecutionHints(value) {
51835
50414
  const batchCapabilityRecord = recordField2(
51836
- isRecord13(value) ? value : {},
50415
+ isRecord9(value) ? value : {},
51837
50416
  "batchCapability",
51838
50417
  "batch_capability"
51839
50418
  );
51840
50419
  const batchCapability = Object.keys(batchCapabilityRecord).length > 0 ? batchCapabilityRecord : null;
51841
50420
  const executionMetadata = recordField2(
51842
- isRecord13(value) ? value : {},
50421
+ isRecord9(value) ? value : {},
51843
50422
  "executionMetadata",
51844
50423
  "execution_metadata"
51845
50424
  );
@@ -51879,7 +50458,7 @@ function printToolExecutionHints(value) {
51879
50458
  executionMetadata,
51880
50459
  "configuredRateLimits",
51881
50460
  "configured_rate_limits"
51882
- ).filter(isRecord13);
50461
+ ).filter(isRecord9);
51883
50462
  if (configuredRateLimits.length > 0) {
51884
50463
  console.log("");
51885
50464
  console.log(
@@ -51944,17 +50523,17 @@ function printJsonPreview(label, payload) {
51944
50523
  }
51945
50524
  function samplePayload(samples, key) {
51946
50525
  const entry = samples[key];
51947
- if (!isRecord13(entry)) return void 0;
50526
+ if (!isRecord9(entry)) return void 0;
51948
50527
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
51949
50528
  }
51950
50529
  function commandEnvelopeFromRawResponse(rawResponse) {
51951
- return isRecord13(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
50530
+ return isRecord9(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
51952
50531
  }
51953
50532
  function toolExecuteExitCode(envelope) {
51954
50533
  return envelope.status === "failed" || envelope.ok === false ? 1 : 0;
51955
50534
  }
51956
50535
  function extractToolExecutionWarningMessages(rawResponse) {
51957
- if (!isRecord13(rawResponse)) return [];
50536
+ if (!isRecord9(rawResponse)) return [];
51958
50537
  const candidates = [
51959
50538
  recordField2(recordField2(rawResponse, "toolResponse"), "meta"),
51960
50539
  recordField2(
@@ -51971,7 +50550,7 @@ function extractToolExecutionWarningMessages(rawResponse) {
51971
50550
  for (const warning of warnings) {
51972
50551
  if (typeof warning === "string" && warning.trim()) {
51973
50552
  messages.push(warning.trim());
51974
- } else if (isRecord13(warning)) {
50553
+ } else if (isRecord9(warning)) {
51975
50554
  const message = stringField2(warning, "message");
51976
50555
  if (message) messages.push(message);
51977
50556
  }
@@ -51980,7 +50559,7 @@ function extractToolExecutionWarningMessages(rawResponse) {
51980
50559
  return [...new Set(messages)];
51981
50560
  }
51982
50561
  function apifySyncRecoveryNext(rawResponse) {
51983
- if (!isRecord13(rawResponse) || rawResponse.status !== "running") return null;
50562
+ if (!isRecord9(rawResponse) || rawResponse.status !== "running") return null;
51984
50563
  const toolResponse = recordField2(rawResponse, "toolResponse");
51985
50564
  const raw = recordField2(toolResponse, "raw");
51986
50565
  if (raw.state !== "awaiting_apify") return null;
@@ -52003,7 +50582,7 @@ function apifySyncRecoveryNext(rawResponse) {
52003
50582
  }
52004
50583
  function listExtractorPathsFromUsageGuidance(tool) {
52005
50584
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
52006
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord13(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
50585
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord9(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
52007
50586
  return extractedLists.flatMap((entry) => {
52008
50587
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
52009
50588
  if (!Array.isArray(paths)) return [];
@@ -52019,7 +50598,7 @@ function formatDecimal(value) {
52019
50598
  function formatUsd(value) {
52020
50599
  return `$${formatDecimal(value)}`;
52021
50600
  }
52022
- function isRecord13(value) {
50601
+ function isRecord9(value) {
52023
50602
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
52024
50603
  }
52025
50604
  function stringField2(source, ...keys) {
@@ -52046,7 +50625,7 @@ function arrayField2(source, ...keys) {
52046
50625
  function recordField2(source, ...keys) {
52047
50626
  for (const key of keys) {
52048
50627
  const value = source[key];
52049
- if (isRecord13(value)) return value;
50628
+ if (isRecord9(value)) return value;
52050
50629
  }
52051
50630
  return {};
52052
50631
  }
@@ -52112,7 +50691,7 @@ function parseJsonObjectArgument(raw, flagName) {
52112
50691
  }
52113
50692
  throw invalidJsonError(flagName, message);
52114
50693
  }
52115
- if (!isRecord13(parsed)) {
50694
+ if (!isRecord9(parsed)) {
52116
50695
  throw invalidJsonError(flagName, "expected an object.");
52117
50696
  }
52118
50697
  return parsed;
@@ -52314,7 +50893,7 @@ function buildToolExecuteBaseEnvelope(input2) {
52314
50893
  kind: summaryEntries.length > 0 ? "object" : "raw",
52315
50894
  summary: input2.summary
52316
50895
  };
52317
- const envelopeHasCanonicalOutput = isRecord13(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
50896
+ const envelopeHasCanonicalOutput = isRecord9(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
52318
50897
  const envelopeHasDeclaredOutput = Object.prototype.hasOwnProperty.call(
52319
50898
  envelope,
52320
50899
  "output"
@@ -52341,7 +50920,7 @@ function buildToolExecuteBaseEnvelope(input2) {
52341
50920
  return {
52342
50921
  ...envelope,
52343
50922
  ...input2.idempotencyKey ? { idempotency_key: input2.idempotencyKey } : {},
52344
- ...isRecord13(input2.rawResponse) && isRecord13(input2.rawResponse.executionRecovery) ? { execution_recovery: input2.rawResponse.executionRecovery } : {},
50923
+ ...isRecord9(input2.rawResponse) && isRecord9(input2.rawResponse.executionRecovery) ? { execution_recovery: input2.rawResponse.executionRecovery } : {},
52345
50924
  ...envelopeHasCanonicalOutput || envelopeHasDeclaredOutput ? { output_preview: outputPreview } : { output: outputPreview },
52346
50925
  ...summaryEntries.length > 0 ? { summary: input2.summary } : {},
52347
50926
  ...warningMessages.length > 0 ? { warnings: warningMessages } : {},
@@ -52400,7 +50979,7 @@ function buildToolExecuteRowArtifactEnvelope(input2) {
52400
50979
  void _render;
52401
50980
  void _next;
52402
50981
  void _local;
52403
- const billingLookup = isRecord13(input2.baseEnvelope.next) && typeof input2.baseEnvelope.next.billing === "string" ? input2.baseEnvelope.next.billing : null;
50982
+ const billingLookup = isRecord9(input2.baseEnvelope.next) && typeof input2.baseEnvelope.next.billing === "string" ? input2.baseEnvelope.next.billing : null;
52404
50983
  return {
52405
50984
  ...base,
52406
50985
  status: typeof base.status === "string" ? base.status : "completed",
@@ -52576,7 +51155,7 @@ async function executeTool(args) {
52576
51155
  {
52577
51156
  ...baseEnvelope,
52578
51157
  local: {
52579
- ...isRecord13(baseEnvelope.local) ? baseEnvelope.local : {},
51158
+ ...isRecord9(baseEnvelope.local) ? baseEnvelope.local : {},
52580
51159
  payload_file: jsonPath
52581
51160
  }
52582
51161
  },
@@ -52890,7 +51469,7 @@ var PLAY_EQUIVALENT = {
52890
51469
  schema: "deepline plays describe <name>",
52891
51470
  runs: "deepline runs list --play <name>",
52892
51471
  run: "deepline runs get <run-id>",
52893
- tail: "deepline runs tail <run-id>",
51472
+ tail: "deepline runs watch <run-id>",
52894
51473
  cancel: "deepline runs stop <run-id>",
52895
51474
  delete: "deepline plays delete <name>"
52896
51475
  };