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.
package/dist/cli/index.js CHANGED
@@ -3454,7 +3454,7 @@ var SDK_RELEASE = {
3454
3454
  // getters keep their established compatibility behavior.
3455
3455
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3456
3456
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3457
- version: "0.3.236",
3457
+ version: "0.3.238",
3458
3458
  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.",
3459
3459
  packageCapabilities: {
3460
3460
  updatePreferences: 1
@@ -4103,19 +4103,19 @@ function withErrorCause(error, cause) {
4103
4103
  }
4104
4104
  return error;
4105
4105
  }
4106
- function mapNetworkError(baseUrl, error, targetLabel2) {
4106
+ function mapNetworkError(baseUrl, error, targetLabel) {
4107
4107
  const tagged = error;
4108
4108
  const timeoutMs = tagged?.[REQUEST_TIMEOUT_MARKER];
4109
4109
  if (typeof timeoutMs === "number") {
4110
4110
  return {
4111
- message: `Request to ${targetLabel2} timed out after ${timeoutMs}ms while waiting for a response.`,
4111
+ message: `Request to ${targetLabel} timed out after ${timeoutMs}ms while waiting for a response.`,
4112
4112
  code: "NETWORK_TIMEOUT",
4113
- details: { timeoutMs, target: targetLabel2 }
4113
+ details: { timeoutMs, target: targetLabel }
4114
4114
  };
4115
4115
  }
4116
4116
  if (tagged?.[REQUEST_ABORT_MARKER]) {
4117
4117
  return {
4118
- message: `Request to ${targetLabel2} was aborted before it completed.`,
4118
+ message: `Request to ${targetLabel} was aborted before it completed.`,
4119
4119
  code: "NETWORK_ABORTED"
4120
4120
  };
4121
4121
  }
@@ -4878,30 +4878,6 @@ var DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING = {
4878
4878
  windowMs: 36e5
4879
4879
  };
4880
4880
 
4881
- // src/stream-reconnect.ts
4882
- var STREAM_RECONNECT_BASE_DELAY_MS = 500;
4883
- var STREAM_RECONNECT_MAX_DELAY_MS = 15e3;
4884
- var STREAM_HEALTHY_CONNECTION_MS = 3e4;
4885
- function streamReconnectDelayMs(attempt) {
4886
- const cappedExponentialMs = Math.min(
4887
- STREAM_RECONNECT_MAX_DELAY_MS,
4888
- STREAM_RECONNECT_BASE_DELAY_MS * 2 ** Math.max(0, attempt)
4889
- );
4890
- return Math.max(1, Math.floor(Math.random() * (cappedExponentialMs + 1)));
4891
- }
4892
- function isTransientPlayStreamError(error) {
4893
- if (error instanceof DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
4894
- return true;
4895
- }
4896
- if (error instanceof DeeplineError && typeof error.statusCode === "number") {
4897
- return error.statusCode >= 500 && error.statusCode < 600;
4898
- }
4899
- const text = error instanceof Error ? error.message : String(error);
4900
- 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(
4901
- text
4902
- );
4903
- }
4904
-
4905
4881
  // ../play-runtime/live-events.ts
4906
4882
  function resolveTimingWindow(input2) {
4907
4883
  const startedAt = typeof input2.startedAt === "number" && Number.isFinite(input2.startedAt) ? input2.startedAt : null;
@@ -4917,19 +4893,6 @@ function resolveTimingWindow(input2) {
4917
4893
  // ../play-runtime/run-failure.ts
4918
4894
  var PUBLIC_FAILURE_TEXT_BYTE_LIMIT = 64 * 1024;
4919
4895
 
4920
- // ../play-runtime/run-terminal-source.ts
4921
- var PLAY_RUN_LEDGER_EVENT_SOURCES = [
4922
- "worker",
4923
- "convex",
4924
- "coordinator",
4925
- "system"
4926
- ];
4927
- function normalizePlayRunLedgerTerminalSource(value) {
4928
- return PLAY_RUN_LEDGER_EVENT_SOURCES.includes(
4929
- value
4930
- ) ? value : null;
4931
- }
4932
-
4933
4896
  // ../play-runtime/run-log-buffer.ts
4934
4897
  var RUNNER_LOG_MAX_BYTES = 5 * 1024 * 1024;
4935
4898
  var TERMINAL_RESERVE_BYTES = 64 * 1024;
@@ -5100,12 +5063,12 @@ function createSecretRedactionContext(initialValues = []) {
5100
5063
  }
5101
5064
  return output2;
5102
5065
  }
5103
- function redactString2(value) {
5066
+ function redactString(value) {
5104
5067
  const output2 = redactRegisteredSecrets(value);
5105
5068
  return redactSecretLikeString(output2);
5106
5069
  }
5107
5070
  function redact(value) {
5108
- if (typeof value === "string") return redactString2(value);
5071
+ if (typeof value === "string") return redactString(value);
5109
5072
  if (Array.isArray(value)) {
5110
5073
  let changed = false;
5111
5074
  const next = new Array(value.length);
@@ -5138,7 +5101,7 @@ function createSecretRedactionContext(initialValues = []) {
5138
5101
  return value;
5139
5102
  }
5140
5103
  function redactKnownSecrets(value) {
5141
- if (typeof value === "string") return redactString2(value);
5104
+ if (typeof value === "string") return redactString(value);
5142
5105
  if (Array.isArray(value)) {
5143
5106
  return value.map((entry) => redactKnownSecrets(entry));
5144
5107
  }
@@ -5157,7 +5120,7 @@ function createSecretRedactionContext(initialValues = []) {
5157
5120
  containsRegisteredSecret,
5158
5121
  matchesRegisteredSecret,
5159
5122
  redactRegisteredSecrets,
5160
- redactString: redactString2,
5123
+ redactString,
5161
5124
  redactKnownSecrets,
5162
5125
  redact
5163
5126
  };
@@ -5181,981 +5144,8 @@ var JSON_SIZE_LIMIT_REACHED = Symbol("JSON_SIZE_LIMIT_REACHED");
5181
5144
  var ledgerIngressRedactor = createSecretRedactionContext();
5182
5145
 
5183
5146
  // ../play-runtime/docflow-node-io.ts
5184
- var DOCFLOW_NODE_IO_LIMITS = {
5185
- maxPaths: 16,
5186
- maxDepth: 3,
5187
- maxObjectFields: 12,
5188
- maxArrayItems: 3,
5189
- maxStringBytes: 256,
5190
- maxPhaseBytes: 2e3,
5191
- maxErrorBytes: 512
5192
- };
5193
5147
  var utf8Encoder = new TextEncoder();
5194
5148
  var PLAY_DATASET_BRAND = Symbol.for("deepline.play.dataset");
5195
- var MAX_CONVEX_PREVIEW_KEY_LENGTH = 1024;
5196
- function ledgerSafeDocflowPreviewKey(key) {
5197
- const source = key.startsWith("$") ? key.replace(/^\$+/, "") || "output" : key || "output";
5198
- let encoded = "";
5199
- for (const character of source) {
5200
- const code = character.charCodeAt(0);
5201
- if (code >= 32 && code < 127) {
5202
- encoded += character;
5203
- continue;
5204
- }
5205
- for (const byte of utf8Encoder.encode(character)) {
5206
- encoded += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
5207
- }
5208
- }
5209
- if (encoded.length <= MAX_CONVEX_PREVIEW_KEY_LENGTH) return encoded;
5210
- let hashA = 2166136261;
5211
- let hashB = 2654435769;
5212
- for (let index = 0; index < encoded.length; index += 1) {
5213
- const code = encoded.charCodeAt(index);
5214
- hashA = Math.imul(hashA ^ code, 16777619);
5215
- hashB = Math.imul(hashB ^ code, 16777619);
5216
- }
5217
- const suffix = `~${(hashA >>> 0).toString(16).padStart(8, "0")}${(hashB >>> 0).toString(16).padStart(8, "0")}`;
5218
- return `${encoded.slice(0, MAX_CONVEX_PREVIEW_KEY_LENGTH - suffix.length)}${suffix}`;
5219
- }
5220
- function utf8Bytes(value) {
5221
- return utf8Encoder.encode(value).byteLength;
5222
- }
5223
- function truncateUtf8(value, maxBytes) {
5224
- if (utf8Bytes(value) <= maxBytes) return value;
5225
- let output2 = "";
5226
- for (const character of value) {
5227
- if (utf8Bytes(`${output2}${character}\u2026`) > maxBytes) break;
5228
- output2 += character;
5229
- }
5230
- return `${output2}\u2026`;
5231
- }
5232
- function redactString(redactor, value, key) {
5233
- if (!key) return redactor.redactString(value);
5234
- const wrapped = redactor.redact({ [key]: value });
5235
- return typeof wrapped[key] === "string" ? wrapped[key] : redactor.redactString(value);
5236
- }
5237
- function safeString(value, redactor, key) {
5238
- if (typeof value !== "string") return void 0;
5239
- return truncateUtf8(
5240
- redactString(redactor, value, key),
5241
- DOCFLOW_NODE_IO_LIMITS.maxStringBytes
5242
- );
5243
- }
5244
- function previewValue(value, input2) {
5245
- if (value === null) return { kind: "null" };
5246
- if (value === void 0) return { kind: "unavailable", reason: "undefined" };
5247
- if (typeof value === "string") {
5248
- return {
5249
- kind: "scalar",
5250
- value: safeString(value, input2.redactor, input2.key) ?? ""
5251
- };
5252
- }
5253
- if (typeof value === "number") {
5254
- return Number.isFinite(value) ? { kind: "scalar", value } : { kind: "unavailable", reason: "unsupported" };
5255
- }
5256
- if (typeof value === "boolean") return { kind: "scalar", value };
5257
- if (typeof value === "bigint") {
5258
- return { kind: "unavailable", reason: "bigint" };
5259
- }
5260
- if (typeof value === "function") {
5261
- return { kind: "unavailable", reason: "function" };
5262
- }
5263
- if (typeof value === "symbol") {
5264
- return { kind: "unavailable", reason: "symbol" };
5265
- }
5266
- if (typeof value !== "object") {
5267
- return { kind: "unavailable", reason: "unsupported" };
5268
- }
5269
- try {
5270
- const brand = readDataProperty(value, PLAY_DATASET_BRAND);
5271
- const datasetKind = readDataProperty(value, "datasetKind");
5272
- const datasetId = readDataProperty(value, "datasetId");
5273
- const tableNamespace = readDataProperty(value, "tableNamespace");
5274
- if (brand.ok && brand.value === true && datasetKind.ok && (datasetKind.value === "csv" || datasetKind.value === "map") && datasetId.ok && typeof datasetId.value === "string") {
5275
- return {
5276
- kind: "dataset",
5277
- datasetId: safeString(datasetId.value, input2.redactor, "datasetId") ?? "dataset",
5278
- datasetKind: datasetKind.value,
5279
- tableNamespace: tableNamespace.ok && tableNamespace.value === null ? null : tableNamespace.ok ? safeString(
5280
- tableNamespace.value,
5281
- input2.redactor,
5282
- "tableNamespace"
5283
- ) : void 0
5284
- };
5285
- }
5286
- const kind = readDataProperty(value, "kind");
5287
- const count = readDataProperty(value, "count");
5288
- const preview = readDataProperty(value, "preview");
5289
- 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)) {
5290
- return {
5291
- kind: "dataset",
5292
- datasetId: safeString(datasetId.value, input2.redactor, "datasetId") ?? "dataset",
5293
- datasetKind: datasetKind.value,
5294
- tableNamespace: tableNamespace.ok && tableNamespace.value === null ? null : tableNamespace.ok ? safeString(
5295
- tableNamespace.value,
5296
- input2.redactor,
5297
- "tableNamespace"
5298
- ) : void 0,
5299
- rowCount: Math.max(0, Math.floor(count.value))
5300
- };
5301
- }
5302
- } catch {
5303
- return { kind: "unavailable", reason: "access_error" };
5304
- }
5305
- if (input2.ancestors.has(value)) {
5306
- return { kind: "unavailable", reason: "cycle" };
5307
- }
5308
- if (input2.depth >= DOCFLOW_NODE_IO_LIMITS.maxDepth) {
5309
- return { kind: "unavailable", reason: "depth" };
5310
- }
5311
- input2.ancestors.add(value);
5312
- try {
5313
- if (Array.isArray(value)) {
5314
- const items = [];
5315
- for (let index = 0; index < Math.min(value.length, DOCFLOW_NODE_IO_LIMITS.maxArrayItems); index += 1) {
5316
- const descriptor = Object.getOwnPropertyDescriptor(
5317
- value,
5318
- String(index)
5319
- );
5320
- items.push(
5321
- descriptor && "value" in descriptor ? previewValue(descriptor.value, {
5322
- ...input2,
5323
- depth: input2.depth + 1
5324
- }) : { kind: "unavailable", reason: "access_error" }
5325
- );
5326
- }
5327
- return {
5328
- kind: "array",
5329
- items,
5330
- totalItems: value.length,
5331
- ...value.length > items.length ? { truncated: true } : {}
5332
- };
5333
- }
5334
- let descriptors;
5335
- try {
5336
- descriptors = Object.getOwnPropertyDescriptors(value);
5337
- } catch {
5338
- return { kind: "unavailable", reason: "access_error" };
5339
- }
5340
- const entries = Object.entries(descriptors).filter(
5341
- ([, descriptor]) => descriptor.enumerable
5342
- );
5343
- const selected = entries.slice(0, DOCFLOW_NODE_IO_LIMITS.maxObjectFields);
5344
- const fields2 = {};
5345
- for (const [key, descriptor] of selected) {
5346
- const safeKey = truncateUtf8(
5347
- ledgerSafeDocflowPreviewKey(input2.redactor.redactString(key)),
5348
- DOCFLOW_NODE_IO_LIMITS.maxStringBytes
5349
- );
5350
- fields2[safeKey] = "value" in descriptor ? previewValue(descriptor.value, {
5351
- ...input2,
5352
- depth: input2.depth + 1,
5353
- key
5354
- }) : { kind: "unavailable", reason: "access_error" };
5355
- }
5356
- return {
5357
- kind: "object",
5358
- fields: fields2,
5359
- totalFields: entries.length,
5360
- ...entries.length > selected.length ? { truncated: true } : {}
5361
- };
5362
- } catch {
5363
- return { kind: "unavailable", reason: "access_error" };
5364
- } finally {
5365
- input2.ancestors.delete(value);
5366
- }
5367
- }
5368
- function readDataProperty(value, property) {
5369
- if ((typeof value !== "object" || value === null) && typeof value !== "function") {
5370
- return { ok: false };
5371
- }
5372
- try {
5373
- let owner = value;
5374
- while (owner) {
5375
- const descriptor = Object.getOwnPropertyDescriptor(owner, property);
5376
- if (descriptor) {
5377
- return "value" in descriptor ? { ok: true, value: descriptor.value } : { ok: false };
5378
- }
5379
- owner = Object.getPrototypeOf(owner);
5380
- }
5381
- } catch {
5382
- return { ok: false };
5383
- }
5384
- return { ok: false };
5385
- }
5386
- function buildPlayDocflowNodeErrorPreview(error, redactor = createSecretRedactionContext()) {
5387
- try {
5388
- const message = error instanceof Error ? error.message : String(error);
5389
- return truncateUtf8(
5390
- redactor.redactString(message),
5391
- DOCFLOW_NODE_IO_LIMITS.maxErrorBytes
5392
- );
5393
- } catch {
5394
- return "Non-Error value thrown (message unavailable)";
5395
- }
5396
- }
5397
- function isRecord4(value) {
5398
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
5399
- }
5400
- function normalizePreview(value, depth) {
5401
- if (!isRecord4(value) || typeof value.kind !== "string") return null;
5402
- if (value.kind === "null") return { kind: "null" };
5403
- if (value.kind === "scalar") {
5404
- if (typeof value.value === "string" || typeof value.value === "boolean" || typeof value.value === "number" && Number.isFinite(value.value)) {
5405
- return previewValue(value.value, {
5406
- depth: 0,
5407
- ancestors: /* @__PURE__ */ new WeakSet(),
5408
- redactor: createSecretRedactionContext()
5409
- });
5410
- }
5411
- return null;
5412
- }
5413
- if (value.kind === "unavailable") {
5414
- const reason = value.reason;
5415
- return typeof reason === "string" && [
5416
- "undefined",
5417
- "function",
5418
- "symbol",
5419
- "bigint",
5420
- "cycle",
5421
- "depth",
5422
- "access_error",
5423
- "limit",
5424
- "unsupported"
5425
- ].includes(reason) ? {
5426
- kind: "unavailable",
5427
- reason
5428
- } : null;
5429
- }
5430
- if (value.kind === "dataset") {
5431
- const datasetId = safeString(
5432
- value.datasetId,
5433
- createSecretRedactionContext(),
5434
- "datasetId"
5435
- );
5436
- if (!datasetId || value.datasetKind !== "csv" && value.datasetKind !== "map") {
5437
- return null;
5438
- }
5439
- return {
5440
- kind: "dataset",
5441
- datasetId,
5442
- datasetKind: value.datasetKind,
5443
- ...value.tableNamespace === null ? { tableNamespace: null } : typeof value.tableNamespace === "string" ? {
5444
- tableNamespace: safeString(
5445
- value.tableNamespace,
5446
- createSecretRedactionContext(),
5447
- "tableNamespace"
5448
- )
5449
- } : {},
5450
- ...typeof value.rowCount === "number" && Number.isFinite(value.rowCount) ? { rowCount: Math.max(0, Math.floor(value.rowCount)) } : {}
5451
- };
5452
- }
5453
- if (depth >= DOCFLOW_NODE_IO_LIMITS.maxDepth) {
5454
- return { kind: "unavailable", reason: "depth" };
5455
- }
5456
- if (value.kind === "array" && Array.isArray(value.items)) {
5457
- const items = value.items.slice(0, DOCFLOW_NODE_IO_LIMITS.maxArrayItems).map((item) => normalizePreview(item, depth + 1)).filter((item) => item !== null);
5458
- const totalItems = typeof value.totalItems === "number" && Number.isFinite(value.totalItems) ? Math.max(items.length, Math.floor(value.totalItems)) : items.length;
5459
- return {
5460
- kind: "array",
5461
- items,
5462
- totalItems,
5463
- ...value.truncated === true || totalItems > items.length ? { truncated: true } : {}
5464
- };
5465
- }
5466
- if (value.kind === "object" && isRecord4(value.fields)) {
5467
- const fields2 = {};
5468
- for (const [key, field] of Object.entries(value.fields).slice(
5469
- 0,
5470
- DOCFLOW_NODE_IO_LIMITS.maxObjectFields
5471
- )) {
5472
- const normalized = normalizePreview(field, depth + 1);
5473
- if (normalized) fields2[ledgerSafeDocflowPreviewKey(key)] = normalized;
5474
- }
5475
- const totalFields = typeof value.totalFields === "number" && Number.isFinite(value.totalFields) ? Math.max(Object.keys(fields2).length, Math.floor(value.totalFields)) : Object.keys(fields2).length;
5476
- return {
5477
- kind: "object",
5478
- fields: fields2,
5479
- totalFields,
5480
- ...value.truncated === true || totalFields > Object.keys(fields2).length ? { truncated: true } : {}
5481
- };
5482
- }
5483
- return null;
5484
- }
5485
- function normalizePlayDocflowNodeIoState(value) {
5486
- if (!isRecord4(value)) return void 0;
5487
- const attempt = typeof value.attempt === "number" && Number.isFinite(value.attempt) ? Math.max(0, Math.floor(value.attempt)) : 0;
5488
- const normalizeMap = (raw) => {
5489
- if (!isRecord4(raw)) return void 0;
5490
- const output2 = {};
5491
- for (const [path, preview] of Object.entries(raw).slice(
5492
- 0,
5493
- DOCFLOW_NODE_IO_LIMITS.maxPaths
5494
- )) {
5495
- const normalized = normalizePreview(preview, 0);
5496
- if (!normalized) continue;
5497
- const safePath = ledgerSafeDocflowPreviewKey(path);
5498
- const candidate = { ...output2, [safePath]: normalized };
5499
- if (utf8Bytes(JSON.stringify(candidate)) > DOCFLOW_NODE_IO_LIMITS.maxPhaseBytes) {
5500
- break;
5501
- }
5502
- output2[safePath] = normalized;
5503
- }
5504
- return output2;
5505
- };
5506
- const inputs = normalizeMap(value.inputs);
5507
- const outputs = normalizeMap(value.outputs);
5508
- const error = typeof value.error === "string" ? buildPlayDocflowNodeErrorPreview(value.error) : value.error === null ? null : void 0;
5509
- return {
5510
- attempt,
5511
- ...typeof value.invocationId === "string" && value.invocationId.trim() ? {
5512
- invocationId: truncateUtf8(
5513
- value.invocationId.trim(),
5514
- DOCFLOW_NODE_IO_LIMITS.maxStringBytes
5515
- )
5516
- } : {},
5517
- ...inputs ? { inputs } : {},
5518
- ...outputs ? { outputs } : {},
5519
- ...value.inputsTruncated === true ? { inputsTruncated: true } : {},
5520
- ...value.outputsTruncated === true ? { outputsTruncated: true } : {},
5521
- ...error !== void 0 ? { error } : {}
5522
- };
5523
- }
5524
-
5525
- // ../play-runtime/activity-observation.ts
5526
- function isRecord5(value) {
5527
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
5528
- }
5529
- function isPlayActivityObservation(value) {
5530
- 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)) {
5531
- return false;
5532
- }
5533
- const targetKinds = /* @__PURE__ */ new Set([
5534
- "provider",
5535
- "dataset",
5536
- "lease",
5537
- "runner",
5538
- "step",
5539
- "capacity"
5540
- ]);
5541
- const stateKinds = /* @__PURE__ */ new Set([
5542
- "active",
5543
- "queued",
5544
- "waiting",
5545
- "retrying",
5546
- "scheduled",
5547
- "completed",
5548
- "failed"
5549
- ]);
5550
- return typeof value.target.kind === "string" && targetKinds.has(value.target.kind) && typeof value.state.kind === "string" && stateKinds.has(value.state.kind);
5551
- }
5552
- function derivePlayActivityVisibility(input2) {
5553
- const { state } = input2.observation;
5554
- if (state.kind === "failed") return "action";
5555
- if (state.kind === "waiting") {
5556
- return state.reason.kind === "external_event" ? "action" : "headline";
5557
- }
5558
- if (state.kind === "queued" || state.kind === "scheduled") return "headline";
5559
- if (state.kind === "retrying") {
5560
- if (state.reason === "rate_limit" && input2.observation.target.kind === "capacity") {
5561
- return "headline";
5562
- }
5563
- if (state.retryAt - input2.now <= 3e4) return "hidden";
5564
- return state.reason === "rate_limit" ? "headline" : "timeline";
5565
- }
5566
- if (state.kind === "active") return "headline";
5567
- return "timeline";
5568
- }
5569
- function targetLabel(target) {
5570
- switch (target.kind) {
5571
- case "provider":
5572
- return target.label ?? `${target.provider} ${target.operation}`;
5573
- case "dataset":
5574
- return target.label ?? `dataset ${target.tableNamespace}`;
5575
- case "lease":
5576
- return `${target.resourceKind} ${target.resourceLabel}`;
5577
- case "runner":
5578
- return target.label ?? `${target.backend} runner`;
5579
- case "step":
5580
- return target.label ?? target.stepId;
5581
- case "capacity":
5582
- return target.label ?? `${target.pool} capacity`;
5583
- }
5584
- }
5585
- function summarizePlayActivity(observation) {
5586
- const label = targetLabel(observation.target);
5587
- const { state } = observation;
5588
- switch (state.kind) {
5589
- case "active": {
5590
- const progress = state.progress;
5591
- const counts = typeof progress?.completed === "number" && typeof progress.total === "number" ? ` (${progress.completed}/${progress.total})` : "";
5592
- return `Active: ${label}${counts}.`;
5593
- }
5594
- case "queued":
5595
- return `Queued: waiting for ${label}.`;
5596
- case "waiting":
5597
- if (state.reason.kind === "external_event") {
5598
- const provider = state.reason.provider ? ` from ${state.reason.provider}` : "";
5599
- return `Blocked: waiting for an external event${provider}.`;
5600
- }
5601
- if (state.reason.kind === "dataset") {
5602
- return `Blocked: waiting for dataset ${state.reason.tableNamespace} to become ${state.reason.requiredPhase}.`;
5603
- }
5604
- if (state.reason.kind === "lease") {
5605
- return `Contended: waiting for ${state.reason.resourceKind} lease ${state.reason.resourceLabel}.`;
5606
- }
5607
- return `Paused: ${label}; the legacy producer did not report a typed reason.`;
5608
- case "retrying":
5609
- if (state.reason === "rate_limit") {
5610
- return `Waiting for ${label} request capacity; the run will retry automatically.`;
5611
- }
5612
- return `Delayed: ${label} will retry automatically.`;
5613
- case "scheduled":
5614
- return `Scheduled: ${label} will resume automatically.`;
5615
- case "completed":
5616
- return `Completed: ${label}.`;
5617
- case "failed":
5618
- return `Failed: ${label}.`;
5619
- }
5620
- }
5621
- function isTerminalActivityState(state) {
5622
- return state.kind === "completed" || state.kind === "failed";
5623
- }
5624
- function projection(observation, now, classified = true) {
5625
- return {
5626
- observation,
5627
- summary: summarizePlayActivity(observation),
5628
- visibility: derivePlayActivityVisibility({ observation, now }),
5629
- classified
5630
- };
5631
- }
5632
- function projectPlayRunActivity(input2) {
5633
- const now = input2.now ?? Date.now();
5634
- const observedAt = input2.updatedAt ?? now;
5635
- const normalizedStatus = input2.status.trim().toLowerCase();
5636
- if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
5637
- return null;
5638
- }
5639
- const latestExplicit = [...input2.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
5640
- const explicit = latestExplicit?.target.kind === "capacity" && latestExplicit.target.pool === "provider" && latestExplicit.state.kind === "retrying" && latestExplicit.state.retryAt < now ? null : latestExplicit;
5641
- if (explicit) return projection(explicit, now);
5642
- if (input2.waitKind === "detached_runner") {
5643
- return projection(
5644
- {
5645
- activityId: "runner:managed",
5646
- target: {
5647
- kind: "runner",
5648
- backend: input2.runtimeBackend ?? "managed",
5649
- label: "managed play runner"
5650
- },
5651
- state: { kind: "active" },
5652
- observedAt
5653
- },
5654
- now
5655
- );
5656
- }
5657
- if (input2.waitKind === "sleep") {
5658
- return projection(
5659
- {
5660
- activityId: "run:sleep",
5661
- target: {
5662
- kind: "step",
5663
- stepId: input2.activeNodeId ?? "run",
5664
- label: input2.playName ?? "play"
5665
- },
5666
- state: {
5667
- kind: "scheduled",
5668
- reason: "sleep",
5669
- resumeAt: input2.waitUntil ?? observedAt
5670
- },
5671
- observedAt
5672
- },
5673
- now
5674
- );
5675
- }
5676
- if (input2.waitKind === "integration_event" || input2.waitKind === "integration_event_batch") {
5677
- return projection(
5678
- {
5679
- activityId: `event:${input2.activeNodeId ?? "run"}`,
5680
- stepId: input2.activeNodeId ?? void 0,
5681
- target: {
5682
- kind: "step",
5683
- stepId: input2.activeNodeId ?? "run",
5684
- label: input2.playName ?? "play"
5685
- },
5686
- state: {
5687
- kind: "waiting",
5688
- reason: {
5689
- kind: "external_event",
5690
- eventKey: input2.eventKey ?? void 0,
5691
- deadlineAt: input2.waitUntil ?? void 0
5692
- }
5693
- },
5694
- observedAt
5695
- },
5696
- now
5697
- );
5698
- }
5699
- if (normalizedStatus === "waiting") {
5700
- return projection(
5701
- {
5702
- activityId: "run:legacy-wait",
5703
- target: {
5704
- kind: "step",
5705
- stepId: input2.activeNodeId ?? "run",
5706
- label: input2.playName ?? "play"
5707
- },
5708
- state: { kind: "waiting", reason: { kind: "unknown" } },
5709
- observedAt
5710
- },
5711
- now,
5712
- false
5713
- );
5714
- }
5715
- const pendingDataset = [...input2.datasets ?? []].filter(
5716
- (dataset) => dataset.phase === "registered" || dataset.complete !== true && dataset.phase !== "failed"
5717
- ).sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))[0];
5718
- if (pendingDataset) {
5719
- const activeDatasetStep = input2.nodeStates?.find(
5720
- (candidate) => candidate.nodeId === input2.activeNodeId && candidate.status === "running" && candidate.artifactTableNamespace === pendingDataset.tableNamespace
5721
- );
5722
- const datasetStep = activeDatasetStep ?? input2.nodeStates?.find(
5723
- (candidate) => candidate.artifactTableNamespace === pendingDataset.tableNamespace
5724
- );
5725
- const datasetProgress = datasetStep?.progress ?? null;
5726
- return projection(
5727
- {
5728
- activityId: `dataset:${pendingDataset.datasetId ?? pendingDataset.tableNamespace}`,
5729
- target: {
5730
- kind: "dataset",
5731
- tableNamespace: pendingDataset.tableNamespace,
5732
- operation: "materializing"
5733
- },
5734
- state: {
5735
- kind: "active",
5736
- progress: {
5737
- completed: datasetProgress?.completed ?? pendingDataset.persistedRows,
5738
- total: datasetProgress?.total ?? (typeof pendingDataset.succeededRows === "number" || typeof pendingDataset.failedRows === "number" ? (pendingDataset.succeededRows ?? 0) + (pendingDataset.failedRows ?? 0) : void 0),
5739
- failed: datasetProgress?.failed ?? pendingDataset.failedRows
5740
- }
5741
- },
5742
- observedAt: datasetStep?.updatedAt ?? pendingDataset.updatedAt ?? observedAt
5743
- },
5744
- now
5745
- );
5746
- }
5747
- const activeStep = input2.nodeStates?.find(
5748
- (candidate) => candidate.nodeId === input2.activeNodeId
5749
- ) ?? input2.nodeStates?.find((candidate) => candidate.status === "running") ?? null;
5750
- if (activeStep) {
5751
- const toolId = activeStep.nodeId.startsWith("tool:") ? activeStep.nodeId.split(":").at(-1)?.trim() || null : null;
5752
- const provider = toolId?.split(/[._]/)[0]?.trim() || null;
5753
- return projection(
5754
- {
5755
- activityId: `step:${activeStep.nodeId}`,
5756
- stepId: activeStep.nodeId,
5757
- target: toolId && provider ? {
5758
- kind: "provider",
5759
- provider,
5760
- operation: toolId,
5761
- label: activeStep.label ?? toolId
5762
- } : {
5763
- kind: "step",
5764
- stepId: activeStep.nodeId,
5765
- label: activeStep.label
5766
- },
5767
- state: {
5768
- kind: "active",
5769
- progress: activeStep.progress ?? void 0
5770
- },
5771
- observedAt: activeStep.updatedAt ?? observedAt
5772
- },
5773
- now
5774
- );
5775
- }
5776
- if (normalizedStatus === "queued") {
5777
- return projection(
5778
- {
5779
- activityId: "capacity:worker",
5780
- target: { kind: "capacity", pool: "worker" },
5781
- state: { kind: "queued", reason: "capacity" },
5782
- observedAt
5783
- },
5784
- now
5785
- );
5786
- }
5787
- const fallback = {
5788
- activityId: "run:legacy",
5789
- target: {
5790
- kind: "step",
5791
- stepId: input2.activeNodeId ?? "run",
5792
- label: input2.playName ?? "play"
5793
- },
5794
- state: normalizedStatus === "waiting" ? { kind: "waiting", reason: { kind: "unknown" } } : { kind: "active" },
5795
- observedAt
5796
- };
5797
- return projection(fallback, now, normalizedStatus !== "waiting");
5798
- }
5799
-
5800
- // ../play-runtime/cell-provenance.ts
5801
- function finiteNonNegativeInteger2(value) {
5802
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
5803
- return null;
5804
- }
5805
- return Math.trunc(value);
5806
- }
5807
- function nonEmptyString(value) {
5808
- if (typeof value !== "string") return null;
5809
- const trimmed = value.trim();
5810
- return trimmed ? trimmed : null;
5811
- }
5812
- function normalizeDatasetBornFrom(value) {
5813
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
5814
- const record3 = value;
5815
- const table = nonEmptyString(record3.table);
5816
- const rowCountIn = finiteNonNegativeInteger2(record3.rowCountIn);
5817
- if (!table || rowCountIn === null) return null;
5818
- return { table, rowCountIn };
5819
- }
5820
-
5821
- // ../play-runtime/run-ledger.ts
5822
- var LOG_TAIL_LIMIT = 100;
5823
- var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
5824
- "completed",
5825
- "failed",
5826
- "cancelled",
5827
- "terminated",
5828
- "timed_out"
5829
- ]);
5830
- function isRecord6(value) {
5831
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
5832
- }
5833
- function finiteNumber(value) {
5834
- return typeof value === "number" && Number.isFinite(value) ? value : null;
5835
- }
5836
- function nonnegativeSafeInteger(value) {
5837
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
5838
- }
5839
- function isWorkCounterSegmentId(value) {
5840
- 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(
5841
- value
5842
- );
5843
- }
5844
- function normalizePlayRunLedgerTerminalWorkCounterSegment(value) {
5845
- if (!isRecord6(value)) return void 0;
5846
- if (!nonnegativeSafeInteger(value.attempt) || !nonnegativeSafeInteger(value.invocationSeq) || value.invocationSeq === 0 || !isWorkCounterSegmentId(value.segmentId)) {
5847
- return void 0;
5848
- }
5849
- return {
5850
- attempt: value.attempt,
5851
- invocationSeq: value.invocationSeq,
5852
- segmentId: value.segmentId
5853
- };
5854
- }
5855
- function hasConfirmedPlayRunLedgerWorkCounters(snapshot) {
5856
- const counters = snapshot.workCounters;
5857
- const terminal = snapshot.terminalWorkCounterSegment;
5858
- return Boolean(
5859
- 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(
5860
- counters.completedLogicalCalls + counters.logicalCalls
5861
- ) && Number.isSafeInteger(
5862
- counters.completedProviderRequests + counters.providerRequests
5863
- ) && Number.isSafeInteger(
5864
- counters.completedProvider429s + counters.provider429s
5865
- )
5866
- );
5867
- }
5868
- function normalizeWorkCounters(value) {
5869
- if (!isRecord6(value)) return void 0;
5870
- for (const field of [
5871
- "attempt",
5872
- "invocationSeq",
5873
- "logicalCalls",
5874
- "providerRequests",
5875
- "provider429s",
5876
- "completedLogicalCalls",
5877
- "completedProviderRequests",
5878
- "completedProvider429s"
5879
- ]) {
5880
- if (!nonnegativeSafeInteger(value[field])) return void 0;
5881
- }
5882
- if (value.invocationSeq === 0 || !isWorkCounterSegmentId(value.segmentId) || typeof value.final !== "boolean" || typeof value.completeThroughAttempt !== "boolean" || typeof value.consistent !== "boolean") {
5883
- return void 0;
5884
- }
5885
- return {
5886
- ...value,
5887
- attempt: value.attempt,
5888
- invocationSeq: value.invocationSeq,
5889
- segmentId: value.segmentId,
5890
- logicalCalls: value.logicalCalls,
5891
- providerRequests: value.providerRequests,
5892
- provider429s: value.provider429s,
5893
- final: value.final,
5894
- completedLogicalCalls: value.completedLogicalCalls,
5895
- completedProviderRequests: value.completedProviderRequests,
5896
- completedProvider429s: value.completedProvider429s,
5897
- completeThroughAttempt: value.completeThroughAttempt,
5898
- consistent: value.consistent
5899
- };
5900
- }
5901
- function optionalFiniteNumber(value) {
5902
- const normalized = finiteNumber(value);
5903
- return normalized === null ? void 0 : normalized;
5904
- }
5905
- function optionalString(value) {
5906
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
5907
- }
5908
- function optionalNullableString(value) {
5909
- if (value === null) return null;
5910
- return optionalString(value);
5911
- }
5912
- function normalizePlayRunLedgerStatus(value) {
5913
- const normalized = String(value ?? "").trim().toLowerCase();
5914
- switch (normalized) {
5915
- case "queued":
5916
- case "pending":
5917
- return "queued";
5918
- case "running":
5919
- case "started":
5920
- return "running";
5921
- case "waiting":
5922
- return "waiting";
5923
- case "completed":
5924
- case "complete":
5925
- case "succeeded":
5926
- return "completed";
5927
- case "failed":
5928
- case "error":
5929
- return "failed";
5930
- case "cancelled":
5931
- case "canceled":
5932
- return "cancelled";
5933
- case "terminated":
5934
- return "terminated";
5935
- case "timed_out":
5936
- case "timeout":
5937
- return "timed_out";
5938
- default:
5939
- return "unknown";
5940
- }
5941
- }
5942
- function isTerminalPlayRunLedgerStatus(status) {
5943
- return TERMINAL_STATUSES.has(status);
5944
- }
5945
- function summarizeRunRowOutcomes(snapshot) {
5946
- let completedRows = 0;
5947
- let failedRows = 0;
5948
- let totalRows = 0;
5949
- let supersededRows = 0;
5950
- for (const step of Object.values(snapshot.stepsById)) {
5951
- const progress = step.progress;
5952
- if (!progress) continue;
5953
- completedRows += Math.max(0, finiteNumber(progress.completed) ?? 0);
5954
- failedRows += Math.max(0, finiteNumber(progress.failed) ?? 0);
5955
- supersededRows += Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
5956
- const stepTotal = finiteNumber(progress.total);
5957
- 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);
5958
- }
5959
- const resultSummary = isRecord6(snapshot.resultSummary) ? snapshot.resultSummary : null;
5960
- const resultRowOutcomes = isRecord6(resultSummary?.rowOutcomes) ? resultSummary.rowOutcomes : null;
5961
- const terminalCompletedRows = finiteNumber(resultRowOutcomes?.completedRows);
5962
- const terminalFailedRows = finiteNumber(resultRowOutcomes?.failedRows);
5963
- const terminalTotalRows = finiteNumber(resultRowOutcomes?.totalRows);
5964
- const terminalSupersededRows = finiteNumber(
5965
- resultRowOutcomes?.supersededRows
5966
- );
5967
- const settledCompletedRows = terminalCompletedRows ?? completedRows;
5968
- const settledFailedRows = terminalFailedRows ?? failedRows;
5969
- return {
5970
- completedRows: settledCompletedRows,
5971
- failedRows: settledFailedRows,
5972
- totalRows: terminalTotalRows ?? totalRows,
5973
- hasRowFailures: settledFailedRows > 0,
5974
- ...(terminalSupersededRows ?? supersededRows) > 0 ? { supersededRows: terminalSupersededRows ?? supersededRows } : {}
5975
- };
5976
- }
5977
- function createEmptyPlayRunLedgerSnapshot(input2) {
5978
- const status = normalizePlayRunLedgerStatus(input2.status ?? "unknown");
5979
- const startedAt = finiteNumber(input2.startedAt) ?? null;
5980
- const finishedAt = finiteNumber(input2.finishedAt) ?? null;
5981
- return {
5982
- runId: input2.runId,
5983
- playName: input2.playName ?? null,
5984
- status,
5985
- waitKind: null,
5986
- waitUntil: null,
5987
- error: optionalNullableString(input2.error) ?? null,
5988
- createdAt: finiteNumber(input2.createdAt) ?? null,
5989
- startedAt,
5990
- updatedAt: finiteNumber(input2.updatedAt) ?? finishedAt ?? startedAt ?? finiteNumber(input2.createdAt) ?? null,
5991
- finishedAt,
5992
- durationMs: startedAt !== null && finishedAt !== null ? Math.max(0, finishedAt - startedAt) : null,
5993
- orderedStepIds: [],
5994
- stepsById: {},
5995
- orderedDatasetIds: [],
5996
- datasetsById: {},
5997
- orderedActivityIds: [],
5998
- activitiesById: {},
5999
- logTail: [],
6000
- totalLogCount: 0,
6001
- logsTruncated: false,
6002
- activeStepId: null,
6003
- activeActivityId: null,
6004
- activeArtifactTableNamespace: null,
6005
- resultTableNamespace: null
6006
- };
6007
- }
6008
- function normalizePlayRunLedgerSnapshot(value, fallback) {
6009
- if (!isRecord6(value)) {
6010
- return createEmptyPlayRunLedgerSnapshot(fallback);
6011
- }
6012
- const orderedStepIds = Array.isArray(value.orderedStepIds) ? value.orderedStepIds.filter(
6013
- (entry) => typeof entry === "string" && Boolean(entry.trim())
6014
- ) : [];
6015
- const rawSteps = isRecord6(value.stepsById) ? value.stepsById : {};
6016
- const stepsById = {};
6017
- for (const [stepId, rawStep] of Object.entries(rawSteps)) {
6018
- if (!stepId.trim() || !isRecord6(rawStep)) continue;
6019
- const rawStatus = normalizeStepStatus(rawStep.status);
6020
- if (!rawStatus) continue;
6021
- const completedAt = finiteNumber(rawStep.completedAt);
6022
- const status = rawStatus === "running" && completedAt !== null ? "completed" : rawStatus;
6023
- const rawProgress = isRecord6(rawStep.progress) ? rawStep.progress : null;
6024
- stepsById[stepId] = {
6025
- stepId,
6026
- label: optionalString(rawStep.label),
6027
- kind: optionalString(rawStep.kind),
6028
- status,
6029
- error: optionalNullableString(rawStep.error),
6030
- artifactTableNamespace: optionalNullableString(
6031
- rawStep.artifactTableNamespace
6032
- ),
6033
- startedAt: finiteNumber(rawStep.startedAt),
6034
- completedAt,
6035
- updatedAt: finiteNumber(rawStep.updatedAt),
6036
- progress: rawProgress ? normalizeStepProgress(rawProgress) : null
6037
- };
6038
- }
6039
- const rawDatasets = isRecord6(value.datasetsById) ? value.datasetsById : {};
6040
- const datasetsById = {};
6041
- for (const [datasetId, rawDataset] of Object.entries(rawDatasets)) {
6042
- if (!datasetId.trim() || !isRecord6(rawDataset)) continue;
6043
- const phase = rawDataset.phase === "available" || rawDataset.phase === "failed" ? rawDataset.phase : "registered";
6044
- const datasetBornFrom = normalizeDatasetBornFrom(rawDataset.bornFrom);
6045
- datasetsById[datasetId] = {
6046
- datasetId,
6047
- path: optionalString(rawDataset.path) ?? `datasets.${datasetId}`,
6048
- tableNamespace: optionalString(rawDataset.tableNamespace) ?? datasetId,
6049
- phase,
6050
- persistedRows: Math.max(0, finiteNumber(rawDataset.persistedRows) ?? 0),
6051
- persistedRowsObserved: rawDataset.persistedRowsObserved === true,
6052
- succeededRows: Math.max(0, finiteNumber(rawDataset.succeededRows) ?? 0),
6053
- succeededRowsObserved: rawDataset.succeededRowsObserved === true,
6054
- failedRows: Math.max(0, finiteNumber(rawDataset.failedRows) ?? 0),
6055
- failedRowsObserved: rawDataset.failedRowsObserved === true,
6056
- complete: rawDataset.complete === true,
6057
- completeObserved: rawDataset.completeObserved === true,
6058
- // ADR 0019 birth survives the snapshot round trip. A partial record is
6059
- // dropped rather than half-admitted, so a dataset either states where its
6060
- // rows came from or says nothing.
6061
- ...datasetBornFrom ? { bornFrom: datasetBornFrom } : {},
6062
- updatedAt: finiteNumber(rawDataset.updatedAt) ?? 0
6063
- };
6064
- }
6065
- const rawActivities = isRecord6(value.activitiesById) ? value.activitiesById : {};
6066
- const activitiesById = {};
6067
- for (const [activityId, rawActivity] of Object.entries(rawActivities)) {
6068
- if (activityId.trim() && isPlayActivityObservation(rawActivity) && rawActivity.activityId === activityId) {
6069
- activitiesById[activityId] = rawActivity;
6070
- }
6071
- }
6072
- const createdAt = finiteNumber(value.createdAt) ?? fallback.createdAt ?? null;
6073
- const startedAt = finiteNumber(value.startedAt) ?? fallback.startedAt ?? null;
6074
- const finishedAt = finiteNumber(value.finishedAt) ?? fallback.finishedAt ?? null;
6075
- const updatedAt = finiteNumber(value.updatedAt) ?? fallback.updatedAt ?? finishedAt ?? startedAt ?? createdAt ?? null;
6076
- const error = Object.prototype.hasOwnProperty.call(value, "error") ? optionalNullableString(value.error) ?? null : fallback.error ?? null;
6077
- const rawTail = Array.isArray(value.logTail) ? value.logTail : value.logs;
6078
- const logTail = Array.isArray(rawTail) ? rawTail.filter((line) => typeof line === "string") : [];
6079
- const workCounters = normalizeWorkCounters(value.workCounters);
6080
- const terminalWorkCounterSegment = normalizePlayRunLedgerTerminalWorkCounterSegment(
6081
- value.terminalWorkCounterSegment
6082
- );
6083
- return {
6084
- runId: optionalString(value.runId) ?? fallback.runId,
6085
- playName: optionalNullableString(value.playName) ?? fallback.playName ?? null,
6086
- status: normalizePlayRunLedgerStatus(value.status ?? fallback.status),
6087
- waitKind: optionalNullableString(value.waitKind),
6088
- waitUntil: finiteNumber(value.waitUntil),
6089
- error,
6090
- createdAt,
6091
- startedAt,
6092
- updatedAt,
6093
- finishedAt,
6094
- durationMs: startedAt !== null && finishedAt !== null ? Math.max(0, finishedAt - startedAt) : finiteNumber(value.durationMs),
6095
- orderedStepIds: orderedStepIds.filter((stepId) => stepsById[stepId]),
6096
- stepsById,
6097
- orderedDatasetIds: (Array.isArray(value.orderedDatasetIds) ? value.orderedDatasetIds : Object.keys(datasetsById)).filter(
6098
- (datasetId) => typeof datasetId === "string" && Boolean(datasetsById[datasetId])
6099
- ),
6100
- datasetsById,
6101
- orderedActivityIds: (Array.isArray(value.orderedActivityIds) ? value.orderedActivityIds : Object.keys(activitiesById)).filter(
6102
- (activityId) => typeof activityId === "string" && Boolean(activitiesById[activityId])
6103
- ),
6104
- activitiesById,
6105
- ...workCounters ? { workCounters } : {},
6106
- ...terminalWorkCounterSegment ? { terminalWorkCounterSegment } : {},
6107
- logTail: logTail.slice(-LOG_TAIL_LIMIT),
6108
- // Snapshots persisted before totalLogCount existed only know the retained
6109
- // tail, so the best lower bound for the cumulative count is the tail size.
6110
- totalLogCount: Math.max(
6111
- finiteNumber(value.totalLogCount) ?? logTail.length,
6112
- logTail.length
6113
- ),
6114
- // A persisted snapshot carrying more lines than the tail keeps is
6115
- // truncated here, whatever the stored flag says. Reporting `false` while
6116
- // dropping lines is silent loss: a reader would take the tail for the
6117
- // whole log.
6118
- logsTruncated: value.logsTruncated === true || logTail.length > LOG_TAIL_LIMIT,
6119
- activeStepId: optionalNullableString(value.activeStepId),
6120
- activeActivityId: optionalNullableString(value.activeActivityId),
6121
- activeArtifactTableNamespace: optionalNullableString(
6122
- value.activeArtifactTableNamespace
6123
- ),
6124
- resultTableNamespace: optionalNullableString(value.resultTableNamespace),
6125
- resultSummary: value.resultSummary,
6126
- result: value.result,
6127
- terminalSource: normalizePlayRunLedgerTerminalSource(value.terminalSource)
6128
- };
6129
- }
6130
- function normalizeStepStatus(value) {
6131
- const normalized = String(value ?? "").trim().toLowerCase();
6132
- if (normalized === "running" || normalized === "completed" || normalized === "failed" || normalized === "skipped") {
6133
- return normalized;
6134
- }
6135
- return null;
6136
- }
6137
- function normalizeStepProgress(value) {
6138
- return {
6139
- ...optionalFiniteNumber(value.completed) !== void 0 ? { completed: optionalFiniteNumber(value.completed) } : {},
6140
- ...optionalFiniteNumber(value.total) !== void 0 ? { total: optionalFiniteNumber(value.total) } : {},
6141
- ...optionalFiniteNumber(value.failed) !== void 0 ? { failed: optionalFiniteNumber(value.failed) } : {},
6142
- ...optionalFiniteNumber(value.startedRows) !== void 0 ? { startedRows: optionalFiniteNumber(value.startedRows) } : {},
6143
- ...optionalFiniteNumber(value.activeRows) !== void 0 ? { activeRows: optionalFiniteNumber(value.activeRows) } : {},
6144
- ...optionalFiniteNumber(value.waitingRows) !== void 0 ? { waitingRows: optionalFiniteNumber(value.waitingRows) } : {},
6145
- ...optionalFiniteNumber(value.completedRows) !== void 0 ? { completedRows: optionalFiniteNumber(value.completedRows) } : {},
6146
- ...optionalFiniteNumber(value.supersededRows) !== void 0 ? { supersededRows: optionalFiniteNumber(value.supersededRows) } : {},
6147
- ...optionalString(value.message) ? { message: optionalString(value.message) } : {},
6148
- ...optionalNullableString(value.artifactTableNamespace) !== void 0 ? {
6149
- artifactTableNamespace: optionalNullableString(
6150
- value.artifactTableNamespace
6151
- )
6152
- } : {},
6153
- ...finiteNumber(value.startedAt) !== null ? { startedAt: finiteNumber(value.startedAt) } : {},
6154
- ...finiteNumber(value.completedAt) !== null ? { completedAt: finiteNumber(value.completedAt) } : {},
6155
- ...finiteNumber(value.updatedAt) !== null ? { updatedAt: finiteNumber(value.updatedAt) } : {},
6156
- ...normalizePlayDocflowNodeIoState(value.nodeIo) ? { nodeIo: normalizePlayDocflowNodeIoState(value.nodeIo) } : {}
6157
- };
6158
- }
6159
5149
 
