deepline 0.1.108 → 0.1.109

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
@@ -238,7 +238,7 @@ var SDK_RELEASE = {
238
238
  // preflight (existence, data rows, quotes, duplicate headers), HTML error
239
239
  // scrubbing, and word-boundary watch truncation.
240
240
  // 0.1.103 ships the refined SDK CLI command surface.
241
- // 0.1.104 ships postgres_fast suspension/billing parity and runtime worker hardening.
241
+ // 0.1.104 shipped the retired Postgres scheduler suspension/billing parity and runtime worker hardening.
242
242
  // 0.1.105 ships the billing catalog surface: billing plans, subscribe,
243
243
  // subscription status/cancel, invoices, and the client.billing namespace.
244
244
  // 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
@@ -246,10 +246,10 @@ var SDK_RELEASE = {
246
246
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
247
247
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
248
248
  // the SDK enrich generator's one-second stale policy.
249
- version: "0.1.108",
249
+ version: "0.1.109",
250
250
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
251
251
  supportPolicy: {
252
- latest: "0.1.108",
252
+ latest: "0.1.109",
253
253
  minimumSupported: "0.1.53",
254
254
  deprecatedBelow: "0.1.53",
255
255
  commandMinimumSupported: [
@@ -271,6 +271,7 @@ var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
271
271
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
272
272
  var COORDINATOR_URL_OVERRIDE_HEADER = "x-deepline-coordinator-url";
273
273
  var WORKER_CALLBACK_URL_OVERRIDE_HEADER = "x-deepline-worker-callback-url";
274
+ var RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER = "x-deepline-runtime-scheduler-schema";
274
275
  var SYNTHETIC_RUN_HEADER = "x-deepline-synthetic-run";
275
276
 
276
277
  // src/http.ts
@@ -339,6 +340,10 @@ var HttpClient = class {
339
340
  if (workerCallbackUrl?.trim()) {
340
341
  headers[WORKER_CALLBACK_URL_OVERRIDE_HEADER] = workerCallbackUrl.trim();
341
342
  }
343
+ const runtimeSchedulerSchema = typeof process !== "undefined" ? process.env?.DEEPLINE_RUNTIME_SCHEDULER_SCHEMA : void 0;
344
+ if (runtimeSchedulerSchema?.trim()) {
345
+ headers[RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER] = runtimeSchedulerSchema.trim();
346
+ }
342
347
  const syntheticRun = typeof process !== "undefined" ? process.env?.DEEPLINE_SYNTHETIC_RUN : void 0;
343
348
  if (syntheticRun && syntheticRun.trim() && syntheticRun.trim() !== "0") {
344
349
  headers[SYNTHETIC_RUN_HEADER] = "1";
@@ -545,8 +550,19 @@ var HttpClient = class {
545
550
  headers
546
551
  });
547
552
  }
553
+ /**
554
+ * Send a PATCH request with a JSON body.
555
+ *
556
+ * @typeParam T - Expected response body type
557
+ * @param path - API path
558
+ * @param body - JSON-serializable request body
559
+ */
548
560
  async patch(path, body, headers) {
549
- return this.request(path, { method: "PATCH", body, headers });
561
+ return this.request(path, {
562
+ method: "PATCH",
563
+ body,
564
+ headers
565
+ });
550
566
  }
551
567
  /**
552
568
  * Send a DELETE request.
@@ -897,6 +913,35 @@ function normalizePlayRunLiveStatus(value) {
897
913
  function isTerminalPlayRunLiveStatus(status) {
898
914
  return status === "completed" || status === "failed" || status === "cancelled" || status === "terminated" || status === "timed_out";
899
915
  }
916
+ function isRecord2(value) {
917
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
918
+ }
919
+ function finiteNumber2(value) {
920
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
921
+ }
922
+ function extractTerminalRunLogTail(result) {
923
+ if (!isRecord2(result) || !isRecord2(result._metadata)) {
924
+ return null;
925
+ }
926
+ const runLogTail = result._metadata.runLogTail;
927
+ if (!isRecord2(runLogTail) || !Array.isArray(runLogTail.tail)) {
928
+ return null;
929
+ }
930
+ const logTail = runLogTail.tail.filter(
931
+ (line) => typeof line === "string" && line.trim().length > 0
932
+ );
933
+ if (logTail.length === 0) {
934
+ return null;
935
+ }
936
+ const totalLogCount = Math.max(
937
+ finiteNumber2(runLogTail.totalLogCount) ?? logTail.length,
938
+ logTail.length
939
+ );
940
+ return {
941
+ logTail: logTail.slice(-LOG_TAIL_LIMIT),
942
+ totalLogCount
943
+ };
944
+ }
900
945
  function buildSnapshotFromLedger(snapshot) {
901
946
  const nodeStates = snapshot.orderedStepIds.map((stepId) => snapshot.stepsById[stepId]).filter((step) => Boolean(step)).map((step) => ({
902
947
  nodeId: step.stepId,
@@ -943,6 +988,14 @@ function buildPlayRunStatusSnapshot(input2) {
943
988
  updatedAt: input2.run.updatedAt ?? null,
944
989
  finishedAt: input2.run.finishedAt ?? null
945
990
  });
991
+ const terminalRunLogTail = extractTerminalRunLogTail(input2.run.result);
992
+ if (terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount) {
993
+ return buildSnapshotFromLedger({
994
+ ...ledgerSnapshot,
995
+ logTail: terminalRunLogTail.logTail,
996
+ totalLogCount: terminalRunLogTail.totalLogCount
997
+ });
998
+ }
946
999
  return buildSnapshotFromLedger(ledgerSnapshot);
947
1000
  }
948
1001
  function makeRunStreamEvent(input2) {
@@ -1537,7 +1590,7 @@ function chunkRegisterPlayArtifacts(artifacts) {
1537
1590
  return chunks;
1538
1591
  }
1539
1592
  var RUN_LOGS_PAGE_LIMIT = 1e3;
1540
- function isRecord2(value) {
1593
+ function isRecord3(value) {
1541
1594
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1542
1595
  }
1543
1596
  function isPrebuiltPlayDescription(play) {
@@ -1639,7 +1692,7 @@ function updatePlayLiveStatusState(state, event) {
1639
1692
  }
1640
1693
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
1641
1694
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
1642
- const progressPayload = isRecord2(payload.progress) ? payload.progress : {};
1695
+ const progressPayload = isRecord3(payload.progress) ? payload.progress : {};
1643
1696
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
1644
1697
  const payloadLogs = readStringArray(payload.logs);
1645
1698
  const progressLogs = readStringArray(progressPayload.logs);
@@ -1752,9 +1805,9 @@ var DeeplineClient = class {
1752
1805
  return fields.length > 0 ? { fields } : schema;
1753
1806
  }
1754
1807
  schemaMetadata(schema, key) {
1755
- if (!isRecord2(schema)) return null;
1808
+ if (!isRecord3(schema)) return null;
1756
1809
  const value = schema[key];
1757
- return isRecord2(value) ? value : null;
1810
+ return isRecord3(value) ? value : null;
1758
1811
  }
1759
1812
  playRunCommand(play, options) {
1760
1813
  const target = play.reference || play.name;
@@ -1801,7 +1854,7 @@ var DeeplineClient = class {
1801
1854
  aliases,
1802
1855
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
1803
1856
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
1804
- staticPipeline: isRecord2(play.staticPipeline) ? play.staticPipeline : isRecord2(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord2(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
1857
+ staticPipeline: isRecord3(play.staticPipeline) ? play.staticPipeline : isRecord3(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord3(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
1805
1858
  ...csvInput ? { csvInput } : {},
1806
1859
  ...rowOutputSchema ? { rowOutputSchema } : {},
1807
1860
  runCommand: runCommand2,
@@ -5295,14 +5348,14 @@ function sanitizeCsvProjectionInfo(input2) {
5295
5348
  const rows = input2.rows.map(stripCsvProjectionFields);
5296
5349
  return { rows, columns };
5297
5350
  }
5298
- function isRecord3(value) {
5351
+ function isRecord4(value) {
5299
5352
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
5300
5353
  }
5301
5354
  function isSerializedDataset(value) {
5302
- return isRecord3(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
5355
+ return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
5303
5356
  }
5304
5357
  function isPackagedDatasetOutput(value) {
5305
- return isRecord3(value) && value.kind === "dataset" && isRecord3(value.preview) && Array.isArray(value.preview.rows);
5358
+ return isRecord4(value) && value.kind === "dataset" && isRecord4(value.preview) && Array.isArray(value.preview.rows);
5306
5359
  }
5307
5360
  function pathParts(path) {
5308
5361
  return path.split(".").map((part) => part.trim()).filter(Boolean);
@@ -5310,7 +5363,7 @@ function pathParts(path) {
5310
5363
  function valueAtPath(root, path) {
5311
5364
  let cursor = root;
5312
5365
  for (const part of pathParts(path)) {
5313
- if (!isRecord3(cursor)) {
5366
+ if (!isRecord4(cursor)) {
5314
5367
  return void 0;
5315
5368
  }
5316
5369
  cursor = cursor[part];
@@ -5318,17 +5371,17 @@ function valueAtPath(root, path) {
5318
5371
  return cursor;
5319
5372
  }
5320
5373
  function totalRowsForDataset(result, datasetPath) {
5321
- const metadata = isRecord3(result._metadata) ? result._metadata : null;
5374
+ const metadata = isRecord4(result._metadata) ? result._metadata : null;
5322
5375
  const parentPath = datasetPath.split(".").slice(0, -1).join(".");
5323
5376
  const parent = parentPath ? valueAtPath({ result }, parentPath) : result;
5324
- return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord3(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
5377
+ return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord4(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
5325
5378
  }
5326
5379
  function rowArray(value) {
5327
5380
  if (!Array.isArray(value)) {
5328
5381
  return null;
5329
5382
  }
5330
5383
  const rows = value.filter(
5331
- (row) => isRecord3(row)
5384
+ (row) => isRecord4(row)
5332
5385
  );
5333
5386
  return rows.length === value.length ? rows : null;
5334
5387
  }
@@ -5352,7 +5405,7 @@ function inferColumns(rows) {
5352
5405
  return columns;
5353
5406
  }
5354
5407
  function columnsFromDatasetSummary(summary) {
5355
- if (!isRecord3(summary) || !isRecord3(summary.columnStats)) {
5408
+ if (!isRecord4(summary) || !isRecord4(summary.columnStats)) {
5356
5409
  return [];
5357
5410
  }
5358
5411
  return Object.keys(summary.columnStats).filter((column) => column);
@@ -5381,7 +5434,7 @@ function canonicalRowsInfoFromCandidate(input2) {
5381
5434
  }
5382
5435
  if (isPackagedDatasetOutput(candidate.value)) {
5383
5436
  const rawRows = rowArray(candidate.value.preview?.rows) ?? [];
5384
- const totalRows2 = readNumber(candidate.value.preview?.totalRows) ?? readNumber(candidate.value.rowCount) ?? rawRows.length;
5437
+ const totalRows2 = readNumber(candidate.value.rowCount) ?? readNumber(candidate.value.preview?.totalRows) ?? rawRows.length;
5385
5438
  const explicitColumns = Array.isArray(candidate.value.columns) ? candidate.value.columns.filter(
5386
5439
  (column) => typeof column === "string"
5387
5440
  ) : [];
@@ -5442,7 +5495,7 @@ function collectDatasetCandidates(input2) {
5442
5495
  });
5443
5496
  return;
5444
5497
  }
5445
- if (!isRecord3(input2.value)) {
5498
+ if (!isRecord4(input2.value)) {
5446
5499
  return;
5447
5500
  }
5448
5501
  for (const [key, child] of Object.entries(input2.value)) {
@@ -5459,12 +5512,12 @@ function collectDatasetCandidates(input2) {
5459
5512
  }
5460
5513
  }
5461
5514
  function collectCanonicalRowsInfos(statusOrResult) {
5462
- const root = isRecord3(statusOrResult) ? statusOrResult : null;
5463
- const result = isRecord3(root?.result) ? root.result : root;
5515
+ const root = isRecord4(statusOrResult) ? statusOrResult : null;
5516
+ const result = isRecord4(root?.result) ? root.result : root;
5464
5517
  if (!result) {
5465
5518
  return [];
5466
5519
  }
5467
- const metadata = isRecord3(result._metadata) ? result._metadata : null;
5520
+ const metadata = isRecord4(result._metadata) ? result._metadata : null;
5468
5521
  const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
5469
5522
  const candidates = [
5470
5523
  {
@@ -5488,8 +5541,8 @@ function collectCanonicalRowsInfos(statusOrResult) {
5488
5541
  total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
5489
5542
  }
5490
5543
  ];
5491
- if (isRecord3(result.output)) {
5492
- const outputMetadata = isRecord3(result.output._metadata) ? result.output._metadata : null;
5544
+ if (isRecord4(result.output)) {
5545
+ const outputMetadata = isRecord4(result.output._metadata) ? result.output._metadata : null;
5493
5546
  const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
5494
5547
  candidates.push(
5495
5548
  {
@@ -5516,14 +5569,14 @@ function collectCanonicalRowsInfos(statusOrResult) {
5516
5569
  }
5517
5570
  if (Array.isArray(result.steps)) {
5518
5571
  result.steps.forEach((step, index) => {
5519
- if (!isRecord3(step) || !isRecord3(step.output)) {
5572
+ if (!isRecord4(step) || !isRecord4(step.output)) {
5520
5573
  return;
5521
5574
  }
5522
5575
  const source = typeof step.output.path === "string" ? step.output.path : typeof step.id === "string" ? `steps.${step.id}.output` : `steps.${index}.output`;
5523
5576
  candidates.push({
5524
5577
  source,
5525
5578
  value: step.output,
5526
- total: step.output.rowCount ?? (isRecord3(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord3(step.progress) ? step.progress.total : void 0)
5579
+ total: step.output.rowCount ?? (isRecord4(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord4(step.progress) ? step.progress.total : void 0)
5527
5580
  });
5528
5581
  });
5529
5582
  }
@@ -5550,15 +5603,15 @@ function collectCanonicalRowsInfos(statusOrResult) {
5550
5603
  return infos;
5551
5604
  }
5552
5605
  function collectPackagedStepDatasetCandidates(statusOrResult) {
5553
- const root = isRecord3(statusOrResult) ? statusOrResult : null;
5606
+ const root = isRecord4(statusOrResult) ? statusOrResult : null;
5554
5607
  if (!root) {
5555
5608
  return [];
5556
5609
  }
5557
- const pkg = isRecord3(root.package) ? root.package : root;
5610
+ const pkg = isRecord4(root.package) ? root.package : root;
5558
5611
  const steps = Array.isArray(pkg.steps) ? pkg.steps : [];
5559
5612
  const candidates = [];
5560
5613
  for (const step of steps) {
5561
- if (!isRecord3(step) || !isRecord3(step.output)) {
5614
+ if (!isRecord4(step) || !isRecord4(step.output)) {
5562
5615
  continue;
5563
5616
  }
5564
5617
  const output2 = step.output;
@@ -5572,14 +5625,14 @@ function collectPackagedStepDatasetCandidates(statusOrResult) {
5572
5625
  candidates.push({
5573
5626
  source,
5574
5627
  value: output2,
5575
- total: output2.rowCount ?? (isRecord3(output2.preview) ? output2.preview.totalRows : void 0) ?? (isRecord3(step.progress) ? step.progress.total : void 0)
5628
+ total: output2.rowCount ?? (isRecord4(output2.preview) ? output2.preview.totalRows : void 0) ?? (isRecord4(step.progress) ? step.progress.total : void 0)
5576
5629
  });
5577
5630
  }
5578
5631
  return candidates;
5579
5632
  }
5580
5633
  function collectSerializedDatasetRowsInfos(statusOrResult) {
5581
- const root = isRecord3(statusOrResult) ? statusOrResult : null;
5582
- const result = isRecord3(root?.result) ? root.result : root;
5634
+ const root = isRecord4(statusOrResult) ? statusOrResult : null;
5635
+ const result = isRecord4(root?.result) ? root.result : root;
5583
5636
  const candidates = [];
5584
5637
  if (result) {
5585
5638
  collectDatasetCandidates({
@@ -5615,17 +5668,17 @@ function percentText(numerator, denominator) {
5615
5668
  return datasetSummaryPercentText(numerator, denominator);
5616
5669
  }
5617
5670
  function isDatasetExecutionStatsInput(value) {
5618
- return isRecord3(value) && isRecord3(value.columnStats) && Object.values(value.columnStats).every(isRecord3);
5671
+ return isRecord4(value) && isRecord4(value.columnStats) && Object.values(value.columnStats).every(isRecord4);
5619
5672
  }
5620
5673
  function extractDatasetExecutionStats(statusOrResult) {
5621
- if (!isRecord3(statusOrResult)) {
5674
+ if (!isRecord4(statusOrResult)) {
5622
5675
  return null;
5623
5676
  }
5624
5677
  const direct = statusOrResult.dataset_execution_stats;
5625
5678
  if (isDatasetExecutionStatsInput(direct)) {
5626
5679
  return direct;
5627
5680
  }
5628
- const nested = isRecord3(statusOrResult.result) ? statusOrResult.result.dataset_execution_stats : null;
5681
+ const nested = isRecord4(statusOrResult.result) ? statusOrResult.result.dataset_execution_stats : null;
5629
5682
  return isDatasetExecutionStatsInput(nested) ? nested : null;
5630
5683
  }
5631
5684
  function countPercentText(count, denominator) {
@@ -5666,13 +5719,13 @@ function summarizeSampleValue(value, depth = 0) {
5666
5719
  if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
5667
5720
  if (depth >= 3) {
5668
5721
  if (Array.isArray(parsed)) return [];
5669
- if (isRecord3(parsed)) return {};
5722
+ if (isRecord4(parsed)) return {};
5670
5723
  return compactScalar(parsed);
5671
5724
  }
5672
5725
  if (Array.isArray(parsed)) {
5673
5726
  return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
5674
5727
  }
5675
- if (isRecord3(parsed)) {
5728
+ if (isRecord4(parsed)) {
5676
5729
  const out = {};
5677
5730
  for (const [key, nested] of Object.entries(parsed)) {
5678
5731
  if (["__dl", "meta", "metadata"].includes(key)) {
@@ -5703,7 +5756,7 @@ function compactCell(value) {
5703
5756
  }
5704
5757
  return `[${parsed.length} items]`;
5705
5758
  }
5706
- if (isRecord3(parsed)) {
5759
+ if (isRecord4(parsed)) {
5707
5760
  for (const key of ["matched_result", "output"]) {
5708
5761
  if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
5709
5762
  return compactCell(parsed[key]);
@@ -7473,16 +7526,19 @@ var PLAY_DEDUP_BACKENDS = {
7473
7526
  var PLAY_SCHEDULER_BACKENDS = {
7474
7527
  temporal: "temporal",
7475
7528
  cfWorkflows: "cf-workflows",
7529
+ /**
7530
+ * Private legacy id retained only so old persisted rows can be interpreted.
7531
+ * It is not a selectable scheduler backend after the Hatchet hard cutover.
7532
+ */
7476
7533
  postgres: "postgres",
7534
+ hatchet: "hatchet",
7477
7535
  inProcess: "in-process"
7478
7536
  };
7479
7537
 
7480
7538
  // ../shared_libs/play-runtime/providers.ts
7481
7539
  var PLAY_RUNTIME_PROVIDER_IDS = {
7482
7540
  workersEdge: "workers_edge",
7483
- postgresFast: "postgres_fast",
7484
- postgresFastSandbox: "postgres_fast_sandbox",
7485
- postgresFastWorkers: "postgres_fast_workers",
7541
+ hatchet: "hatchet",
7486
7542
  local: "local"
7487
7543
  };
7488
7544
  var PLAY_RUNTIME_PROVIDERS = {
@@ -7494,29 +7550,13 @@ var PLAY_RUNTIME_PROVIDERS = {
7494
7550
  artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
7495
7551
  label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
7496
7552
  },
7497
- postgres_fast: {
7498
- id: PLAY_RUNTIME_PROVIDER_IDS.postgresFast,
7499
- scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
7500
- runner: PLAY_RUNTIME_BACKENDS.daytona,
7501
- dedup: PLAY_DEDUP_BACKENDS.durableObject,
7502
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
7503
- label: "BETA: Postgres Scheduler + warm sandbox runner + DO dedup"
7504
- },
7505
- postgres_fast_sandbox: {
7506
- id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastSandbox,
7507
- scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
7553
+ hatchet: {
7554
+ id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
7555
+ scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
7508
7556
  runner: PLAY_RUNTIME_BACKENDS.daytona,
7509
7557
  dedup: PLAY_DEDUP_BACKENDS.durableObject,
7510
7558
  artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
7511
- label: "BETA: Postgres Scheduler + warm sandbox runner + DO dedup"
7512
- },
7513
- postgres_fast_workers: {
7514
- id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastWorkers,
7515
- scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
7516
- runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
7517
- dedup: PLAY_DEDUP_BACKENDS.durableObject,
7518
- artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
7519
- label: "Experimental Postgres Scheduler + Queue/DO-woken Workers + DO dedup"
7559
+ label: "Hatchet scheduler + one-shot Daytona runner + DO dedup"
7520
7560
  },
7521
7561
  local: {
7522
7562
  id: PLAY_RUNTIME_PROVIDER_IDS.local,
@@ -8028,17 +8068,17 @@ function parsePositiveInteger2(value, flagName) {
8028
8068
  }
8029
8069
  return parsed;
8030
8070
  }
8031
- function isRecord4(value) {
8071
+ function isRecord5(value) {
8032
8072
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
8033
8073
  }
8034
8074
  function stringValue(value) {
8035
8075
  return typeof value === "string" ? value.trim() : "";
8036
8076
  }
8037
8077
  function extractionEntries(value) {
8038
- if (Array.isArray(value)) return value.filter(isRecord4);
8039
- if (!isRecord4(value)) return [];
8078
+ if (Array.isArray(value)) return value.filter(isRecord5);
8079
+ if (!isRecord5(value)) return [];
8040
8080
  return Object.entries(value).map(
8041
- ([name, entry]) => isRecord4(entry) ? { name, ...entry } : { name }
8081
+ ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
8042
8082
  );
8043
8083
  }
8044
8084
  var PlayBootstrapError = class extends Error {
@@ -8458,7 +8498,7 @@ function readCsvSampleRows(sample) {
8458
8498
  relax_column_count: true,
8459
8499
  trim: true
8460
8500
  });
8461
- return Array.isArray(parsedRows) ? parsedRows.filter(isRecord4) : [];
8501
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord5) : [];
8462
8502
  }
8463
8503
  function readSourceCsvColumnSpecs(csvPath) {
8464
8504
  const sample = readCsvSample(csvPath);
@@ -8491,16 +8531,16 @@ function packagedCsvPathForPlay(csvPath) {
8491
8531
  return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
8492
8532
  }
8493
8533
  function getterNamesFromTool(tool, kind) {
8494
- const usageGuidance = isRecord4(tool?.usageGuidance) ? tool.usageGuidance : {};
8495
- const resultGuidance = isRecord4(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord4(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
8534
+ const usageGuidance = isRecord5(tool?.usageGuidance) ? tool.usageGuidance : {};
8535
+ const resultGuidance = isRecord5(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord5(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
8496
8536
  const key = kind === "list" ? "extractedLists" : "extractedValues";
8497
8537
  const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
8498
8538
  return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
8499
8539
  }
8500
8540
  function targetGettersFromTool(tool) {
8501
- const record = isRecord4(tool) ? tool : {};
8541
+ const record = isRecord5(tool) ? tool : {};
8502
8542
  const raw = record.targetGetters ?? record.target_getters;
8503
- if (!isRecord4(raw)) return {};
8543
+ if (!isRecord5(raw)) return {};
8504
8544
  const entries = [];
8505
8545
  for (const [target, value] of Object.entries(raw)) {
8506
8546
  const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
@@ -8521,10 +8561,10 @@ function listRowCandidateKeysFromTool(tool) {
8521
8561
  return [...keys].sort();
8522
8562
  }
8523
8563
  function inputPropertyNames(schema) {
8524
- if (!isRecord4(schema)) return [];
8525
- if (isRecord4(schema.properties)) return Object.keys(schema.properties);
8564
+ if (!isRecord5(schema)) return [];
8565
+ if (isRecord5(schema.properties)) return Object.keys(schema.properties);
8526
8566
  if (Array.isArray(schema.fields)) {
8527
- return schema.fields.filter(isRecord4).map((field) => stringValue(field.name)).filter(Boolean);
8567
+ return schema.fields.filter(isRecord5).map((field) => stringValue(field.name)).filter(Boolean);
8528
8568
  }
8529
8569
  return [];
8530
8570
  }
@@ -8538,7 +8578,7 @@ function schemaFieldDetails(schema) {
8538
8578
  return { required, optional };
8539
8579
  }
8540
8580
  function jsonSchemaTypeExpression(schema) {
8541
- if (!isRecord4(schema)) return "unknown";
8581
+ if (!isRecord5(schema)) return "unknown";
8542
8582
  const type = schema.type;
8543
8583
  if (Array.isArray(type)) {
8544
8584
  return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
@@ -8568,7 +8608,7 @@ function jsonSchemaTypeExpression(schema) {
8568
8608
  }
8569
8609
  }
8570
8610
  function objectPropertySchema(schema, property) {
8571
- return isRecord4(schema) && isRecord4(schema.properties) ? schema.properties[property] : null;
8611
+ return isRecord5(schema) && isRecord5(schema.properties) ? schema.properties[property] : null;
8572
8612
  }
8573
8613
  function playOutputHasField(schema, field) {
8574
8614
  return objectPropertySchema(schema, field) != null;
@@ -8744,14 +8784,14 @@ ${indent2.slice(2)}}`;
8744
8784
  }
8745
8785
  function requiredPlayInputFields(play) {
8746
8786
  const schema = play?.inputSchema;
8747
- if (!isRecord4(schema)) return [];
8787
+ if (!isRecord5(schema)) return [];
8748
8788
  if (Array.isArray(schema.required)) {
8749
8789
  return schema.required.filter(
8750
8790
  (value) => typeof value === "string"
8751
8791
  );
8752
8792
  }
8753
8793
  if (Array.isArray(schema.fields)) {
8754
- return schema.fields.filter(isRecord4).filter(
8794
+ return schema.fields.filter(isRecord5).filter(
8755
8795
  (field) => field.required === true && typeof field.name === "string"
8756
8796
  ).map((field) => String(field.name));
8757
8797
  }
@@ -8932,7 +8972,7 @@ function validateBootstrapRoutes(input2) {
8932
8972
  }
8933
8973
  }
8934
8974
  function staticPipelineSubsteps(pipeline) {
8935
- if (!isRecord4(pipeline)) return [];
8975
+ if (!isRecord5(pipeline)) return [];
8936
8976
  return [
8937
8977
  ...extractionEntries(pipeline.stages),
8938
8978
  ...extractionEntries(pipeline.substeps)
@@ -8940,7 +8980,7 @@ function staticPipelineSubsteps(pipeline) {
8940
8980
  }
8941
8981
  function playUsesMapBackedRuntime(play) {
8942
8982
  const pipeline = play?.staticPipeline;
8943
- if (!isRecord4(pipeline)) return false;
8983
+ if (!isRecord5(pipeline)) return false;
8944
8984
  if (stringValue(pipeline.tableNamespace)) return true;
8945
8985
  return staticPipelineSubsteps(pipeline).some((substep) => {
8946
8986
  if (stringValue(substep.type) === "map") return true;
@@ -8949,7 +8989,7 @@ function playUsesMapBackedRuntime(play) {
8949
8989
  aliases: [],
8950
8990
  runCommand: "",
8951
8991
  examples: [],
8952
- staticPipeline: isRecord4(substep.pipeline) ? substep.pipeline : null
8992
+ staticPipeline: isRecord5(substep.pipeline) ? substep.pipeline : null
8953
8993
  });
8954
8994
  });
8955
8995
  }
@@ -10511,10 +10551,12 @@ function playStatusValue(value) {
10511
10551
  return value === "queued" || value === "running" || value === "waiting" || value === "completed" || value === "failed" || value === "cancelled" ? value : null;
10512
10552
  }
10513
10553
  function getRunRecordFromPackage(value) {
10514
- if (!isPlayRunPackageValue(value)) {
10554
+ const nestedPackage = value.package;
10555
+ const playRunPackage = isPlayRunPackageValue(value) ? value : isPlayRunPackageValue(nestedPackage) ? nestedPackage : null;
10556
+ if (!playRunPackage) {
10515
10557
  return null;
10516
10558
  }
10517
- const run = value.run;
10559
+ const run = playRunPackage.run;
10518
10560
  return run && typeof run === "object" && !Array.isArray(run) ? run : null;
10519
10561
  }
10520
10562
  function getRunIdFromLiveEvent(event) {
@@ -10544,10 +10586,12 @@ function getFinalStatusFromLiveEvent(event) {
10544
10586
  return null;
10545
10587
  }
10546
10588
  const runId = typeof payload.runId === "string" ? payload.runId : typeof packageRun?.id === "string" ? packageRun.id : "";
10589
+ const error = typeof payload.error === "string" ? payload.error : typeof packageRun?.error === "string" ? packageRun.error : void 0;
10547
10590
  return {
10548
10591
  ...payload,
10549
10592
  runId,
10550
- status
10593
+ status,
10594
+ ...error ? { error } : {}
10551
10595
  };
10552
10596
  }
10553
10597
  function getLogLinesFromLiveEvent(event) {
@@ -11866,7 +11910,16 @@ function withTerminalPlayIdentity(status, playName) {
11866
11910
  function compactPlayStatus(status) {
11867
11911
  const packaged = getPlayRunPackage(status);
11868
11912
  if (packaged) {
11869
- return packaged;
11913
+ const error2 = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : null);
11914
+ if (!error2) {
11915
+ return packaged;
11916
+ }
11917
+ const run = packaged.run && typeof packaged.run === "object" ? packaged.run : null;
11918
+ return {
11919
+ ...packaged,
11920
+ error: error2,
11921
+ ...run ? { run: { ...run, error: error2 } } : {}
11922
+ };
11870
11923
  }
11871
11924
  const rowsInfo = extractCanonicalRowsInfo(status);
11872
11925
  const result = status && typeof status === "object" ? status.result : null;
@@ -12206,10 +12259,17 @@ function writePlayResult(status, jsonOutput, options) {
12206
12259
  ` }
12207
12260
  );
12208
12261
  }
12209
- function playRunPackageStepCount(pkg) {
12210
- if (!pkg) return 0;
12211
- const steps = pkg.steps;
12212
- return Array.isArray(steps) ? steps.length : 0;
12262
+ function playRunPackageTextLedgerIncomplete(pkg) {
12263
+ if (!pkg) return true;
12264
+ const steps = readRecordArray(pkg.steps);
12265
+ if (steps.length === 0) return true;
12266
+ for (const step of steps) {
12267
+ if (step.kind !== "dataset" || step.status !== "completed") continue;
12268
+ const output2 = readRecord(step.output);
12269
+ if (!output2 || typeof output2.rowCount !== "number") return true;
12270
+ if (!readRecord(output2.summary)) return true;
12271
+ }
12272
+ return false;
12213
12273
  }
12214
12274
  async function resolvePlayRunOutputStatus(input2) {
12215
12275
  const runId = input2.status.runId;
@@ -12218,7 +12278,7 @@ async function resolvePlayRunOutputStatus(input2) {
12218
12278
  }
12219
12279
  const streamedPackage = getPlayRunPackage(input2.status);
12220
12280
  const refreshForFullJson = input2.fullJson && streamedPackage !== null;
12221
- const streamedTextPackageIncomplete = !input2.jsonOutput && input2.status.status === "completed" && playRunPackageStepCount(streamedPackage) === 0;
12281
+ const streamedTextPackageIncomplete = !input2.jsonOutput && input2.status.status === "completed" && playRunPackageTextLedgerIncomplete(streamedPackage);
12222
12282
  if (!refreshForFullJson && !streamedTextPackageIncomplete) {
12223
12283
  return input2.status;
12224
12284
  }
@@ -12226,7 +12286,7 @@ async function resolvePlayRunOutputStatus(input2) {
12226
12286
  billing: false,
12227
12287
  full: input2.fullJson
12228
12288
  });
12229
- for (let attempt = 0; attempt < 3 && streamedTextPackageIncomplete && refreshedStatus.status === "completed" && playRunPackageStepCount(getPlayRunPackage(refreshedStatus)) === 0; attempt += 1) {
12289
+ for (let attempt = 0; attempt < 3 && streamedTextPackageIncomplete && refreshedStatus.status === "completed" && playRunPackageTextLedgerIncomplete(getPlayRunPackage(refreshedStatus)); attempt += 1) {
12230
12290
  await sleep5(250);
12231
12291
  refreshedStatus = await input2.client.getPlayStatus(runId, {
12232
12292
  billing: false,
@@ -12535,7 +12595,7 @@ function extractPlayValidationErrors(value) {
12535
12595
  if (value instanceof DeeplineError) {
12536
12596
  return extractPlayValidationErrors(value.details);
12537
12597
  }
12538
- if (!isRecord5(value)) {
12598
+ if (!isRecord6(value)) {
12539
12599
  return [];
12540
12600
  }
12541
12601
  const directErrors = stringArrayField(value, "errors");
@@ -12748,7 +12808,7 @@ function writeStartedPlayRun(input2) {
12748
12808
  );
12749
12809
  }
12750
12810
  function parsePlayRunOptions(args) {
12751
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge; postgres_fast is BETA (opt-in per run, never the default).\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.dataset guidance.";
12811
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge; hatchet is the durable Daytona-backed preview runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.dataset guidance.";
12752
12812
  let filePath = null;
12753
12813
  let playName = null;
12754
12814
  let input2 = null;
@@ -12893,7 +12953,7 @@ function shouldUseLocalOnlyPlayCheck() {
12893
12953
  const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
12894
12954
  return value === "1" || value === "true" || value === "yes" || value === "on";
12895
12955
  }
12896
- function isRecord5(value) {
12956
+ function isRecord6(value) {
12897
12957
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
12898
12958
  }
12899
12959
  function stringValue2(value) {
@@ -12903,14 +12963,14 @@ function asArray(value) {
12903
12963
  return Array.isArray(value) ? value : [];
12904
12964
  }
12905
12965
  function extractionEntries2(value) {
12906
- if (Array.isArray(value)) return value.filter(isRecord5);
12907
- if (!isRecord5(value)) return [];
12966
+ if (Array.isArray(value)) return value.filter(isRecord6);
12967
+ if (!isRecord6(value)) return [];
12908
12968
  return Object.entries(value).map(
12909
- ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
12969
+ ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
12910
12970
  );
12911
12971
  }
12912
12972
  function firstRawPath(entry) {
12913
- const details = isRecord5(entry.details) ? entry.details : {};
12973
+ const details = isRecord6(entry.details) ? entry.details : {};
12914
12974
  const paths = [
12915
12975
  ...asArray(details.rawToolOutputPaths),
12916
12976
  ...asArray(details.raw_tool_output_paths),
@@ -12928,12 +12988,12 @@ function checkHintRawPath(value) {
12928
12988
  function collectStaticPipelineToolIds(staticPipeline) {
12929
12989
  const seen = /* @__PURE__ */ new Set();
12930
12990
  const visitPipeline = (pipeline) => {
12931
- if (!isRecord5(pipeline)) return;
12991
+ if (!isRecord6(pipeline)) return;
12932
12992
  for (const step of [
12933
12993
  ...asArray(pipeline.stages),
12934
12994
  ...asArray(pipeline.substeps)
12935
12995
  ]) {
12936
- if (!isRecord5(step)) continue;
12996
+ if (!isRecord6(step)) continue;
12937
12997
  if (step.type === "tool") {
12938
12998
  const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
12939
12999
  if (toolId) seen.add(toolId);
@@ -12947,9 +13007,9 @@ function collectStaticPipelineToolIds(staticPipeline) {
12947
13007
  return [...seen].sort();
12948
13008
  }
12949
13009
  function toolGetterHintFromMetadata(toolId, tool) {
12950
- const usageGuidance = isRecord5(tool.usageGuidance) ? tool.usageGuidance : {};
12951
- const resultGuidance = isRecord5(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord5(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
12952
- const toolResponse = isRecord5(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord5(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
13010
+ const usageGuidance = isRecord6(tool.usageGuidance) ? tool.usageGuidance : {};
13011
+ const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
13012
+ const toolResponse = isRecord6(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord6(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
12953
13013
  const lists = extractionEntries2(
12954
13014
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
12955
13015
  ).map((entry) => ({
@@ -14274,6 +14334,40 @@ async function handlePlayDescribe(args) {
14274
14334
  );
14275
14335
  return 2;
14276
14336
  }
14337
+ if (isFileTarget(playName) || looksLikeFilePath(playName)) {
14338
+ const message = "Local play files can be checked and run, but describe only supports saved/prebuilt play references.";
14339
+ const definedName = isFileTarget(playName) ? (() => {
14340
+ try {
14341
+ return extractPlayName(
14342
+ (0, import_node_fs10.readFileSync)((0, import_node_path12.resolve)(playName), "utf-8"),
14343
+ playName
14344
+ );
14345
+ } catch {
14346
+ return null;
14347
+ }
14348
+ })() : null;
14349
+ const next = [
14350
+ `deepline plays check ${playName}`,
14351
+ ...definedName ? [`deepline plays describe <workspace>/${definedName}`] : []
14352
+ ];
14353
+ if (argsWantJson(args)) {
14354
+ process.stdout.write(
14355
+ `${JSON.stringify({
14356
+ ok: false,
14357
+ error: { message },
14358
+ next
14359
+ })}
14360
+ `
14361
+ );
14362
+ } else {
14363
+ console.error(message);
14364
+ console.error(`Try: ${next[0]}`);
14365
+ if (next[1]) {
14366
+ console.error(`Or after publishing/running: ${next[1]}`);
14367
+ }
14368
+ }
14369
+ return 2;
14370
+ }
14277
14371
  const client2 = new DeeplineClient();
14278
14372
  await assertCanonicalNamedPlayReference(client2, playName);
14279
14373
  const play = await client2.describePlay(
@@ -15355,6 +15449,18 @@ function getterFromLegacyExtractJs(extractJs, fallbackAlias) {
15355
15449
  return null;
15356
15450
  }
15357
15451
 
15452
+ // src/cli/enrich-compat-adapter.ts
15453
+ var ENRICH_COMPAT_DEFAULT_PLAY_NAME = "deepline-enrich-v1-compat";
15454
+ var ENRICH_COMPAT_DEFAULT_MAP_NAME = "deepline_enrich_rows";
15455
+ var ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE = "{ recompute: true }";
15456
+ function buildEnrichCompatibilityPlan(options = {}) {
15457
+ return {
15458
+ playName: options.playName?.trim() || ENRICH_COMPAT_DEFAULT_PLAY_NAME,
15459
+ mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME,
15460
+ metadataCellPolicySource: ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE
15461
+ };
15462
+ }
15463
+
15358
15464
  // src/cli/user-code-safety.ts
15359
15465
  var FORBIDDEN = [
15360
15466
  // Non-deterministic — breaks replay.
@@ -15526,12 +15632,16 @@ function renderPlayStep(command, options) {
15526
15632
  const runIfJs = command.run_if_js ? `(row) => { const input = row; const context = row;
15527
15633
  ${indent(renderJavascriptBody(command.run_if_js), 6)}
15528
15634
  }` : "null";
15529
- const runIfLines = command.run_if_js ? [` const __dlRunIf = ${runIfJs};`, ` if (!__dlRunIf(row)) return null;`] : [];
15635
+ const runIfLines = command.run_if_js ? [
15636
+ ` const __dlRunIf = ${runIfJs};`,
15637
+ ` if (!__dlRunIf(templateRow)) return null;`
15638
+ ] : [];
15530
15639
  return [
15531
15640
  `async (row, stepCtx) => {`,
15532
15641
  ...options.precheck ? [` if (${options.precheck}) return null;`] : [],
15642
+ ` const templateRow = __dlPrepareEnrichRow(row, [${alias}]);`,
15533
15643
  ...runIfLines,
15534
- ` const payload = __dlTemplate(${payload}, row) as Record<string, unknown>;`,
15644
+ ` const payload = __dlTemplate(${payload}, templateRow) as Record<string, unknown>;`,
15535
15645
  ` const result = await stepCtx.runPlay(${callId}, ${playRef}, payload, {`,
15536
15646
  ` description: ${stringLiteral(command.description ?? command.alias)}`,
15537
15647
  ` });`,
@@ -15632,7 +15742,7 @@ function collectGeneratedAliases(commands) {
15632
15742
  }
15633
15743
  return aliases;
15634
15744
  }
15635
- function renderMetadataColumnStep(config) {
15745
+ function renderMetadataColumnStep(config, policySource) {
15636
15746
  const columns = collectMetadataColumns(config.commands);
15637
15747
  if (Object.keys(columns).length === 0) {
15638
15748
  return "";
@@ -15640,7 +15750,7 @@ function renderMetadataColumnStep(config) {
15640
15750
  return [
15641
15751
  ` .withColumn('_metadata',`,
15642
15752
  ` (row) => __dlMergeMetadata(__dlMetadataFromRow(row), ${stableJson({ columns })}),`,
15643
- ` { recompute: true },`,
15753
+ ` ${policySource},`,
15644
15754
  ` )`
15645
15755
  ].join("\n");
15646
15756
  }
@@ -15694,8 +15804,8 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15694
15804
  ];
15695
15805
  }
15696
15806
  function compileEnrichConfigToPlaySource(config, options = {}) {
15697
- const playName = options.playName ?? "deepline-enrich-v1-compat";
15698
- const mapName = options.mapName ?? "deepline_enrich_rows";
15807
+ const compatibility = buildEnrichCompatibilityPlan(options);
15808
+ const { playName, mapName } = compatibility;
15699
15809
  const inlineRunJavascript = options.inlineRunJavascript ?? false;
15700
15810
  const idiomaticGetters = options.idiomaticGetters ?? false;
15701
15811
  const forceAliases = new Set(
@@ -15731,15 +15841,25 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15731
15841
  );
15732
15842
  });
15733
15843
  const columnStepSource = columnSteps.length > 0 ? columnSteps.join("\n") : ` .withColumn('noop', () => null)`;
15734
- const metadataColumnSource = renderMetadataColumnStep(config);
15844
+ const metadataColumnSource = renderMetadataColumnStep(
15845
+ config,
15846
+ compatibility.metadataCellPolicySource
15847
+ );
15735
15848
  const generatedAliases = collectGeneratedAliases(config.commands);
15736
15849
  const body = [
15737
15850
  `export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
15738
15851
  ` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
15739
15852
  ` const rowStart = __dlNonNegativeInteger(input.rowStart, 0);`,
15740
15853
  ` const rowEndExclusive = Number.isFinite(input.rowEnd) ? Math.max(rowStart, __dlWholeNumber(input.rowEnd, rowStart) + 1) : undefined;`,
15741
- ` const selectedRows = sourceRows.slice(rowStart, rowEndExclusive, { key: 'deepline_enrich_selected_rows', sourceLabel: 'Selected enrich rows' });`,
15742
- ` const rows = selectedRows.map((row) => __dlStripErroredGeneratedColumns(row, ${stableJson(generatedAliases)}), { key: 'deepline_enrich_repair_rows', sourceLabel: 'Selected enrich rows' });`,
15854
+ ` const rows: Array<Record<string, unknown>> = [];`,
15855
+ ` let sourceRowIndex = 0;`,
15856
+ ` for await (const row of sourceRows) {`,
15857
+ ` if (rowEndExclusive !== undefined && sourceRowIndex >= rowEndExclusive) break;`,
15858
+ ` if (sourceRowIndex >= rowStart) {`,
15859
+ ` rows.push(__dlPrepareEnrichRow(row, ${stableJson(generatedAliases)}));`,
15860
+ ` }`,
15861
+ ` sourceRowIndex += 1;`,
15862
+ ` }`,
15743
15863
  ` const enriched = await ctx`,
15744
15864
  ` .dataset(${stringLiteral(mapName)}, rows)`,
15745
15865
  columnStepSource,
@@ -15870,17 +15990,55 @@ function helperSource() {
15870
15990
  ` return parts;`,
15871
15991
  `}`,
15872
15992
  ``,
15993
+ `function __dlNormalizeHeader(value: string): string {`,
15994
+ ` return value.trim().replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');`,
15995
+ `}`,
15996
+ ``,
15997
+ `function __dlOwnStringKeys(record: Record<string, unknown>): string[] {`,
15998
+ ` return Object.keys(record);`,
15999
+ `}`,
16000
+ ``,
16001
+ `function __dlReadOwnField(record: Record<string, unknown>, key: string): unknown {`,
16002
+ ` return record[key];`,
16003
+ `}`,
16004
+ ``,
16005
+ `function __dlGetNormalizedKey(record: Record<string, unknown>, part: string): string | null {`,
16006
+ ` const normalized = __dlNormalizeHeader(part);`,
16007
+ ` for (const key of __dlOwnStringKeys(record)) {`,
16008
+ ` if (__dlNormalizeHeader(key) === normalized) return key;`,
16009
+ ` }`,
16010
+ ` return null;`,
16011
+ `}`,
16012
+ ``,
16013
+ `function __dlGetRecordField(record: Record<string, unknown>, part: string): { found: boolean; value: unknown } {`,
16014
+ ` if (part in record) return { found: true, value: record[part] };`,
16015
+ ` const normalizedKey = __dlGetNormalizedKey(record, part);`,
16016
+ ` if (normalizedKey) return { found: true, value: __dlReadOwnField(record, normalizedKey) };`,
16017
+ ` const projectedValues = record.__deeplineCsvProjectedValues;`,
16018
+ ` if (projectedValues && typeof projectedValues === 'object' && !Array.isArray(projectedValues)) {`,
16019
+ ` const projectedRecord = projectedValues as Record<string, unknown>;`,
16020
+ ` if (part in projectedRecord) return { found: true, value: projectedRecord[part] };`,
16021
+ ` const projectedKey = __dlGetNormalizedKey(projectedRecord, part);`,
16022
+ ` if (projectedKey) return { found: true, value: __dlReadOwnField(projectedRecord, projectedKey) };`,
16023
+ ` }`,
16024
+ ` const data = record.data;`,
16025
+ ` if (data && typeof data === 'object' && !Array.isArray(data)) {`,
16026
+ ` const dataRecord = data as Record<string, unknown>;`,
16027
+ ` if (part in dataRecord) return { found: true, value: dataRecord[part] };`,
16028
+ ` const dataKey = __dlGetNormalizedKey(dataRecord, part);`,
16029
+ ` if (dataKey) return { found: true, value: __dlReadOwnField(dataRecord, dataKey) };`,
16030
+ ` }`,
16031
+ ` return { found: false, value: undefined };`,
16032
+ `}`,
16033
+ ``,
15873
16034
  `function __dlGetByPath(root: unknown, path: string): unknown {`,
15874
16035
  ` let cursor = root;`,
15875
16036
  ` for (const part of __dlPathParts(path)) {`,
15876
16037
  ` if (!cursor || typeof cursor !== 'object') return undefined;`,
15877
16038
  ` const record = cursor as Record<string, unknown>;`,
15878
- ` if (part in record) {`,
15879
- ` cursor = record[part];`,
15880
- ` continue;`,
15881
- ` }`,
15882
- ` const data = record.data;`,
15883
- ` cursor = data && typeof data === 'object' ? (data as Record<string, unknown>)[part] : undefined;`,
16039
+ ` const field = __dlGetRecordField(record, part);`,
16040
+ ` if (!field.found) return undefined;`,
16041
+ ` cursor = field.value;`,
15884
16042
  ` }`,
15885
16043
  ` return cursor;`,
15886
16044
  `}`,
@@ -15945,6 +16103,30 @@ function helperSource() {
15945
16103
  ` return next ?? row;`,
15946
16104
  `}`,
15947
16105
  ``,
16106
+ `function __dlTemplateContext(row: Record<string, unknown>): Record<string, unknown> {`,
16107
+ ` const context: Record<string, unknown> = {};`,
16108
+ ` const projectedValues = row.__deeplineCsvProjectedValues;`,
16109
+ ` if (__dlRecord(projectedValues)) {`,
16110
+ ` for (const [key, value] of Object.entries(projectedValues)) context[key] = value;`,
16111
+ ` }`,
16112
+ ` for (const [key, value] of Object.entries(row)) {`,
16113
+ ` if (key.startsWith('__deepline')) continue;`,
16114
+ ` context[key] = value;`,
16115
+ ` }`,
16116
+ ` return context;`,
16117
+ `}`,
16118
+ ``,
16119
+ `function __dlPrepareEnrichRow(row: Record<string, unknown>, aliases: string[]): Record<string, unknown> {`,
16120
+ ` const cleaned = __dlStripErroredGeneratedColumns(row, aliases);`,
16121
+ ` const templateContext = __dlTemplateContext(cleaned);`,
16122
+ ` return {`,
16123
+ ` ...templateContext,`,
16124
+ ` ...cleaned,`,
16125
+ ` __deeplineCsvProjectedFields: Object.keys(templateContext),`,
16126
+ ` __deeplineCsvProjectedValues: templateContext,`,
16127
+ ` };`,
16128
+ `}`,
16129
+ ``,
15948
16130
  `function __dlRawToolOutput(result: unknown): unknown {`,
15949
16131
  ` if (!result || typeof result !== 'object') return result;`,
15950
16132
  ` const record = result as Record<string, unknown>;`,
@@ -16982,7 +17164,7 @@ async function resolveWatchedGeneratedPlayStatus(input2) {
16982
17164
  }
16983
17165
  return input2.client.runs.get(runId, { full: true });
16984
17166
  }
16985
- function isRecord6(value) {
17167
+ function isRecord7(value) {
16986
17168
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
16987
17169
  }
16988
17170
  async function captureStdout(run, options = {}) {
@@ -17030,12 +17212,12 @@ async function writeOutputCsv(outputPath, status, options) {
17030
17212
  if (!rowsInfo) {
17031
17213
  throw new Error("The generated play did not return row-shaped output.");
17032
17214
  }
17033
- if (!rowsInfo.complete && options?.client) {
17215
+ if (options?.client) {
17034
17216
  rowsInfo = await fetchBackingRowsForCsvExport({
17035
17217
  client: options.client,
17036
17218
  status,
17037
17219
  rowsInfo
17038
- }) ?? rowsInfo;
17220
+ }).catch(() => null) ?? rowsInfo;
17039
17221
  }
17040
17222
  assertCompleteRowsForCsvExport(rowsInfo, status, outputPath);
17041
17223
  const merged = mergeRowsForCsvExport(rowsInfo.rows, options);
@@ -17051,10 +17233,14 @@ async function writeOutputCsv(outputPath, status, options) {
17051
17233
  csvStringFromRows(merged.rows, columns),
17052
17234
  "utf8"
17053
17235
  );
17236
+ const sourceCsvRows = options?.sourceCsvPath ? readCsvRows(options.sourceCsvPath).length : null;
17054
17237
  return {
17238
+ sourceCsvRows,
17239
+ selectedRows: rowsInfo.totalRows,
17240
+ enrichedRows: rowsInfo.rows.length,
17055
17241
  rows: merged.rows.length,
17056
17242
  path: (0, import_node_path13.resolve)(outputPath),
17057
- enrichedRows: rowsInfo.rows
17243
+ enrichedDataRows: rowsInfo.rows
17058
17244
  };
17059
17245
  }
17060
17246
  function recordField(value, key) {
@@ -17135,12 +17321,12 @@ function collectHardFailureAliases(config) {
17135
17321
  }
17136
17322
  function cellFailureError(value) {
17137
17323
  const parsed = parseMaybeJsonObject(value);
17138
- if (!isRecord6(parsed)) {
17324
+ if (!isRecord7(parsed)) {
17139
17325
  return null;
17140
17326
  }
17141
17327
  const status = typeof parsed.status === "string" ? parsed.status.trim().toLowerCase() : "";
17142
17328
  const directError = typeof parsed.error === "string" ? parsed.error.trim() : typeof parsed.last_error === "string" ? parsed.last_error.trim() : "";
17143
- const result = isRecord6(parsed.result) ? parsed.result : null;
17329
+ const result = isRecord7(parsed.result) ? parsed.result : null;
17144
17330
  const resultError = typeof result?.error === "string" ? result.error.trim() : typeof result?.message === "string" ? result.message.trim() : "";
17145
17331
  if (!directError && !resultError && status !== "error" && status !== "failed") {
17146
17332
  return null;
@@ -17206,6 +17392,136 @@ function collectEnrichFailureJobs(input2) {
17206
17392
  });
17207
17393
  return jobs;
17208
17394
  }
17395
+ function parseExecutionCount(value) {
17396
+ if (typeof value === "number" && Number.isFinite(value)) {
17397
+ return Math.max(0, Math.trunc(value));
17398
+ }
17399
+ if (typeof value !== "string") {
17400
+ return null;
17401
+ }
17402
+ const match = value.trim().match(/^(\d+)\s*\//);
17403
+ return match?.[1] ? Number.parseInt(match[1], 10) : null;
17404
+ }
17405
+ function executionSummaryText(count, total) {
17406
+ const percent = total > 0 ? Math.round(count / total * 100) : 0;
17407
+ return `${count}/${total} (${percent}%)`;
17408
+ }
17409
+ function collectColumnStats(status) {
17410
+ const summaries = [];
17411
+ const visit = (value) => {
17412
+ if (Array.isArray(value)) {
17413
+ value.forEach(visit);
17414
+ return;
17415
+ }
17416
+ if (!isRecord7(value)) {
17417
+ return;
17418
+ }
17419
+ if (isRecord7(value.columnStats)) {
17420
+ summaries.push(value.columnStats);
17421
+ }
17422
+ Object.values(value).forEach(visit);
17423
+ };
17424
+ visit(status);
17425
+ return summaries;
17426
+ }
17427
+ function firstAliasExecutionCounts(input2) {
17428
+ const aliases = collectConfigScalarAliasOrder(input2.config);
17429
+ const summaries = collectColumnStats(input2.status);
17430
+ for (const alias of aliases) {
17431
+ const stat4 = summaries.map((summary) => summary[alias]).find(isRecord7);
17432
+ if (!stat4) continue;
17433
+ if (input2.forceAliases.has(normalizeAlias2(alias))) {
17434
+ return { executed: input2.selectedRows, reused: 0 };
17435
+ }
17436
+ const execution = isRecord7(stat4.execution) ? stat4.execution : null;
17437
+ if (!execution) continue;
17438
+ return {
17439
+ executed: parseExecutionCount(execution["completed:executed"]),
17440
+ reused: parseExecutionCount(execution["completed:reused"])
17441
+ };
17442
+ }
17443
+ return { executed: null, reused: null };
17444
+ }
17445
+ function rewriteEnrichJsonStatus(input2) {
17446
+ const selectedRows = input2.output?.selectedRows ?? extractCanonicalRowsInfo(input2.status)?.totalRows ?? 0;
17447
+ const failedRows = new Set(
17448
+ input2.failureReport?.jobs.map((job) => job.row_id) ?? []
17449
+ ).size;
17450
+ const executionCounts = firstAliasExecutionCounts({
17451
+ status: input2.status,
17452
+ config: input2.config,
17453
+ forceAliases: input2.forceAliases,
17454
+ selectedRows
17455
+ });
17456
+ const forcedAliases = new Set(
17457
+ collectConfigScalarAliasOrder(input2.config).filter((alias) => input2.forceAliases.has(normalizeAlias2(alias))).map((alias) => alias)
17458
+ );
17459
+ const rewrite = (value) => {
17460
+ if (Array.isArray(value)) {
17461
+ return value.map(rewrite);
17462
+ }
17463
+ if (!isRecord7(value)) {
17464
+ return value;
17465
+ }
17466
+ const next = {};
17467
+ for (const [key, entry] of Object.entries(value)) {
17468
+ next[key] = rewrite(entry);
17469
+ }
17470
+ if (isRecord7(next.progress)) {
17471
+ next.progress = {
17472
+ ...next.progress,
17473
+ ...selectedRows > 0 ? { total: selectedRows } : {},
17474
+ ...executionCounts.executed !== null ? { executed: executionCounts.executed } : {},
17475
+ ...executionCounts.reused !== null ? { reused: executionCounts.reused } : {},
17476
+ ...failedRows > 0 ? { failed: failedRows, pending: 0 } : {}
17477
+ };
17478
+ }
17479
+ if (isRecord7(next.summary)) {
17480
+ const rowCounts = isRecord7(next.summary.rowCounts) ? next.summary.rowCounts : null;
17481
+ if (failedRows > 0) {
17482
+ next.summary = {
17483
+ ...next.summary,
17484
+ rowCounts: {
17485
+ ...rowCounts ?? {},
17486
+ persisted: selectedRows,
17487
+ succeeded: Math.max(0, selectedRows - failedRows),
17488
+ failed: failedRows
17489
+ }
17490
+ };
17491
+ }
17492
+ }
17493
+ if (isRecord7(next.columnStats) && selectedRows > 0) {
17494
+ const columnStats = { ...next.columnStats };
17495
+ for (const alias of forcedAliases) {
17496
+ const stat4 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
17497
+ const execution = isRecord7(stat4?.execution) ? stat4.execution : null;
17498
+ if (!stat4 || !execution) continue;
17499
+ columnStats[alias] = {
17500
+ ...stat4,
17501
+ execution: {
17502
+ ...execution,
17503
+ "completed:executed": executionSummaryText(
17504
+ selectedRows,
17505
+ selectedRows
17506
+ ),
17507
+ "completed:reused": executionSummaryText(0, selectedRows)
17508
+ }
17509
+ };
17510
+ }
17511
+ next.columnStats = columnStats;
17512
+ }
17513
+ return next;
17514
+ };
17515
+ const rewritten = rewrite(input2.status);
17516
+ if (failedRows === 0 || !isRecord7(rewritten)) {
17517
+ return rewritten;
17518
+ }
17519
+ return {
17520
+ ...rewritten,
17521
+ ...rewritten.status === "completed" ? { status: "failed" } : {},
17522
+ ...isRecord7(rewritten.run) && rewritten.run.status === "completed" ? { run: { ...rewritten.run, status: "failed" } } : {}
17523
+ };
17524
+ }
17209
17525
  function summarizeFailedJobError(value) {
17210
17526
  const text = String(value ?? "").trim();
17211
17527
  return text.length > 500 ? `${text.slice(0, 497)}...` : text;
@@ -17474,11 +17790,11 @@ function normalizeEnrichRowsForCsvExport(rows) {
17474
17790
  }
17475
17791
  function legacyMetadataFromRow(row) {
17476
17792
  const direct = parseLegacyMetadataCell(row._metadata);
17477
- if (direct && isRecord6(direct.columns)) {
17793
+ if (direct && isRecord7(direct.columns)) {
17478
17794
  return direct;
17479
17795
  }
17480
17796
  const relocated = parseLegacyMetadataCell(row.metadata);
17481
- if (relocated && isRecord6(relocated.columns)) {
17797
+ if (relocated && isRecord7(relocated.columns)) {
17482
17798
  return relocated;
17483
17799
  }
17484
17800
  const flattenedColumns = parseLegacyMetadataCell(row["metadata.columns"]);
@@ -17495,7 +17811,7 @@ function legacyMetadataFromRow(row) {
17495
17811
  }
17496
17812
  function parseLegacyMetadataCell(value) {
17497
17813
  const parsed = parseMaybeJsonObject(value);
17498
- if (isRecord6(parsed)) {
17814
+ if (isRecord7(parsed)) {
17499
17815
  return parsed;
17500
17816
  }
17501
17817
  if (typeof value !== "string") {
@@ -17512,12 +17828,12 @@ function parseLegacyMetadataCell(value) {
17512
17828
  for (const candidate of candidates) {
17513
17829
  try {
17514
17830
  const decoded = JSON.parse(candidate);
17515
- if (isRecord6(decoded)) {
17831
+ if (isRecord7(decoded)) {
17516
17832
  return decoded;
17517
17833
  }
17518
17834
  if (typeof decoded === "string") {
17519
17835
  const nested = JSON.parse(decoded);
17520
- if (isRecord6(nested)) {
17836
+ if (isRecord7(nested)) {
17521
17837
  return nested;
17522
17838
  }
17523
17839
  }
@@ -17527,8 +17843,8 @@ function parseLegacyMetadataCell(value) {
17527
17843
  return null;
17528
17844
  }
17529
17845
  function mergeLegacyMetadataRecords(base, enriched) {
17530
- const baseColumns = isRecord6(base.columns) ? base.columns : null;
17531
- const enrichedColumns = isRecord6(enriched.columns) ? enriched.columns : null;
17846
+ const baseColumns = isRecord7(base.columns) ? base.columns : null;
17847
+ const enrichedColumns = isRecord7(enriched.columns) ? enriched.columns : null;
17532
17848
  const merged = {
17533
17849
  ...base,
17534
17850
  ...enriched
@@ -17730,7 +18046,7 @@ function registerEnrichCommand(program) {
17730
18046
  sourceCsvPath,
17731
18047
  rows
17732
18048
  }) : null;
17733
- const rowsForFailureReport = exportResult?.enrichedRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
18049
+ const rowsForFailureReport = exportResult?.enrichedDataRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
17734
18050
  if (options.json) {
17735
18051
  const failureReport2 = await maybeEmitEnrichFailureReport({
17736
18052
  config,
@@ -17739,10 +18055,22 @@ function registerEnrichCommand(program) {
17739
18055
  client: client2,
17740
18056
  outputPath: exportResult?.path ?? outputPath ?? null
17741
18057
  });
18058
+ const run = rewriteEnrichJsonStatus({
18059
+ status,
18060
+ config,
18061
+ forceAliases,
18062
+ output: exportResult,
18063
+ failureReport: failureReport2
18064
+ });
17742
18065
  printJson({
17743
18066
  ok: !failureReport2,
17744
- run: status,
17745
- output: exportResult ? { rows: exportResult.rows, path: exportResult.path } : null,
18067
+ run,
18068
+ output: exportResult ? {
18069
+ sourceCsvRows: exportResult.sourceCsvRows,
18070
+ selectedRows: exportResult.selectedRows,
18071
+ enrichedRows: exportResult.enrichedRows,
18072
+ path: exportResult.path
18073
+ } : null,
17746
18074
  ...failureReport2 ? {
17747
18075
  failure_report: {
17748
18076
  path: failureReport2.path,
@@ -17762,7 +18090,7 @@ function registerEnrichCommand(program) {
17762
18090
  );
17763
18091
  const waterfallSummaryLines = buildEnrichWaterfallSummaryLines(
17764
18092
  config,
17765
- exportResult.enrichedRows
18093
+ exportResult.enrichedDataRows
17766
18094
  );
17767
18095
  if (waterfallSummaryLines.length > 0) {
17768
18096
  process.stdout.write(`${waterfallSummaryLines.join("\n")}
@@ -17829,6 +18157,129 @@ Examples:
17829
18157
  ).argument("<text>", "Feedback text").option("--command <command>", "Command that reproduced the issue").option("--payload <payload>", "JSON or plain-text payload for the repro").option("--json", "Emit JSON output").action(handleFeedback);
17830
18158
  }
17831
18159
 
18160
+ // src/cli/commands/legacy-noops.ts
18161
+ var SESSION_SUBCOMMANDS = [
18162
+ "start",
18163
+ "status",
18164
+ "output",
18165
+ "alert",
18166
+ "usage",
18167
+ "limit",
18168
+ "render",
18169
+ "send"
18170
+ ];
18171
+ var BACKEND_SUBCOMMANDS = [
18172
+ "start",
18173
+ "stop",
18174
+ "status",
18175
+ "refresh-runtime",
18176
+ "sync-runtime"
18177
+ ];
18178
+ function legacyNoopEnvelope(input2) {
18179
+ const command = [
18180
+ "deepline",
18181
+ input2.family,
18182
+ input2.subcommand
18183
+ ].filter(Boolean).join(" ");
18184
+ const subject = input2.family === "session" ? "Legacy Session UI/playground command" : "Legacy local playground backend command";
18185
+ const note = input2.family === "session" ? "The SDK CLI does not manage the legacy Python Session UI. This command is accepted for backwards compatibility and intentionally does nothing." : "The SDK CLI does not start or stop the legacy Python local playground backend. This command is accepted for backwards compatibility and intentionally does nothing.";
18186
+ return {
18187
+ ok: true,
18188
+ noop: true,
18189
+ command,
18190
+ compatibility: {
18191
+ family: "legacy_python_cli",
18192
+ sdk_behavior: "noop"
18193
+ },
18194
+ render: {
18195
+ sections: [
18196
+ {
18197
+ title: subject,
18198
+ lines: [note]
18199
+ }
18200
+ ]
18201
+ }
18202
+ };
18203
+ }
18204
+ function printLegacyNoop(input2) {
18205
+ printCommandEnvelope(legacyNoopEnvelope(input2), { json: input2.options.json });
18206
+ }
18207
+ function legacySubcommandFromArgv(family) {
18208
+ const args = process.argv.slice(2);
18209
+ const familyIndex = args.indexOf(family);
18210
+ const nextToken = familyIndex >= 0 ? args[familyIndex + 1] : void 0;
18211
+ return nextToken && !nextToken.startsWith("-") ? nextToken : void 0;
18212
+ }
18213
+ function addLegacyNoopSubcommand(parent, family, subcommand, description) {
18214
+ parent.command(subcommand).description(description).allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").action((_args, options) => {
18215
+ printLegacyNoop({ family, subcommand, options });
18216
+ });
18217
+ }
18218
+ function registerLegacyNoopCommands(program) {
18219
+ const session = program.command("session").description(
18220
+ "Compatibility no-ops for legacy Python Session UI commands."
18221
+ ).allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
18222
+ "after",
18223
+ `
18224
+ Notes:
18225
+ The SDK CLI accepts singular session commands from older agent skills so they
18226
+ do not fail, but it does not manage the legacy Python Session UI.
18227
+ Use "deepline sessions send" or "deepline sessions render" for real SDK
18228
+ transcript workflows.
18229
+
18230
+ Examples:
18231
+ deepline session start --steps '["Inspect CSV","Run pilot"]'
18232
+ deepline session status --message "Running pilot"
18233
+ deepline session output --csv ./results.csv --label "Results"
18234
+ `
18235
+ ).action((args, options) => {
18236
+ void args;
18237
+ printLegacyNoop({
18238
+ family: "session",
18239
+ subcommand: legacySubcommandFromArgv("session"),
18240
+ options
18241
+ });
18242
+ });
18243
+ for (const subcommand of SESSION_SUBCOMMANDS) {
18244
+ addLegacyNoopSubcommand(
18245
+ session,
18246
+ "session",
18247
+ subcommand,
18248
+ `Accept legacy "deepline session ${subcommand}" as an SDK no-op.`
18249
+ );
18250
+ }
18251
+ const backend = program.command("backend").description(
18252
+ "Compatibility no-ops for legacy Python local backend commands."
18253
+ ).allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
18254
+ "after",
18255
+ `
18256
+ Notes:
18257
+ The SDK CLI uses the configured Deepline host and V2 play runtime. It does not
18258
+ start, stop, or refresh the legacy Python local playground backend.
18259
+
18260
+ Examples:
18261
+ deepline backend start
18262
+ deepline backend stop --just-backend
18263
+ deepline backend status --json
18264
+ `
18265
+ ).action((args, options) => {
18266
+ void args;
18267
+ printLegacyNoop({
18268
+ family: "backend",
18269
+ subcommand: legacySubcommandFromArgv("backend"),
18270
+ options
18271
+ });
18272
+ });
18273
+ for (const subcommand of BACKEND_SUBCOMMANDS) {
18274
+ addLegacyNoopSubcommand(
18275
+ backend,
18276
+ "backend",
18277
+ subcommand,
18278
+ `Accept legacy "deepline backend ${subcommand}" as an SDK no-op.`
18279
+ );
18280
+ }
18281
+ }
18282
+
17832
18283
  // src/cli/commands/org.ts
17833
18284
  async function fetchOrganizations(http, apiKey) {
17834
18285
  return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
@@ -19731,11 +20182,13 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
19731
20182
  "deeplineUsdPerPricingUnit",
19732
20183
  "deepline_usd_per_pricing_unit"
19733
20184
  );
19734
- const starterScript = seedToolListScript({
19735
- toolId,
19736
- payload: samplePayloadForInputFields(inputFields),
19737
- rows: []
19738
- });
20185
+ const starterScript = extractedLists.length > 0 ? starterScriptJson(
20186
+ seedToolListScript({
20187
+ toolId,
20188
+ payload: samplePayloadForInputFields(inputFields),
20189
+ rows: []
20190
+ })
20191
+ ) : null;
19739
20192
  return {
19740
20193
  schemaVersion: 1,
19741
20194
  toolId,
@@ -19761,20 +20214,12 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
19761
20214
  extractedValues
19762
20215
  },
19763
20216
  executeCommand: `deepline tools execute ${toolId} --input '{...}' --json`,
19764
- starterScript: {
19765
- path: starterScript.path,
19766
- sourceCode: starterScript.sourceCode,
19767
- projectDir: starterScript.projectDir,
19768
- copyToProject: {
19769
- macosLinux: starterScript.macCopyCommand,
19770
- windowsPowerShell: starterScript.windowsCopyCommand
19771
- }
19772
- }
20217
+ ...starterScript ? { starterScript } : {}
19773
20218
  };
19774
20219
  }
19775
20220
  function extractionContractEntries(entries) {
19776
20221
  return entries.flatMap((entry) => {
19777
- if (!isRecord7(entry)) return [];
20222
+ if (!isRecord8(entry)) return [];
19778
20223
  const name = stringField(entry, "name");
19779
20224
  const expression = stringField(entry, "expression");
19780
20225
  return name && expression ? [{ name, expression }] : [];
@@ -19782,8 +20227,8 @@ function extractionContractEntries(entries) {
19782
20227
  }
19783
20228
  function printCompactToolContract(tool, requestedToolId) {
19784
20229
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
19785
- const cost = isRecord7(contract.cost) ? contract.cost : {};
19786
- const getters = isRecord7(contract.getters) ? contract.getters : {};
20230
+ const cost = isRecord8(contract.cost) ? contract.cost : {};
20231
+ const getters = isRecord8(contract.getters) ? contract.getters : {};
19787
20232
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
19788
20233
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
19789
20234
  const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
@@ -19800,7 +20245,7 @@ function printCompactToolContract(tool, requestedToolId) {
19800
20245
  console.log("");
19801
20246
  console.log("Inputs:");
19802
20247
  for (const field of inputFields) {
19803
- if (!isRecord7(field)) continue;
20248
+ if (!isRecord8(field)) continue;
19804
20249
  const name = stringField(field, "name");
19805
20250
  if (!name) continue;
19806
20251
  const required = field.required ? "*" : "";
@@ -19813,7 +20258,7 @@ function printCompactToolContract(tool, requestedToolId) {
19813
20258
  }
19814
20259
  console.log("");
19815
20260
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
19816
- const starterScript = isRecord7(contract.starterScript) ? contract.starterScript : {};
20261
+ const starterScript = isRecord8(contract.starterScript) ? contract.starterScript : {};
19817
20262
  const starterPath = stringField(starterScript, "path");
19818
20263
  if (starterPath) {
19819
20264
  console.log("");
@@ -19827,14 +20272,14 @@ function printCompactToolContract(tool, requestedToolId) {
19827
20272
  console.log("Getters:");
19828
20273
  if (listGetters.length) console.log("Lists:");
19829
20274
  for (const entry of listGetters) {
19830
- if (isRecord7(entry))
20275
+ if (isRecord8(entry))
19831
20276
  console.log(
19832
20277
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19833
20278
  );
19834
20279
  }
19835
20280
  if (valueGetters.length) console.log("Values:");
19836
20281
  for (const entry of valueGetters) {
19837
- if (isRecord7(entry))
20282
+ if (isRecord8(entry))
19838
20283
  console.log(
19839
20284
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19840
20285
  );
@@ -19847,7 +20292,7 @@ function printCompactToolContract(tool, requestedToolId) {
19847
20292
  }
19848
20293
  function printToolPricingOnly(tool, requestedToolId, options = {}) {
19849
20294
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
19850
- const cost = isRecord7(contract.cost) ? contract.cost : {};
20295
+ const cost = isRecord8(contract.cost) ? contract.cost : {};
19851
20296
  const pricingModel = stringField(cost, "pricingModel") || "unknown";
19852
20297
  const billingMode = stringField(cost, "billingMode") || "unknown";
19853
20298
  const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
@@ -19867,7 +20312,7 @@ function printToolSchemaOnly(tool, requestedToolId) {
19867
20312
  }
19868
20313
  console.log("Inputs:");
19869
20314
  for (const field of inputFields) {
19870
- if (!isRecord7(field)) continue;
20315
+ if (!isRecord8(field)) continue;
19871
20316
  const name = stringField(field, "name");
19872
20317
  if (!name) continue;
19873
20318
  const required = field.required ? "*" : "";
@@ -19893,10 +20338,10 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
19893
20338
  ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
19894
20339
  );
19895
20340
  console.log("});");
19896
- const getters = isRecord7(contract.getters) ? contract.getters : {};
20341
+ const getters = isRecord8(contract.getters) ? contract.getters : {};
19897
20342
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
19898
20343
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
19899
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord7);
20344
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord8);
19900
20345
  if (firstGetter) {
19901
20346
  const name = stringField(firstGetter, "name") || "value";
19902
20347
  const expression = stringField(firstGetter, "expression");
@@ -19913,7 +20358,7 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
19913
20358
  }
19914
20359
  function printToolGettersOnly(tool, requestedToolId) {
19915
20360
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
19916
- const getters = isRecord7(contract.getters) ? contract.getters : {};
20361
+ const getters = isRecord8(contract.getters) ? contract.getters : {};
19917
20362
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
19918
20363
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
19919
20364
  console.log(`Getters: ${contract.toolId}`);
@@ -19926,7 +20371,7 @@ function printToolGettersOnly(tool, requestedToolId) {
19926
20371
  if (listGetters.length) {
19927
20372
  console.log("Lists:");
19928
20373
  for (const entry of listGetters) {
19929
- if (isRecord7(entry))
20374
+ if (isRecord8(entry))
19930
20375
  console.log(
19931
20376
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19932
20377
  );
@@ -19935,7 +20380,7 @@ function printToolGettersOnly(tool, requestedToolId) {
19935
20380
  if (valueGetters.length) {
19936
20381
  console.log("Values:");
19937
20382
  for (const entry of valueGetters) {
19938
- if (isRecord7(entry))
20383
+ if (isRecord8(entry))
19939
20384
  console.log(
19940
20385
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19941
20386
  );
@@ -19961,7 +20406,7 @@ function sampleValueForField(field) {
19961
20406
  function samplePayloadForInputFields(fields) {
19962
20407
  return Object.fromEntries(
19963
20408
  fields.slice(0, 4).flatMap((field) => {
19964
- if (!isRecord7(field)) return [];
20409
+ if (!isRecord8(field)) return [];
19965
20410
  const name = stringField(field, "name");
19966
20411
  if (!name) return [];
19967
20412
  return [[name, sampleValueForField(field)]];
@@ -19986,11 +20431,24 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
19986
20431
  const inputFields = toolInputFieldsForDisplay(
19987
20432
  recordField2(tool, "inputSchema", "input_schema")
19988
20433
  );
19989
- const starterScript = seedToolListScript({
19990
- toolId,
19991
- payload: samplePayloadForInputFields(inputFields),
19992
- rows: []
19993
- });
20434
+ const usageGuidance = usageGuidanceWithAccessDefaults(
20435
+ recordField2(tool, "usageGuidance", "usage_guidance")
20436
+ );
20437
+ const toolExecutionResult = recordField2(
20438
+ usageGuidance,
20439
+ "toolExecutionResult",
20440
+ "tool_execution_result"
20441
+ );
20442
+ const extractedLists = extractionContractEntries(
20443
+ arrayField(toolExecutionResult, "extractedLists", "extracted_lists")
20444
+ );
20445
+ const starterScript = extractedLists.length > 0 ? starterScriptJson(
20446
+ seedToolListScript({
20447
+ toolId,
20448
+ payload: samplePayloadForInputFields(inputFields),
20449
+ rows: []
20450
+ })
20451
+ ) : null;
19994
20452
  const {
19995
20453
  cost: _cost,
19996
20454
  deeplineCreditsPerPricingUnit: _deeplineCreditsPerPricingUnit,
@@ -20010,9 +20468,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
20010
20468
  toolId,
20011
20469
  provider: tool.provider,
20012
20470
  displayName: tool.displayName,
20013
- usageGuidance: usageGuidanceWithAccessDefaults(
20014
- recordField2(tool, "usageGuidance", "usage_guidance")
20015
- ),
20471
+ usageGuidance,
20016
20472
  runtimeOutputHelp: {
20017
20473
  contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
20018
20474
  getterScope: "extractedValues/extractedLists .get() only works for declared Deepline getters listed in usageGuidance.toolExecutionResult.",
@@ -20023,15 +20479,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
20023
20479
  forPlayGetterBugs: "Run a tiny play, inspect `deepline runs get <run-id> --full --json`, and export returned dataset handles with `deepline runs export`. Backing tables exist only for ctx.map(...).run(...) stages that actually executed.",
20024
20480
  executeOutputFields: "tools execute JSON may include output_preview for this direct probe only; play debugging uses run output and returned dataset handles."
20025
20481
  },
20026
- starterScript: {
20027
- path: starterScript.path,
20028
- sourceCode: starterScript.sourceCode,
20029
- projectDir: starterScript.projectDir,
20030
- copyToProject: {
20031
- macosLinux: starterScript.macCopyCommand,
20032
- windowsPowerShell: starterScript.windowsCopyCommand
20033
- }
20034
- }
20482
+ ...starterScript ? { starterScript } : {}
20035
20483
  };
20036
20484
  }
20037
20485
  function usageGuidanceWithAccessDefaults(usageGuidance) {
@@ -20075,12 +20523,12 @@ function formatListedToolCost(tool) {
20075
20523
  }
20076
20524
  function toolInputFieldsForDisplay(inputSchema) {
20077
20525
  if (Array.isArray(inputSchema.fields))
20078
- return inputSchema.fields.filter(isRecord7);
20079
- const jsonSchema = isRecord7(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
20080
- const properties = isRecord7(jsonSchema.properties) ? jsonSchema.properties : {};
20526
+ return inputSchema.fields.filter(isRecord8);
20527
+ const jsonSchema = isRecord8(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
20528
+ const properties = isRecord8(jsonSchema.properties) ? jsonSchema.properties : {};
20081
20529
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
20082
20530
  return Object.entries(properties).map(([name, value]) => {
20083
- const property = isRecord7(value) ? value : {};
20531
+ const property = isRecord8(value) ? value : {};
20084
20532
  return {
20085
20533
  name,
20086
20534
  type: typeof property.type === "string" ? property.type : "unknown",
@@ -20109,15 +20557,15 @@ function printJsonPreview(label, payload) {
20109
20557
  }
20110
20558
  function samplePayload(samples, key) {
20111
20559
  const entry = samples[key];
20112
- if (!isRecord7(entry)) return void 0;
20560
+ if (!isRecord8(entry)) return void 0;
20113
20561
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
20114
20562
  }
20115
20563
  function commandEnvelopeFromRawResponse(rawResponse) {
20116
- return isRecord7(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
20564
+ return isRecord8(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
20117
20565
  }
20118
20566
  function listExtractorPathsFromUsageGuidance(tool) {
20119
20567
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
20120
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord7(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
20568
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord8(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
20121
20569
  return extractedLists.flatMap((entry) => {
20122
20570
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
20123
20571
  if (!Array.isArray(paths)) return [];
@@ -20133,7 +20581,7 @@ function formatDecimal(value) {
20133
20581
  function formatUsd(value) {
20134
20582
  return `$${formatDecimal(value)}`;
20135
20583
  }
20136
- function isRecord7(value) {
20584
+ function isRecord8(value) {
20137
20585
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
20138
20586
  }
20139
20587
  function stringField(source, ...keys) {
@@ -20160,7 +20608,7 @@ function arrayField(source, ...keys) {
20160
20608
  function recordField2(source, ...keys) {
20161
20609
  for (const key of keys) {
20162
20610
  const value = source[key];
20163
- if (isRecord7(value)) return value;
20611
+ if (isRecord8(value)) return value;
20164
20612
  }
20165
20613
  return {};
20166
20614
  }
@@ -20226,7 +20674,7 @@ function parseJsonObjectArgument(raw, flagName) {
20226
20674
  }
20227
20675
  throw invalidJsonError(flagName, message);
20228
20676
  }
20229
- if (!isRecord7(parsed)) {
20677
+ if (!isRecord8(parsed)) {
20230
20678
  throw invalidJsonError(flagName, "expected an object.");
20231
20679
  }
20232
20680
  return parsed;
@@ -20285,6 +20733,17 @@ function shellQuote2(value) {
20285
20733
  function powerShellQuote(value) {
20286
20734
  return `'${value.replace(/'/g, "''")}'`;
20287
20735
  }
20736
+ function starterScriptJson(script) {
20737
+ return {
20738
+ path: script.path,
20739
+ sourceCode: script.sourceCode,
20740
+ projectDir: script.projectDir,
20741
+ copyToProject: {
20742
+ macosLinux: script.macCopyCommand,
20743
+ windowsPowerShell: script.windowsCopyCommand
20744
+ }
20745
+ };
20746
+ }
20288
20747
  function seedToolListScript(input2) {
20289
20748
  const stem = safeFileStem(input2.toolId);
20290
20749
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
@@ -20349,7 +20808,7 @@ function buildToolExecuteBaseEnvelope(input2) {
20349
20808
  kind: summaryEntries.length > 0 ? "object" : "raw",
20350
20809
  summary: input2.summary
20351
20810
  };
20352
- const envelopeHasCanonicalOutput = isRecord7(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
20811
+ const envelopeHasCanonicalOutput = isRecord8(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
20353
20812
  const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote2(JSON.stringify(input2.params))} --json`;
20354
20813
  const actions = input2.listConversion ? [
20355
20814
  {
@@ -20458,7 +20917,7 @@ async function executeTool(args) {
20458
20917
  {
20459
20918
  ...baseEnvelope,
20460
20919
  local: {
20461
- ...isRecord7(baseEnvelope.local) ? baseEnvelope.local : {},
20920
+ ...isRecord8(baseEnvelope.local) ? baseEnvelope.local : {},
20462
20921
  payload_file: jsonPath
20463
20922
  }
20464
20923
  },
@@ -21218,10 +21677,6 @@ var command_compatibility_default = {
21218
21677
  label: "a legacy Python CLI workflow command",
21219
21678
  sdk_alternative: "Use `deepline plays ...` in the SDK CLI."
21220
21679
  },
21221
- backend: {
21222
- family: "python",
21223
- label: "a legacy Python CLI playground backend command"
21224
- },
21225
21680
  events: {
21226
21681
  family: "python",
21227
21682
  label: "a legacy Python CLI event command"
@@ -21450,7 +21905,11 @@ var import_node_os11 = require("os");
21450
21905
  var import_node_path19 = require("path");
21451
21906
  var CHECK_TIMEOUT_MS2 = 3e3;
21452
21907
  var SDK_SKILL_NAME = "deepline-plays";
21453
- var SDK_SKILL_NAMES = [SDK_SKILL_NAME, "deepline-plays-quickstart"];
21908
+ var SDK_SKILL_NAMES = [
21909
+ SDK_SKILL_NAME,
21910
+ "deepline-plays-feedback",
21911
+ "deepline-plays-quickstart"
21912
+ ];
21454
21913
  var attemptedSync = false;
21455
21914
  function shouldSkipSkillsSync() {
21456
21915
  const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
@@ -21672,7 +22131,9 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
21672
22131
  if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
21673
22132
  return;
21674
22133
  }
21675
- writeSdkSkillsStatusLine("SDK skills changed; syncing Deepline SDK skills...");
22134
+ writeSdkSkillsStatusLine(
22135
+ "SDK skills changed; syncing Deepline SDK skills..."
22136
+ );
21676
22137
  const installed = await runSkillsInstall(baseUrl);
21677
22138
  if (!installed) return;
21678
22139
  if (installedSdkSkillHasStalePositionalExecuteExamples()) {
@@ -21712,6 +22173,19 @@ function shouldDeferSkillsSyncForCommand() {
21712
22173
  const subcommand = args[1];
21713
22174
  return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
21714
22175
  }
22176
+ function isLegacyNoopInvocation() {
22177
+ const command = process.argv.slice(2)[0];
22178
+ return command === "session" || command === "backend";
22179
+ }
22180
+ function topLevelCommandKnown(program, commandName) {
22181
+ const normalized = commandName.trim();
22182
+ if (!normalized || normalized.startsWith("-")) {
22183
+ return true;
22184
+ }
22185
+ return program.commands.some(
22186
+ (command) => command.name() === normalized || command.aliases().includes(normalized)
22187
+ );
22188
+ }
21715
22189
  async function runPlayRunnerHealthCheck() {
21716
22190
  const dir = await (0, import_promises7.mkdtemp)((0, import_node_path20.join)((0, import_node_os12.tmpdir)(), "deepline-health-play-"));
21717
22191
  const file = (0, import_node_path20.join)(dir, "health-check.play.ts");
@@ -21931,7 +22405,7 @@ Exit codes:
21931
22405
  `
21932
22406
  );
21933
22407
  program.hook("preAction", async (_thisCommand, actionCommand) => {
21934
- if (actionCommand.name() === "version" || actionCommand.name() === "update") {
22408
+ if (actionCommand.name() === "version" || actionCommand.name() === "update" || isLegacyNoopInvocation()) {
21935
22409
  return;
21936
22410
  }
21937
22411
  if (printStartupPhase) {
@@ -21948,9 +22422,7 @@ Exit codes:
21948
22422
  if (compatibility.error) {
21949
22423
  return;
21950
22424
  }
21951
- const relaunched = await maybeAutoUpdateAndRelaunch(
21952
- compatibility.response
21953
- );
22425
+ const relaunched = await maybeAutoUpdateAndRelaunch(compatibility.response);
21954
22426
  if (relaunched) {
21955
22427
  return;
21956
22428
  }
@@ -21978,6 +22450,7 @@ Exit codes:
21978
22450
  registerCsvCommands(program);
21979
22451
  registerDbCommands(program);
21980
22452
  registerFeedbackCommands(program);
22453
+ registerLegacyNoopCommands(program);
21981
22454
  registerUpdateCommand(program);
21982
22455
  registerQuickstartCommands(program);
21983
22456
  program.command("preflight").description("Run compact health, auth, and Deepline billing checks.").option("--json", "Force JSON output.").addHelpText(
@@ -22078,6 +22551,20 @@ Examples:
22078
22551
  process.exitCode = 2;
22079
22552
  return;
22080
22553
  }
22554
+ const requestedTopLevelCommand = process.argv.slice(2)[0] ?? "";
22555
+ if (!topLevelCommandKnown(program, requestedTopLevelCommand)) {
22556
+ console.error(`error: unknown command '${requestedTopLevelCommand}'`);
22557
+ const hint = commandCompatibilityHint(
22558
+ "sdk",
22559
+ requestedTopLevelCommand,
22560
+ autoDetectBaseUrl()
22561
+ );
22562
+ if (hint && !process.argv.includes("--json")) {
22563
+ console.error(hint);
22564
+ }
22565
+ process.exitCode = 2;
22566
+ return;
22567
+ }
22081
22568
  try {
22082
22569
  await program.parseAsync(process.argv);
22083
22570
  recordCliTrace({