6160
5150
  // ../play-runtime/run-lifecycle-policy.ts
6161
5151
  var TERMINAL_PLAY_RUN_STATUSES = /* @__PURE__ */ new Set([
@@ -6271,9 +5261,6 @@ function readProvenanceTag(line) {
6271
5261
  const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
6272
5262
  return { provenance, line: line.slice(end + 1) };
6273
5263
  }
6274
- function stripProvenanceTag(line) {
6275
- return readProvenanceTag(line).line;
6276
- }
6277
5264
  function classifyLegacyLogLine(line) {
6278
5265
  const message = stripLeadingTimestamp(line);
6279
5266
  if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
@@ -6346,143 +5333,9 @@ function stripLeadingTimestamp(line) {
6346
5333
  }
6347
5334
 
6348
5335
  // ../play-runtime/run-snapshot-stream.ts
6349
- function normalizePlayRunLiveStatus(value) {
6350
- return normalizePlayRunLifecycleStatus(value);
6351
- }
6352
5336
  function isTerminalPlayRunLiveStatus(status) {
6353
5337
  return isTerminalPlayRunLifecycleStatus(status);
6354
5338
  }
6355
- function isRecord7(value) {
6356
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
6357
- }
6358
- function finiteNumber2(value) {
6359
- return typeof value === "number" && Number.isFinite(value) ? value : null;
6360
- }
6361
- function extractTerminalRunLogTail(result) {
6362
- if (!isRecord7(result) || !isRecord7(result._metadata)) {
6363
- return null;
6364
- }
6365
- const runLogTail = result._metadata.runLogTail;
6366
- if (!isRecord7(runLogTail) || !Array.isArray(runLogTail.tail)) {
6367
- return null;
6368
- }
6369
- const logTail = runLogTail.tail.filter(
6370
- (line) => typeof line === "string" && line.trim().length > 0
6371
- );
6372
- if (logTail.length === 0) {
6373
- return null;
6374
- }
6375
- const totalLogCount = Math.max(
6376
- finiteNumber2(runLogTail.totalLogCount) ?? logTail.length,
6377
- logTail.length
6378
- );
6379
- return {
6380
- logTail: logTail.slice(-LOG_TAIL_LIMIT),
6381
- totalLogCount
6382
- };
6383
- }
6384
- function buildSnapshotFromLedger(snapshot) {
6385
- const nodeStates = snapshot.orderedStepIds.map((stepId) => snapshot.stepsById[stepId]).filter((step) => Boolean(step)).map((step) => ({
6386
- nodeId: step.stepId,
6387
- status: step.status,
6388
- error: step.error ?? null,
6389
- artifactTableNamespace: step.artifactTableNamespace ?? null,
6390
- progress: step.progress ? {
6391
- completed: step.progress.completed,
6392
- total: step.progress.total,
6393
- failed: step.progress.failed,
6394
- startedRows: step.progress.startedRows,
6395
- activeRows: step.progress.activeRows,
6396
- waitingRows: step.progress.waitingRows,
6397
- completedRows: step.progress.completedRows,
6398
- supersededRows: step.progress.supersededRows,
6399
- message: step.progress.message,
6400
- artifactTableNamespace: step.progress.artifactTableNamespace ?? step.artifactTableNamespace ?? null,
6401
- startedAt: step.startedAt ?? null,
6402
- completedAt: step.completedAt ?? null,
6403
- updatedAt: step.progress.updatedAt ?? step.updatedAt ?? null,
6404
- nodeIo: step.progress.nodeIo
6405
- } : null,
6406
- startedAt: step.startedAt ?? null,
6407
- completedAt: step.completedAt ?? null,
6408
- updatedAt: step.updatedAt ?? null,
6409
- ...step.progress?.nodeIo ? { nodeIo: step.progress.nodeIo } : {}
6410
- }));
6411
- const liveStatus = normalizePlayRunLiveStatus(snapshot.status);
6412
- const terminalRowOutcomes = isTerminalPlayRunLiveStatus(liveStatus) ? summarizeRunRowOutcomes(snapshot) : null;
6413
- const rowOutcomes = terminalRowOutcomes && (Object.keys(snapshot.stepsById).length > 0 || terminalRowOutcomes.totalRows > 0 || (terminalRowOutcomes.supersededRows ?? 0) > 0) ? terminalRowOutcomes : null;
6414
- const workCounters = snapshot.workCounters;
6415
- const calls = workCounters ? {
6416
- logicalCalls: workCounters.completedLogicalCalls + workCounters.logicalCalls,
6417
- providerRequests: workCounters.completedProviderRequests + workCounters.providerRequests,
6418
- provider429s: workCounters.completedProvider429s + workCounters.provider429s,
6419
- confirmed: isTerminalPlayRunLiveStatus(liveStatus) && hasConfirmedPlayRunLedgerWorkCounters(snapshot)
6420
- } : null;
6421
- return {
6422
- runId: snapshot.runId,
6423
- status: liveStatus,
6424
- createdAt: snapshot.createdAt ?? null,
6425
- startedAt: snapshot.startedAt ?? null,
6426
- finishedAt: snapshot.finishedAt ?? null,
6427
- durationMs: snapshot.durationMs ?? null,
6428
- updatedAt: snapshot.updatedAt ?? snapshot.finishedAt ?? snapshot.startedAt ?? null,
6429
- // This snapshot is public SDK/API transport. Keep the historical plain
6430
- // timestamp-prefixed text while provenance remains runtime metadata.
6431
- logs: snapshot.logTail.map(stripProvenanceTag),
6432
- totalLogCount: snapshot.totalLogCount,
6433
- ...snapshot.logsTruncated ? { logsTruncated: true } : {},
6434
- activeArtifactTableNamespace: snapshot.activeArtifactTableNamespace ?? null,
6435
- resultTableNamespace: snapshot.resultTableNamespace ?? null,
6436
- datasets: snapshot.orderedDatasetIds.map((datasetId) => snapshot.datasetsById[datasetId]).filter(
6437
- (dataset) => Boolean(dataset)
6438
- ),
6439
- activities: snapshot.orderedActivityIds.map((activityId) => snapshot.activitiesById[activityId]).filter(
6440
- (activity) => Boolean(activity)
6441
- ),
6442
- activeActivity: snapshot.activeActivityId ? snapshot.activitiesById[snapshot.activeActivityId] ?? null : null,
6443
- nodeStates,
6444
- activeNodeId: snapshot.activeStepId ?? null,
6445
- ...rowOutcomes ? { rowOutcomes } : {},
6446
- ...calls && Object.values(calls).every(
6447
- (value) => typeof value === "boolean" || Number.isSafeInteger(value)
6448
- ) ? { calls } : {}
6449
- };
6450
- }
6451
- function buildPlayRunStatusSnapshot(input2) {
6452
- const ledgerSnapshot = normalizePlayRunLedgerSnapshot(input2.run.runSnapshot, {
6453
- runId: input2.run.workflowId,
6454
- playName: input2.run.name ?? null,
6455
- status: input2.run.status,
6456
- createdAt: input2.run.createdAt ?? null,
6457
- startedAt: input2.run.startedAt ?? null,
6458
- updatedAt: input2.run.updatedAt ?? null,
6459
- finishedAt: input2.run.finishedAt ?? null
6460
- });
6461
- const terminalRunLogTail = extractTerminalRunLogTail(input2.run.result);
6462
- const projectedSnapshot = terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount ? buildSnapshotFromLedger({
6463
- ...ledgerSnapshot,
6464
- logTail: terminalRunLogTail.logTail,
6465
- totalLogCount: terminalRunLogTail.totalLogCount
6466
- }) : buildSnapshotFromLedger(ledgerSnapshot);
6467
- const activity = projectPlayRunActivity({
6468
- runId: input2.run.workflowId,
6469
- playName: input2.run.name,
6470
- status: projectedSnapshot.status,
6471
- updatedAt: projectedSnapshot.updatedAt,
6472
- waitKind: input2.run.waitKind ?? input2.run.wait?.kind ?? null,
6473
- waitUntil: input2.run.waitUntil,
6474
- eventKey: input2.run.wait?.eventKey ?? null,
6475
- runtimeBackend: input2.run.runtimeBackend,
6476
- activeNodeId: input2.run.activeBoundaryId ?? projectedSnapshot.activeNodeId,
6477
- nodeStates: projectedSnapshot.nodeStates,
6478
- datasets: projectedSnapshot.datasets,
6479
- explicit: projectedSnapshot.activities
6480
- });
6481
- return {
6482
- ...projectedSnapshot,
6483
- activity
6484
- };
6485
- }
6486
5339
  function makeRunStreamEvent(input2) {
6487
5340
  return {
6488
5341
  ...input2,
@@ -6565,7 +5418,7 @@ function diffLogLines(input2) {
6565
5418
  const missingCount = tailFirstSeq - 1 - input2.lastLogSeq;
6566
5419
  return {
6567
5420
  lines: [
6568
- `[stream] ${missingCount} log lines not retained in the live window; full logs via runs logs`,
5421
+ `[watch] ${missingCount} log lines not retained in the live window; full logs via runs logs`,
6569
5422
  ...logs
6570
5423
  ],
6571
5424
  lastLogSeq: totalLogCount,
@@ -6711,310 +5564,156 @@ function diffPlayRunStreamEvents(input2) {
6711
5564
  return { events, next };
6712
5565
  }
6713
5566
 
6714
- // src/runs/observe-transport.ts
6715
- var RunObserveTransportUnavailableError = class extends Error {
6716
- constructor(message, reason) {
6717
- super(message);
6718
- this.reason = reason;
6719
- this.name = "RunObserveTransportUnavailableError";
5567
+ // src/stream-reconnect.ts
5568
+ function isTransientPlayRunReadError(error) {
5569
+ if (error instanceof DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
5570
+ return true;
6720
5571
  }
6721
- };
6722
- var OBSERVE_BOOTSTRAP_TIMEOUT_MS = 1e4;
6723
- var OBSERVE_RECONNECT_NOTICE_MS = 1e4;
6724
- var OBSERVE_STALE_WARNING_MS = 12e4;
6725
- var OBSERVE_WATCHDOG_TICK_MS = 5e3;
6726
- var GRANT_REFRESH_MARGIN_MS = 5 * 6e4;
6727
- var BACKFILL_PAGE_LIMIT = 1e3;
6728
- var BACKFILL_MAX_PAGES = 30;
6729
- var OBSERVER_SNAPSHOT_QUERY = "runObservers:getPlayRunSnapshotForObserver";
6730
- var OBSERVER_LOG_PAGE_QUERY = "runObservers:getRunLogPageForObserver";
6731
- function errorText(error) {
6732
- return error instanceof Error ? error.message : String(error);
5572
+ if (error instanceof DeeplineError && typeof error.statusCode === "number") {
5573
+ return error.statusCode >= 500 && error.statusCode < 600;
5574
+ }
5575
+ const text = error instanceof Error ? error.message : String(error);
5576
+ 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(
5577
+ text
5578
+ );
6733
5579
  }
6734
- async function mintRunObserveGrant(http, runId) {
6735
- let response;
6736
- try {
6737
- response = await http.post(
6738
- `/api/v2/runs/${encodeURIComponent(runId)}/observe-grant`,
6739
- {}
6740
- );
6741
- } catch (error) {
6742
- if (error instanceof DeeplineError) {
6743
- if (error.statusCode === 401 || error.statusCode === 403) {
6744
- throw error;
6745
- }
6746
- throw new RunObserveTransportUnavailableError(
6747
- `observe-grant endpoint unavailable (${error.statusCode ?? "network"}): ${error.message}`,
6748
- "grant_endpoint_unavailable"
6749
- );
6750
- }
6751
- throw new RunObserveTransportUnavailableError(
6752
- `observe-grant request failed: ${errorText(error)}`,
6753
- "grant_request_failed"
6754
- );
5580
+
5581
+ // src/runs/watch-polling.ts
5582
+ var RUN_WATCH_POLL_INTERVAL_MS = 2e3;
5583
+ function waitForNextPoll(ms, signal) {
5584
+ if (signal?.aborted) {
5585
+ return Promise.resolve(false);
6755
5586
  }
6756
- const grant = response;
6757
- if (!grant || typeof grant.convexUrl !== "string" || !grant.convexUrl.trim() || typeof grant.token !== "string" || !grant.token.trim() || typeof grant.expiresAt !== "number") {
6758
- throw new RunObserveTransportUnavailableError(
6759
- "observe-grant endpoint returned an invalid grant payload.",
6760
- "grant_payload_invalid"
6761
- );
5587
+ return new Promise((resolve22) => {
5588
+ const finish = (elapsed) => {
5589
+ clearTimeout(timeout);
5590
+ signal?.removeEventListener("abort", onAbort);
5591
+ resolve22(elapsed);
5592
+ };
5593
+ const onAbort = () => finish(false);
5594
+ const timeout = setTimeout(() => finish(true), ms);
5595
+ signal?.addEventListener("abort", onAbort, { once: true });
5596
+ });
5597
+ }
5598
+ function readSnapshotResponse(response, runId) {
5599
+ if (!response || typeof response !== "object" || Array.isArray(response)) {
5600
+ throw new Error("Run watch returned an invalid snapshot response.");
5601
+ }
5602
+ const record3 = response;
5603
+ const snapshot = record3.snapshot;
5604
+ 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(
5605
+ (line) => typeof line === "string"
5606
+ ) || typeof snapshot.totalLogCount !== "number" || !Array.isArray(snapshot.nodeStates)) {
5607
+ throw new Error(`Run watch returned an invalid snapshot for ${runId}.`);
6762
5608
  }
6763
- return grant;
5609
+ return { runId, snapshot };
6764
5610
  }
6765
- async function backfillLogGap(input2) {
5611
+ async function backfillRotatedLogTail(input2) {
5612
+ if (!input2.previous.runSignature) {
5613
+ return input2.snapshot;
5614
+ }
5615
+ const gap = resolvePlayRunLogGap(input2.snapshot, input2.previous.lastLogSeq);
5616
+ if (!gap) {
5617
+ return input2.snapshot;
5618
+ }
6766
5619
  const lines = [];
6767
- let cursor = input2.lastLogSeq;
6768
- for (let page = 0; page < BACKFILL_MAX_PAGES; page += 1) {
6769
- if (cursor >= input2.tailFirstSeq - 1) {
6770
- break;
6771
- }
6772
- let logPage;
6773
- try {
6774
- logPage = await input2.queryLogPage(
6775
- cursor,
6776
- Math.min(BACKFILL_PAGE_LIMIT, input2.tailFirstSeq - 1 - cursor)
6777
- );
6778
- } catch {
6779
- return null;
6780
- }
6781
- const entries = (logPage?.entries ?? []).filter(
6782
- (entry) => entry.seq > cursor && entry.seq < input2.tailFirstSeq
5620
+ let cursor = input2.previous.lastLogSeq;
5621
+ const targetSeq = gap.tailFirstSeq - 1;
5622
+ while (cursor < targetSeq) {
5623
+ const limit = Math.min(1e3, targetSeq - cursor);
5624
+ const page = await input2.http.get(
5625
+ `/api/v2/runs/${encodeURIComponent(input2.runId)}/logs?afterSeq=${cursor}&limit=${limit}`,
5626
+ { signal: input2.signal }
6783
5627
  );
6784
- if (entries.length === 0) {
6785
- break;
5628
+ if (!page || !Array.isArray(page.entries) || page.entries.length === 0) {
5629
+ return input2.snapshot;
6786
5630
  }
6787
- for (const entry of entries) {
6788
- if (entry.seq !== cursor + 1) {
6789
- return null;
5631
+ for (const entry of page.entries) {
5632
+ if (!entry || entry.seq !== cursor + 1 || typeof entry.line !== "string") {
5633
+ return input2.snapshot;
6790
5634
  }
6791
5635
  lines.push(entry.line);
6792
5636
  cursor = entry.seq;
6793
5637
  }
6794
5638
  }
6795
- if (cursor < input2.tailFirstSeq - 1) {
6796
- return null;
5639
+ if (cursor !== targetSeq) {
5640
+ return input2.snapshot;
6797
5641
  }
6798
- return lines;
5642
+ return { ...input2.snapshot, logs: [...lines, ...input2.snapshot.logs] };
6799
5643
  }
6800
- async function* observeRunEvents(options) {
6801
- const { http, runId } = options;
6802
- let grant = await mintRunObserveGrant(http, runId);
6803
- let convexBrowser;
6804
- let convexServer;
6805
- try {
6806
- convexBrowser = await import("convex/browser");
6807
- convexServer = await import("convex/server");
6808
- } catch (error) {
6809
- throw new RunObserveTransportUnavailableError(
6810
- `convex client module unavailable: ${errorText(error)}`,
6811
- "convex_module_unavailable"
6812
- );
6813
- }
6814
- let webSocketConstructor;
6815
- if (typeof WebSocket === "undefined") {
5644
+ async function* watchRunEvents(options) {
5645
+ const { http, runId, signal } = options;
5646
+ const path = `/api/v2/runs/${encodeURIComponent(runId)}?watchSnapshot=true`;
5647
+ const streamId = `play-run-watch:${runId}`;
5648
+ const pollIntervalMs = options.pollIntervalMs ?? RUN_WATCH_POLL_INTERVAL_MS;
5649
+ let previous = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
5650
+ let consecutiveFailures = 0;
5651
+ let outageNoticeSent = false;
5652
+ while (!signal?.aborted) {
5653
+ const pollStartedAt = Date.now();
5654
+ let snapshot;
6816
5655
  try {
6817
- const wsModuleName = "ws";
6818
- const ws = await import(wsModuleName);
6819
- webSocketConstructor = ws.default;
6820
- } catch (error) {
6821
- throw new RunObserveTransportUnavailableError(
6822
- `no WebSocket implementation available: ${errorText(error)}`,
6823
- "websocket_unavailable"
6824
- );
6825
- }
6826
- }
6827
- const snapshotQuery = convexServer.makeFunctionReference(
6828
- OBSERVER_SNAPSHOT_QUERY
6829
- );
6830
- const logPageQuery = convexServer.makeFunctionReference(
6831
- OBSERVER_LOG_PAGE_QUERY
6832
- );
6833
- const client2 = new convexBrowser.ConvexClient(grant.convexUrl, {
6834
- ...webSocketConstructor ? { webSocketConstructor } : {},
6835
- unsavedChangesWarning: false
6836
- });
6837
- const queue = [];
6838
- let wake = null;
6839
- const push = (item) => {
6840
- queue.push(item);
6841
- wake?.();
6842
- wake = null;
6843
- };
6844
- let lastForcedRefreshAt = 0;
6845
- client2.setAuth(async ({ forceRefreshToken }) => {
6846
- const now = Date.now();
6847
- if (!forceRefreshToken && grant.expiresAt - now > GRANT_REFRESH_MARGIN_MS) {
6848
- return grant.token;
6849
- }
6850
- if (forceRefreshToken && now - lastForcedRefreshAt < 5e3) {
6851
- push({
6852
- kind: "error",
6853
- error: new DeeplineError(
6854
- `Run observe grant for ${runId} was rejected after a re-mint. The server and Convex deployment disagree on the grant issuer/JWKS.`,
6855
- 401,
6856
- "RUN_OBSERVE_GRANT_REJECTED"
6857
- )
5656
+ const response = await http.get(path, { signal });
5657
+ snapshot = await backfillRotatedLogTail({
5658
+ http,
5659
+ runId,
5660
+ snapshot: readSnapshotResponse(response, runId).snapshot,
5661
+ previous,
5662
+ signal
6858
5663
  });
6859
- return null;
6860
- }
6861
- if (forceRefreshToken) {
6862
- lastForcedRefreshAt = now;
6863
- }
6864
- try {
6865
- grant = await mintRunObserveGrant(http, runId);
6866
- return grant.token;
6867
5664
  } catch (error) {
6868
- push({ kind: "error", error });
6869
- return null;
6870
- }
6871
- });
6872
- const unsubscribe = client2.onUpdate(
6873
- snapshotQuery,
6874
- { workflowId: runId },
6875
- (run) => push({ kind: "run", run: run ?? null }),
6876
- (error) => push({ kind: "error", error })
6877
- );
6878
- let lastUpdateAt = Date.now();
6879
- let lastStatusTerminal = false;
6880
- let disconnectedSince = null;
6881
- let warnedReconnecting = false;
6882
- let warnedStale = false;
6883
- const watchdog = setInterval(() => {
6884
- const now = Date.now();
6885
- try {
6886
- const connectionState = client2.connectionState();
6887
- if (connectionState.isWebSocketConnected) {
6888
- disconnectedSince = null;
6889
- warnedReconnecting = false;
6890
- } else {
6891
- disconnectedSince ??= now;
6892
- if (!warnedReconnecting && now - disconnectedSince >= OBSERVE_RECONNECT_NOTICE_MS) {
6893
- warnedReconnecting = true;
6894
- options.onNotice?.(
6895
- `[observe] connection lost; reconnecting to live run ${runId}\u2026`
6896
- );
6897
- }
6898
- }
6899
- } catch {
6900
- }
6901
- if (!lastStatusTerminal && !warnedStale && now - lastUpdateAt >= OBSERVE_STALE_WARNING_MS) {
6902
- warnedStale = true;
6903
- options.onNotice?.(
6904
- `[observe] no live updates for ${Math.round((now - lastUpdateAt) / 1e3)}s; run ${runId} may be stalled (status checks continue)`
6905
- );
6906
- }
6907
- }, OBSERVE_WATCHDOG_TICK_MS);
6908
- watchdog.unref?.();
6909
- const abortListener = () => push({
6910
- kind: "error",
6911
- error: new DeeplineError(
6912
- "Run observation aborted.",
6913
- void 0,
6914
- "ABORTED"
6915
- )
6916
- });
6917
- options.signal?.addEventListener("abort", abortListener, { once: true });
6918
- let diffState = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
6919
- const streamId = ["observe", runId].join(":");
6920
- let sawFirstSnapshot = false;
6921
- try {
6922
- for (; ; ) {
6923
- if (queue.length === 0) {
6924
- const waitForItem = new Promise((resolve22) => {
6925
- wake = resolve22;
6926
- });
6927
- if (!sawFirstSnapshot) {
6928
- const timedOut = await Promise.race([
6929
- waitForItem.then(() => false),
6930
- new Promise(
6931
- (resolve22) => setTimeout(() => resolve22(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
6932
- )
6933
- ]);
6934
- if (timedOut && queue.length === 0) {
6935
- throw new RunObserveTransportUnavailableError(
6936
- `no snapshot from Convex at ${grant.convexUrl} within ${OBSERVE_BOOTSTRAP_TIMEOUT_MS}ms`,
6937
- "convex_unreachable"
6938
- );
6939
- }
6940
- } else {
6941
- await waitForItem;
6942
- }
6943
- continue;
6944
- }
6945
- const item = queue.shift();
6946
- if (item.kind === "error") {
6947
- if (options.signal?.aborted) {
6948
- return;
6949
- }
6950
- throw item.error;
5665
+ if (signal?.aborted) {
5666
+ return;
6951
5667
  }
6952
- sawFirstSnapshot = true;
6953
- lastUpdateAt = Date.now();
6954
- warnedStale = false;
6955
- if (item.run === null) {
6956
- throw new DeeplineError(
6957
- `Run ${runId} was not found (or is not visible to this grant).`,
6958
- 404,
6959
- "RUN_NOT_FOUND"
6960
- );
5668
+ if (!isTransientPlayRunReadError(error)) {
5669
+ throw error;
6961
5670
  }
6962
- const snapshot = buildPlayRunStatusSnapshot({ run: item.run });
6963
- lastStatusTerminal = isTerminalPlayRunLiveStatus(snapshot.status);
6964
- const gap = resolvePlayRunLogGap(snapshot, diffState.lastLogSeq);
6965
- if (gap && diffState.lastLogSeq > 0) {
6966
- const backfilled = await backfillLogGap({
6967
- queryLogPage: (afterSeq, limit) => client2.query(logPageQuery, {
6968
- workflowId: runId,
6969
- afterSeq,
6970
- limit
6971
- }),
6972
- lastLogSeq: diffState.lastLogSeq,
6973
- tailFirstSeq: gap.tailFirstSeq
5671
+ consecutiveFailures += 1;
5672
+ const reason = error instanceof Error ? error.message : String(error);
5673
+ if (!outageNoticeSent) {
5674
+ options.onRetry?.({
5675
+ attempt: consecutiveFailures,
5676
+ delayMs: pollIntervalMs,
5677
+ reason
6974
5678
  });
6975
- if (backfilled && backfilled.length > 0) {
6976
- yield {
6977
- cursor: String(snapshot.updatedAt ?? Date.now()),
6978
- streamId,
6979
- scope: "play",
6980
- type: "play.run.log",
6981
- at: (/* @__PURE__ */ new Date()).toISOString(),
6982
- payload: {
6983
- runId: snapshot.runId,
6984
- lines: backfilled,
6985
- source: "worker",
6986
- firstSeq: diffState.lastLogSeq + 1,
6987
- totalLogCount: snapshot.totalLogCount
6988
- }
6989
- };
6990
- diffState = { ...diffState, lastLogSeq: gap.tailFirstSeq - 1 };
6991
- }
6992
- }
6993
- const { events, next } = diffPlayRunStreamEvents({
6994
- streamId,
6995
- snapshot,
6996
- previous: diffState
6997
- });
6998
- diffState = next;
6999
- const ordered = [
7000
- ...events.filter((event) => event.type === "play.run.snapshot"),
7001
- ...events.filter((event) => event.type !== "play.run.snapshot")
7002
- ];
7003
- for (const event of ordered) {
7004
- yield event;
5679
+ options.onNotice?.(
5680
+ `[watch] run snapshot request failed; retrying every ${pollIntervalMs / 1e3}s (${reason})`
5681
+ );
5682
+ outageNoticeSent = true;
7005
5683
  }
7006
- if (lastStatusTerminal) {
5684
+ const remaining2 = Math.max(
5685
+ 0,
5686
+ pollIntervalMs - (Date.now() - pollStartedAt)
5687
+ );
5688
+ if (!await waitForNextPoll(remaining2, signal)) {
7007
5689
  return;
7008
5690
  }
5691
+ continue;
7009
5692
  }
7010
- } finally {
7011
- clearInterval(watchdog);
7012
- options.signal?.removeEventListener("abort", abortListener);
7013
- try {
7014
- unsubscribe();
7015
- } catch {
5693
+ if (outageNoticeSent) {
5694
+ options.onNotice?.("[watch] run snapshot polling recovered");
5695
+ outageNoticeSent = false;
5696
+ }
5697
+ consecutiveFailures = 0;
5698
+ const diff = diffPlayRunStreamEvents({
5699
+ streamId,
5700
+ snapshot,
5701
+ previous
5702
+ });
5703
+ previous = diff.next;
5704
+ for (const event of diff.events) {
5705
+ yield event;
5706
+ }
5707
+ if (isTerminalPlayRunLiveStatus(snapshot.status)) {
5708
+ return;
5709
+ }
5710
+ const remaining = Math.max(
5711
+ 0,
5712
+ pollIntervalMs - (Date.now() - pollStartedAt)
5713
+ );
5714
+ if (!await waitForNextPoll(remaining, signal)) {
5715
+ return;
7016
5716
  }
7017
- await client2.close().catch(() => void 0);
7018
5717
  }
7019
5718
  }
7020
5719
 
@@ -7345,7 +6044,7 @@ function requireTargetBillingIdempotencyKey(value) {
7345
6044
  }
7346
6045
  return normalized;
7347
6046
  }
7348
- function isRecord8(value) {
6047
+ function isRecord4(value) {
7349
6048
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
7350
6049
  }
7351
6050
  function isPrebuiltPlayDescription(play) {
@@ -7377,10 +6076,10 @@ function normalizePlayStatus(raw) {
7377
6076
  return {
7378
6077
  ...raw,
7379
6078
  runId,
7380
- ...isRecord8(legacyOverview) ? {
6079
+ ...isRecord4(legacyOverview) ? {
7381
6080
  overview: legacyOverview
7382
6081
  } : {},
7383
- ...isRecord8(runStatus) ? { runStatus } : {},
6082
+ ...isRecord4(runStatus) ? { runStatus } : {},
7384
6083
  ...runPackage ? {
7385
6084
  package: runPackage,
7386
6085
  outputs: runPackage.outputs
@@ -7519,7 +6218,7 @@ function updatePlayLiveStatusState(state, event) {
7519
6218
  }
7520
6219
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
7521
6220
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
7522
- const progressPayload = isRecord8(payload.progress) ? payload.progress : {};
6221
+ const progressPayload = isRecord4(payload.progress) ? payload.progress : {};
7523
6222
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
7524
6223
  const payloadLogs = readStringArray(payload.logs);
7525
6224
  const progressLogs = readStringArray(progressPayload.logs);
@@ -7598,6 +6297,7 @@ var DeeplineClient = class _DeeplineClient {
7598
6297
  status: (runId) => this.getRunLifecycleStatus(runId),
7599
6298
  list: (options2) => this.listRuns(options2),
7600
6299
  listPage: (options2) => this.listRunsPage(options2),
6300
+ watch: (runId, options2) => this.watchRunToTerminal(runId, options2),
7601
6301
  tail: (runId, options2) => this.tailRun(runId, options2),
7602
6302
  logs: (runId, options2) => this.getRunLogs(runId, options2),
7603
6303
  input: (runId) => this.getRunInput(runId),
@@ -7720,9 +6420,9 @@ var DeeplineClient = class _DeeplineClient {
7720
6420
  return fields2.length > 0 ? { fields: fields2 } : schema;
7721
6421
  }
7722
6422
  schemaMetadata(schema, key) {
7723
- if (!isRecord8(schema)) return null;
6423
+ if (!isRecord4(schema)) return null;
7724
6424
  const value = schema[key];
7725
- return isRecord8(value) ? value : null;
6425
+ return isRecord4(value) ? value : null;
7726
6426
  }
7727
6427
  playRunCommand(play, options) {
7728
6428
  const target = play.reference || play.name;
@@ -7777,7 +6477,7 @@ var DeeplineClient = class _DeeplineClient {
7777
6477
  aliases,
7778
6478
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
7779
6479
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
7780
- staticPipeline: isRecord8(play.staticPipeline) ? play.staticPipeline : isRecord8(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord8(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
6480
+ staticPipeline: isRecord4(play.staticPipeline) ? play.staticPipeline : isRecord4(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord4(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
7781
6481
  ...csvInput ? { csvInput } : {},
7782
6482
  ...rowOutputSchema ? { rowOutputSchema } : {},
7783
6483
  runCommand: runCommand2,
@@ -8137,15 +6837,17 @@ var DeeplineClient = class _DeeplineClient {
8137
6837
  return normalizePlayRunStart(response);
8138
6838
  }
8139
6839
  /**
8140
- * Start a play run and stream live runtime events from the same request.
6840
+ * Submit a play run through the legacy event response.
8141
6841
  *
8142
- * Use this when a caller wants low-level event handling instead of submitting
8143
- * first and then connecting to `streamPlayRunEvents(runId)`.
6842
+ * This reports admission from the start request; it does not watch an
6843
+ * existing run. Use `startPlayRun()` and `watchRunEvents(runId)` separately.
6844
+ *
6845
+ * @deprecated Use the separate start and watch methods.
8144
6846
  *
8145
6847
  * @param request - Play run configuration.
8146
- * @param options - Optional streaming options.
8147
- * @param options.signal - Optional abort signal for the streaming request.
8148
- * @returns Async stream of play-scoped live events.
6848
+ * @param options - Optional compatibility response options.
6849
+ * @param options.signal - Abort the start response.
6850
+ * @returns Async generator of play-scoped live events.
8149
6851
  */
8150
6852
  async *startPlayRunStream(request, options) {
8151
6853
  const integrationMode = resolvePlayRunIntegrationMode(request);
@@ -8627,11 +7329,23 @@ var DeeplineClient = class _DeeplineClient {
8627
7329
  );
8628
7330
  return normalizePlayStatus(response);
8629
7331
  }
7332
+ /** Poll authenticated run snapshots every two seconds and emit changed events. */
7333
+ async *watchRunEvents(workflowId, options) {
7334
+ for await (const event of watchRunEvents({
7335
+ http: this.http,
7336
+ runId: workflowId,
7337
+ signal: options?.signal,
7338
+ onNotice: options?.onNotice,
7339
+ onRetry: options?.onRetry
7340
+ })) {
7341
+ yield event;
7342
+ }
7343
+ }
8630
7344
  /**
8631
- * Stream semantic play-run events using the same SSE feed as the dashboard.
7345
+ * Read raw legacy SSE events for callers that explicitly require that
7346
+ * compatibility endpoint. Ordinary run watching uses REST snapshot polling.
8632
7347
  *
8633
- * The server emits a canonical `play.run.snapshot` event first for every
8634
- * connection, then incremental live events until terminal state or reconnect.
7348
+ * @deprecated Use `watchRunEvents` for ordinary run watching.
8635
7349
  */
8636
7350
  async *streamPlayRunEvents(workflowId, options) {
8637
7351
  const headers = options?.lastEventId && options.lastEventId.trim() ? { "Last-Event-ID": options.lastEventId.trim() } : void 0;
@@ -8646,6 +7360,68 @@ var DeeplineClient = class _DeeplineClient {
8646
7360
  }
8647
7361
  }
8648
7362
  }
7363
+ /**
7364
+ * Compatibility alias for polling canonical run snapshots and emitting
7365
+ * their changed events.
7366
+ *
7367
+ * @deprecated Use `watchRunEvents`; kept as a source-compatible alias.
7368
+ * The `fallback` option is ignored because watching uses REST polling.
7369
+ */
7370
+ async *observeRunEvents(runId, options) {
7371
+ yield* this.watchRunEvents(runId, {
7372
+ signal: options?.signal,
7373
+ onNotice: options?.onNotice
7374
+ });
7375
+ }
7376
+ /** Poll snapshots to terminal status and return the durable package. */
7377
+ async watchRunToTerminal(runId, options) {
7378
+ const state = {
7379
+ runId,
7380
+ status: "running",
7381
+ logs: [],
7382
+ lastLogSeq: 0,
7383
+ latest: null
7384
+ };
7385
+ let terminalObserved = false;
7386
+ for await (const event of this.watchRunEvents(runId, {
7387
+ signal: options?.signal,
7388
+ onNotice: options?.onNotice,
7389
+ onRetry: options?.onRetry ?? options?.onReconnect
7390
+ })) {
7391
+ options?.onEvent?.(event);
7392
+ const status = updatePlayLiveStatusState(state, event);
7393
+ if (status && TERMINAL_PLAY_STATUSES.has(status.status)) {
7394
+ terminalObserved = true;
7395
+ }
7396
+ }
7397
+ if (options?.signal?.aborted) {
7398
+ throw new DeeplineError("Run watch aborted.", void 0, "ABORTED");
7399
+ }
7400
+ if (terminalObserved) {
7401
+ return await this.getRunStatus(runId);
7402
+ }
7403
+ const refreshed = await this.getRunStatus(runId);
7404
+ if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) return refreshed;
7405
+ throw new DeeplineError(
7406
+ `Run watch for ${runId} ended before a terminal status.`,
7407
+ void 0,
7408
+ "PLAY_WATCH_ENDED"
7409
+ );
7410
+ }
7411
+ /**
7412
+ * Wait for a run and return its terminal status.
7413
+ *
7414
+ * This source-compatible alias uses the same authenticated two-second REST
7415
+ * snapshot polling as `client.runs.watch`.
7416
+ *
7417
+ * @deprecated Use `client.runs.watch`; retained for SDK compatibility.
7418
+ * @param runId - Public Deepline play-run id.
7419
+ * @param options - Optional callbacks and cancellation signal.
7420
+ * @returns The final durable run status.
7421
+ */
7422
+ async tailRun(runId, options) {
7423
+ return this.watchRunToTerminal(runId, options);
7424
+ }
8649
7425
  /**
8650
7426
  * Cancel a running play execution.
8651
7427
  *
@@ -8809,10 +7585,10 @@ var DeeplineClient = class _DeeplineClient {
8809
7585
  const responseRunStatus = isPlayRunPackage(response) ? response.runStatus : isPlayRunPackage(response.package) ? response.package.runStatus : response.runStatus;
8810
7586
  const responseOverview = isPlayRunPackage(response) ? response.overview : isPlayRunPackage(response.package) ? response.package.overview : response.overview;
8811
7587
  const status = normalizePlayStatus(response);
8812
- if (isRecord8(responseRunStatus)) {
7588
+ if (isRecord4(responseRunStatus)) {
8813
7589
  status.runStatus = responseRunStatus;
8814
7590
  }
8815
- if (isRecord8(responseOverview)) {
7591
+ if (isRecord4(responseOverview)) {
8816
7592
  status.overview = responseOverview;
8817
7593
  }
8818
7594
  if (options?.failedLogs !== true || status.status !== "failed") {
@@ -8911,222 +7687,6 @@ var DeeplineClient = class _DeeplineClient {
8911
7687
  );
8912
7688
  return { ...response, runs: response.runs ?? [] };
8913
7689
  }
8914
- /**
8915
- * Observe one run's live events. Uses the Convex Run Snapshot subscription
8916
- * transport first (ADR-0008), then falls back to the canonical SSE stream
8917
- * when the subscription transport or its optional client modules are not
8918
- * available. Pass `fallback: 'none'` to receive
8919
- * {@link RunObserveTransportUnavailableError} instead.
8920
- */
8921
- async *observeRunEvents(runId, options) {
8922
- let yieldedObserveEvent = false;
8923
- try {
8924
- for await (const event of observeRunEvents({
8925
- http: this.http,
8926
- runId,
8927
- signal: options?.signal,
8928
- onNotice: options?.onNotice
8929
- })) {
8930
- yieldedObserveEvent = true;
8931
- yield event;
8932
- }
8933
- } catch (error) {
8934
- if (!(error instanceof RunObserveTransportUnavailableError) || yieldedObserveEvent || options?.fallback === "none") {
8935
- throw error;
8936
- }
8937
- options?.onNotice?.(
8938
- `[observe] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
8939
- );
8940
- yield* this.streamPlayRunEventsUntilTerminal(runId, options);
8941
- }
8942
- }
8943
- async *streamPlayRunEventsUntilTerminal(runId, options) {
8944
- const state = {
8945
- runId,
8946
- status: "running",
8947
- logs: [],
8948
- lastLogSeq: 0,
8949
- latest: null
8950
- };
8951
- let lastEventId;
8952
- let reconnectAttempt = 0;
8953
- for (; ; ) {
8954
- if (options?.signal?.aborted) {
8955
- return;
8956
- }
8957
- const connectedAt = Date.now();
8958
- let sawEvent = false;
8959
- let endedReason = "stream window ended before a terminal event";
8960
- try {
8961
- for await (const event of this.streamPlayRunEvents(runId, {
8962
- mode: "cli",
8963
- signal: options?.signal,
8964
- ...lastEventId ? { lastEventId } : {}
8965
- })) {
8966
- sawEvent = true;
8967
- if (event.cursor?.trim()) {
8968
- lastEventId = event.cursor;
8969
- }
8970
- yield event;
8971
- const status = updatePlayLiveStatusState(state, event);
8972
- if (status && TERMINAL_PLAY_STATUSES.has(status.status)) {
8973
- return;
8974
- }
8975
- }
8976
- } catch (error) {
8977
- if (options?.signal?.aborted) {
8978
- return;
8979
- }
8980
- if (!isTransientPlayStreamError(error)) {
8981
- throw error;
8982
- }
8983
- endedReason = error instanceof Error ? error.message : String(error);
8984
- }
8985
- let refreshed = null;
8986
- try {
8987
- refreshed = await this.getRunStatus(runId);
8988
- } catch (error) {
8989
- if (!isTransientPlayStreamError(error)) {
8990
- throw error;
8991
- }
8992
- }
8993
- if (refreshed && TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
8994
- yield {
8995
- cursor: String(Date.now()),
8996
- streamId: `sse-fallback:${runId}`,
8997
- scope: "play",
8998
- type: "play.run.status",
8999
- at: (/* @__PURE__ */ new Date()).toISOString(),
9000
- payload: refreshed
9001
- };
9002
- return;
9003
- }
9004
- if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
9005
- reconnectAttempt = 0;
9006
- }
9007
- const delayMs = streamReconnectDelayMs(reconnectAttempt);
9008
- reconnectAttempt += 1;
9009
- options?.onNotice?.(
9010
- `[observe] SSE tail window ended before terminal status (${endedReason}); reconnecting to run ${runId}`
9011
- );
9012
- await sleep2(delayMs);
9013
- }
9014
- }
9015
- /**
9016
- * Tail one run through the subscription transport until terminal, then
9017
- * return one durable REST status read (the final Run Response Package).
9018
- */
9019
- async tailRunViaObserveTransport(runId, options) {
9020
- const state = {
9021
- runId,
9022
- status: "running",
9023
- logs: [],
9024
- lastLogSeq: 0,
9025
- latest: null
9026
- };
9027
- for await (const event of this.observeRunEvents(runId, {
9028
- signal: options?.signal,
9029
- onNotice: options?.onNotice,
9030
- fallback: "none"
9031
- })) {
9032
- options?.onEvent?.(event);
9033
- const status = updatePlayLiveStatusState(state, event);
9034
- if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
9035
- continue;
9036
- }
9037
- return await this.getRunStatus(status.runId || runId);
9038
- }
9039
- if (options?.signal?.aborted) {
9040
- throw new DeeplineError("Run observation aborted.", void 0, "ABORTED");
9041
- }
9042
- const refreshed = await this.getRunStatus(runId);
9043
- if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
9044
- return refreshed;
9045
- }
9046
- throw new DeeplineError(
9047
- `Run observation for ${runId} ended before a terminal status.`,
9048
- void 0,
9049
- "PLAY_LIVE_STREAM_ENDED"
9050
- );
9051
- }
9052
- /**
9053
- * Read the canonical run stream until a terminal run status is observed.
9054
- *
9055
- * Tries the Convex Run Snapshot subscription transport first (ADR-0008);
9056
- * when the server cannot serve it (grant endpoint missing/unconfigured or
9057
- * Convex unreachable) it falls back — with one `onNotice` message — to the
9058
- * support-window SSE stream below.
9059
- *
9060
- * Server stream windows are finite: they end cleanly at the function
9061
- * ceiling even while the run keeps executing. A window that ends (cleanly
9062
- * or via transient network error) without a terminal event triggers one
9063
- * durable-status re-check followed by a backed-off reconnect, so long runs
9064
- * tail to completion. Abort via `options.signal` to stop waiting.
9065
- */
9066
- async tailRun(runId, options) {
9067
- try {
9068
- return await this.tailRunViaObserveTransport(runId, options);
9069
- } catch (error) {
9070
- if (!(error instanceof RunObserveTransportUnavailableError)) {
9071
- throw error;
9072
- }
9073
- options?.onNotice?.(
9074
- `[observe] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
9075
- );
9076
- }
9077
- const state = {
9078
- runId,
9079
- status: "running",
9080
- logs: [],
9081
- lastLogSeq: 0,
9082
- latest: null
9083
- };
9084
- let reconnectAttempt = 0;
9085
- for (; ; ) {
9086
- const connectedAt = Date.now();
9087
- let sawEvent = false;
9088
- let terminalRunId = null;
9089
- let endedReason = "stream window ended before a terminal event";
9090
- try {
9091
- for await (const event of this.streamPlayRunEvents(runId, {
9092
- mode: "cli",
9093
- signal: options?.signal
9094
- })) {
9095
- options?.onEvent?.(event);
9096
- sawEvent = true;
9097
- const status = updatePlayLiveStatusState(state, event);
9098
- if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
9099
- continue;
9100
- }
9101
- terminalRunId = status.runId || runId;
9102
- break;
9103
- }
9104
- } catch (error) {
9105
- if (options?.signal?.aborted || !isTransientPlayStreamError(error)) {
9106
- throw error;
9107
- }
9108
- endedReason = error instanceof Error ? error.message : String(error);
9109
- }
9110
- if (terminalRunId) {
9111
- return await this.getRunStatus(terminalRunId);
9112
- }
9113
- const refreshed = await this.getRunStatus(runId);
9114
- if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
9115
- return refreshed;
9116
- }
9117
- if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
9118
- reconnectAttempt = 0;
9119
- }
9120
- const delayMs = streamReconnectDelayMs(reconnectAttempt);
9121
- reconnectAttempt += 1;
9122
- options?.onReconnect?.({
9123
- attempt: reconnectAttempt,
9124
- delayMs,
9125
- reason: endedReason
9126
- });
9127
- await sleep2(delayMs);
9128
- }
9129
- }
9130
7690
  /** Get the exact original input retained for a run. This is intentionally separate from status. */
9131
7691
  async getRunInput(runId) {
9132
7692
  return this.http.get(`/api/v2/runs/${encodeURIComponent(runId)}/input`);
@@ -9917,10 +8477,10 @@ var DeeplineClient = class _DeeplineClient {
9917
8477
  // Plays — high-level orchestration
9918
8478
  // ——————————————————————————————————————————————————————————
9919
8479
  /**
9920
- * Run a play end-to-end: submit, stream until terminal, return result.
8480
+ * Run a play end-to-end: submit, poll progress until terminal, return result.
9921
8481
  *
9922
8482
  * This is the highest-level play execution method. It submits the play,
9923
- * reads the canonical run stream for status updates, and returns a structured
8483
+ * reads the canonical run snapshot for status updates, and returns a structured
9924
8484
  * result with logs and timing. Supports cancellation via `AbortSignal`.
9925
8485
  *
9926
8486
  * @param code - Source string fallback; pass the bundled artifact in `options.artifact`
@@ -9976,6 +8536,7 @@ var DeeplineClient = class _DeeplineClient {
9976
8536
  lastLogSeq: 0,
9977
8537
  latest: null
9978
8538
  };
8539
+ let terminalObserved = null;
9979
8540
  if (options?.signal?.aborted) {
9980
8541
  await this.cancelPlay(workflowId);
9981
8542
  return {
@@ -9986,8 +8547,7 @@ var DeeplineClient = class _DeeplineClient {
9986
8547
  error: "Cancelled by user"
9987
8548
  };
9988
8549
  }
9989
- for await (const event of this.streamPlayRunEvents(workflowId, {
9990
- mode: "cli",
8550
+ for await (const event of this.watchRunEvents(workflowId, {
9991
8551
  signal: options?.signal
9992
8552
  })) {
9993
8553
  if (options?.signal?.aborted) {
@@ -10000,20 +8560,36 @@ var DeeplineClient = class _DeeplineClient {
10000
8560
  error: "Cancelled by user"
10001
8561
  };
10002
8562
  }
8563
+ const previousStatus = state.latest?.status;
10003
8564
  const status = updatePlayLiveStatusState(state, event);
10004
8565
  if (!status) {
10005
8566
  continue;
10006
8567
  }
10007
- options?.onProgress?.(status);
8568
+ if (event.type !== "play.run.status" || status.status !== previousStatus) {
8569
+ options?.onProgress?.(status);
8570
+ }
10008
8571
  if (TERMINAL_PLAY_STATUSES.has(status.status)) {
10009
- const finalStatus = await this.getPlayStatus(
10010
- status.runId || workflowId
10011
- ).catch(() => status);
10012
- return playRunResultFromStatus(finalStatus, start, workflowId);
8572
+ terminalObserved = status;
10013
8573
  }
10014
8574
  }
8575
+ if (options?.signal?.aborted) {
8576
+ await this.cancelPlay(workflowId);
8577
+ return {
8578
+ success: false,
8579
+ runId: workflowId,
8580
+ logs: state.logs,
8581
+ durationMs: Date.now() - start,
8582
+ error: "Cancelled by user"
8583
+ };
8584
+ }
8585
+ if (terminalObserved) {
8586
+ const finalStatus = await this.getPlayStatus(
8587
+ terminalObserved.runId || workflowId
8588
+ ).catch(() => terminalObserved);
8589
+ return playRunResultFromStatus(finalStatus, start, workflowId);
8590
+ }
10015
8591
  throw new DeeplineError(
10016
- `Run stream for ${workflowId} ended before the run reached a terminal state.`,
8592
+ `Run watch for ${workflowId} ended before the run reached a terminal state.`,
10017
8593
  void 0,
10018
8594
  "PLAY_RUN_STREAM_ENDED",
10019
8595
  { runId: workflowId, workflowId }
@@ -12899,9 +11475,13 @@ function recentUsageLines(entries) {
12899
11475
  for (const entry of entries) {
12900
11476
  const op = `${humanize(entry.provider)} ${humanize(entry.operation)}`.trim();
12901
11477
  const roughUsd = Number(entry.rough_usd_cost);
12902
- const usdText = entry.charge_state !== "pending" && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
12903
- 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}`;
12904
- const state = entry.charge_state === "temporary_hold" ? "temporary hold, final charge pending" : entry.charge_state === "pending" ? "no final charge recorded yet" : entry.status || "completed";
11478
+ const credits = entry.credits !== null && entry.credits !== void 0 && String(entry.credits).trim().length > 0 && Number.isFinite(Number(entry.credits)) ? Number(entry.credits) : null;
11479
+ const temporaryHold = entry.charge_state === "temporary_hold";
11480
+ const pending = entry.charge_state === "pending" || entry.charge_finality === "pending";
11481
+ const unknown = entry.charge_finality === "unknown" || credits === null;
11482
+ const usdText = !pending && !unknown && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
11483
+ 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}`;
11484
+ const state = temporaryHold ? "temporary hold, final charge pending" : pending ? "no final charge recorded yet" : entry.status || "unknown";
12905
11485
  const auditBits = [
12906
11486
  entry.outcome ? `outcome=${entry.outcome}` : null,
12907
11487
  entry.pricing_basis ? `priced_by=${entry.pricing_basis}` : null,
@@ -13098,6 +11678,7 @@ async function handleUsage(options) {
13098
11678
  const recentLines = recentUsageLines(
13099
11679
  Array.isArray(recent.entries) ? recent.entries : []
13100
11680
  );
11681
+ 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;
13101
11682
  const lines = options.requestId ? [`Charge lookup: ${options.requestId}`, ...recentLines] : [
13102
11683
  `Balance: ${payload.balance ?? "(unknown)"}`,
13103
11684
  `Last 30 days usage: ${last30Usage ?? "(unknown)"}`,
@@ -13106,8 +11687,10 @@ async function handleUsage(options) {
13106
11687
  ...options.runId && recent.run_id ? [
13107
11688
  `Run spend: ${(payload.run ?? {}).spent_credits ?? "(unknown)"} Deepline Credits`
13108
11689
  ] : [],
11690
+ ...matchingActivity ? [matchingActivity] : [],
13109
11691
  ...recentLines,
13110
- ...recent.has_more === true || recent.incomplete === true ? ["List truncated \u2014 more recent calls match this query."] : [],
11692
+ ...recent.has_more === true ? ["More activity pages are available."] : [],
11693
+ ...recent.incomplete === true ? ["Recent activity is incomplete; the matching count may be higher."] : [],
13111
11694
  ...nextPage ? [`Next page: ${nextPage}`] : [],
13112
11695
  ...!nextPage && (recent.has_more === true || recent.incomplete === true) ? [
13113
11696
  "No continuation is available for this view. Use deepline billing ledger export all --json for the full ledger."
@@ -13187,7 +11770,13 @@ async function handleLimitOff(options) {
13187
11770
  async function exportLedger(http, outputPath, options) {
13188
11771
  let summary = { row_count: 0, net_delta_credits: 0 };
13189
11772
  let initialized = false;
11773
+ let pageNumber = 0;
11774
+ console.error(`Exporting billing ledger to ${outputPath}`);
13190
11775
  for await (const entries of iterateCursorPages(async (cursor) => {
11776
+ pageNumber += 1;
11777
+ console.error(
11778
+ `Fetching page ${pageNumber}; ${summary.row_count} rows written.`
11779
+ );
13191
11780
  const params = new URLSearchParams({ limit: "5000" });
13192
11781
  if (cursor) params.set("cursor", cursor);
13193
11782
  if (options.sinceAt !== null)
@@ -13214,7 +11803,11 @@ async function exportLedger(http, outputPath, options) {
13214
11803
  const rows = entries.map(ledgerApiEntryToRow);
13215
11804
  await (0, import_promises2.appendFile)(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
13216
11805
  summary = summarizeLedgerRows(summary, rows);
11806
+ console.error(
11807
+ `Wrote page ${pageNumber}; ${summary.row_count} rows written.`
11808
+ );
13217
11809
  }
11810
+ console.error(`Export complete: ${summary.row_count} rows written.`);
13218
11811
  return summary;
13219
11812
  }
13220
11813
  async function handleHistory(options) {
@@ -14014,6 +12607,8 @@ function registerBillingCommands(program) {
14014
12607
  `
14015
12608
  Concepts:
14016
12609
  Billing commands show Deepline credits, not raw provider spend.
12610
+ Balance is shared by the workspace; concurrent work changes it. Use a job_id
12611
+ charge lookup to attribute one tool command instead of comparing balances.
14017
12612
  checkout/subscribe/redeem-code can open a browser unless --no-open is set.
14018
12613
 
14019
12614
  Examples:
@@ -14023,6 +12618,10 @@ Examples:
14023
12618
  deepline billing plans --json
14024
12619
  deepline billing subscription status --json
14025
12620
 
12621
+ # Price a tool before execution; look up its exact charge afterward
12622
+ deepline tools describe <tool-id> --pricing-only
12623
+ deepline billing usage --request-id <job_id> --json
12624
+
14026
12625
  # Buy credits or a plan
14027
12626
  deepline billing top-up 1000 --json
14028
12627
  deepline billing checkout --credits 1000 --no-open --json
@@ -14044,6 +12643,8 @@ Examples:
14044
12643
  `
14045
12644
  Notes:
14046
12645
  Read-only. Shows the current Deepline credit balance for the active workspace.
12646
+ The balance includes concurrent workspace activity, so a before/after difference
12647
+ cannot isolate one command. Use billing usage --request-id <job_id> --json.
14047
12648
 
14048
12649
  Examples:
14049
12650
  deepline billing balance
@@ -14056,6 +12657,9 @@ Examples:
14056
12657
  Notes:
14057
12658
  Read-only. Shows last-30-day Deepline credit usage plus a bounded recent-call
14058
12659
  page. Use --limit/--cursor to paginate the recent-call section.
12660
+ For one tool command, use the job_id returned by tools execute, or its next.billing
12661
+ command. Pending charges and temporary holds are not final spend; unknown means
12662
+ final charge evidence is unavailable. Workspace balance changes include other work.
14059
12663
 
14060
12664
  Examples:
14061
12665
  deepline billing usage
@@ -14617,24 +13221,24 @@ function sanitizeCsvProjectionInfo(input2) {
14617
13221
  const rows = input2.rows.map(stripCsvProjectionFields);
14618
13222
  return { rows, columns };
14619
13223
  }
14620
- function isRecord9(value) {
13224
+ function isRecord5(value) {
14621
13225
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
14622
13226
  }
14623
13227
  function isSerializedDataset(value) {
14624
- return isRecord9(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
13228
+ return isRecord5(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
14625
13229
  }
14626
13230
  function isPackagedDatasetOutput(value) {
14627
- return isRecord9(value) && value.kind === "dataset" && isRecord9(value.preview) && Array.isArray(value.preview.rows);
13231
+ return isRecord5(value) && value.kind === "dataset" && isRecord5(value.preview) && Array.isArray(value.preview.rows);
14628
13232
  }
14629
13233
  function hasCurrentTableExport(value) {
14630
- if (!isRecord9(value) || !isRecord9(value.actions)) return false;
13234
+ if (!isRecord5(value) || !isRecord5(value.actions)) return false;
14631
13235
  const exportCsv = value.actions.exportCsv;
14632
- return isRecord9(exportCsv) && isRecord9(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
13236
+ return isRecord5(exportCsv) && isRecord5(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
14633
13237
  }
14634
13238
  function currentTableQueryCommand(value) {
14635
- if (!isRecord9(value) || !isRecord9(value.actions)) return void 0;
13239
+ if (!isRecord5(value) || !isRecord5(value.actions)) return void 0;
14636
13240
  const query = value.actions.queryCurrentTable;
14637
- const command = isRecord9(query) ? query.command : void 0;
13241
+ const command = isRecord5(query) ? query.command : void 0;
14638
13242
  return typeof command === "string" && command.trim() ? command.trim() : void 0;
14639
13243
  }
14640
13244
  function recoveredReturnPaths(value) {
@@ -14653,7 +13257,7 @@ function pathParts(path) {
14653
13257
  function valueAtPath(root, path) {
14654
13258
  let cursor = root;
14655
13259
  for (const part of pathParts(path)) {
14656
- if (!isRecord9(cursor)) {
13260
+ if (!isRecord5(cursor)) {
14657
13261
  return void 0;
14658
13262
  }
14659
13263
  cursor = cursor[part];
@@ -14661,17 +13265,17 @@ function valueAtPath(root, path) {
14661
13265
  return cursor;
14662
13266
  }
14663
13267
  function totalRowsForDataset(result, datasetPath) {
14664
- const metadata = isRecord9(result._metadata) ? result._metadata : null;
13268
+ const metadata = isRecord5(result._metadata) ? result._metadata : null;
14665
13269
  const parentPath = datasetPath.split(".").slice(0, -1).join(".");
14666
13270
  const parent = parentPath ? valueAtPath({ result }, parentPath) : result;
14667
- return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord9(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
13271
+ return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord5(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
14668
13272
  }
14669
13273
  function rowArray(value) {
14670
13274
  if (!Array.isArray(value)) {
14671
13275
  return null;
14672
13276
  }
14673
13277
  const rows = value.filter(
14674
- (row) => isRecord9(row)
13278
+ (row) => isRecord5(row)
14675
13279
  );
14676
13280
  return rows.length === value.length ? rows : null;
14677
13281
  }
@@ -14695,7 +13299,7 @@ function inferColumns(rows) {
14695
13299
  return columns;
14696
13300
  }
14697
13301
  function columnsFromDatasetSummary(summary) {
14698
- if (!isRecord9(summary) || !isRecord9(summary.columnStats)) {
13302
+ if (!isRecord5(summary) || !isRecord5(summary.columnStats)) {
14699
13303
  return [];
14700
13304
  }
14701
13305
  return Object.keys(summary.columnStats).filter((column) => column);
@@ -14752,7 +13356,7 @@ function canonicalRowsInfoFromCandidate(input2) {
14752
13356
  candidate.value.recoveredReturnPaths
14753
13357
  )
14754
13358
  } : {},
14755
- ...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") ? {
13359
+ ...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") ? {
14756
13360
  exportUnavailableReason: candidate.value.exportUnavailable.reason,
14757
13361
  ...typeof candidate.value.exportUnavailable.message === "string" ? {
14758
13362
  exportUnavailableMessage: candidate.value.exportUnavailable.message
@@ -14800,7 +13404,7 @@ function collectDatasetCandidates(input2) {
14800
13404
  });
14801
13405
  return;
14802
13406
  }
14803
- if (!isRecord9(input2.value)) {
13407
+ if (!isRecord5(input2.value)) {
14804
13408
  return;
14805
13409
  }
14806
13410
  for (const [key, child] of Object.entries(input2.value)) {
@@ -14817,12 +13421,12 @@ function collectDatasetCandidates(input2) {
14817
13421
  }
14818
13422
  }
14819
13423
  function collectCanonicalRowsInfos(statusOrResult) {
14820
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
14821
- const result = isRecord9(root?.result) ? root.result : root;
13424
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
13425
+ const result = isRecord5(root?.result) ? root.result : root;
14822
13426
  if (!result) {
14823
13427
  return [];
14824
13428
  }
14825
- const metadata = isRecord9(result._metadata) ? result._metadata : null;
13429
+ const metadata = isRecord5(result._metadata) ? result._metadata : null;
14826
13430
  const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
14827
13431
  const candidates = [
14828
13432
  {
@@ -14846,8 +13450,8 @@ function collectCanonicalRowsInfos(statusOrResult) {
14846
13450
  total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
14847
13451
  }
14848
13452
  ];
14849
- if (isRecord9(result.output)) {
14850
- const outputMetadata = isRecord9(result.output._metadata) ? result.output._metadata : null;
13453
+ if (isRecord5(result.output)) {
13454
+ const outputMetadata = isRecord5(result.output._metadata) ? result.output._metadata : null;
14851
13455
  const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
14852
13456
  candidates.push(
14853
13457
  {
@@ -14874,14 +13478,14 @@ function collectCanonicalRowsInfos(statusOrResult) {
14874
13478
  }
14875
13479
  if (Array.isArray(result.steps)) {
14876
13480
  result.steps.forEach((step, index) => {
14877
- if (!isRecord9(step) || !isRecord9(step.output)) {
13481
+ if (!isRecord5(step) || !isRecord5(step.output)) {
14878
13482
  return;
14879
13483
  }
14880
13484
  const source = typeof step.output.path === "string" ? step.output.path : typeof step.id === "string" ? `steps.${step.id}.output` : `steps.${index}.output`;
14881
13485
  candidates.push({
14882
13486
  source,
14883
13487
  value: step.output,
14884
- total: step.output.rowCount ?? (isRecord9(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord9(step.progress) ? step.progress.total : void 0)
13488
+ total: step.output.rowCount ?? (isRecord5(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord5(step.progress) ? step.progress.total : void 0)
14885
13489
  });
14886
13490
  });
14887
13491
  }
@@ -14909,15 +13513,15 @@ function collectCanonicalRowsInfos(statusOrResult) {
14909
13513
  return infos;
14910
13514
  }
14911
13515
  function collectPackagedDatasetCandidates(statusOrResult) {
14912
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
13516
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
14913
13517
  if (!root) {
14914
13518
  return [];
14915
13519
  }
14916
- const pkg = isRecord9(root.package) ? root.package : root;
13520
+ const pkg = isRecord5(root.package) ? root.package : root;
14917
13521
  const datasets = Array.isArray(pkg.datasets) ? pkg.datasets : [];
14918
13522
  const candidates = [];
14919
13523
  for (const output2 of datasets) {
14920
- if (!isRecord9(output2) || !isPackagedDatasetOutput(output2)) {
13524
+ if (!isRecord5(output2) || !isPackagedDatasetOutput(output2)) {
14921
13525
  continue;
14922
13526
  }
14923
13527
  const source = typeof output2.path === "string" && output2.path.trim() ? output2.path.trim() : null;
@@ -14927,18 +13531,18 @@ function collectPackagedDatasetCandidates(statusOrResult) {
14927
13531
  candidates.push({
14928
13532
  source,
14929
13533
  value: output2,
14930
- total: output2.rowCount ?? (isRecord9(output2.preview) ? output2.preview.totalRows : void 0)
13534
+ total: output2.rowCount ?? (isRecord5(output2.preview) ? output2.preview.totalRows : void 0)
14931
13535
  });
14932
13536
  }
14933
13537
  return candidates;
14934
13538
  }
14935
13539
  function collectPackagedStepDatasetCandidates(statusOrResult) {
14936
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
13540
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
14937
13541
  if (!root) return [];
14938
- const pkg = isRecord9(root.package) ? root.package : root;
13542
+ const pkg = isRecord5(root.package) ? root.package : root;
14939
13543
  const steps = Array.isArray(pkg.steps) ? pkg.steps : [];
14940
13544
  return steps.flatMap((step) => {
14941
- if (!isRecord9(step) || !isPackagedDatasetOutput(step.output)) return [];
13545
+ if (!isRecord5(step) || !isPackagedDatasetOutput(step.output)) return [];
14942
13546
  const source = typeof step.output.path === "string" && step.output.path.trim() ? step.output.path.trim() : null;
14943
13547
  return source ? [
14944
13548
  {
@@ -14950,8 +13554,8 @@ function collectPackagedStepDatasetCandidates(statusOrResult) {
14950
13554
  });
14951
13555
  }
14952
13556
  function collectSerializedDatasetRowsInfos(statusOrResult) {
14953
- const root = isRecord9(statusOrResult) ? statusOrResult : null;
14954
- const result = isRecord9(root?.result) ? root.result : root;
13557
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
13558
+ const result = isRecord5(root?.result) ? root.result : root;
14955
13559
  const candidates = [];
14956
13560
  if (result) {
14957
13561
  collectDatasetCandidates({
@@ -14959,7 +13563,7 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
14959
13563
  path: "result",
14960
13564
  output: candidates
14961
13565
  });
14962
- if (isRecord9(result.output)) {
13566
+ if (isRecord5(result.output)) {
14963
13567
  collectDatasetCandidates({
14964
13568
  value: result.output,
14965
13569
  path: "result",
@@ -15042,13 +13646,13 @@ function summarizeSampleValue(value, depth = 0) {
15042
13646
  if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
15043
13647
  if (depth >= 3) {
15044
13648
  if (Array.isArray(parsed)) return [];
15045
- if (isRecord9(parsed)) return {};
13649
+ if (isRecord5(parsed)) return {};
15046
13650
  return compactScalar(parsed);
15047
13651
  }
15048
13652
  if (Array.isArray(parsed)) {
15049
13653
  return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
15050
13654
  }
15051
- if (isRecord9(parsed)) {
13655
+ if (isRecord5(parsed)) {
15052
13656
  const out = {};
15053
13657
  for (const [key, nested] of Object.entries(parsed)) {
15054
13658
  if (["__dl", "meta", "metadata"].includes(key)) {
@@ -15079,7 +13683,7 @@ function compactCell(value) {
15079
13683
  }
15080
13684
  return `[${parsed.length} items]`;
15081
13685
  }
15082
- if (isRecord9(parsed)) {
13686
+ if (isRecord5(parsed)) {
15083
13687
  for (const key of ["matched_result", "output"]) {
15084
13688
  if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
15085
13689
  return compactCell(parsed[key]);
@@ -16474,17 +15078,17 @@ function parsePositiveInteger2(value, flagName) {
16474
15078
  }
16475
15079
  return parsed;
16476
15080
  }
16477
- function isRecord10(value) {
15081
+ function isRecord6(value) {
16478
15082
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
16479
15083
  }
16480
15084
  function stringValue(value) {
16481
15085
  return typeof value === "string" ? value.trim() : "";
16482
15086
  }
16483
15087
  function extractionEntries(value) {
16484
- if (Array.isArray(value)) return value.filter(isRecord10);
16485
- if (!isRecord10(value)) return [];
15088
+ if (Array.isArray(value)) return value.filter(isRecord6);
15089
+ if (!isRecord6(value)) return [];
16486
15090
  return Object.entries(value).map(
16487
- ([name, entry]) => isRecord10(entry) ? { name, ...entry } : { name }
15091
+ ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
16488
15092
  );
16489
15093
  }
16490
15094
  var PlayBootstrapError = class extends Error {
@@ -17045,7 +15649,7 @@ function readCsvSampleRows(sample) {
17045
15649
  relax_column_count: true,
17046
15650
  trim: true
17047
15651
  });
17048
- return Array.isArray(parsedRows) ? parsedRows.filter(isRecord10) : [];
15652
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord6) : [];
17049
15653
  }
17050
15654
  function readSourceCsvColumnSpecs(csvPath) {
17051
15655
  const sample = readCsvSample(csvPath);
@@ -17078,16 +15682,16 @@ function packagedCsvPathForPlay(csvPath) {
17078
15682
  return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
17079
15683
  }
17080
15684
  function getterNamesFromTool(tool, kind) {
17081
- const usageGuidance = isRecord10(tool?.usageGuidance) ? tool.usageGuidance : {};
17082
- const resultGuidance = isRecord10(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord10(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
15685
+ const usageGuidance = isRecord6(tool?.usageGuidance) ? tool.usageGuidance : {};
15686
+ const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
17083
15687
  const key = kind === "list" ? "extractedLists" : "extractedValues";
17084
15688
  const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
17085
15689
  return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
17086
15690
  }
17087
15691
  function targetGettersFromTool(tool) {
17088
- const record3 = isRecord10(tool) ? tool : {};
15692
+ const record3 = isRecord6(tool) ? tool : {};
17089
15693
  const raw = record3.targetGetters ?? record3.target_getters;
17090
- if (!isRecord10(raw)) return {};
15694
+ if (!isRecord6(raw)) return {};
17091
15695
  const entries = [];
17092
15696
  for (const [target, value] of Object.entries(raw)) {
17093
15697
  const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
@@ -17108,10 +15712,10 @@ function listRowCandidateKeysFromTool(tool) {
17108
15712
  return [...keys].sort();
17109
15713
  }
17110
15714
  function inputPropertyNames(schema) {
17111
- if (!isRecord10(schema)) return [];
17112
- if (isRecord10(schema.properties)) return Object.keys(schema.properties);
15715
+ if (!isRecord6(schema)) return [];
15716
+ if (isRecord6(schema.properties)) return Object.keys(schema.properties);
17113
15717
  if (Array.isArray(schema.fields)) {
17114
- return schema.fields.filter(isRecord10).map((field) => stringValue(field.name)).filter(Boolean);
15718
+ return schema.fields.filter(isRecord6).map((field) => stringValue(field.name)).filter(Boolean);
17115
15719
  }
17116
15720
  return [];
17117
15721
  }
@@ -17125,7 +15729,7 @@ function schemaFieldDetails(schema) {
17125
15729
  return { required, optional };
17126
15730
  }
17127
15731
  function jsonSchemaTypeExpression(schema) {
17128
- if (!isRecord10(schema)) return "unknown";
15732
+ if (!isRecord6(schema)) return "unknown";
17129
15733
  const type = schema.type;
17130
15734
  if (Array.isArray(type)) {
17131
15735
  return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
@@ -17155,7 +15759,7 @@ function jsonSchemaTypeExpression(schema) {
17155
15759
  }
17156
15760
  }
17157
15761
  function objectPropertySchema(schema, property) {
17158
- return isRecord10(schema) && isRecord10(schema.properties) ? schema.properties[property] : null;
15762
+ return isRecord6(schema) && isRecord6(schema.properties) ? schema.properties[property] : null;
17159
15763
  }
17160
15764
  function playOutputHasField(schema, field) {
17161
15765
  return objectPropertySchema(schema, field) != null;
@@ -17331,14 +15935,14 @@ ${indent2.slice(2)}}`;
17331
15935
  }
17332
15936
  function requiredPlayInputFields(play) {
17333
15937
  const schema = play?.inputSchema;
17334
- if (!isRecord10(schema)) return [];
15938
+ if (!isRecord6(schema)) return [];
17335
15939
  if (Array.isArray(schema.required)) {
17336
15940
  return schema.required.filter(
17337
15941
  (value) => typeof value === "string"
17338
15942
  );
17339
15943
  }
17340
15944
  if (Array.isArray(schema.fields)) {
17341
- return schema.fields.filter(isRecord10).filter(
15945
+ return schema.fields.filter(isRecord6).filter(
17342
15946
  (field) => field.required === true && typeof field.name === "string"
17343
15947
  ).map((field) => String(field.name));
17344
15948
  }
@@ -17519,7 +16123,7 @@ function validateBootstrapRoutes(input2) {
17519
16123
  }
17520
16124
  }
17521
16125
  function staticPipelineSubsteps(pipeline) {
17522
- if (!isRecord10(pipeline)) return [];
16126
+ if (!isRecord6(pipeline)) return [];
17523
16127
  return [
17524
16128
  ...extractionEntries(pipeline.stages),
17525
16129
  ...extractionEntries(pipeline.substeps)
@@ -17527,7 +16131,7 @@ function staticPipelineSubsteps(pipeline) {
17527
16131
  }
17528
16132
  function playUsesMapBackedRuntime(play) {
17529
16133
  const pipeline = play?.staticPipeline;
17530
- if (!isRecord10(pipeline)) return false;
16134
+ if (!isRecord6(pipeline)) return false;
17531
16135
  if (stringValue(pipeline.tableNamespace)) return true;
17532
16136
  return staticPipelineSubsteps(pipeline).some((substep) => {
17533
16137
  if (stringValue(substep.type) === "map") return true;
@@ -17536,7 +16140,7 @@ function playUsesMapBackedRuntime(play) {
17536
16140
  aliases: [],
17537
16141
  runCommand: "",
17538
16142
  examples: [],
17539
- staticPipeline: isRecord10(substep.pipeline) ? substep.pipeline : null
16143
+ staticPipeline: isRecord6(substep.pipeline) ? substep.pipeline : null
17540
16144
  });
17541
16145
  });
17542
16146
  }
@@ -22865,35 +21469,35 @@ async function runDeployment(params, hooks) {
22865
21469
  } catch (error) {
22866
21470
  if (revokedFinalStatus(error)) throw error;
22867
21471
  const body = error instanceof DeployApiError ? error.body : null;
22868
- const errorText2 = body?.error ?? (error instanceof Error ? error.message : String(error));
22869
- if (/PLAY_DEPLOYMENT_NOT_ACTIVE/.test(errorText2)) {
21472
+ const errorText = body?.error ?? (error instanceof Error ? error.message : String(error));
21473
+ if (/PLAY_DEPLOYMENT_NOT_ACTIVE/.test(errorText)) {
22870
21474
  console.info("[deploy-worker] cancelled at promote", {
22871
21475
  deploymentId: params.deploymentId
22872
21476
  });
22873
21477
  return { finalStatus: "cancelled", outcomes: [] };
22874
21478
  }
22875
- if (/PLAY_DEPLOYMENT_STALE/.test(errorText2)) {
21479
+ if (/PLAY_DEPLOYMENT_STALE/.test(errorText)) {
22876
21480
  console.info("[deploy-worker] superseded at promote", {
22877
21481
  deploymentId: params.deploymentId
22878
21482
  });
22879
21483
  await setStatus({
22880
21484
  status: "superseded",
22881
- error: errorText2.slice(0, 2e3),
21485
+ error: errorText.slice(0, 2e3),
22882
21486
  buildSeconds: buildSeconds()
22883
21487
  });
22884
21488
  return { finalStatus: "superseded", outcomes: [] };
22885
21489
  }
22886
21490
  return await failWithCheck({
22887
21491
  title: "Deploy failed during promotion",
22888
- summary: errorText2,
22889
- error: errorText2,
21492
+ summary: errorText,
21493
+ error: errorText,
22890
21494
  outcomes: [
22891
21495
  ...outcomes,
22892
21496
  ...(body?.outcomes ?? toPromote).map((entry) => ({
22893
21497
  name: entry.name,
22894
21498
  file: playByName.get(entry.name)?.file ?? entry.name,
22895
21499
  status: "failed",
22896
- error: ("error" in entry ? entry.error : void 0) ?? errorText2
21500
+ error: ("error" in entry ? entry.error : void 0) ?? errorText
22897
21501
  }))
22898
21502
  ]
22899
21503
  });
@@ -24768,7 +23372,7 @@ function playStatusErrorText(status) {
24768
23372
  function isRetryablePendingStartFailure(status) {
24769
23373
  if (status.status !== "failed") return false;
24770
23374
  if (status.runId && status.runId !== "pending") return false;
24771
- return isTransientPlayStreamError(new Error(playStatusErrorText(status)));
23375
+ return isTransientPlayRunReadError(new Error(playStatusErrorText(status)));
24772
23376
  }
24773
23377
  function pendingStartFailureStatus(input2) {
24774
23378
  const message = input2.error instanceof Error ? input2.error.message : String(input2.error);
@@ -25303,7 +23907,7 @@ function assertPlayWaitNotTimedOut(input2) {
25303
23907
  if (input2.waitTimeoutMs !== null && Date.now() - input2.startedAt >= input2.waitTimeoutMs) {
25304
23908
  const hasRealRunId = input2.workflowId.length > 0 && input2.workflowId !== "pending";
25305
23909
  const phaseSuffix = input2.lastPhase && input2.lastPhase.trim() ? ` (last observed phase: ${input2.lastPhase.trim()})` : "";
25306
- 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.`;
23910
+ 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.`;
25307
23911
  throw new DeeplineError(
25308
23912
  `Timed out waiting for play ${hasRealRunId ? input2.workflowId : "<no run id>"} after ${Math.ceil(input2.waitTimeoutMs / 1e3)}s${phaseSuffix}.${tailHint}`,
25309
23913
  void 0,
@@ -25316,63 +23920,54 @@ function assertPlayWaitNotTimedOut(input2) {
25316
23920
  );
25317
23921
  }
25318
23922
  }
25319
- var PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS = 15e3;
23923
+ var RUN_WATCH_RETRY_INTERVAL_MS = 2e3;
25320
23924
  function isAdmittedRunVisibilityDelay(error) {
25321
23925
  return error instanceof DeeplineError && error.statusCode === 404 && error.message.trim() === "Workflow run not found.";
25322
23926
  }
25323
- async function waitForPlayCompletionByStream(input2) {
23927
+ async function waitForPlayCompletionByWatch(input2) {
25324
23928
  let lastPhase = null;
25325
- let reconnectAttempt = 0;
25326
- const durableStatusProbeIntervalMs = input2.durableStatusProbeIntervalMs ?? PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS;
25327
- let nextDurableProbeAt = Date.now() + durableStatusProbeIntervalMs;
25328
- let durableStatusProbe = null;
25329
23929
  let admissionConfirmed = false;
23930
+ let visibilityNoticeSent = false;
23931
+ let terminalStatusRead = null;
23932
+ const controller = new AbortController();
23933
+ let timedOut = false;
23934
+ const remainingWaitMs = () => input2.waitTimeoutMs === null ? null : input2.waitTimeoutMs - (Date.now() - input2.startedAt);
23935
+ const remaining = remainingWaitMs();
23936
+ const timeout = remaining === null ? null : setTimeout(
23937
+ () => {
23938
+ timedOut = true;
23939
+ controller.abort();
23940
+ },
23941
+ Math.max(1, remaining)
23942
+ );
25330
23943
  const confirmAdmission = async () => {
25331
23944
  if (admissionConfirmed) return;
25332
23945
  admissionConfirmed = true;
25333
23946
  await input2.onRunAdmitted?.(input2.workflowId);
25334
23947
  };
25335
23948
  const withDashboardUrl = (status) => input2.dashboardUrl ? { ...status, dashboardUrl: input2.dashboardUrl } : status;
25336
- const remainingWaitMs = () => input2.waitTimeoutMs === null ? null : input2.waitTimeoutMs - (Date.now() - input2.startedAt);
25337
23949
  const fetchTerminalStatus = async () => {
25338
- if (durableStatusProbe) return durableStatusProbe;
25339
- const probe = (async () => {
25340
- let refreshed;
25341
- try {
25342
- refreshed = await input2.client.getPlayStatus(input2.workflowId, {
25343
- billing: false
25344
- });
25345
- } catch (error) {
25346
- if (isTransientPlayStreamError(error) || isAdmittedRunVisibilityDelay(error)) {
25347
- return null;
25348
- }
25349
- throw error;
25350
- }
25351
- if (refreshed.runId === input2.workflowId && statusProvesPlayRunExecution(refreshed.status)) {
25352
- await confirmAdmission();
25353
- }
25354
- return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? withDashboardUrl(refreshed) : null;
25355
- })();
25356
- durableStatusProbe = probe;
23950
+ let refreshed;
25357
23951
  try {
25358
- return await probe;
25359
- } finally {
25360
- if (durableStatusProbe === probe) durableStatusProbe = null;
23952
+ refreshed = await input2.client.getPlayStatus(input2.workflowId, {
23953
+ billing: false
23954
+ });
23955
+ } catch (error) {
23956
+ if (isTransientPlayRunReadError(error) || isAdmittedRunVisibilityDelay(error)) {
23957
+ return null;
23958
+ }
23959
+ throw error;
23960
+ }
23961
+ if (refreshed.runId === input2.workflowId && statusProvesPlayRunExecution(refreshed.status)) {
23962
+ await confirmAdmission();
25361
23963
  }
23964
+ return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? withDashboardUrl(refreshed) : null;
25362
23965
  };
25363
- const handleLiveEvent = async (event, probeDurableStatus) => {
23966
+ const handleLiveEvent = async (event) => {
25364
23967
  assertPlayWaitNotTimedOut({ ...input2, lastPhase });
25365
23968
  if (getRunIdFromLiveEvent(event) === input2.workflowId && (eventConfirmsPlayRunLaunch(event) || eventProvesPlayRunExecution(event))) {
25366
23969
  await confirmAdmission();
25367
23970
  }
25368
- const now = Date.now();
25369
- if (now >= nextDurableProbeAt) {
25370
- nextDurableProbeAt = now + durableStatusProbeIntervalMs;
25371
- const durableTerminal = await probeDurableStatus();
25372
- if (durableTerminal) {
25373
- return durableTerminal;
25374
- }
25375
- }
25376
23971
  const phase = describeLiveEventPhase(event);
25377
23972
  if (phase) {
25378
23973
  lastPhase = phase;
@@ -25423,144 +24018,57 @@ async function waitForPlayCompletionByStream(input2) {
25423
24018
  }
25424
24019
  }
25425
24020
  const finalStatus = getFinalStatusFromLiveEvent(event);
25426
- if (finalStatus) {
24021
+ if (event.type === "play.run.final_status" && finalStatus) {
25427
24022
  return withDashboardUrl(finalStatus);
25428
24023
  }
25429
24024
  const status = getStatusFromLiveEvent(event);
25430
24025
  if (status && TERMINAL_PLAY_STATUSES2.has(status)) {
25431
- const refreshedStatus = await probeDurableStatus();
25432
- if (refreshedStatus) return refreshedStatus;
24026
+ terminalStatusRead ??= fetchTerminalStatus();
24027
+ return await terminalStatusRead;
25433
24028
  }
25434
24029
  return null;
25435
24030
  };
25436
- const streamOneWindow = async () => {
25437
- const controller = new AbortController();
25438
- let timedOut = false;
25439
- let sawEvent = false;
25440
- let durableTerminal = null;
25441
- let durableProbeError = null;
25442
- let durableProbeTimer = null;
25443
- const remaining = remainingWaitMs();
25444
- const timeout = remaining === null ? null : setTimeout(
25445
- () => {
25446
- timedOut = true;
25447
- controller.abort();
25448
- },
25449
- Math.max(1, remaining)
25450
- );
25451
- const scheduleDurableStatusProbe = () => {
25452
- durableProbeTimer = setTimeout(() => {
25453
- durableProbeTimer = null;
25454
- if (controller.signal.aborted) return;
25455
- nextDurableProbeAt = Date.now() + durableStatusProbeIntervalMs;
25456
- void fetchTerminalStatus().then((status) => {
25457
- if (controller.signal.aborted) return;
25458
- if (status) {
25459
- durableTerminal = status;
25460
- controller.abort();
25461
- return;
25462
- }
25463
- scheduleDurableStatusProbe();
25464
- }).catch((error) => {
25465
- if (controller.signal.aborted) return;
25466
- durableProbeError = error;
25467
- controller.abort();
25468
- });
25469
- }, durableStatusProbeIntervalMs);
25470
- };
25471
- try {
25472
- scheduleDurableStatusProbe();
25473
- for await (const event of input2.client.streamPlayRunEvents(
25474
- input2.workflowId,
25475
- { signal: controller.signal }
25476
- )) {
25477
- sawEvent = true;
25478
- if (durableTerminal) {
25479
- return { kind: "terminal", status: durableTerminal };
24031
+ try {
24032
+ for (; ; ) {
24033
+ try {
24034
+ let terminalFromWatch = null;
24035
+ for await (const event of input2.client.watchRunEvents(
24036
+ input2.workflowId,
24037
+ { signal: controller.signal }
24038
+ )) {
24039
+ const terminal3 = await handleLiveEvent(event);
24040
+ if (terminal3) terminalFromWatch = terminal3;
25480
24041
  }
25481
- const terminal = await handleLiveEvent(event, fetchTerminalStatus);
25482
- if (terminal) {
25483
- return { kind: "terminal", status: terminal };
24042
+ if (terminalFromWatch) return terminalFromWatch;
24043
+ } catch (error) {
24044
+ if (timedOut || controller.signal.aborted) break;
24045
+ if (!isAdmittedRunVisibilityDelay(error)) throw error;
24046
+ if (!visibilityNoticeSent && !input2.jsonOutput) {
24047
+ input2.progress.writeLine(
24048
+ `[play watch] run is accepted and waiting for its snapshot; checking again in ${RUN_WATCH_RETRY_INTERVAL_MS / 1e3}s`
24049
+ );
24050
+ visibilityNoticeSent = true;
25484
24051
  }
25485
24052
  }
25486
- } catch (error) {
25487
- if (timedOut) {
25488
- return { kind: "timed_out", sawEvent };
25489
- }
25490
- if (durableTerminal) {
25491
- return { kind: "terminal", status: durableTerminal };
25492
- }
25493
- if (durableProbeError) {
25494
- throw durableProbeError;
25495
- }
25496
- if (!isTransientPlayStreamError(error) && !isAdmittedRunVisibilityDelay(error)) {
25497
- throw error;
25498
- }
25499
- return {
25500
- kind: "ended",
25501
- sawEvent,
25502
- reason: error instanceof Error ? error.message : String(error)
25503
- };
25504
- } finally {
25505
- if (timeout) {
25506
- clearTimeout(timeout);
25507
- }
25508
- if (durableProbeTimer) {
25509
- clearTimeout(durableProbeTimer);
25510
- }
25511
- controller.abort();
25512
- }
25513
- if (timedOut) {
25514
- return { kind: "timed_out", sawEvent };
25515
- }
25516
- if (durableTerminal) {
25517
- return { kind: "terminal", status: durableTerminal };
25518
- }
25519
- if (durableProbeError) {
25520
- throw durableProbeError;
25521
- }
25522
- return {
25523
- kind: "ended",
25524
- sawEvent,
25525
- reason: "stream window ended before a terminal event"
25526
- };
25527
- };
25528
- for (; ; ) {
25529
- const connectedAt = Date.now();
25530
- const window = await streamOneWindow();
25531
- if (window.kind === "terminal") {
25532
- return window.status;
24053
+ const terminal2 = await fetchTerminalStatus();
24054
+ if (terminal2) return terminal2;
24055
+ assertPlayWaitNotTimedOut({ ...input2, lastPhase });
24056
+ const nextWait = remainingWaitMs();
24057
+ await sleep5(
24058
+ nextWait === null ? RUN_WATCH_RETRY_INTERVAL_MS : Math.min(RUN_WATCH_RETRY_INTERVAL_MS, Math.max(1, nextWait))
24059
+ );
25533
24060
  }
25534
24061
  const terminal = await fetchTerminalStatus();
25535
- if (terminal) {
25536
- return terminal;
25537
- }
24062
+ if (terminal) return terminal;
25538
24063
  assertPlayWaitNotTimedOut({ ...input2, lastPhase });
25539
- if (window.sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
25540
- reconnectAttempt = 0;
25541
- }
25542
- const delayMs = streamReconnectDelayMs(reconnectAttempt);
25543
- reconnectAttempt += 1;
25544
- const reason = window.kind === "ended" ? window.reason : "wait timeout raced the stream";
25545
- if (!input2.jsonOutput) {
25546
- input2.progress.writeLine(
25547
- `[play watch] stream ended without a terminal status; reconnecting to run ${input2.workflowId} (${reason})`
25548
- );
25549
- }
25550
- recordCliTrace({
25551
- phase: "cli.play_tail_stream_reconnect",
25552
- ms: Date.now() - input2.startedAt,
25553
- ok: true,
25554
- playName: input2.playName,
25555
- workflowId: input2.workflowId,
25556
- attempt: reconnectAttempt,
25557
- delayMs,
25558
- reason
25559
- });
25560
- const remainingBeforeSleep = remainingWaitMs();
25561
- await sleep5(
25562
- remainingBeforeSleep === null ? delayMs : Math.min(delayMs, Math.max(1, remainingBeforeSleep))
24064
+ throw new DeeplineError(
24065
+ `Run watch for ${input2.workflowId} ended before a terminal status.`,
24066
+ void 0,
24067
+ "PLAY_WATCH_ENDED"
25563
24068
  );
24069
+ } finally {
24070
+ if (timeout) clearTimeout(timeout);
24071
+ controller.abort();
25564
24072
  }
25565
24073
  }
25566
24074
  async function startAndWaitForPlayCompletionByStream(input2) {
@@ -25637,7 +24145,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25637
24145
  billing: false
25638
24146
  });
25639
24147
  } catch (error) {
25640
- if (isTransientPlayStreamError(error)) {
24148
+ if (isTransientPlayRunReadError(error)) {
25641
24149
  return null;
25642
24150
  }
25643
24151
  throw error;
@@ -25808,7 +24316,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25808
24316
  firstRunIdMs,
25809
24317
  lastPhase
25810
24318
  });
25811
- return waitForPlayCompletionByStream({
24319
+ return waitForPlayCompletionByWatch({
25812
24320
  client: input2.client,
25813
24321
  playName: input2.playName,
25814
24322
  workflowId: lastKnownWorkflowId,
@@ -25847,7 +24355,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25847
24355
  lastPhase
25848
24356
  });
25849
24357
  }
25850
- if (lastKnownWorkflowId && isTransientPlayStreamError(error)) {
24358
+ if (lastKnownWorkflowId && isTransientPlayRunReadError(error)) {
25851
24359
  if (timeout) {
25852
24360
  clearTimeout(timeout);
25853
24361
  }
@@ -25869,7 +24377,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25869
24377
  lastPhase,
25870
24378
  reason
25871
24379
  });
25872
- return waitForPlayCompletionByStream({
24380
+ return waitForPlayCompletionByWatch({
25873
24381
  client: input2.client,
25874
24382
  playName: input2.playName,
25875
24383
  workflowId: lastKnownWorkflowId,
@@ -25883,7 +24391,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25883
24391
  onRunAdmitted: confirmAdmission
25884
24392
  });
25885
24393
  }
25886
- if (!lastKnownWorkflowId && isTransientPlayStreamError(error)) {
24394
+ if (!lastKnownWorkflowId && isTransientPlayRunReadError(error)) {
25887
24395
  recordCliTrace({
25888
24396
  phase: "cli.play_start_stream_transient_failure",
25889
24397
  ms: Date.now() - startedAt,
@@ -25923,7 +24431,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25923
24431
  lastPhase,
25924
24432
  reason: "stream ended before terminal event"
25925
24433
  });
25926
- return waitForPlayCompletionByStream({
24434
+ return waitForPlayCompletionByWatch({
25927
24435
  client: input2.client,
25928
24436
  playName: input2.playName,
25929
24437
  workflowId: lastKnownWorkflowId,
@@ -25940,7 +24448,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
25940
24448
  const phaseSuffix = lastPhase && lastPhase.trim() ? ` (last observed phase: ${lastPhase.trim()})` : "";
25941
24449
  const idSuffix = lastKnownWorkflowId ? ` runId=${lastKnownWorkflowId}` : "";
25942
24450
  throw new DeeplineError(
25943
- `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>'.`,
24451
+ `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>'.`,
25944
24452
  void 0,
25945
24453
  "PLAY_START_STREAM_ENDED",
25946
24454
  {
@@ -28053,7 +26561,7 @@ function extractPlayValidationErrors(value) {
28053
26561
  if (value instanceof DeeplineError) {
28054
26562
  return extractPlayValidationErrors(value.details);
28055
26563
  }
28056
- if (!isRecord11(value)) {
26564
+ if (!isRecord7(value)) {
28057
26565
  return [];
28058
26566
  }
28059
26567
  const directErrors = stringArrayField(value, "errors");
@@ -28449,7 +26957,7 @@ function parsePlayRunOptions(args) {
28449
26957
  }
28450
26958
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
28451
26959
  throw new Error(
28452
- `${arg} was removed. --watch uses the canonical run stream directly.`
26960
+ `${arg} was removed. --watch polls the canonical run snapshot.`
28453
26961
  );
28454
26962
  }
28455
26963
  if ((arg === "--tail-timeout-ms" || arg === "--timeout-ms") && args[index + 1]) {
@@ -28717,7 +27225,7 @@ function formatPlayRuntimeLimit(runtimeLimit) {
28717
27225
  if (seconds % 60 === 0) return `${seconds / 60} min`;
28718
27226
  return `${seconds} sec`;
28719
27227
  }
28720
- function isRecord11(value) {
27228
+ function isRecord7(value) {
28721
27229
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
28722
27230
  }
28723
27231
  function stringValue3(value) {
@@ -28727,14 +27235,14 @@ function asArray(value) {
28727
27235
  return Array.isArray(value) ? value : [];
28728
27236
  }
28729
27237
  function extractionEntries2(value) {
28730
- if (Array.isArray(value)) return value.filter(isRecord11);
28731
- if (!isRecord11(value)) return [];
27238
+ if (Array.isArray(value)) return value.filter(isRecord7);
27239
+ if (!isRecord7(value)) return [];
28732
27240
  return Object.entries(value).map(
28733
- ([name, entry]) => isRecord11(entry) ? { name, ...entry } : { name }
27241
+ ([name, entry]) => isRecord7(entry) ? { name, ...entry } : { name }
28734
27242
  );
28735
27243
  }
28736
27244
  function firstRawPath(entry) {
28737
- const details = isRecord11(entry.details) ? entry.details : {};
27245
+ const details = isRecord7(entry.details) ? entry.details : {};
28738
27246
  const paths = [
28739
27247
  ...asArray(details.rawToolOutputPaths),
28740
27248
  ...asArray(details.raw_tool_output_paths),
@@ -28752,12 +27260,12 @@ function checkHintRawPath(value) {
28752
27260
  function collectStaticPipelineToolIds(staticPipeline) {
28753
27261
  const seen = /* @__PURE__ */ new Set();
28754
27262
  const visitPipeline = (pipeline) => {
28755
- if (!isRecord11(pipeline)) return;
27263
+ if (!isRecord7(pipeline)) return;
28756
27264
  for (const step of [
28757
27265
  ...asArray(pipeline.stages),
28758
27266
  ...asArray(pipeline.substeps)
28759
27267
  ]) {
28760
- if (!isRecord11(step)) continue;
27268
+ if (!isRecord7(step)) continue;
28761
27269
  if (step.type === "tool") {
28762
27270
  const toolId = stringValue3(step.toolId) || stringValue3(step.tool);
28763
27271
  if (toolId) seen.add(toolId);
@@ -28771,9 +27279,9 @@ function collectStaticPipelineToolIds(staticPipeline) {
28771
27279
  return [...seen].sort();
28772
27280
  }
28773
27281
  function toolGetterHintFromMetadata(toolId, tool) {
28774
- const usageGuidance = isRecord11(tool.usageGuidance) ? tool.usageGuidance : {};
28775
- const resultGuidance = isRecord11(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord11(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
28776
- const toolResponse = isRecord11(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord11(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
27282
+ const usageGuidance = isRecord7(tool.usageGuidance) ? tool.usageGuidance : {};
27283
+ const resultGuidance = isRecord7(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord7(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
27284
+ const toolResponse = isRecord7(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord7(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
28777
27285
  const lists = extractionEntries2(
28778
27286
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
28779
27287
  ).map((entry) => ({
@@ -29136,7 +27644,7 @@ function artifactForProductionCompatibilityCheck(artifact) {
29136
27644
  "DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
29137
27645
  );
29138
27646
  }
29139
- const compatibility = isRecord11(artifact.compatibility) ? artifact.compatibility : {};
27647
+ const compatibility = isRecord7(artifact.compatibility) ? artifact.compatibility : {};
29140
27648
  return {
29141
27649
  ...artifact,
29142
27650
  compatibility: {
@@ -29941,7 +28449,23 @@ async function handleRunsList(args) {
29941
28449
  }
29942
28450
  }
29943
28451
  if (!playName && !statusFilter) {
29944
- console.error(usage);
28452
+ const message = "runs list requires --play or --status.";
28453
+ const next = {
28454
+ discover: "deepline plays list --json",
28455
+ running: "deepline runs list --status running --json"
28456
+ };
28457
+ console.error(
28458
+ `${message}
28459
+ ${usage}
28460
+ Discover Plays: ${next.discover}
28461
+ Active runs: ${next.running}`
28462
+ );
28463
+ if (argsWantJson(args)) {
28464
+ printCommandEnvelope(
28465
+ { ok: false, exitCode: 1, code: "RUN_FILTER_REQUIRED", message, next },
28466
+ { json: true }
28467
+ );
28468
+ }
29945
28469
  return 1;
29946
28470
  }
29947
28471
  if ((offset ?? 0) > 0 && !playName) {
@@ -30020,7 +28544,7 @@ async function handleRunsList(args) {
30020
28544
  return 0;
30021
28545
  }
30022
28546
  async function handleRunTail(args) {
30023
- const usage = "Usage: deepline runs tail <run-id> [--json | --jsonl] [--compact] [--log-level debug|info|warn|error]";
28547
+ const usage = "Usage: deepline runs watch <run-id> [--json | --jsonl] [--compact] [--log-level debug|info|warn|error]";
30024
28548
  let runId;
30025
28549
  try {
30026
28550
  runId = parseRunIdPositional(args, usage);
@@ -30035,7 +28559,7 @@ async function handleRunTail(args) {
30035
28559
  const arg = args[index];
30036
28560
  if (arg === "--cursor") {
30037
28561
  console.error(
30038
- "--cursor was removed. deepline runs tail reads the canonical run stream."
28562
+ "--cursor was removed. deepline runs watch polls the canonical run snapshot."
30039
28563
  );
30040
28564
  return 1;
30041
28565
  }
@@ -30061,7 +28585,7 @@ async function handleRunTail(args) {
30061
28585
  continue;
30062
28586
  }
30063
28587
  if (arg.startsWith("--") && arg !== "--json" && arg !== "--jsonl" && arg !== "--compact") {
30064
- console.error(`${arg} is not supported by deepline runs tail.`);
28588
+ console.error(`${arg} is not supported by deepline runs watch.`);
30065
28589
  return 1;
30066
28590
  }
30067
28591
  }
@@ -30097,7 +28621,7 @@ async function handleRunTail(args) {
30097
28621
  verbose: debug,
30098
28622
  logLevel
30099
28623
  };
30100
- const status = await client2.runs.tail(runId, {
28624
+ const status = await client2.runs.watch(runId, {
30101
28625
  onEvent: jsonLines ? (event) => {
30102
28626
  process.stdout.write(
30103
28627
  `${JSON.stringify({
@@ -30143,9 +28667,9 @@ async function handleRunTail(args) {
30143
28667
  }
30144
28668
  } : void 0,
30145
28669
  // Human mode only: in --json mode emit nothing non-protocol.
30146
- onReconnect: jsonOutput && !debug && !hasExplicitLogLevel ? void 0 : ({ reason }) => {
28670
+ onRetry: jsonOutput && !debug && !hasExplicitLogLevel ? void 0 : ({ reason }) => {
30147
28671
  process.stderr.write(
30148
- `[runs tail] stream ended without a terminal status; reconnecting to run ${runId} (${reason})
28672
+ `[runs watch] snapshot polling failed; retrying for run ${runId} (${reason})
30149
28673
  `
30150
28674
  );
30151
28675
  }
@@ -31812,7 +30336,10 @@ Examples:
31812
30336
  ).option(
31813
30337
  "--log-level <level>",
31814
30338
  "Minimum live log severity: debug, info (default), warn, or error"
31815
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
30339
+ ).option(
30340
+ "--tail-timeout-ms <ms>",
30341
+ "Timeout while waiting for terminal run status"
30342
+ ).option("--force", "Start a fresh run graph").option(
31816
30343
  "--force-tool-refresh",
31817
30344
  "Refresh completed tool receipts; may repeat billed provider calls"
31818
30345
  ).option(
@@ -32282,13 +30809,13 @@ Concepts:
32282
30809
  stop mutates cloud state by requesting cancellation.
32283
30810
 
32284
30811
  Debug a run:
32285
- Active: deepline runs tail <run-id> --log-level debug
30812
+ Active: deepline runs watch <run-id> --log-level debug
32286
30813
  Historical: deepline runs logs <run-id> --out run.log --log-level debug --json
32287
30814
  Full state: deepline runs get <run-id> --full --json
32288
30815
 
32289
30816
  Examples:
32290
30817
  deepline runs get play/my-play/run/20260501t000000-000 --json
32291
- deepline runs tail play/my-play/run/20260501t000000-000
30818
+ deepline runs watch play/my-play/run/20260501t000000-000
32292
30819
  deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --log-level debug --json
32293
30820
  deepline runs list --play my-play --status failed --json
32294
30821
  deepline runs list --status running --json
@@ -32374,11 +30901,15 @@ Examples:
32374
30901
  "after",
32375
30902
  `
32376
30903
  Notes:
30904
+ Requires --play or --status. Discover Play references with deepline plays list --json.
32377
30905
  Bounded inventory for a play's recent runs. Use --compact for agent loops.
30906
+ Use the exact qualified Play reference, such as workspace/my-play or prebuilt/my-play.
30907
+ --offset requires --play; narrow status-only lists with a Play reference to paginate.
32378
30908
  Common statuses include running, completed, failed, and stopped.
32379
30909
 
32380
30910
  Examples:
32381
30911
  deepline runs list --play my-play
30912
+ deepline runs list --play workspace/my-play --json
32382
30913
  deepline runs list --play my-play --status failed --compact --json
32383
30914
  deepline runs list --status running --compact --json
32384
30915
  `
@@ -32418,29 +30949,30 @@ Examples:
32418
30949
  ...options.json ? ["--json"] : []
32419
30950
  ]);
32420
30951
  });
32421
- runs.command("tail <runId>").description("Read the canonical live stream for a play run.").addHelpText(
30952
+ runs.command("watch <runId>").alias("tail").description("Poll the canonical run snapshot until terminal status.").addHelpText(
32422
30953
  "after",
32423
30954
  `
32424
30955
  Notes:
32425
- Streams live run events until the stream ends. Human output shows info and
32426
- warning logs as they arrive. Use get for current status and logs for persisted
32427
- log history. In human output, --compact prints deduplicated
32428
- step transitions and progress instead of the full event stream. --json emits
32429
- one terminal package. --jsonl emits canonical live events as JSON Lines and
32430
- ends with the same compact package shape as runs get --json. --log-level
30956
+ Polls the authenticated run snapshot every two seconds. Human output shows
30957
+ info and warning logs as snapshots change. Use get for current status and
30958
+ logs for persisted log history. In human output, --compact prints
30959
+ deduplicated step transitions and progress. --json emits one terminal
30960
+ package. --jsonl emits canonical watched events as JSON Lines and ends with
30961
+ the same compact package shape as runs get --json. The tail command remains
30962
+ an alias. --log-level
32431
30963
  filters the rendered customer-safe runtime log lines; debug includes runtime
32432
30964
  and receipt diagnostics and writes them to stderr alongside JSON output.
32433
30965
 
32434
30966
  Examples:
32435
- deepline runs tail play/my-play/run/20260501t000000-000
32436
- deepline runs tail play/my-play/run/20260501t000000-000 --compact
32437
- deepline runs tail play/my-play/run/20260501t000000-000 --log-level debug
32438
- deepline runs tail play/my-play/run/20260501t000000-000 --log-level error
32439
- deepline runs tail play/my-play/run/20260501t000000-000 --jsonl
30967
+ deepline runs watch play/my-play/run/20260501t000000-000
30968
+ deepline runs watch play/my-play/run/20260501t000000-000 --compact
30969
+ deepline runs watch play/my-play/run/20260501t000000-000 --log-level debug
30970
+ deepline runs watch play/my-play/run/20260501t000000-000 --log-level error
30971
+ deepline runs watch play/my-play/run/20260501t000000-000 --jsonl
32440
30972
  `
32441
30973
  ).option("--json", "Emit one terminal JSON package after the run completes").option(
32442
30974
  "--jsonl",
32443
- "Stream live events as JSON Lines, then the terminal package"
30975
+ "Emit watched events as JSON Lines, then the terminal package"
32444
30976
  ).option(
32445
30977
  "--compact",
32446
30978
  "Show deduplicated human step transitions and progress"
@@ -34358,7 +32890,7 @@ function isMarkedTestAiInferenceCommand(command) {
34358
32890
  if (normalizeEnrichPlayRef(command.tool) !== "run_javascript") {
34359
32891
  return false;
34360
32892
  }
34361
- return isRecord12(command.payload) && command.payload[ENRICH_TEST_AI_INFERENCE_PAYLOAD_MARKER] === true;
32893
+ return isRecord8(command.payload) && command.payload[ENRICH_TEST_AI_INFERENCE_PAYLOAD_MARKER] === true;
34362
32894
  }
34363
32895
  function enrichDebugEnabled(env = process.env) {
34364
32896
  const raw = String(env.DEEPLINE_DEBUG_ENRICH ?? "").trim().toLowerCase();
@@ -34622,7 +33154,7 @@ function rewriteGeneratedPlayRerunForEnrich(status, enrichCommand) {
34622
33154
  if (Array.isArray(value)) {
34623
33155
  return value.map(rewrite);
34624
33156
  }
34625
- if (!isRecord12(value)) {
33157
+ if (!isRecord8(value)) {
34626
33158
  return value;
34627
33159
  }
34628
33160
  const next = Object.fromEntries(
@@ -34631,7 +33163,7 @@ function rewriteGeneratedPlayRerunForEnrich(status, enrichCommand) {
34631
33163
  key === "rerunCommand" && typeof entry === "string" ? enrichCommand : rewrite(entry)
34632
33164
  ])
34633
33165
  );
34634
- if (isRecord12(next.next) && typeof next.next.run === "string") {
33166
+ if (isRecord8(next.next) && typeof next.next.run === "string") {
34635
33167
  next.next = { ...next.next, run: enrichCommand };
34636
33168
  }
34637
33169
  return next;
@@ -35113,7 +33645,7 @@ async function resolveWatchedGeneratedPlayStatus(input2) {
35113
33645
  }
35114
33646
  return input2.client.runs.get(runId, { full: true });
35115
33647
  }
35116
- function isRecord12(value) {
33648
+ function isRecord8(value) {
35117
33649
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
35118
33650
  }
35119
33651
  async function captureStdout(run, options = {}) {
@@ -35365,15 +33897,15 @@ function readFirstEnrichDatasetActions(value) {
35365
33897
  return null;
35366
33898
  }
35367
33899
  const record3 = candidate;
35368
- const actions = isRecord12(record3.actions) ? record3.actions : null;
35369
- const currentQuery = isRecord12(actions?.queryCurrentTable) ? actions.queryCurrentTable : null;
35370
- const legacyQuery = isRecord12(actions?.query) ? actions.query : null;
33900
+ const actions = isRecord8(record3.actions) ? record3.actions : null;
33901
+ const currentQuery = isRecord8(actions?.queryCurrentTable) ? actions.queryCurrentTable : null;
33902
+ const legacyQuery = isRecord8(actions?.query) ? actions.query : null;
35371
33903
  const query = currentQuery?.kind === "deepline_db_query" ? currentQuery : legacyQuery?.kind === "deepline_db_query" ? legacyQuery : null;
35372
33904
  if (query?.kind === "deepline_db_query") {
35373
33905
  return {
35374
33906
  dataset: record3,
35375
33907
  query,
35376
- ...isRecord12(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
33908
+ ...isRecord8(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
35377
33909
  };
35378
33910
  }
35379
33911
  if (options.allowLegacy && record3.kind === "dataset" && typeof record3.queryDatasetCommand === "string" && record3.queryDatasetCommand.trim()) {
@@ -35426,7 +33958,7 @@ function enrichCustomerDbJson(input2) {
35426
33958
  const dataset = actions.dataset;
35427
33959
  const sql = actionStringField(query, "sql") ?? parseSqlFromDbQueryCommand(actions.queryDatasetCommand);
35428
33960
  const datasetPath = actionStringField(query, "datasetPath") ?? actionStringField(dataset, "path") ?? actionStringField(dataset, "tableNamespace");
35429
- const api = isRecord12(query.api) ? query.api : null;
33961
+ const api = isRecord8(query.api) ? query.api : null;
35430
33962
  const apiPath = actionStringField(api ?? {}, "path") ?? "/api/v2/db/query";
35431
33963
  const apiMethod = actionStringField(api ?? {}, "method") ?? "POST";
35432
33964
  if (!datasetPath) {
@@ -35495,11 +34027,11 @@ function sqlStringLiteral(value) {
35495
34027
  return `'${value.replace(/'/g, "''")}'`;
35496
34028
  }
35497
34029
  function failureAliasFromCellMeta(cellMeta) {
35498
- if (!isRecord12(cellMeta)) {
34030
+ if (!isRecord8(cellMeta)) {
35499
34031
  return null;
35500
34032
  }
35501
34033
  for (const [alias, meta] of Object.entries(cellMeta)) {
35502
- if (!isRecord12(meta)) {
34034
+ if (!isRecord8(meta)) {
35503
34035
  continue;
35504
34036
  }
35505
34037
  const failure = failureCellFromMeta(meta, {});
@@ -35993,7 +34525,7 @@ function exportableSheetRow2(row, sourceRowStart = 0) {
35993
34525
  return fallback;
35994
34526
  }
35995
34527
  function failureCellFromMeta(meta, fallback) {
35996
- if (!isRecord12(meta)) {
34528
+ if (!isRecord8(meta)) {
35997
34529
  return null;
35998
34530
  }
35999
34531
  const status = typeof meta.status === "string" ? meta.status.trim().toLowerCase() : "";
@@ -36013,7 +34545,7 @@ function failureCellFromMeta(meta, fallback) {
36013
34545
  };
36014
34546
  }
36015
34547
  function applyFailureCellMeta(row, cellMeta, fallback) {
36016
- if (!isRecord12(cellMeta)) {
34548
+ if (!isRecord8(cellMeta)) {
36017
34549
  return;
36018
34550
  }
36019
34551
  for (const [field, meta] of Object.entries(cellMeta)) {
@@ -36241,7 +34773,7 @@ function stableRowSnapshot(value) {
36241
34773
  }
36242
34774
  function cellFailureError(value) {
36243
34775
  const parsed = parseMaybeJsonObject(value);
36244
- if (!isRecord12(parsed)) {
34776
+ if (!isRecord8(parsed)) {
36245
34777
  const text = typeof parsed === "string" ? parsed.trim() : "";
36246
34778
  if (/^(?:[A-Za-z0-9_:-]+:\s*)?(?:Error|TypeError|ReferenceError|SyntaxError|RangeError):\s+/.test(
36247
34779
  text
@@ -36249,12 +34781,12 @@ function cellFailureError(value) {
36249
34781
  return { message: text };
36250
34782
  }
36251
34783
  }
36252
- if (!isRecord12(parsed)) {
34784
+ if (!isRecord8(parsed)) {
36253
34785
  return null;
36254
34786
  }
36255
34787
  const status = typeof parsed.status === "string" ? parsed.status.trim().toLowerCase() : "";
36256
34788
  const directError = typeof parsed.error === "string" ? parsed.error.trim() : typeof parsed.last_error === "string" ? parsed.last_error.trim() : "";
36257
- const result = isRecord12(parsed.result) ? parsed.result : null;
34789
+ const result = isRecord8(parsed.result) ? parsed.result : null;
36258
34790
  const resultError = typeof result?.error === "string" ? result.error.trim() : typeof result?.message === "string" ? result.message.trim() : "";
36259
34791
  if (!directError && !resultError && status !== "error" && status !== "failed") {
36260
34792
  return null;
@@ -36324,7 +34856,7 @@ function assignFlattenedFailurePath(target, field, value) {
36324
34856
  let cursor = target;
36325
34857
  for (const part of normalized.slice(0, -1)) {
36326
34858
  const existing = cursor[part];
36327
- if (!isRecord12(existing)) {
34859
+ if (!isRecord8(existing)) {
36328
34860
  const next = {};
36329
34861
  cursor[part] = next;
36330
34862
  cursor = next;
@@ -36488,10 +35020,10 @@ function waterfallExecutionSignal(status, spec) {
36488
35020
  let everyChildStatOnlyConditionSkipped = true;
36489
35021
  const childAliasesWithStats = /* @__PURE__ */ new Set();
36490
35022
  for (const childAlias of childAliases) {
36491
- for (const stat5 of summaries.map((summary) => summary[childAlias]).filter(isRecord12)) {
35023
+ for (const stat5 of summaries.map((summary) => summary[childAlias]).filter(isRecord8)) {
36492
35024
  sawChildStats = true;
36493
35025
  childAliasesWithStats.add(childAlias);
36494
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35026
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36495
35027
  const executedSummary = parseExecutionSummary(
36496
35028
  execution?.["completed:executed"]
36497
35029
  );
@@ -36521,7 +35053,7 @@ function waterfallExecutionSignal(status, spec) {
36521
35053
  }
36522
35054
  function emptyWaterfallStatsEvidence(status, spec) {
36523
35055
  const summaries = collectColumnStats(status);
36524
- const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord12);
35056
+ const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord8);
36525
35057
  for (const stat5 of parentStats) {
36526
35058
  const nonEmpty = parseExecutionSummary(stat5.non_empty);
36527
35059
  if (nonEmpty?.total && nonEmpty.count === 0) {
@@ -36535,7 +35067,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
36535
35067
  let selectedRows = 0;
36536
35068
  let sawStatsForEveryChild = true;
36537
35069
  for (const childAlias of childAliases) {
36538
- const stat5 = summaries.map((summary) => summary[childAlias]).find(isRecord12);
35070
+ const stat5 = summaries.map((summary) => summary[childAlias]).find(isRecord8);
36539
35071
  if (!stat5) {
36540
35072
  sawStatsForEveryChild = false;
36541
35073
  break;
@@ -36544,7 +35076,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
36544
35076
  if ((nonEmpty?.count ?? 0) > 0) {
36545
35077
  return null;
36546
35078
  }
36547
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35079
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36548
35080
  const executed = parseExecutionSummary(execution?.["completed:executed"]);
36549
35081
  const reused = parseExecutionSummary(execution?.["completed:reused"]);
36550
35082
  const skipped = parseExecutionSummary(execution?.["skipped:condition"]);
@@ -36586,11 +35118,11 @@ function collectStatusFailureJobs(input2) {
36586
35118
  const jobs = [];
36587
35119
  aliases.forEach((spec, aliasIndex) => {
36588
35120
  const { alias } = spec;
36589
- const stat5 = summaries.map((summary) => summary[alias]).find(isRecord12);
35121
+ const stat5 = summaries.map((summary) => summary[alias]).find(isRecord8);
36590
35122
  if (!stat5) {
36591
35123
  return;
36592
35124
  }
36593
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35125
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36594
35126
  const failedCount = Math.min(
36595
35127
  selectedRows,
36596
35128
  Math.max(
@@ -36697,10 +35229,10 @@ function collectColumnStats(status) {
36697
35229
  value.forEach(visit);
36698
35230
  return;
36699
35231
  }
36700
- if (!isRecord12(value)) {
35232
+ if (!isRecord8(value)) {
36701
35233
  return;
36702
35234
  }
36703
- if (isRecord12(value.columnStats)) {
35235
+ if (isRecord8(value.columnStats)) {
36704
35236
  summaries.push(value.columnStats);
36705
35237
  }
36706
35238
  Object.values(value).forEach(visit);
@@ -36712,12 +35244,12 @@ function firstAliasExecutionCounts(input2) {
36712
35244
  const aliases = collectConfigScalarAliasOrder(input2.config);
36713
35245
  const summaries = collectColumnStats(input2.status);
36714
35246
  for (const alias of aliases) {
36715
- const stat5 = summaries.map((summary) => summary[alias]).find(isRecord12);
35247
+ const stat5 = summaries.map((summary) => summary[alias]).find(isRecord8);
36716
35248
  if (!stat5) continue;
36717
35249
  if (input2.forceAliases.has(normalizeAlias2(alias))) {
36718
35250
  return { executed: input2.selectedRows, reused: 0 };
36719
35251
  }
36720
- const execution = isRecord12(stat5.execution) ? stat5.execution : null;
35252
+ const execution = isRecord8(stat5.execution) ? stat5.execution : null;
36721
35253
  if (!execution) continue;
36722
35254
  return {
36723
35255
  executed: parseExecutionCount(execution["completed:executed"]),
@@ -36744,14 +35276,14 @@ function rewriteEnrichJsonStatus(input2) {
36744
35276
  if (Array.isArray(value)) {
36745
35277
  return value.map(rewrite);
36746
35278
  }
36747
- if (!isRecord12(value)) {
35279
+ if (!isRecord8(value)) {
36748
35280
  return value;
36749
35281
  }
36750
35282
  const next = {};
36751
35283
  for (const [key, entry] of Object.entries(value)) {
36752
35284
  next[key] = rewrite(entry);
36753
35285
  }
36754
- if (isRecord12(next.progress)) {
35286
+ if (isRecord8(next.progress)) {
36755
35287
  next.progress = {
36756
35288
  ...next.progress,
36757
35289
  ...selectedRows > 0 ? { total: selectedRows } : {},
@@ -36760,8 +35292,8 @@ function rewriteEnrichJsonStatus(input2) {
36760
35292
  ...failedRows > 0 ? { failed: failedRows, pending: 0 } : {}
36761
35293
  };
36762
35294
  }
36763
- if (isRecord12(next.summary)) {
36764
- const rowCounts = isRecord12(next.summary.rowCounts) ? next.summary.rowCounts : null;
35295
+ if (isRecord8(next.summary)) {
35296
+ const rowCounts = isRecord8(next.summary.rowCounts) ? next.summary.rowCounts : null;
36765
35297
  if (failedRows > 0) {
36766
35298
  next.summary = {
36767
35299
  ...next.summary,
@@ -36774,11 +35306,11 @@ function rewriteEnrichJsonStatus(input2) {
36774
35306
  };
36775
35307
  }
36776
35308
  }
36777
- if (isRecord12(next.columnStats) && selectedRows > 0) {
35309
+ if (isRecord8(next.columnStats) && selectedRows > 0) {
36778
35310
  const columnStats = { ...next.columnStats };
36779
35311
  for (const alias of forcedAliases) {
36780
- const stat5 = isRecord12(columnStats[alias]) ? columnStats[alias] : null;
36781
- const execution = isRecord12(stat5?.execution) ? stat5.execution : null;
35312
+ const stat5 = isRecord8(columnStats[alias]) ? columnStats[alias] : null;
35313
+ const execution = isRecord8(stat5?.execution) ? stat5.execution : null;
36782
35314
  if (!stat5 || !execution) continue;
36783
35315
  columnStats[alias] = {
36784
35316
  ...stat5,
@@ -36797,14 +35329,14 @@ function rewriteEnrichJsonStatus(input2) {
36797
35329
  return next;
36798
35330
  };
36799
35331
  const rewritten = rewrite(input2.status);
36800
- if (failedRows === 0 || !isRecord12(rewritten)) {
35332
+ if (failedRows === 0 || !isRecord8(rewritten)) {
36801
35333
  return rewritten;
36802
35334
  }
36803
35335
  const partialStatus = selectedRows > 0 && failedRows < selectedRows ? "partial_success" : "failed";
36804
35336
  return {
36805
35337
  ...rewritten,
36806
35338
  ...rewritten.status === "completed" || rewritten.status === "failed" ? { status: partialStatus } : {},
36807
- ...isRecord12(rewritten.run) && (rewritten.run.status === "completed" || rewritten.run.status === "failed") ? { run: { ...rewritten.run, status: partialStatus } } : {}
35339
+ ...isRecord8(rewritten.run) && (rewritten.run.status === "completed" || rewritten.run.status === "failed") ? { run: { ...rewritten.run, status: partialStatus } } : {}
36808
35340
  };
36809
35341
  }
36810
35342
  function summarizeFailedJobError(value) {
@@ -37428,7 +35960,7 @@ function materializeCsvCellValue(value) {
37428
35960
  return value;
37429
35961
  }
37430
35962
  function compactArrayEnvelopeCompleteValue(value) {
37431
- if (!isRecord12(value) || value.kind !== "array") {
35963
+ if (!isRecord8(value) || value.kind !== "array") {
37432
35964
  return null;
37433
35965
  }
37434
35966
  if (!Array.isArray(value.preview)) {
@@ -37442,7 +35974,7 @@ function compactArrayEnvelopeCompleteValue(value) {
37442
35974
  }
37443
35975
  function disambiguateCompactAiInferencePayload(value) {
37444
35976
  const parsed = parseMaybeJsonObject(value);
37445
- if (!isRecord12(parsed) || !cellFailureError(parsed)) {
35977
+ if (!isRecord8(parsed) || !cellFailureError(parsed)) {
37446
35978
  return value;
37447
35979
  }
37448
35980
  return {
@@ -37451,14 +35983,14 @@ function disambiguateCompactAiInferencePayload(value) {
37451
35983
  };
37452
35984
  }
37453
35985
  function compactAiInferenceCellForCsv(value) {
37454
- if (!isRecord12(value)) {
35986
+ if (!isRecord8(value)) {
37455
35987
  return value;
37456
35988
  }
37457
35989
  const extractedJson = value.extracted_json;
37458
35990
  if (extractedJson !== null && extractedJson !== void 0) {
37459
35991
  return disambiguateCompactAiInferencePayload(extractedJson);
37460
35992
  }
37461
- const result = isRecord12(value.result) ? value.result : null;
35993
+ const result = isRecord8(value.result) ? value.result : null;
37462
35994
  const object = result?.object;
37463
35995
  if (object !== null && object !== void 0) {
37464
35996
  return disambiguateCompactAiInferencePayload(object);
@@ -37475,12 +36007,12 @@ function compactAiInferenceCellForCsv(value) {
37475
36007
  }
37476
36008
  function materializeEnrichAliasCellForCsv(row, alias, options) {
37477
36009
  const direct = row[alias];
37478
- if (isRecord12(direct)) {
36010
+ if (isRecord8(direct)) {
37479
36011
  const completeArray = compactArrayEnvelopeCompleteValue(direct);
37480
36012
  if (completeArray) {
37481
36013
  return materializeCsvCellValue(completeArray);
37482
36014
  }
37483
- if (options?.compactAiCell && direct.status === "completed" && (isRecord12(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
36015
+ if (options?.compactAiCell && direct.status === "completed" && (isRecord8(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
37484
36016
  return materializeCsvCellValue(compactAiInferenceCellForCsv(direct));
37485
36017
  }
37486
36018
  if (Object.prototype.hasOwnProperty.call(direct, "matched_result") || Object.prototype.hasOwnProperty.call(direct, "matchedResult") || Object.prototype.hasOwnProperty.call(direct, "result")) {
@@ -37621,11 +36153,11 @@ function normalizeEnrichRowsForCsvExport(rows, config, options) {
37621
36153
  }
37622
36154
  function legacyMetadataFromRow(row) {
37623
36155
  const direct = parseLegacyMetadataCell(row._metadata);
37624
- if (direct && isRecord12(direct.columns)) {
36156
+ if (direct && isRecord8(direct.columns)) {
37625
36157
  return direct;
37626
36158
  }
37627
36159
  const relocated = parseLegacyMetadataCell(row.metadata);
37628
- if (relocated && isRecord12(relocated.columns)) {
36160
+ if (relocated && isRecord8(relocated.columns)) {
37629
36161
  return relocated;
37630
36162
  }
37631
36163
  const flattenedColumns = parseLegacyMetadataCell(row["metadata.columns"]);
@@ -37642,7 +36174,7 @@ function legacyMetadataFromRow(row) {
37642
36174
  }
37643
36175
  function parseLegacyMetadataCell(value) {
37644
36176
  const parsed = parseMaybeJsonObject(value);
37645
- if (isRecord12(parsed)) {
36177
+ if (isRecord8(parsed)) {
37646
36178
  return parsed;
37647
36179
  }
37648
36180
  if (typeof value !== "string") {
@@ -37659,12 +36191,12 @@ function parseLegacyMetadataCell(value) {
37659
36191
  for (const candidate of candidates) {
37660
36192
  try {
37661
36193
  const decoded = JSON.parse(candidate);
37662
- if (isRecord12(decoded)) {
36194
+ if (isRecord8(decoded)) {
37663
36195
  return decoded;
37664
36196
  }
37665
36197
  if (typeof decoded === "string") {
37666
36198
  const nested = JSON.parse(decoded);
37667
- if (isRecord12(nested)) {
36199
+ if (isRecord8(nested)) {
37668
36200
  return nested;
37669
36201
  }
37670
36202
  }
@@ -37674,8 +36206,8 @@ function parseLegacyMetadataCell(value) {
37674
36206
  return null;
37675
36207
  }
37676
36208
  function mergeLegacyMetadataRecords(base, enriched) {
37677
- const baseColumns = isRecord12(base.columns) ? base.columns : null;
37678
- const enrichedColumns = isRecord12(enriched.columns) ? enriched.columns : null;
36209
+ const baseColumns = isRecord8(base.columns) ? base.columns : null;
36210
+ const enrichedColumns = isRecord8(enriched.columns) ? enriched.columns : null;
37679
36211
  const merged = {
37680
36212
  ...base,
37681
36213
  ...enriched
@@ -49856,11 +48388,17 @@ var CapabilityDescription = class _CapabilityDescription {
49856
48388
  legacyCost.pricingModel ?? legacyCost.pricing_model
49857
48389
  );
49858
48390
  const pricingModel = unit === "call" ? "fixed" : unit === "result" || unit === "page" ? `per_${unit}` : unit === "usage" ? "provider_usage" : legacyPricingModel;
49859
- const canonicalCredits = numberValue(
49860
- pricing.creditsPerUnit ?? pricing.credits_per_unit
49861
- );
49862
- const canonicalUsd = numberValue(
49863
- pricing.usdPerUnit ?? pricing.usd_per_unit
48391
+ const canonicalCredits = pricingNumber(
48392
+ pricing,
48393
+ "creditsPerUnit",
48394
+ "credits_per_unit",
48395
+ this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
48396
+ );
48397
+ const canonicalUsd = pricingNumber(
48398
+ pricing,
48399
+ "usdPerUnit",
48400
+ "usd_per_unit",
48401
+ this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
49864
48402
  );
49865
48403
  const billingSource = stringValue4(
49866
48404
  this.#catalogEntry.billingSource ?? this.#catalogEntry.billing_source
@@ -49879,12 +48417,8 @@ var CapabilityDescription = class _CapabilityDescription {
49879
48417
  ),
49880
48418
  billingSource,
49881
48419
  billingSourceLabel,
49882
- deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits ?? numberValue(
49883
- this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
49884
- ),
49885
- deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd ?? numberValue(
49886
- this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
49887
- )
48420
+ deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits,
48421
+ deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd
49888
48422
  };
49889
48423
  }
49890
48424
  };
@@ -49897,6 +48431,13 @@ function stringValue4(value) {
49897
48431
  function numberValue(value) {
49898
48432
  return typeof value === "number" && Number.isFinite(value) ? value : null;
49899
48433
  }
48434
+ function pricingNumber(pricing, canonicalKey, aliasKey, legacyValue) {
48435
+ for (const key of [canonicalKey, aliasKey]) {
48436
+ if (Object.prototype.hasOwnProperty.call(pricing, key))
48437
+ return numberValue(pricing[key]);
48438
+ }
48439
+ return numberValue(legacyValue);
48440
+ }
49900
48441
 
49901
48442
  // src/cli/tool-connection-status.ts
49902
48443
  function toolConnectionStatusMessage(input2) {
@@ -50490,11 +49031,15 @@ Concepts:
50490
49031
  Common commands:
50491
49032
  deepline tools search email --json
50492
49033
  deepline tools describe hunter_email_verifier --json
49034
+ deepline tools describe hunter_email_verifier --pricing-only --json
50493
49035
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
49036
+ deepline billing usage --request-id <job_id> --json
50494
49037
 
50495
49038
  Output:
50496
49039
  Use describe for tool contracts.
50497
49040
  Use execute to run a tool.
49041
+ Read pricing before execution; use the returned next.billing command for its
49042
+ exact charge. Workspace balance changes also include other callers' activity.
50498
49043
  `
50499
49044
  );
50500
49045
  tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
@@ -50620,6 +49165,7 @@ Notes:
50620
49165
  Examples:
50621
49166
  deepline tools describe hunter_email_verifier
50622
49167
  deepline tools describe hunter_email_verifier --pricing-only
49168
+ deepline tools describe hunter_email_verifier --pricing-only --json
50623
49169
  deepline tools describe hunter_email_verifier --schema-only
50624
49170
  deepline tools describe hunter_email_verifier --examples-only
50625
49171
  deepline tools describe hunter_email_verifier --json
@@ -50669,10 +49215,15 @@ Notes:
50669
49215
  waterfalls, row maps, checkpoints, and retries.
50670
49216
  Calling a provider-backed tool can spend Deepline credits. Use --json for the
50671
49217
  stable result payload plus output preview and debugging helpers.
49218
+ Read pricing first with tools describe <toolId> --pricing-only --json.
49219
+ Use the returned next.billing command to look up this execution's exact charge;
49220
+ workspace balance changes also include other callers' activity.
50672
49221
  --timeout sets this CLI request's HTTP deadline; it does not cancel provider work.
50673
49222
 
50674
49223
  Examples:
50675
49224
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
49225
+ deepline tools describe hunter_email_verifier --pricing-only --json
49226
+ deepline billing usage --request-id <job_id> --json
50676
49227
  deepline tools execute bounceban_verify_bulk --input @batch.json --timeout 10m --json
50677
49228
  deepline tools execute hunter_email_verifier -p email=a@b.com
50678
49229
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
@@ -50776,6 +49327,38 @@ async function getTool(toolId, options = {}) {
50776
49327
  );
50777
49328
  return 2;
50778
49329
  }
49330
+ const onlyModes = [
49331
+ options.pricingOnly,
49332
+ options.schemaOnly,
49333
+ options.examplesOnly,
49334
+ options.gettersOnly
49335
+ ].filter(Boolean).length;
49336
+ if (onlyModes > 1) {
49337
+ console.error(
49338
+ "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
49339
+ );
49340
+ return 2;
49341
+ }
49342
+ if (options.pricingOnly) {
49343
+ const lines = toolPricingOnlyLines(tool, toolId);
49344
+ if (inferenceQuote)
49345
+ lines.push(...inferenceQuoteSummaryLines(inferenceQuote));
49346
+ printCommandEnvelope(
49347
+ {
49348
+ toolId: String(tool.toolId || toolId),
49349
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
49350
+ ...modelDescription ? { modelOptions: modelDescription } : {},
49351
+ ...isMonitorTypeTool(tool) ? { pricing: recordField2(tool, "pricing") } : {},
49352
+ ...inferenceQuote ? { inferenceQuote } : {}
49353
+ },
49354
+ {
49355
+ json: Boolean(options.json || options.contractJson),
49356
+ text: `${lines.join("\n")}
49357
+ `
49358
+ }
49359
+ );
49360
+ return 0;
49361
+ }
50779
49362
  if (options.contractJson) {
50780
49363
  printCompactJson({
50781
49364
  ...toolContractJsonForDescribe(tool, toolId),
@@ -50793,23 +49376,6 @@ async function getTool(toolId, options = {}) {
50793
49376
  });
50794
49377
  return 0;
50795
49378
  }
50796
- const onlyModes = [
50797
- options.pricingOnly,
50798
- options.schemaOnly,
50799
- options.examplesOnly,
50800
- options.gettersOnly
50801
- ].filter(Boolean).length;
50802
- if (onlyModes > 1) {
50803
- console.error(
50804
- "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
50805
- );
50806
- return 2;
50807
- }
50808
- if (options.pricingOnly) {
50809
- printToolPricingOnly(tool, toolId);
50810
- if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50811
- return 0;
50812
- }
50813
49379
  if (options.schemaOnly) {
50814
49380
  printToolSchemaOnly(tool, toolId);
50815
49381
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
@@ -50850,11 +49416,16 @@ ${formatModelDescription(modelDescription)}`);
50850
49416
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50851
49417
  return 0;
50852
49418
  }
50853
- function printInferenceQuoteSummary(_quote) {
50854
- console.log("");
50855
- console.log("Inference quote:");
50856
- console.log("- Temporary hold: priced estimate (minimum 0.02 credits)");
50857
- console.log("- Final charge: actual usage");
49419
+ function inferenceQuoteSummaryLines(_quote) {
49420
+ return [
49421
+ "",
49422
+ "Inference quote:",
49423
+ "- Temporary hold: priced estimate (minimum 0.02 credits)",
49424
+ "- Final charge: actual usage"
49425
+ ];
49426
+ }
49427
+ function printInferenceQuoteSummary(quote) {
49428
+ for (const line of inferenceQuoteSummaryLines(quote)) console.log(line);
50858
49429
  }
50859
49430
  function toolContractJsonForDescribe(tool, requestedToolId) {
50860
49431
  const toolId = String(tool.toolId || requestedToolId);
@@ -50913,6 +49484,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
50913
49484
  toolId,
50914
49485
  provider: tool.provider,
50915
49486
  displayName: tool.displayName,
49487
+ cost: pricing,
50916
49488
  description: tool.description,
50917
49489
  categories: tool.categories,
50918
49490
  ...deprecated ? {
@@ -50932,7 +49504,6 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
50932
49504
  } : {},
50933
49505
  ...executionMetadata ? { executionMetadata } : {},
50934
49506
  ...batchCapability ? { batchCapability } : {},
50935
- cost: pricing,
50936
49507
  getters: {
50937
49508
  extractedLists,
50938
49509
  extractedValues
@@ -50943,7 +49514,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
50943
49514
  }
50944
49515
  function extractionContractEntries(entries) {
50945
49516
  return entries.flatMap((entry) => {
50946
- if (!isRecord13(entry)) return [];
49517
+ if (!isRecord9(entry)) return [];
50947
49518
  const name = stringField2(entry, "name");
50948
49519
  const expression = stringField2(entry, "expression");
50949
49520
  return name && expression ? [{ name, expression }] : [];
@@ -50964,7 +49535,7 @@ function printMonitorTypeFilters(tool) {
50964
49535
  }
50965
49536
  console.log("Deploy filters (set in the monitor payload):");
50966
49537
  for (const name of names) {
50967
- const field = isRecord13(properties[name]) ? properties[name] : {};
49538
+ const field = isRecord9(properties[name]) ? properties[name] : {};
50968
49539
  const star = required.has(name) ? "*" : "";
50969
49540
  const enumVals = arrayField2(field, "enum").filter(
50970
49541
  (v) => typeof v === "string"
@@ -50978,7 +49549,7 @@ function printMonitorTypeFilterExamples(tool) {
50978
49549
  const documentation = recordField2(tool, "documentation");
50979
49550
  const fields2 = recordField2(documentation, "fields");
50980
49551
  const examples = Object.entries(fields2).flatMap(([name, rawField]) => {
50981
- const grammar = recordField2(isRecord13(rawField) ? rawField : {}, "grammar");
49552
+ const grammar = recordField2(isRecord9(rawField) ? rawField : {}, "grammar");
50982
49553
  const example = stringField2(grammar, "example");
50983
49554
  const values = [
50984
49555
  ...arrayField2(grammar, "examples").filter(
@@ -50997,18 +49568,18 @@ function printMonitorTypeFilterExamples(tool) {
50997
49568
  }
50998
49569
  function printMonitorTypeStreams(tool) {
50999
49570
  const streams = arrayField2(tool, "streams", "output_streams").filter(
51000
- isRecord13
49571
+ isRecord9
51001
49572
  );
51002
49573
  if (!streams.length) return;
51003
49574
  console.log("");
51004
49575
  console.log("Filter columns (a play's sqlListeners.where, per stream):");
51005
49576
  for (const stream of streams) {
51006
49577
  const name = stringField2(stream, "stream");
51007
- const cols = arrayField2(stream, "columns").filter(isRecord13).map((col) => stringField2(col, "name")).filter(Boolean);
49578
+ const cols = arrayField2(stream, "columns").filter(isRecord9).map((col) => stringField2(col, "name")).filter(Boolean);
51008
49579
  console.log(`- ${name}: ${cols.join(", ")}`);
51009
49580
  }
51010
49581
  }
51011
- function printMonitorTypePricing(tool) {
49582
+ function monitorTypePricingLines(tool) {
51012
49583
  const pricing = recordField2(tool, "pricing");
51013
49584
  const byType = recordField2(
51014
49585
  pricing,
@@ -51017,17 +49588,20 @@ function printMonitorTypePricing(tool) {
51017
49588
  );
51018
49589
  const keys = Object.keys(byType);
51019
49590
  if (!keys.length) {
51020
- console.log("Pricing: Deepline credits per accepted event (see --json)");
51021
- return;
49591
+ return ["Pricing: Deepline credits per accepted event (see --json)"];
51022
49592
  }
51023
- console.log("Pricing (Deepline credits per accepted event):");
49593
+ const lines = ["Pricing (Deepline credits per accepted event):"];
51024
49594
  for (const key of keys) {
51025
- const entry = isRecord13(byType[key]) ? byType[key] : {};
49595
+ const entry = isRecord9(byType[key]) ? byType[key] : {};
51026
49596
  const credits = numberField2(entry, "deepline_credits", "deeplineCredits");
51027
49597
  const display = stringField2(entry, "display");
51028
49598
  const shown = display || (credits !== null ? `${formatDecimal(credits)} credits/event` : "see --json");
51029
- console.log(`- ${key}: ${shown}`);
49599
+ lines.push(`- ${key}: ${shown}`);
51030
49600
  }
49601
+ return lines;
49602
+ }
49603
+ function printMonitorTypePricing(tool) {
49604
+ for (const line of monitorTypePricingLines(tool)) console.log(line);
51031
49605
  }
51032
49606
  function printMonitorTypeDeploy(tool) {
51033
49607
  const deploy = recordField2(tool, "deploy");
@@ -51068,8 +49642,8 @@ function printCompactToolContract(tool, requestedToolId) {
51068
49642
  return;
51069
49643
  }
51070
49644
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
51071
- const cost = isRecord13(contract.cost) ? contract.cost : {};
51072
- const getters = isRecord13(contract.getters) ? contract.getters : {};
49645
+ const cost = isRecord9(contract.cost) ? contract.cost : {};
49646
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
51073
49647
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
51074
49648
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
51075
49649
  const inputFields = recursiveToolInputFieldsForDisplay(
@@ -51086,7 +49660,7 @@ function printCompactToolContract(tool, requestedToolId) {
51086
49660
  printToolOutputArrayShape(contract);
51087
49661
  printToolExecutionHints(contract);
51088
49662
  if (contract.deprecated === true) {
51089
- const deprecation = isRecord13(contract.deprecation) ? contract.deprecation : {};
49663
+ const deprecation = isRecord9(contract.deprecation) ? contract.deprecation : {};
51090
49664
  const message = stringField2(deprecation, "message");
51091
49665
  const replacementToolId = stringField2(
51092
49666
  deprecation,
@@ -51113,7 +49687,7 @@ function printCompactToolContract(tool, requestedToolId) {
51113
49687
  console.log("");
51114
49688
  console.log("Inputs:");
51115
49689
  for (const field of inputFields) {
51116
- if (!isRecord13(field)) continue;
49690
+ if (!isRecord9(field)) continue;
51117
49691
  const name = stringField2(field, "name");
51118
49692
  if (!name) continue;
51119
49693
  const required = field.required ? "*" : "";
@@ -51133,7 +49707,7 @@ function printCompactToolContract(tool, requestedToolId) {
51133
49707
  }
51134
49708
  console.log("");
51135
49709
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
51136
- const starterScript = isRecord13(contract.starterScript) ? contract.starterScript : {};
49710
+ const starterScript = isRecord9(contract.starterScript) ? contract.starterScript : {};
51137
49711
  const starterPath = stringField2(starterScript, "path");
51138
49712
  if (starterPath) {
51139
49713
  console.log("");
@@ -51147,14 +49721,14 @@ function printCompactToolContract(tool, requestedToolId) {
51147
49721
  console.log("Getters:");
51148
49722
  if (listGetters.length) console.log("Lists:");
51149
49723
  for (const entry of listGetters) {
51150
- if (isRecord13(entry))
49724
+ if (isRecord9(entry))
51151
49725
  console.log(
51152
49726
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51153
49727
  );
51154
49728
  }
51155
49729
  if (valueGetters.length) console.log("Values:");
51156
49730
  for (const entry of valueGetters) {
51157
- if (isRecord13(entry))
49731
+ if (isRecord9(entry))
51158
49732
  console.log(
51159
49733
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51160
49734
  );
@@ -51165,13 +49739,12 @@ function printCompactToolContract(tool, requestedToolId) {
51165
49739
  `More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`
51166
49740
  );
51167
49741
  }
51168
- function printToolPricingOnly(tool, requestedToolId, options = {}) {
49742
+ function toolPricingOnlyLines(tool, requestedToolId, options = {}) {
51169
49743
  if (isMonitorTypeTool(tool)) {
51170
- printMonitorTypePricing(tool);
51171
- return;
49744
+ return monitorTypePricingLines(tool);
51172
49745
  }
51173
- const contract = toolContractJsonForDescribe(tool, requestedToolId);
51174
- const cost = isRecord13(contract.cost) ? contract.cost : {};
49746
+ const toolId = String(tool.toolId || requestedToolId);
49747
+ const cost = Capability.fromCatalogEntry(tool).describe().customerCost();
51175
49748
  const pricingModel = stringField2(cost, "pricingModel") || "unknown";
51176
49749
  const billing = stringField2(cost, "billingSourceLabel") || stringField2(cost, "billingSource") || stringField2(cost, "billingMode") || "unknown";
51177
49750
  const explicitUnit = stringField2(cost, "unit");
@@ -51181,8 +49754,14 @@ function printToolPricingOnly(tool, requestedToolId, options = {}) {
51181
49754
  const displayText = stringField2(cost, "displayText");
51182
49755
  const summary = stringField2(cost, "summary");
51183
49756
  const price = displayText || summary || (credits !== null ? `${formatDecimal(credits)} Deepline credits${usd !== null ? ` / ${formatUsd(usd)}` : ""} per ${unit}` : "pricing unavailable");
51184
- console.log(`${options.heading ?? `Pricing: ${contract.toolId}`}: ${price}`);
51185
- console.log(`Billing: ${billing}`);
49757
+ return [
49758
+ `${options.heading ?? `Pricing: ${toolId}`}: ${price}`,
49759
+ `Billing: ${billing}`
49760
+ ];
49761
+ }
49762
+ function printToolPricingOnly(tool, requestedToolId, options = {}) {
49763
+ for (const line of toolPricingOnlyLines(tool, requestedToolId, options))
49764
+ console.log(line);
51186
49765
  }
51187
49766
  function printToolSchemaOnly(tool, requestedToolId) {
51188
49767
  if (isMonitorTypeTool(tool)) {
@@ -51248,10 +49827,10 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
51248
49827
  ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
51249
49828
  );
51250
49829
  console.log("});");
51251
- const getters = isRecord13(contract.getters) ? contract.getters : {};
49830
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
51252
49831
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
51253
49832
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
51254
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord13);
49833
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord9);
51255
49834
  if (firstGetter) {
51256
49835
  const name = stringField2(firstGetter, "name") || "value";
51257
49836
  const expression = stringField2(firstGetter, "expression");
@@ -51287,7 +49866,7 @@ function printPlayLikeToolUsage(tool, requestedToolId) {
51287
49866
  }
51288
49867
  function printToolGettersOnly(tool, requestedToolId) {
51289
49868
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
51290
- const getters = isRecord13(contract.getters) ? contract.getters : {};
49869
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
51291
49870
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
51292
49871
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
51293
49872
  console.log(`Getters: ${contract.toolId}`);
@@ -51300,7 +49879,7 @@ function printToolGettersOnly(tool, requestedToolId) {
51300
49879
  if (listGetters.length) {
51301
49880
  console.log("Lists:");
51302
49881
  for (const entry of listGetters) {
51303
- if (isRecord13(entry))
49882
+ if (isRecord9(entry))
51304
49883
  console.log(
51305
49884
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51306
49885
  );
@@ -51309,7 +49888,7 @@ function printToolGettersOnly(tool, requestedToolId) {
51309
49888
  if (valueGetters.length) {
51310
49889
  console.log("Values:");
51311
49890
  for (const entry of valueGetters) {
51312
- if (isRecord13(entry))
49891
+ if (isRecord9(entry))
51313
49892
  console.log(
51314
49893
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
51315
49894
  );
@@ -51335,7 +49914,7 @@ function sampleValueForField(field) {
51335
49914
  function samplePayloadForInputFields(fields2) {
51336
49915
  return Object.fromEntries(
51337
49916
  fields2.slice(0, 4).flatMap((field) => {
51338
- if (!isRecord13(field)) return [];
49917
+ if (!isRecord9(field)) return [];
51339
49918
  const name = stringField2(field, "name");
51340
49919
  if (!name) return [];
51341
49920
  return [[name, sampleValueForField(field)]];
@@ -51395,6 +49974,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51395
49974
  } = tool;
51396
49975
  const outputSchemaRecord = recordField2(tool, "outputSchema", "output_schema");
51397
49976
  return {
49977
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51398
49978
  ...publicTool,
51399
49979
  toolId,
51400
49980
  provider: tool.provider,
@@ -51406,7 +49986,6 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51406
49986
  )
51407
49987
  } : {},
51408
49988
  inputFields: inputFields.map(inputFieldJsonForDescribe),
51409
- cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51410
49989
  usageGuidance,
51411
49990
  runtimeOutputHelp: {
51412
49991
  contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
@@ -51465,8 +50044,8 @@ function formatListedToolCost(tool) {
51465
50044
  }
51466
50045
  function toolInputFieldsForDisplay(inputSchema) {
51467
50046
  if (Array.isArray(inputSchema.fields)) {
51468
- const fields2 = inputSchema.fields.filter(isRecord13);
51469
- if (!isRecord13(inputSchema.jsonSchema)) return fields2;
50047
+ const fields2 = inputSchema.fields.filter(isRecord9);
50048
+ if (!isRecord9(inputSchema.jsonSchema)) return fields2;
51470
50049
  const jsonSchemaFields = new Map(
51471
50050
  recursiveToolInputFieldsForDisplay({
51472
50051
  jsonSchema: inputSchema.jsonSchema
@@ -51478,26 +50057,26 @@ function toolInputFieldsForDisplay(inputSchema) {
51478
50057
  const jsonSchemaField = typeof field.name === "string" ? jsonSchemaFields.get(field.name) : void 0;
51479
50058
  const minItems = typeof field.minItems === "number" ? field.minItems : jsonSchemaField?.minItems;
51480
50059
  const maxItems = typeof field.maxItems === "number" ? field.maxItems : jsonSchemaField?.maxItems;
51481
- const items = isRecord13(field.items) ? field.items : jsonSchemaField?.items;
50060
+ const items = isRecord9(field.items) ? field.items : jsonSchemaField?.items;
51482
50061
  return {
51483
50062
  ...field,
51484
- ...isRecord13(items) ? { items } : {},
50063
+ ...isRecord9(items) ? { items } : {},
51485
50064
  ...typeof minItems === "number" ? { minItems } : {},
51486
50065
  ...typeof maxItems === "number" ? { maxItems } : {}
51487
50066
  };
51488
50067
  });
51489
50068
  }
51490
- const jsonSchema = isRecord13(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
51491
- const properties = isRecord13(jsonSchema.properties) ? jsonSchema.properties : {};
50069
+ const jsonSchema = isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
50070
+ const properties = isRecord9(jsonSchema.properties) ? jsonSchema.properties : {};
51492
50071
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
51493
50072
  return Object.entries(properties).map(([name, value]) => {
51494
- const property = isRecord13(value) ? value : {};
50073
+ const property = isRecord9(value) ? value : {};
51495
50074
  return {
51496
50075
  name,
51497
50076
  type: typeof property.type === "string" ? property.type : "unknown",
51498
50077
  required: required.has(name),
51499
50078
  description: property.description,
51500
- ...isRecord13(property.items) ? { items: property.items } : {},
50079
+ ...isRecord9(property.items) ? { items: property.items } : {},
51501
50080
  ...typeof property.minItems === "number" ? { minItems: property.minItems } : {},
51502
50081
  ...typeof property.maxItems === "number" ? { maxItems: property.maxItems } : {},
51503
50082
  ...Object.prototype.hasOwnProperty.call(property, "default") ? { default: property.default } : {}
@@ -51514,7 +50093,7 @@ function toolOutputFieldsForDisplay(outputSchema) {
51514
50093
  }
51515
50094
  function printToolOutputArrayShape(tool) {
51516
50095
  const outputFields = toolOutputFieldsForDisplay(
51517
- recordField2(isRecord13(tool) ? tool : {}, "outputSchema", "output_schema")
50096
+ recordField2(isRecord9(tool) ? tool : {}, "outputSchema", "output_schema")
51518
50097
  );
51519
50098
  if (outputFields.length === 0) return;
51520
50099
  console.log(" Output array shape (declared schema):");
@@ -51529,10 +50108,10 @@ function printToolOutputArrayShape(tool) {
51529
50108
  }
51530
50109
  }
51531
50110
  function canonicalToolJsonSchema(inputSchema) {
51532
- return isRecord13(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
50111
+ return isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
51533
50112
  }
51534
50113
  function declaredToolJsonSchema(inputSchema) {
51535
- if (isRecord13(inputSchema.jsonSchema)) {
50114
+ if (isRecord9(inputSchema.jsonSchema)) {
51536
50115
  return inputSchema.jsonSchema;
51537
50116
  }
51538
50117
  return Array.isArray(inputSchema.fields) ? null : inputSchema;
@@ -51557,7 +50136,7 @@ function publicToolInputSchemaForDescribe(inputSchema) {
51557
50136
  };
51558
50137
  const stripDescriptions = (value) => {
51559
50138
  if (Array.isArray(value)) return value.map(stripDescriptions);
51560
- if (!isRecord13(value)) return value;
50139
+ if (!isRecord9(value)) return value;
51561
50140
  return Object.fromEntries(
51562
50141
  Object.entries(value).flatMap(([key, nested]) => {
51563
50142
  if (key === "description" && typeof nested === "string" && exposesProviderSpend(nested)) {
@@ -51578,7 +50157,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51578
50157
  for (const item of value) collectSchemaIds(item);
51579
50158
  return;
51580
50159
  }
51581
- if (!isRecord13(value)) return;
50160
+ if (!isRecord9(value)) return;
51582
50161
  if (typeof value.$id === "string" && value.$id.trim()) {
51583
50162
  schemasById.set(value.$id.trim(), value);
51584
50163
  }
@@ -51591,10 +50170,10 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51591
50170
  let current = root;
51592
50171
  for (const rawSegment of ref.slice(2).split("/")) {
51593
50172
  const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
51594
- if (!isRecord13(current)) return schema;
50173
+ if (!isRecord9(current)) return schema;
51595
50174
  current = current[segment];
51596
50175
  }
51597
- return isRecord13(current) ? current : schema;
50176
+ return isRecord9(current) ? current : schema;
51598
50177
  };
51599
50178
  const addField = (field) => {
51600
50179
  const name = typeof field.name === "string" ? field.name : "";
@@ -51609,7 +50188,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51609
50188
  if (ref && activeRefs.has(ref)) return;
51610
50189
  const schema = resolveRef(unresolvedSchema);
51611
50190
  const nextActiveRefs = ref ? /* @__PURE__ */ new Set([...activeRefs, ref]) : activeRefs;
51612
- 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";
50191
+ 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";
51613
50192
  if (path) {
51614
50193
  addField({
51615
50194
  name: path,
@@ -51617,18 +50196,18 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51617
50196
  required,
51618
50197
  description: schema.description,
51619
50198
  ...Array.isArray(schema.enum) ? { enum: schema.enum } : {},
51620
- ...isRecord13(schema.items) ? { items: schema.items } : {},
50199
+ ...isRecord9(schema.items) ? { items: schema.items } : {},
51621
50200
  ...typeof schema.minItems === "number" ? { minItems: schema.minItems } : {},
51622
50201
  ...typeof schema.maxItems === "number" ? { maxItems: schema.maxItems } : {},
51623
50202
  ...Object.prototype.hasOwnProperty.call(schema, "default") ? { default: schema.default } : {}
51624
50203
  });
51625
50204
  }
51626
- const properties = isRecord13(schema.properties) ? schema.properties : {};
50205
+ const properties = isRecord9(schema.properties) ? schema.properties : {};
51627
50206
  const requiredNames = new Set(
51628
50207
  Array.isArray(schema.required) ? schema.required.map(String) : []
51629
50208
  );
51630
50209
  for (const [name, value] of Object.entries(properties)) {
51631
- if (!isRecord13(value)) continue;
50210
+ if (!isRecord9(value)) continue;
51632
50211
  visit(
51633
50212
  value,
51634
50213
  path ? `${path}.${name}` : name,
@@ -51636,13 +50215,13 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51636
50215
  nextActiveRefs
51637
50216
  );
51638
50217
  }
51639
- if (isRecord13(schema.items)) {
50218
+ if (isRecord9(schema.items)) {
51640
50219
  visit(schema.items, `${path}[]`, false, nextActiveRefs);
51641
50220
  }
51642
50221
  for (const keyword of ["anyOf", "oneOf", "allOf"]) {
51643
50222
  const branches = Array.isArray(schema[keyword]) ? schema[keyword] : [];
51644
50223
  for (const branch of branches) {
51645
- if (isRecord13(branch)) {
50224
+ if (isRecord9(branch)) {
51646
50225
  visit(branch, path, required, nextActiveRefs);
51647
50226
  }
51648
50227
  }
@@ -51652,21 +50231,21 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
51652
50231
  return fields2.size ? [...fields2.values()] : toolInputFieldsForDisplay(inputSchema);
51653
50232
  }
51654
50233
  function inputFieldJsonForDescribe(field) {
51655
- const publicItems = isRecord13(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;
50234
+ const publicItems = isRecord9(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;
51656
50235
  return {
51657
50236
  name: field.name,
51658
50237
  type: field.type ?? "unknown",
51659
50238
  required: Boolean(field.required),
51660
50239
  ...field.description ? { description: field.description } : {},
51661
- ...isRecord13(publicItems) ? { items: publicItems } : {},
50240
+ ...isRecord9(publicItems) ? { items: publicItems } : {},
51662
50241
  ...typeof field.minItems === "number" ? { minItems: field.minItems } : {},
51663
50242
  ...typeof field.maxItems === "number" ? { maxItems: field.maxItems } : {},
51664
50243
  ...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
51665
50244
  };
51666
50245
  }
51667
50246
  function arrayItemBoundsSuffix(field) {
51668
- const itemSchema = isRecord13(field.items) ? field.items : null;
51669
- const itemType = itemSchema ? typeof itemSchema.type === "string" ? itemSchema.type : isRecord13(itemSchema.properties) ? "object" : "unknown" : null;
50247
+ const itemSchema = isRecord9(field.items) ? field.items : null;
50248
+ const itemType = itemSchema ? typeof itemSchema.type === "string" ? itemSchema.type : isRecord9(itemSchema.properties) ? "object" : "unknown" : null;
51670
50249
  const itemEnum = Array.isArray(itemSchema?.enum) ? ` enum=${itemSchema.enum.map(String).join("|")}` : "";
51671
50250
  const itemTypeSuffix = itemType && itemType !== "unknown" ? ` items=${itemType}${itemEnum}` : "";
51672
50251
  const minItems = typeof field.minItems === "number" && Number.isFinite(field.minItems) ? field.minItems : null;
@@ -51680,13 +50259,13 @@ function arrayItemBoundsSuffix(field) {
51680
50259
  }
51681
50260
  function printToolExecutionHints(value) {
51682
50261
  const batchCapabilityRecord = recordField2(
51683
- isRecord13(value) ? value : {},
50262
+ isRecord9(value) ? value : {},
51684
50263
  "batchCapability",
51685
50264
  "batch_capability"
51686
50265
  );
51687
50266
  const batchCapability = Object.keys(batchCapabilityRecord).length > 0 ? batchCapabilityRecord : null;
51688
50267
  const executionMetadata = recordField2(
51689
- isRecord13(value) ? value : {},
50268
+ isRecord9(value) ? value : {},
51690
50269
  "executionMetadata",
51691
50270
  "execution_metadata"
51692
50271
  );
@@ -51726,7 +50305,7 @@ function printToolExecutionHints(value) {
51726
50305
  executionMetadata,
51727
50306
  "configuredRateLimits",
51728
50307
  "configured_rate_limits"
51729
- ).filter(isRecord13);
50308
+ ).filter(isRecord9);
51730
50309
  if (configuredRateLimits.length > 0) {
51731
50310
  console.log("");
51732
50311
  console.log(
@@ -51791,17 +50370,17 @@ function printJsonPreview(label, payload) {
51791
50370
  }
51792
50371
  function samplePayload(samples, key) {
51793
50372
  const entry = samples[key];
51794
- if (!isRecord13(entry)) return void 0;
50373
+ if (!isRecord9(entry)) return void 0;
51795
50374
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
51796
50375
  }
51797
50376
  function commandEnvelopeFromRawResponse(rawResponse) {
51798
- return isRecord13(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
50377
+ return isRecord9(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
51799
50378
  }
51800
50379
  function toolExecuteExitCode(envelope) {
51801
50380
  return envelope.status === "failed" || envelope.ok === false ? 1 : 0;
51802
50381
  }
51803
50382
  function extractToolExecutionWarningMessages(rawResponse) {
51804
- if (!isRecord13(rawResponse)) return [];
50383
+ if (!isRecord9(rawResponse)) return [];
51805
50384
  const candidates = [
51806
50385
  recordField2(recordField2(rawResponse, "toolResponse"), "meta"),
51807
50386
  recordField2(
@@ -51818,7 +50397,7 @@ function extractToolExecutionWarningMessages(rawResponse) {
51818
50397
  for (const warning of warnings) {
51819
50398
  if (typeof warning === "string" && warning.trim()) {
51820
50399
  messages.push(warning.trim());
51821
- } else if (isRecord13(warning)) {
50400
+ } else if (isRecord9(warning)) {
51822
50401
  const message = stringField2(warning, "message");
51823
50402
  if (message) messages.push(message);
51824
50403
  }
@@ -51827,7 +50406,7 @@ function extractToolExecutionWarningMessages(rawResponse) {
51827
50406
  return [...new Set(messages)];
51828
50407
  }
51829
50408
  function apifySyncRecoveryNext(rawResponse) {
51830
- if (!isRecord13(rawResponse) || rawResponse.status !== "running") return null;
50409
+ if (!isRecord9(rawResponse) || rawResponse.status !== "running") return null;
51831
50410
  const toolResponse = recordField2(rawResponse, "toolResponse");
51832
50411
  const raw = recordField2(toolResponse, "raw");
51833
50412
  if (raw.state !== "awaiting_apify") return null;
@@ -51850,7 +50429,7 @@ function apifySyncRecoveryNext(rawResponse) {
51850
50429
  }
51851
50430
  function listExtractorPathsFromUsageGuidance(tool) {
51852
50431
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
51853
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord13(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
50432
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord9(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
51854
50433
  return extractedLists.flatMap((entry) => {
51855
50434
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
51856
50435
  if (!Array.isArray(paths)) return [];
@@ -51866,7 +50445,7 @@ function formatDecimal(value) {
51866
50445
  function formatUsd(value) {
51867
50446
  return `$${formatDecimal(value)}`;
51868
50447
  }
51869
- function isRecord13(value) {
50448
+ function isRecord9(value) {
51870
50449
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
51871
50450
  }
51872
50451
  function stringField2(source, ...keys) {
@@ -51893,7 +50472,7 @@ function arrayField2(source, ...keys) {
51893
50472
  function recordField2(source, ...keys) {
51894
50473
  for (const key of keys) {
51895
50474
  const value = source[key];
51896
- if (isRecord13(value)) return value;
50475
+ if (isRecord9(value)) return value;
51897
50476
  }
51898
50477
  return {};
51899
50478
  }
@@ -51959,7 +50538,7 @@ function parseJsonObjectArgument(raw, flagName) {
51959
50538
  }
51960
50539
  throw invalidJsonError(flagName, message);
51961
50540
  }
51962
- if (!isRecord13(parsed)) {
50541
+ if (!isRecord9(parsed)) {
51963
50542
  throw invalidJsonError(flagName, "expected an object.");
51964
50543
  }
51965
50544
  return parsed;
@@ -52161,7 +50740,7 @@ function buildToolExecuteBaseEnvelope(input2) {
52161
50740
  kind: summaryEntries.length > 0 ? "object" : "raw",
52162
50741
  summary: input2.summary
52163
50742
  };
52164
- const envelopeHasCanonicalOutput = isRecord13(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
50743
+ const envelopeHasCanonicalOutput = isRecord9(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
52165
50744
  const envelopeHasDeclaredOutput = Object.prototype.hasOwnProperty.call(
52166
50745
  envelope,
52167
50746
  "output"
@@ -52188,7 +50767,7 @@ function buildToolExecuteBaseEnvelope(input2) {
52188
50767
  return {
52189
50768
  ...envelope,
52190
50769
  ...input2.idempotencyKey ? { idempotency_key: input2.idempotencyKey } : {},
52191
- ...isRecord13(input2.rawResponse) && isRecord13(input2.rawResponse.executionRecovery) ? { execution_recovery: input2.rawResponse.executionRecovery } : {},
50770
+ ...isRecord9(input2.rawResponse) && isRecord9(input2.rawResponse.executionRecovery) ? { execution_recovery: input2.rawResponse.executionRecovery } : {},
52192
50771
  ...envelopeHasCanonicalOutput || envelopeHasDeclaredOutput ? { output_preview: outputPreview } : { output: outputPreview },
52193
50772
  ...summaryEntries.length > 0 ? { summary: input2.summary } : {},
52194
50773
  ...warningMessages.length > 0 ? { warnings: warningMessages } : {},
@@ -52247,7 +50826,7 @@ function buildToolExecuteRowArtifactEnvelope(input2) {
52247
50826
  void _render;
52248
50827
  void _next;
52249
50828
  void _local;
52250
- const billingLookup = isRecord13(input2.baseEnvelope.next) && typeof input2.baseEnvelope.next.billing === "string" ? input2.baseEnvelope.next.billing : null;
50829
+ const billingLookup = isRecord9(input2.baseEnvelope.next) && typeof input2.baseEnvelope.next.billing === "string" ? input2.baseEnvelope.next.billing : null;
52251
50830
  return {
52252
50831
  ...base,
52253
50832
  status: typeof base.status === "string" ? base.status : "completed",
@@ -52423,7 +51002,7 @@ async function executeTool(args) {
52423
51002
  {
52424
51003
  ...baseEnvelope,
52425
51004
  local: {
52426
- ...isRecord13(baseEnvelope.local) ? baseEnvelope.local : {},
51005
+ ...isRecord9(baseEnvelope.local) ? baseEnvelope.local : {},
52427
51006
  payload_file: jsonPath
52428
51007
  }
52429
51008
  },
@@ -52737,7 +51316,7 @@ var PLAY_EQUIVALENT = {
52737
51316
  schema: "deepline plays describe <name>",
52738
51317
  runs: "deepline runs list --play <name>",
52739
51318
  run: "deepline runs get <run-id>",
52740
- tail: "deepline runs tail <run-id>",
51319
+ tail: "deepline runs watch <run-id>",
52741
51320
  cancel: "deepline runs stop <run-id>",
52742
51321
  delete: "deepline plays delete <name>"
52743
51322
  };