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.
@@ -215,7 +215,7 @@ var SDK_RELEASE = {
215
215
  // preflight (existence, data rows, quotes, duplicate headers), HTML error
216
216
  // scrubbing, and word-boundary watch truncation.
217
217
  // 0.1.103 ships the refined SDK CLI command surface.
218
- // 0.1.104 ships postgres_fast suspension/billing parity and runtime worker hardening.
218
+ // 0.1.104 shipped the retired Postgres scheduler suspension/billing parity and runtime worker hardening.
219
219
  // 0.1.105 ships the billing catalog surface: billing plans, subscribe,
220
220
  // subscription status/cancel, invoices, and the client.billing namespace.
221
221
  // 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
@@ -223,10 +223,10 @@ var SDK_RELEASE = {
223
223
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
224
224
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
225
225
  // the SDK enrich generator's one-second stale policy.
226
- version: "0.1.108",
226
+ version: "0.1.109",
227
227
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
228
228
  supportPolicy: {
229
- latest: "0.1.108",
229
+ latest: "0.1.109",
230
230
  minimumSupported: "0.1.53",
231
231
  deprecatedBelow: "0.1.53",
232
232
  commandMinimumSupported: [
@@ -248,6 +248,7 @@ var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
248
248
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
249
249
  var COORDINATOR_URL_OVERRIDE_HEADER = "x-deepline-coordinator-url";
250
250
  var WORKER_CALLBACK_URL_OVERRIDE_HEADER = "x-deepline-worker-callback-url";
251
+ var RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER = "x-deepline-runtime-scheduler-schema";
251
252
  var SYNTHETIC_RUN_HEADER = "x-deepline-synthetic-run";
252
253
 
253
254
  // src/http.ts
@@ -316,6 +317,10 @@ var HttpClient = class {
316
317
  if (workerCallbackUrl?.trim()) {
317
318
  headers[WORKER_CALLBACK_URL_OVERRIDE_HEADER] = workerCallbackUrl.trim();
318
319
  }
320
+ const runtimeSchedulerSchema = typeof process !== "undefined" ? process.env?.DEEPLINE_RUNTIME_SCHEDULER_SCHEMA : void 0;
321
+ if (runtimeSchedulerSchema?.trim()) {
322
+ headers[RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER] = runtimeSchedulerSchema.trim();
323
+ }
319
324
  const syntheticRun = typeof process !== "undefined" ? process.env?.DEEPLINE_SYNTHETIC_RUN : void 0;
320
325
  if (syntheticRun && syntheticRun.trim() && syntheticRun.trim() !== "0") {
321
326
  headers[SYNTHETIC_RUN_HEADER] = "1";
@@ -522,8 +527,19 @@ var HttpClient = class {
522
527
  headers
523
528
  });
524
529
  }
530
+ /**
531
+ * Send a PATCH request with a JSON body.
532
+ *
533
+ * @typeParam T - Expected response body type
534
+ * @param path - API path
535
+ * @param body - JSON-serializable request body
536
+ */
525
537
  async patch(path, body, headers) {
526
- return this.request(path, { method: "PATCH", body, headers });
538
+ return this.request(path, {
539
+ method: "PATCH",
540
+ body,
541
+ headers
542
+ });
527
543
  }
528
544
  /**
529
545
  * Send a DELETE request.
@@ -874,6 +890,35 @@ function normalizePlayRunLiveStatus(value) {
874
890
  function isTerminalPlayRunLiveStatus(status) {
875
891
  return status === "completed" || status === "failed" || status === "cancelled" || status === "terminated" || status === "timed_out";
876
892
  }
893
+ function isRecord2(value) {
894
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
895
+ }
896
+ function finiteNumber2(value) {
897
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
898
+ }
899
+ function extractTerminalRunLogTail(result) {
900
+ if (!isRecord2(result) || !isRecord2(result._metadata)) {
901
+ return null;
902
+ }
903
+ const runLogTail = result._metadata.runLogTail;
904
+ if (!isRecord2(runLogTail) || !Array.isArray(runLogTail.tail)) {
905
+ return null;
906
+ }
907
+ const logTail = runLogTail.tail.filter(
908
+ (line) => typeof line === "string" && line.trim().length > 0
909
+ );
910
+ if (logTail.length === 0) {
911
+ return null;
912
+ }
913
+ const totalLogCount = Math.max(
914
+ finiteNumber2(runLogTail.totalLogCount) ?? logTail.length,
915
+ logTail.length
916
+ );
917
+ return {
918
+ logTail: logTail.slice(-LOG_TAIL_LIMIT),
919
+ totalLogCount
920
+ };
921
+ }
877
922
  function buildSnapshotFromLedger(snapshot) {
878
923
  const nodeStates = snapshot.orderedStepIds.map((stepId) => snapshot.stepsById[stepId]).filter((step) => Boolean(step)).map((step) => ({
879
924
  nodeId: step.stepId,
@@ -920,6 +965,14 @@ function buildPlayRunStatusSnapshot(input2) {
920
965
  updatedAt: input2.run.updatedAt ?? null,
921
966
  finishedAt: input2.run.finishedAt ?? null
922
967
  });
968
+ const terminalRunLogTail = extractTerminalRunLogTail(input2.run.result);
969
+ if (terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount) {
970
+ return buildSnapshotFromLedger({
971
+ ...ledgerSnapshot,
972
+ logTail: terminalRunLogTail.logTail,
973
+ totalLogCount: terminalRunLogTail.totalLogCount
974
+ });
975
+ }
923
976
  return buildSnapshotFromLedger(ledgerSnapshot);
924
977
  }
925
978
  function makeRunStreamEvent(input2) {
@@ -1514,7 +1567,7 @@ function chunkRegisterPlayArtifacts(artifacts) {
1514
1567
  return chunks;
1515
1568
  }
1516
1569
  var RUN_LOGS_PAGE_LIMIT = 1e3;
1517
- function isRecord2(value) {
1570
+ function isRecord3(value) {
1518
1571
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1519
1572
  }
1520
1573
  function isPrebuiltPlayDescription(play) {
@@ -1616,7 +1669,7 @@ function updatePlayLiveStatusState(state, event) {
1616
1669
  }
1617
1670
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
1618
1671
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
1619
- const progressPayload = isRecord2(payload.progress) ? payload.progress : {};
1672
+ const progressPayload = isRecord3(payload.progress) ? payload.progress : {};
1620
1673
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
1621
1674
  const payloadLogs = readStringArray(payload.logs);
1622
1675
  const progressLogs = readStringArray(progressPayload.logs);
@@ -1729,9 +1782,9 @@ var DeeplineClient = class {
1729
1782
  return fields.length > 0 ? { fields } : schema;
1730
1783
  }
1731
1784
  schemaMetadata(schema, key) {
1732
- if (!isRecord2(schema)) return null;
1785
+ if (!isRecord3(schema)) return null;
1733
1786
  const value = schema[key];
1734
- return isRecord2(value) ? value : null;
1787
+ return isRecord3(value) ? value : null;
1735
1788
  }
1736
1789
  playRunCommand(play, options) {
1737
1790
  const target = play.reference || play.name;
@@ -1778,7 +1831,7 @@ var DeeplineClient = class {
1778
1831
  aliases,
1779
1832
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
1780
1833
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
1781
- staticPipeline: isRecord2(play.staticPipeline) ? play.staticPipeline : isRecord2(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord2(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
1834
+ staticPipeline: isRecord3(play.staticPipeline) ? play.staticPipeline : isRecord3(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord3(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
1782
1835
  ...csvInput ? { csvInput } : {},
1783
1836
  ...rowOutputSchema ? { rowOutputSchema } : {},
1784
1837
  runCommand: runCommand2,
@@ -5284,14 +5337,14 @@ function sanitizeCsvProjectionInfo(input2) {
5284
5337
  const rows = input2.rows.map(stripCsvProjectionFields);
5285
5338
  return { rows, columns };
5286
5339
  }
5287
- function isRecord3(value) {
5340
+ function isRecord4(value) {
5288
5341
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
5289
5342
  }
5290
5343
  function isSerializedDataset(value) {
5291
- return isRecord3(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
5344
+ return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
5292
5345
  }
5293
5346
  function isPackagedDatasetOutput(value) {
5294
- return isRecord3(value) && value.kind === "dataset" && isRecord3(value.preview) && Array.isArray(value.preview.rows);
5347
+ return isRecord4(value) && value.kind === "dataset" && isRecord4(value.preview) && Array.isArray(value.preview.rows);
5295
5348
  }
5296
5349
  function pathParts(path) {
5297
5350
  return path.split(".").map((part) => part.trim()).filter(Boolean);
@@ -5299,7 +5352,7 @@ function pathParts(path) {
5299
5352
  function valueAtPath(root, path) {
5300
5353
  let cursor = root;
5301
5354
  for (const part of pathParts(path)) {
5302
- if (!isRecord3(cursor)) {
5355
+ if (!isRecord4(cursor)) {
5303
5356
  return void 0;
5304
5357
  }
5305
5358
  cursor = cursor[part];
@@ -5307,17 +5360,17 @@ function valueAtPath(root, path) {
5307
5360
  return cursor;
5308
5361
  }
5309
5362
  function totalRowsForDataset(result, datasetPath) {
5310
- const metadata = isRecord3(result._metadata) ? result._metadata : null;
5363
+ const metadata = isRecord4(result._metadata) ? result._metadata : null;
5311
5364
  const parentPath = datasetPath.split(".").slice(0, -1).join(".");
5312
5365
  const parent = parentPath ? valueAtPath({ result }, parentPath) : result;
5313
- return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord3(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
5366
+ return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord4(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
5314
5367
  }
5315
5368
  function rowArray(value) {
5316
5369
  if (!Array.isArray(value)) {
5317
5370
  return null;
5318
5371
  }
5319
5372
  const rows = value.filter(
5320
- (row) => isRecord3(row)
5373
+ (row) => isRecord4(row)
5321
5374
  );
5322
5375
  return rows.length === value.length ? rows : null;
5323
5376
  }
@@ -5341,7 +5394,7 @@ function inferColumns(rows) {
5341
5394
  return columns;
5342
5395
  }
5343
5396
  function columnsFromDatasetSummary(summary) {
5344
- if (!isRecord3(summary) || !isRecord3(summary.columnStats)) {
5397
+ if (!isRecord4(summary) || !isRecord4(summary.columnStats)) {
5345
5398
  return [];
5346
5399
  }
5347
5400
  return Object.keys(summary.columnStats).filter((column) => column);
@@ -5370,7 +5423,7 @@ function canonicalRowsInfoFromCandidate(input2) {
5370
5423
  }
5371
5424
  if (isPackagedDatasetOutput(candidate.value)) {
5372
5425
  const rawRows = rowArray(candidate.value.preview?.rows) ?? [];
5373
- const totalRows2 = readNumber(candidate.value.preview?.totalRows) ?? readNumber(candidate.value.rowCount) ?? rawRows.length;
5426
+ const totalRows2 = readNumber(candidate.value.rowCount) ?? readNumber(candidate.value.preview?.totalRows) ?? rawRows.length;
5374
5427
  const explicitColumns = Array.isArray(candidate.value.columns) ? candidate.value.columns.filter(
5375
5428
  (column) => typeof column === "string"
5376
5429
  ) : [];
@@ -5431,7 +5484,7 @@ function collectDatasetCandidates(input2) {
5431
5484
  });
5432
5485
  return;
5433
5486
  }
5434
- if (!isRecord3(input2.value)) {
5487
+ if (!isRecord4(input2.value)) {
5435
5488
  return;
5436
5489
  }
5437
5490
  for (const [key, child] of Object.entries(input2.value)) {
@@ -5448,12 +5501,12 @@ function collectDatasetCandidates(input2) {
5448
5501
  }
5449
5502
  }
5450
5503
  function collectCanonicalRowsInfos(statusOrResult) {
5451
- const root = isRecord3(statusOrResult) ? statusOrResult : null;
5452
- const result = isRecord3(root?.result) ? root.result : root;
5504
+ const root = isRecord4(statusOrResult) ? statusOrResult : null;
5505
+ const result = isRecord4(root?.result) ? root.result : root;
5453
5506
  if (!result) {
5454
5507
  return [];
5455
5508
  }
5456
- const metadata = isRecord3(result._metadata) ? result._metadata : null;
5509
+ const metadata = isRecord4(result._metadata) ? result._metadata : null;
5457
5510
  const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
5458
5511
  const candidates = [
5459
5512
  {
@@ -5477,8 +5530,8 @@ function collectCanonicalRowsInfos(statusOrResult) {
5477
5530
  total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
5478
5531
  }
5479
5532
  ];
5480
- if (isRecord3(result.output)) {
5481
- const outputMetadata = isRecord3(result.output._metadata) ? result.output._metadata : null;
5533
+ if (isRecord4(result.output)) {
5534
+ const outputMetadata = isRecord4(result.output._metadata) ? result.output._metadata : null;
5482
5535
  const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
5483
5536
  candidates.push(
5484
5537
  {
@@ -5505,14 +5558,14 @@ function collectCanonicalRowsInfos(statusOrResult) {
5505
5558
  }
5506
5559
  if (Array.isArray(result.steps)) {
5507
5560
  result.steps.forEach((step, index) => {
5508
- if (!isRecord3(step) || !isRecord3(step.output)) {
5561
+ if (!isRecord4(step) || !isRecord4(step.output)) {
5509
5562
  return;
5510
5563
  }
5511
5564
  const source = typeof step.output.path === "string" ? step.output.path : typeof step.id === "string" ? `steps.${step.id}.output` : `steps.${index}.output`;
5512
5565
  candidates.push({
5513
5566
  source,
5514
5567
  value: step.output,
5515
- total: step.output.rowCount ?? (isRecord3(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord3(step.progress) ? step.progress.total : void 0)
5568
+ total: step.output.rowCount ?? (isRecord4(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord4(step.progress) ? step.progress.total : void 0)
5516
5569
  });
5517
5570
  });
5518
5571
  }
@@ -5539,15 +5592,15 @@ function collectCanonicalRowsInfos(statusOrResult) {
5539
5592
  return infos;
5540
5593
  }
5541
5594
  function collectPackagedStepDatasetCandidates(statusOrResult) {
5542
- const root = isRecord3(statusOrResult) ? statusOrResult : null;
5595
+ const root = isRecord4(statusOrResult) ? statusOrResult : null;
5543
5596
  if (!root) {
5544
5597
  return [];
5545
5598
  }
5546
- const pkg = isRecord3(root.package) ? root.package : root;
5599
+ const pkg = isRecord4(root.package) ? root.package : root;
5547
5600
  const steps = Array.isArray(pkg.steps) ? pkg.steps : [];
5548
5601
  const candidates = [];
5549
5602
  for (const step of steps) {
5550
- if (!isRecord3(step) || !isRecord3(step.output)) {
5603
+ if (!isRecord4(step) || !isRecord4(step.output)) {
5551
5604
  continue;
5552
5605
  }
5553
5606
  const output2 = step.output;
@@ -5561,14 +5614,14 @@ function collectPackagedStepDatasetCandidates(statusOrResult) {
5561
5614
  candidates.push({
5562
5615
  source,
5563
5616
  value: output2,
5564
- total: output2.rowCount ?? (isRecord3(output2.preview) ? output2.preview.totalRows : void 0) ?? (isRecord3(step.progress) ? step.progress.total : void 0)
5617
+ total: output2.rowCount ?? (isRecord4(output2.preview) ? output2.preview.totalRows : void 0) ?? (isRecord4(step.progress) ? step.progress.total : void 0)
5565
5618
  });
5566
5619
  }
5567
5620
  return candidates;
5568
5621
  }
5569
5622
  function collectSerializedDatasetRowsInfos(statusOrResult) {
5570
- const root = isRecord3(statusOrResult) ? statusOrResult : null;
5571
- const result = isRecord3(root?.result) ? root.result : root;
5623
+ const root = isRecord4(statusOrResult) ? statusOrResult : null;
5624
+ const result = isRecord4(root?.result) ? root.result : root;
5572
5625
  const candidates = [];
5573
5626
  if (result) {
5574
5627
  collectDatasetCandidates({
@@ -5604,17 +5657,17 @@ function percentText(numerator, denominator) {
5604
5657
  return datasetSummaryPercentText(numerator, denominator);
5605
5658
  }
5606
5659
  function isDatasetExecutionStatsInput(value) {
5607
- return isRecord3(value) && isRecord3(value.columnStats) && Object.values(value.columnStats).every(isRecord3);
5660
+ return isRecord4(value) && isRecord4(value.columnStats) && Object.values(value.columnStats).every(isRecord4);
5608
5661
  }
5609
5662
  function extractDatasetExecutionStats(statusOrResult) {
5610
- if (!isRecord3(statusOrResult)) {
5663
+ if (!isRecord4(statusOrResult)) {
5611
5664
  return null;
5612
5665
  }
5613
5666
  const direct = statusOrResult.dataset_execution_stats;
5614
5667
  if (isDatasetExecutionStatsInput(direct)) {
5615
5668
  return direct;
5616
5669
  }
5617
- const nested = isRecord3(statusOrResult.result) ? statusOrResult.result.dataset_execution_stats : null;
5670
+ const nested = isRecord4(statusOrResult.result) ? statusOrResult.result.dataset_execution_stats : null;
5618
5671
  return isDatasetExecutionStatsInput(nested) ? nested : null;
5619
5672
  }
5620
5673
  function countPercentText(count, denominator) {
@@ -5655,13 +5708,13 @@ function summarizeSampleValue(value, depth = 0) {
5655
5708
  if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
5656
5709
  if (depth >= 3) {
5657
5710
  if (Array.isArray(parsed)) return [];
5658
- if (isRecord3(parsed)) return {};
5711
+ if (isRecord4(parsed)) return {};
5659
5712
  return compactScalar(parsed);
5660
5713
  }
5661
5714
  if (Array.isArray(parsed)) {
5662
5715
  return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
5663
5716
  }
5664
- if (isRecord3(parsed)) {
5717
+ if (isRecord4(parsed)) {
5665
5718
  const out = {};
5666
5719
  for (const [key, nested] of Object.entries(parsed)) {
5667
5720
  if (["__dl", "meta", "metadata"].includes(key)) {
@@ -5692,7 +5745,7 @@ function compactCell(value) {
5692
5745
  }
5693
5746
  return `[${parsed.length} items]`;
5694
5747
  }
5695
- if (isRecord3(parsed)) {
5748
+ if (isRecord4(parsed)) {
5696
5749
  for (const key of ["matched_result", "output"]) {
5697
5750
  if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
5698
5751
  return compactCell(parsed[key]);
@@ -7483,16 +7536,19 @@ var PLAY_DEDUP_BACKENDS = {
7483
7536
  var PLAY_SCHEDULER_BACKENDS = {
7484
7537
  temporal: "temporal",
7485
7538
  cfWorkflows: "cf-workflows",
7539
+ /**
7540
+ * Private legacy id retained only so old persisted rows can be interpreted.
7541
+ * It is not a selectable scheduler backend after the Hatchet hard cutover.
7542
+ */
7486
7543
  postgres: "postgres",
7544
+ hatchet: "hatchet",
7487
7545
  inProcess: "in-process"
7488
7546
  };
7489
7547
 
7490
7548
  // ../shared_libs/play-runtime/providers.ts
7491
7549
  var PLAY_RUNTIME_PROVIDER_IDS = {
7492
7550
  workersEdge: "workers_edge",
7493
- postgresFast: "postgres_fast",
7494
- postgresFastSandbox: "postgres_fast_sandbox",
7495
- postgresFastWorkers: "postgres_fast_workers",
7551
+ hatchet: "hatchet",
7496
7552
  local: "local"
7497
7553
  };
7498
7554
  var PLAY_RUNTIME_PROVIDERS = {
@@ -7504,29 +7560,13 @@ var PLAY_RUNTIME_PROVIDERS = {
7504
7560
  artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
7505
7561
  label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
7506
7562
  },
7507
- postgres_fast: {
7508
- id: PLAY_RUNTIME_PROVIDER_IDS.postgresFast,
7509
- scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
7510
- runner: PLAY_RUNTIME_BACKENDS.daytona,
7511
- dedup: PLAY_DEDUP_BACKENDS.durableObject,
7512
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
7513
- label: "BETA: Postgres Scheduler + warm sandbox runner + DO dedup"
7514
- },
7515
- postgres_fast_sandbox: {
7516
- id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastSandbox,
7517
- scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
7563
+ hatchet: {
7564
+ id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
7565
+ scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
7518
7566
  runner: PLAY_RUNTIME_BACKENDS.daytona,
7519
7567
  dedup: PLAY_DEDUP_BACKENDS.durableObject,
7520
7568
  artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
7521
- label: "BETA: Postgres Scheduler + warm sandbox runner + DO dedup"
7522
- },
7523
- postgres_fast_workers: {
7524
- id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastWorkers,
7525
- scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
7526
- runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
7527
- dedup: PLAY_DEDUP_BACKENDS.durableObject,
7528
- artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
7529
- label: "Experimental Postgres Scheduler + Queue/DO-woken Workers + DO dedup"
7569
+ label: "Hatchet scheduler + one-shot Daytona runner + DO dedup"
7530
7570
  },
7531
7571
  local: {
7532
7572
  id: PLAY_RUNTIME_PROVIDER_IDS.local,
@@ -8045,17 +8085,17 @@ function parsePositiveInteger2(value, flagName) {
8045
8085
  }
8046
8086
  return parsed;
8047
8087
  }
8048
- function isRecord4(value) {
8088
+ function isRecord5(value) {
8049
8089
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
8050
8090
  }
8051
8091
  function stringValue(value) {
8052
8092
  return typeof value === "string" ? value.trim() : "";
8053
8093
  }
8054
8094
  function extractionEntries(value) {
8055
- if (Array.isArray(value)) return value.filter(isRecord4);
8056
- if (!isRecord4(value)) return [];
8095
+ if (Array.isArray(value)) return value.filter(isRecord5);
8096
+ if (!isRecord5(value)) return [];
8057
8097
  return Object.entries(value).map(
8058
- ([name, entry]) => isRecord4(entry) ? { name, ...entry } : { name }
8098
+ ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
8059
8099
  );
8060
8100
  }
8061
8101
  var PlayBootstrapError = class extends Error {
@@ -8475,7 +8515,7 @@ function readCsvSampleRows(sample) {
8475
8515
  relax_column_count: true,
8476
8516
  trim: true
8477
8517
  });
8478
- return Array.isArray(parsedRows) ? parsedRows.filter(isRecord4) : [];
8518
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord5) : [];
8479
8519
  }
8480
8520
  function readSourceCsvColumnSpecs(csvPath) {
8481
8521
  const sample = readCsvSample(csvPath);
@@ -8508,16 +8548,16 @@ function packagedCsvPathForPlay(csvPath) {
8508
8548
  return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
8509
8549
  }
8510
8550
  function getterNamesFromTool(tool, kind) {
8511
- const usageGuidance = isRecord4(tool?.usageGuidance) ? tool.usageGuidance : {};
8512
- const resultGuidance = isRecord4(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord4(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
8551
+ const usageGuidance = isRecord5(tool?.usageGuidance) ? tool.usageGuidance : {};
8552
+ const resultGuidance = isRecord5(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord5(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
8513
8553
  const key = kind === "list" ? "extractedLists" : "extractedValues";
8514
8554
  const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
8515
8555
  return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
8516
8556
  }
8517
8557
  function targetGettersFromTool(tool) {
8518
- const record = isRecord4(tool) ? tool : {};
8558
+ const record = isRecord5(tool) ? tool : {};
8519
8559
  const raw = record.targetGetters ?? record.target_getters;
8520
- if (!isRecord4(raw)) return {};
8560
+ if (!isRecord5(raw)) return {};
8521
8561
  const entries = [];
8522
8562
  for (const [target, value] of Object.entries(raw)) {
8523
8563
  const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
@@ -8538,10 +8578,10 @@ function listRowCandidateKeysFromTool(tool) {
8538
8578
  return [...keys].sort();
8539
8579
  }
8540
8580
  function inputPropertyNames(schema) {
8541
- if (!isRecord4(schema)) return [];
8542
- if (isRecord4(schema.properties)) return Object.keys(schema.properties);
8581
+ if (!isRecord5(schema)) return [];
8582
+ if (isRecord5(schema.properties)) return Object.keys(schema.properties);
8543
8583
  if (Array.isArray(schema.fields)) {
8544
- return schema.fields.filter(isRecord4).map((field) => stringValue(field.name)).filter(Boolean);
8584
+ return schema.fields.filter(isRecord5).map((field) => stringValue(field.name)).filter(Boolean);
8545
8585
  }
8546
8586
  return [];
8547
8587
  }
@@ -8555,7 +8595,7 @@ function schemaFieldDetails(schema) {
8555
8595
  return { required, optional };
8556
8596
  }
8557
8597
  function jsonSchemaTypeExpression(schema) {
8558
- if (!isRecord4(schema)) return "unknown";
8598
+ if (!isRecord5(schema)) return "unknown";
8559
8599
  const type = schema.type;
8560
8600
  if (Array.isArray(type)) {
8561
8601
  return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
@@ -8585,7 +8625,7 @@ function jsonSchemaTypeExpression(schema) {
8585
8625
  }
8586
8626
  }
8587
8627
  function objectPropertySchema(schema, property) {
8588
- return isRecord4(schema) && isRecord4(schema.properties) ? schema.properties[property] : null;
8628
+ return isRecord5(schema) && isRecord5(schema.properties) ? schema.properties[property] : null;
8589
8629
  }
8590
8630
  function playOutputHasField(schema, field) {
8591
8631
  return objectPropertySchema(schema, field) != null;
@@ -8761,14 +8801,14 @@ ${indent2.slice(2)}}`;
8761
8801
  }
8762
8802
  function requiredPlayInputFields(play) {
8763
8803
  const schema = play?.inputSchema;
8764
- if (!isRecord4(schema)) return [];
8804
+ if (!isRecord5(schema)) return [];
8765
8805
  if (Array.isArray(schema.required)) {
8766
8806
  return schema.required.filter(
8767
8807
  (value) => typeof value === "string"
8768
8808
  );
8769
8809
  }
8770
8810
  if (Array.isArray(schema.fields)) {
8771
- return schema.fields.filter(isRecord4).filter(
8811
+ return schema.fields.filter(isRecord5).filter(
8772
8812
  (field) => field.required === true && typeof field.name === "string"
8773
8813
  ).map((field) => String(field.name));
8774
8814
  }
@@ -8949,7 +8989,7 @@ function validateBootstrapRoutes(input2) {
8949
8989
  }
8950
8990
  }
8951
8991
  function staticPipelineSubsteps(pipeline) {
8952
- if (!isRecord4(pipeline)) return [];
8992
+ if (!isRecord5(pipeline)) return [];
8953
8993
  return [
8954
8994
  ...extractionEntries(pipeline.stages),
8955
8995
  ...extractionEntries(pipeline.substeps)
@@ -8957,7 +8997,7 @@ function staticPipelineSubsteps(pipeline) {
8957
8997
  }
8958
8998
  function playUsesMapBackedRuntime(play) {
8959
8999
  const pipeline = play?.staticPipeline;
8960
- if (!isRecord4(pipeline)) return false;
9000
+ if (!isRecord5(pipeline)) return false;
8961
9001
  if (stringValue(pipeline.tableNamespace)) return true;
8962
9002
  return staticPipelineSubsteps(pipeline).some((substep) => {
8963
9003
  if (stringValue(substep.type) === "map") return true;
@@ -8966,7 +9006,7 @@ function playUsesMapBackedRuntime(play) {
8966
9006
  aliases: [],
8967
9007
  runCommand: "",
8968
9008
  examples: [],
8969
- staticPipeline: isRecord4(substep.pipeline) ? substep.pipeline : null
9009
+ staticPipeline: isRecord5(substep.pipeline) ? substep.pipeline : null
8970
9010
  });
8971
9011
  });
8972
9012
  }
@@ -10528,10 +10568,12 @@ function playStatusValue(value) {
10528
10568
  return value === "queued" || value === "running" || value === "waiting" || value === "completed" || value === "failed" || value === "cancelled" ? value : null;
10529
10569
  }
10530
10570
  function getRunRecordFromPackage(value) {
10531
- if (!isPlayRunPackageValue(value)) {
10571
+ const nestedPackage = value.package;
10572
+ const playRunPackage = isPlayRunPackageValue(value) ? value : isPlayRunPackageValue(nestedPackage) ? nestedPackage : null;
10573
+ if (!playRunPackage) {
10532
10574
  return null;
10533
10575
  }
10534
- const run = value.run;
10576
+ const run = playRunPackage.run;
10535
10577
  return run && typeof run === "object" && !Array.isArray(run) ? run : null;
10536
10578
  }
10537
10579
  function getRunIdFromLiveEvent(event) {
@@ -10561,10 +10603,12 @@ function getFinalStatusFromLiveEvent(event) {
10561
10603
  return null;
10562
10604
  }
10563
10605
  const runId = typeof payload.runId === "string" ? payload.runId : typeof packageRun?.id === "string" ? packageRun.id : "";
10606
+ const error = typeof payload.error === "string" ? payload.error : typeof packageRun?.error === "string" ? packageRun.error : void 0;
10564
10607
  return {
10565
10608
  ...payload,
10566
10609
  runId,
10567
- status
10610
+ status,
10611
+ ...error ? { error } : {}
10568
10612
  };
10569
10613
  }
10570
10614
  function getLogLinesFromLiveEvent(event) {
@@ -11883,7 +11927,16 @@ function withTerminalPlayIdentity(status, playName) {
11883
11927
  function compactPlayStatus(status) {
11884
11928
  const packaged = getPlayRunPackage(status);
11885
11929
  if (packaged) {
11886
- return packaged;
11930
+ const error2 = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : null);
11931
+ if (!error2) {
11932
+ return packaged;
11933
+ }
11934
+ const run = packaged.run && typeof packaged.run === "object" ? packaged.run : null;
11935
+ return {
11936
+ ...packaged,
11937
+ error: error2,
11938
+ ...run ? { run: { ...run, error: error2 } } : {}
11939
+ };
11887
11940
  }
11888
11941
  const rowsInfo = extractCanonicalRowsInfo(status);
11889
11942
  const result = status && typeof status === "object" ? status.result : null;
@@ -12223,10 +12276,17 @@ function writePlayResult(status, jsonOutput, options) {
12223
12276
  ` }
12224
12277
  );
12225
12278
  }
12226
- function playRunPackageStepCount(pkg) {
12227
- if (!pkg) return 0;
12228
- const steps = pkg.steps;
12229
- return Array.isArray(steps) ? steps.length : 0;
12279
+ function playRunPackageTextLedgerIncomplete(pkg) {
12280
+ if (!pkg) return true;
12281
+ const steps = readRecordArray(pkg.steps);
12282
+ if (steps.length === 0) return true;
12283
+ for (const step of steps) {
12284
+ if (step.kind !== "dataset" || step.status !== "completed") continue;
12285
+ const output2 = readRecord(step.output);
12286
+ if (!output2 || typeof output2.rowCount !== "number") return true;
12287
+ if (!readRecord(output2.summary)) return true;
12288
+ }
12289
+ return false;
12230
12290
  }
12231
12291
  async function resolvePlayRunOutputStatus(input2) {
12232
12292
  const runId = input2.status.runId;
@@ -12235,7 +12295,7 @@ async function resolvePlayRunOutputStatus(input2) {
12235
12295
  }
12236
12296
  const streamedPackage = getPlayRunPackage(input2.status);
12237
12297
  const refreshForFullJson = input2.fullJson && streamedPackage !== null;
12238
- const streamedTextPackageIncomplete = !input2.jsonOutput && input2.status.status === "completed" && playRunPackageStepCount(streamedPackage) === 0;
12298
+ const streamedTextPackageIncomplete = !input2.jsonOutput && input2.status.status === "completed" && playRunPackageTextLedgerIncomplete(streamedPackage);
12239
12299
  if (!refreshForFullJson && !streamedTextPackageIncomplete) {
12240
12300
  return input2.status;
12241
12301
  }
@@ -12243,7 +12303,7 @@ async function resolvePlayRunOutputStatus(input2) {
12243
12303
  billing: false,
12244
12304
  full: input2.fullJson
12245
12305
  });
12246
- for (let attempt = 0; attempt < 3 && streamedTextPackageIncomplete && refreshedStatus.status === "completed" && playRunPackageStepCount(getPlayRunPackage(refreshedStatus)) === 0; attempt += 1) {
12306
+ for (let attempt = 0; attempt < 3 && streamedTextPackageIncomplete && refreshedStatus.status === "completed" && playRunPackageTextLedgerIncomplete(getPlayRunPackage(refreshedStatus)); attempt += 1) {
12247
12307
  await sleep5(250);
12248
12308
  refreshedStatus = await input2.client.getPlayStatus(runId, {
12249
12309
  billing: false,
@@ -12552,7 +12612,7 @@ function extractPlayValidationErrors(value) {
12552
12612
  if (value instanceof DeeplineError) {
12553
12613
  return extractPlayValidationErrors(value.details);
12554
12614
  }
12555
- if (!isRecord5(value)) {
12615
+ if (!isRecord6(value)) {
12556
12616
  return [];
12557
12617
  }
12558
12618
  const directErrors = stringArrayField(value, "errors");
@@ -12765,7 +12825,7 @@ function writeStartedPlayRun(input2) {
12765
12825
  );
12766
12826
  }
12767
12827
  function parsePlayRunOptions(args) {
12768
- 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.";
12828
+ 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.";
12769
12829
  let filePath = null;
12770
12830
  let playName = null;
12771
12831
  let input2 = null;
@@ -12910,7 +12970,7 @@ function shouldUseLocalOnlyPlayCheck() {
12910
12970
  const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
12911
12971
  return value === "1" || value === "true" || value === "yes" || value === "on";
12912
12972
  }
12913
- function isRecord5(value) {
12973
+ function isRecord6(value) {
12914
12974
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
12915
12975
  }
12916
12976
  function stringValue2(value) {
@@ -12920,14 +12980,14 @@ function asArray(value) {
12920
12980
  return Array.isArray(value) ? value : [];
12921
12981
  }
12922
12982
  function extractionEntries2(value) {
12923
- if (Array.isArray(value)) return value.filter(isRecord5);
12924
- if (!isRecord5(value)) return [];
12983
+ if (Array.isArray(value)) return value.filter(isRecord6);
12984
+ if (!isRecord6(value)) return [];
12925
12985
  return Object.entries(value).map(
12926
- ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
12986
+ ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
12927
12987
  );
12928
12988
  }
12929
12989
  function firstRawPath(entry) {
12930
- const details = isRecord5(entry.details) ? entry.details : {};
12990
+ const details = isRecord6(entry.details) ? entry.details : {};
12931
12991
  const paths = [
12932
12992
  ...asArray(details.rawToolOutputPaths),
12933
12993
  ...asArray(details.raw_tool_output_paths),
@@ -12945,12 +13005,12 @@ function checkHintRawPath(value) {
12945
13005
  function collectStaticPipelineToolIds(staticPipeline) {
12946
13006
  const seen = /* @__PURE__ */ new Set();
12947
13007
  const visitPipeline = (pipeline) => {
12948
- if (!isRecord5(pipeline)) return;
13008
+ if (!isRecord6(pipeline)) return;
12949
13009
  for (const step of [
12950
13010
  ...asArray(pipeline.stages),
12951
13011
  ...asArray(pipeline.substeps)
12952
13012
  ]) {
12953
- if (!isRecord5(step)) continue;
13013
+ if (!isRecord6(step)) continue;
12954
13014
  if (step.type === "tool") {
12955
13015
  const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
12956
13016
  if (toolId) seen.add(toolId);
@@ -12964,9 +13024,9 @@ function collectStaticPipelineToolIds(staticPipeline) {
12964
13024
  return [...seen].sort();
12965
13025
  }
12966
13026
  function toolGetterHintFromMetadata(toolId, tool) {
12967
- const usageGuidance = isRecord5(tool.usageGuidance) ? tool.usageGuidance : {};
12968
- const resultGuidance = isRecord5(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord5(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
12969
- const toolResponse = isRecord5(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord5(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
13027
+ const usageGuidance = isRecord6(tool.usageGuidance) ? tool.usageGuidance : {};
13028
+ const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
13029
+ const toolResponse = isRecord6(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord6(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
12970
13030
  const lists = extractionEntries2(
12971
13031
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
12972
13032
  ).map((entry) => ({
@@ -14291,6 +14351,40 @@ async function handlePlayDescribe(args) {
14291
14351
  );
14292
14352
  return 2;
14293
14353
  }
14354
+ if (isFileTarget(playName) || looksLikeFilePath(playName)) {
14355
+ const message = "Local play files can be checked and run, but describe only supports saved/prebuilt play references.";
14356
+ const definedName = isFileTarget(playName) ? (() => {
14357
+ try {
14358
+ return extractPlayName(
14359
+ readFileSync6(resolve10(playName), "utf-8"),
14360
+ playName
14361
+ );
14362
+ } catch {
14363
+ return null;
14364
+ }
14365
+ })() : null;
14366
+ const next = [
14367
+ `deepline plays check ${playName}`,
14368
+ ...definedName ? [`deepline plays describe <workspace>/${definedName}`] : []
14369
+ ];
14370
+ if (argsWantJson(args)) {
14371
+ process.stdout.write(
14372
+ `${JSON.stringify({
14373
+ ok: false,
14374
+ error: { message },
14375
+ next
14376
+ })}
14377
+ `
14378
+ );
14379
+ } else {
14380
+ console.error(message);
14381
+ console.error(`Try: ${next[0]}`);
14382
+ if (next[1]) {
14383
+ console.error(`Or after publishing/running: ${next[1]}`);
14384
+ }
14385
+ }
14386
+ return 2;
14387
+ }
14294
14388
  const client2 = new DeeplineClient();
14295
14389
  await assertCanonicalNamedPlayReference(client2, playName);
14296
14390
  const play = await client2.describePlay(
@@ -15372,6 +15466,18 @@ function getterFromLegacyExtractJs(extractJs, fallbackAlias) {
15372
15466
  return null;
15373
15467
  }
15374
15468
 
15469
+ // src/cli/enrich-compat-adapter.ts
15470
+ var ENRICH_COMPAT_DEFAULT_PLAY_NAME = "deepline-enrich-v1-compat";
15471
+ var ENRICH_COMPAT_DEFAULT_MAP_NAME = "deepline_enrich_rows";
15472
+ var ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE = "{ recompute: true }";
15473
+ function buildEnrichCompatibilityPlan(options = {}) {
15474
+ return {
15475
+ playName: options.playName?.trim() || ENRICH_COMPAT_DEFAULT_PLAY_NAME,
15476
+ mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME,
15477
+ metadataCellPolicySource: ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE
15478
+ };
15479
+ }
15480
+
15375
15481
  // src/cli/user-code-safety.ts
15376
15482
  var FORBIDDEN = [
15377
15483
  // Non-deterministic — breaks replay.
@@ -15543,12 +15649,16 @@ function renderPlayStep(command, options) {
15543
15649
  const runIfJs = command.run_if_js ? `(row) => { const input = row; const context = row;
15544
15650
  ${indent(renderJavascriptBody(command.run_if_js), 6)}
15545
15651
  }` : "null";
15546
- const runIfLines = command.run_if_js ? [` const __dlRunIf = ${runIfJs};`, ` if (!__dlRunIf(row)) return null;`] : [];
15652
+ const runIfLines = command.run_if_js ? [
15653
+ ` const __dlRunIf = ${runIfJs};`,
15654
+ ` if (!__dlRunIf(templateRow)) return null;`
15655
+ ] : [];
15547
15656
  return [
15548
15657
  `async (row, stepCtx) => {`,
15549
15658
  ...options.precheck ? [` if (${options.precheck}) return null;`] : [],
15659
+ ` const templateRow = __dlPrepareEnrichRow(row, [${alias}]);`,
15550
15660
  ...runIfLines,
15551
- ` const payload = __dlTemplate(${payload}, row) as Record<string, unknown>;`,
15661
+ ` const payload = __dlTemplate(${payload}, templateRow) as Record<string, unknown>;`,
15552
15662
  ` const result = await stepCtx.runPlay(${callId}, ${playRef}, payload, {`,
15553
15663
  ` description: ${stringLiteral(command.description ?? command.alias)}`,
15554
15664
  ` });`,
@@ -15649,7 +15759,7 @@ function collectGeneratedAliases(commands) {
15649
15759
  }
15650
15760
  return aliases;
15651
15761
  }
15652
- function renderMetadataColumnStep(config) {
15762
+ function renderMetadataColumnStep(config, policySource) {
15653
15763
  const columns = collectMetadataColumns(config.commands);
15654
15764
  if (Object.keys(columns).length === 0) {
15655
15765
  return "";
@@ -15657,7 +15767,7 @@ function renderMetadataColumnStep(config) {
15657
15767
  return [
15658
15768
  ` .withColumn('_metadata',`,
15659
15769
  ` (row) => __dlMergeMetadata(__dlMetadataFromRow(row), ${stableJson({ columns })}),`,
15660
- ` { recompute: true },`,
15770
+ ` ${policySource},`,
15661
15771
  ` )`
15662
15772
  ].join("\n");
15663
15773
  }
@@ -15711,8 +15821,8 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15711
15821
  ];
15712
15822
  }
15713
15823
  function compileEnrichConfigToPlaySource(config, options = {}) {
15714
- const playName = options.playName ?? "deepline-enrich-v1-compat";
15715
- const mapName = options.mapName ?? "deepline_enrich_rows";
15824
+ const compatibility = buildEnrichCompatibilityPlan(options);
15825
+ const { playName, mapName } = compatibility;
15716
15826
  const inlineRunJavascript = options.inlineRunJavascript ?? false;
15717
15827
  const idiomaticGetters = options.idiomaticGetters ?? false;
15718
15828
  const forceAliases = new Set(
@@ -15748,15 +15858,25 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15748
15858
  );
15749
15859
  });
15750
15860
  const columnStepSource = columnSteps.length > 0 ? columnSteps.join("\n") : ` .withColumn('noop', () => null)`;
15751
- const metadataColumnSource = renderMetadataColumnStep(config);
15861
+ const metadataColumnSource = renderMetadataColumnStep(
15862
+ config,
15863
+ compatibility.metadataCellPolicySource
15864
+ );
15752
15865
  const generatedAliases = collectGeneratedAliases(config.commands);
15753
15866
  const body = [
15754
15867
  `export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
15755
15868
  ` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
15756
15869
  ` const rowStart = __dlNonNegativeInteger(input.rowStart, 0);`,
15757
15870
  ` const rowEndExclusive = Number.isFinite(input.rowEnd) ? Math.max(rowStart, __dlWholeNumber(input.rowEnd, rowStart) + 1) : undefined;`,
15758
- ` const selectedRows = sourceRows.slice(rowStart, rowEndExclusive, { key: 'deepline_enrich_selected_rows', sourceLabel: 'Selected enrich rows' });`,
15759
- ` const rows = selectedRows.map((row) => __dlStripErroredGeneratedColumns(row, ${stableJson(generatedAliases)}), { key: 'deepline_enrich_repair_rows', sourceLabel: 'Selected enrich rows' });`,
15871
+ ` const rows: Array<Record<string, unknown>> = [];`,
15872
+ ` let sourceRowIndex = 0;`,
15873
+ ` for await (const row of sourceRows) {`,
15874
+ ` if (rowEndExclusive !== undefined && sourceRowIndex >= rowEndExclusive) break;`,
15875
+ ` if (sourceRowIndex >= rowStart) {`,
15876
+ ` rows.push(__dlPrepareEnrichRow(row, ${stableJson(generatedAliases)}));`,
15877
+ ` }`,
15878
+ ` sourceRowIndex += 1;`,
15879
+ ` }`,
15760
15880
  ` const enriched = await ctx`,
15761
15881
  ` .dataset(${stringLiteral(mapName)}, rows)`,
15762
15882
  columnStepSource,
@@ -15887,17 +16007,55 @@ function helperSource() {
15887
16007
  ` return parts;`,
15888
16008
  `}`,
15889
16009
  ``,
16010
+ `function __dlNormalizeHeader(value: string): string {`,
16011
+ ` return value.trim().replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');`,
16012
+ `}`,
16013
+ ``,
16014
+ `function __dlOwnStringKeys(record: Record<string, unknown>): string[] {`,
16015
+ ` return Object.keys(record);`,
16016
+ `}`,
16017
+ ``,
16018
+ `function __dlReadOwnField(record: Record<string, unknown>, key: string): unknown {`,
16019
+ ` return record[key];`,
16020
+ `}`,
16021
+ ``,
16022
+ `function __dlGetNormalizedKey(record: Record<string, unknown>, part: string): string | null {`,
16023
+ ` const normalized = __dlNormalizeHeader(part);`,
16024
+ ` for (const key of __dlOwnStringKeys(record)) {`,
16025
+ ` if (__dlNormalizeHeader(key) === normalized) return key;`,
16026
+ ` }`,
16027
+ ` return null;`,
16028
+ `}`,
16029
+ ``,
16030
+ `function __dlGetRecordField(record: Record<string, unknown>, part: string): { found: boolean; value: unknown } {`,
16031
+ ` if (part in record) return { found: true, value: record[part] };`,
16032
+ ` const normalizedKey = __dlGetNormalizedKey(record, part);`,
16033
+ ` if (normalizedKey) return { found: true, value: __dlReadOwnField(record, normalizedKey) };`,
16034
+ ` const projectedValues = record.__deeplineCsvProjectedValues;`,
16035
+ ` if (projectedValues && typeof projectedValues === 'object' && !Array.isArray(projectedValues)) {`,
16036
+ ` const projectedRecord = projectedValues as Record<string, unknown>;`,
16037
+ ` if (part in projectedRecord) return { found: true, value: projectedRecord[part] };`,
16038
+ ` const projectedKey = __dlGetNormalizedKey(projectedRecord, part);`,
16039
+ ` if (projectedKey) return { found: true, value: __dlReadOwnField(projectedRecord, projectedKey) };`,
16040
+ ` }`,
16041
+ ` const data = record.data;`,
16042
+ ` if (data && typeof data === 'object' && !Array.isArray(data)) {`,
16043
+ ` const dataRecord = data as Record<string, unknown>;`,
16044
+ ` if (part in dataRecord) return { found: true, value: dataRecord[part] };`,
16045
+ ` const dataKey = __dlGetNormalizedKey(dataRecord, part);`,
16046
+ ` if (dataKey) return { found: true, value: __dlReadOwnField(dataRecord, dataKey) };`,
16047
+ ` }`,
16048
+ ` return { found: false, value: undefined };`,
16049
+ `}`,
16050
+ ``,
15890
16051
  `function __dlGetByPath(root: unknown, path: string): unknown {`,
15891
16052
  ` let cursor = root;`,
15892
16053
  ` for (const part of __dlPathParts(path)) {`,
15893
16054
  ` if (!cursor || typeof cursor !== 'object') return undefined;`,
15894
16055
  ` const record = cursor as Record<string, unknown>;`,
15895
- ` if (part in record) {`,
15896
- ` cursor = record[part];`,
15897
- ` continue;`,
15898
- ` }`,
15899
- ` const data = record.data;`,
15900
- ` cursor = data && typeof data === 'object' ? (data as Record<string, unknown>)[part] : undefined;`,
16056
+ ` const field = __dlGetRecordField(record, part);`,
16057
+ ` if (!field.found) return undefined;`,
16058
+ ` cursor = field.value;`,
15901
16059
  ` }`,
15902
16060
  ` return cursor;`,
15903
16061
  `}`,
@@ -15962,6 +16120,30 @@ function helperSource() {
15962
16120
  ` return next ?? row;`,
15963
16121
  `}`,
15964
16122
  ``,
16123
+ `function __dlTemplateContext(row: Record<string, unknown>): Record<string, unknown> {`,
16124
+ ` const context: Record<string, unknown> = {};`,
16125
+ ` const projectedValues = row.__deeplineCsvProjectedValues;`,
16126
+ ` if (__dlRecord(projectedValues)) {`,
16127
+ ` for (const [key, value] of Object.entries(projectedValues)) context[key] = value;`,
16128
+ ` }`,
16129
+ ` for (const [key, value] of Object.entries(row)) {`,
16130
+ ` if (key.startsWith('__deepline')) continue;`,
16131
+ ` context[key] = value;`,
16132
+ ` }`,
16133
+ ` return context;`,
16134
+ `}`,
16135
+ ``,
16136
+ `function __dlPrepareEnrichRow(row: Record<string, unknown>, aliases: string[]): Record<string, unknown> {`,
16137
+ ` const cleaned = __dlStripErroredGeneratedColumns(row, aliases);`,
16138
+ ` const templateContext = __dlTemplateContext(cleaned);`,
16139
+ ` return {`,
16140
+ ` ...templateContext,`,
16141
+ ` ...cleaned,`,
16142
+ ` __deeplineCsvProjectedFields: Object.keys(templateContext),`,
16143
+ ` __deeplineCsvProjectedValues: templateContext,`,
16144
+ ` };`,
16145
+ `}`,
16146
+ ``,
15965
16147
  `function __dlRawToolOutput(result: unknown): unknown {`,
15966
16148
  ` if (!result || typeof result !== 'object') return result;`,
15967
16149
  ` const record = result as Record<string, unknown>;`,
@@ -16999,7 +17181,7 @@ async function resolveWatchedGeneratedPlayStatus(input2) {
16999
17181
  }
17000
17182
  return input2.client.runs.get(runId, { full: true });
17001
17183
  }
17002
- function isRecord6(value) {
17184
+ function isRecord7(value) {
17003
17185
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
17004
17186
  }
17005
17187
  async function captureStdout(run, options = {}) {
@@ -17047,12 +17229,12 @@ async function writeOutputCsv(outputPath, status, options) {
17047
17229
  if (!rowsInfo) {
17048
17230
  throw new Error("The generated play did not return row-shaped output.");
17049
17231
  }
17050
- if (!rowsInfo.complete && options?.client) {
17232
+ if (options?.client) {
17051
17233
  rowsInfo = await fetchBackingRowsForCsvExport({
17052
17234
  client: options.client,
17053
17235
  status,
17054
17236
  rowsInfo
17055
- }) ?? rowsInfo;
17237
+ }).catch(() => null) ?? rowsInfo;
17056
17238
  }
17057
17239
  assertCompleteRowsForCsvExport(rowsInfo, status, outputPath);
17058
17240
  const merged = mergeRowsForCsvExport(rowsInfo.rows, options);
@@ -17068,10 +17250,14 @@ async function writeOutputCsv(outputPath, status, options) {
17068
17250
  csvStringFromRows(merged.rows, columns),
17069
17251
  "utf8"
17070
17252
  );
17253
+ const sourceCsvRows = options?.sourceCsvPath ? readCsvRows(options.sourceCsvPath).length : null;
17071
17254
  return {
17255
+ sourceCsvRows,
17256
+ selectedRows: rowsInfo.totalRows,
17257
+ enrichedRows: rowsInfo.rows.length,
17072
17258
  rows: merged.rows.length,
17073
17259
  path: resolve11(outputPath),
17074
- enrichedRows: rowsInfo.rows
17260
+ enrichedDataRows: rowsInfo.rows
17075
17261
  };
17076
17262
  }
17077
17263
  function recordField(value, key) {
@@ -17152,12 +17338,12 @@ function collectHardFailureAliases(config) {
17152
17338
  }
17153
17339
  function cellFailureError(value) {
17154
17340
  const parsed = parseMaybeJsonObject(value);
17155
- if (!isRecord6(parsed)) {
17341
+ if (!isRecord7(parsed)) {
17156
17342
  return null;
17157
17343
  }
17158
17344
  const status = typeof parsed.status === "string" ? parsed.status.trim().toLowerCase() : "";
17159
17345
  const directError = typeof parsed.error === "string" ? parsed.error.trim() : typeof parsed.last_error === "string" ? parsed.last_error.trim() : "";
17160
- const result = isRecord6(parsed.result) ? parsed.result : null;
17346
+ const result = isRecord7(parsed.result) ? parsed.result : null;
17161
17347
  const resultError = typeof result?.error === "string" ? result.error.trim() : typeof result?.message === "string" ? result.message.trim() : "";
17162
17348
  if (!directError && !resultError && status !== "error" && status !== "failed") {
17163
17349
  return null;
@@ -17223,6 +17409,136 @@ function collectEnrichFailureJobs(input2) {
17223
17409
  });
17224
17410
  return jobs;
17225
17411
  }
17412
+ function parseExecutionCount(value) {
17413
+ if (typeof value === "number" && Number.isFinite(value)) {
17414
+ return Math.max(0, Math.trunc(value));
17415
+ }
17416
+ if (typeof value !== "string") {
17417
+ return null;
17418
+ }
17419
+ const match = value.trim().match(/^(\d+)\s*\//);
17420
+ return match?.[1] ? Number.parseInt(match[1], 10) : null;
17421
+ }
17422
+ function executionSummaryText(count, total) {
17423
+ const percent = total > 0 ? Math.round(count / total * 100) : 0;
17424
+ return `${count}/${total} (${percent}%)`;
17425
+ }
17426
+ function collectColumnStats(status) {
17427
+ const summaries = [];
17428
+ const visit = (value) => {
17429
+ if (Array.isArray(value)) {
17430
+ value.forEach(visit);
17431
+ return;
17432
+ }
17433
+ if (!isRecord7(value)) {
17434
+ return;
17435
+ }
17436
+ if (isRecord7(value.columnStats)) {
17437
+ summaries.push(value.columnStats);
17438
+ }
17439
+ Object.values(value).forEach(visit);
17440
+ };
17441
+ visit(status);
17442
+ return summaries;
17443
+ }
17444
+ function firstAliasExecutionCounts(input2) {
17445
+ const aliases = collectConfigScalarAliasOrder(input2.config);
17446
+ const summaries = collectColumnStats(input2.status);
17447
+ for (const alias of aliases) {
17448
+ const stat4 = summaries.map((summary) => summary[alias]).find(isRecord7);
17449
+ if (!stat4) continue;
17450
+ if (input2.forceAliases.has(normalizeAlias2(alias))) {
17451
+ return { executed: input2.selectedRows, reused: 0 };
17452
+ }
17453
+ const execution = isRecord7(stat4.execution) ? stat4.execution : null;
17454
+ if (!execution) continue;
17455
+ return {
17456
+ executed: parseExecutionCount(execution["completed:executed"]),
17457
+ reused: parseExecutionCount(execution["completed:reused"])
17458
+ };
17459
+ }
17460
+ return { executed: null, reused: null };
17461
+ }
17462
+ function rewriteEnrichJsonStatus(input2) {
17463
+ const selectedRows = input2.output?.selectedRows ?? extractCanonicalRowsInfo(input2.status)?.totalRows ?? 0;
17464
+ const failedRows = new Set(
17465
+ input2.failureReport?.jobs.map((job) => job.row_id) ?? []
17466
+ ).size;
17467
+ const executionCounts = firstAliasExecutionCounts({
17468
+ status: input2.status,
17469
+ config: input2.config,
17470
+ forceAliases: input2.forceAliases,
17471
+ selectedRows
17472
+ });
17473
+ const forcedAliases = new Set(
17474
+ collectConfigScalarAliasOrder(input2.config).filter((alias) => input2.forceAliases.has(normalizeAlias2(alias))).map((alias) => alias)
17475
+ );
17476
+ const rewrite = (value) => {
17477
+ if (Array.isArray(value)) {
17478
+ return value.map(rewrite);
17479
+ }
17480
+ if (!isRecord7(value)) {
17481
+ return value;
17482
+ }
17483
+ const next = {};
17484
+ for (const [key, entry] of Object.entries(value)) {
17485
+ next[key] = rewrite(entry);
17486
+ }
17487
+ if (isRecord7(next.progress)) {
17488
+ next.progress = {
17489
+ ...next.progress,
17490
+ ...selectedRows > 0 ? { total: selectedRows } : {},
17491
+ ...executionCounts.executed !== null ? { executed: executionCounts.executed } : {},
17492
+ ...executionCounts.reused !== null ? { reused: executionCounts.reused } : {},
17493
+ ...failedRows > 0 ? { failed: failedRows, pending: 0 } : {}
17494
+ };
17495
+ }
17496
+ if (isRecord7(next.summary)) {
17497
+ const rowCounts = isRecord7(next.summary.rowCounts) ? next.summary.rowCounts : null;
17498
+ if (failedRows > 0) {
17499
+ next.summary = {
17500
+ ...next.summary,
17501
+ rowCounts: {
17502
+ ...rowCounts ?? {},
17503
+ persisted: selectedRows,
17504
+ succeeded: Math.max(0, selectedRows - failedRows),
17505
+ failed: failedRows
17506
+ }
17507
+ };
17508
+ }
17509
+ }
17510
+ if (isRecord7(next.columnStats) && selectedRows > 0) {
17511
+ const columnStats = { ...next.columnStats };
17512
+ for (const alias of forcedAliases) {
17513
+ const stat4 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
17514
+ const execution = isRecord7(stat4?.execution) ? stat4.execution : null;
17515
+ if (!stat4 || !execution) continue;
17516
+ columnStats[alias] = {
17517
+ ...stat4,
17518
+ execution: {
17519
+ ...execution,
17520
+ "completed:executed": executionSummaryText(
17521
+ selectedRows,
17522
+ selectedRows
17523
+ ),
17524
+ "completed:reused": executionSummaryText(0, selectedRows)
17525
+ }
17526
+ };
17527
+ }
17528
+ next.columnStats = columnStats;
17529
+ }
17530
+ return next;
17531
+ };
17532
+ const rewritten = rewrite(input2.status);
17533
+ if (failedRows === 0 || !isRecord7(rewritten)) {
17534
+ return rewritten;
17535
+ }
17536
+ return {
17537
+ ...rewritten,
17538
+ ...rewritten.status === "completed" ? { status: "failed" } : {},
17539
+ ...isRecord7(rewritten.run) && rewritten.run.status === "completed" ? { run: { ...rewritten.run, status: "failed" } } : {}
17540
+ };
17541
+ }
17226
17542
  function summarizeFailedJobError(value) {
17227
17543
  const text = String(value ?? "").trim();
17228
17544
  return text.length > 500 ? `${text.slice(0, 497)}...` : text;
@@ -17491,11 +17807,11 @@ function normalizeEnrichRowsForCsvExport(rows) {
17491
17807
  }
17492
17808
  function legacyMetadataFromRow(row) {
17493
17809
  const direct = parseLegacyMetadataCell(row._metadata);
17494
- if (direct && isRecord6(direct.columns)) {
17810
+ if (direct && isRecord7(direct.columns)) {
17495
17811
  return direct;
17496
17812
  }
17497
17813
  const relocated = parseLegacyMetadataCell(row.metadata);
17498
- if (relocated && isRecord6(relocated.columns)) {
17814
+ if (relocated && isRecord7(relocated.columns)) {
17499
17815
  return relocated;
17500
17816
  }
17501
17817
  const flattenedColumns = parseLegacyMetadataCell(row["metadata.columns"]);
@@ -17512,7 +17828,7 @@ function legacyMetadataFromRow(row) {
17512
17828
  }
17513
17829
  function parseLegacyMetadataCell(value) {
17514
17830
  const parsed = parseMaybeJsonObject(value);
17515
- if (isRecord6(parsed)) {
17831
+ if (isRecord7(parsed)) {
17516
17832
  return parsed;
17517
17833
  }
17518
17834
  if (typeof value !== "string") {
@@ -17529,12 +17845,12 @@ function parseLegacyMetadataCell(value) {
17529
17845
  for (const candidate of candidates) {
17530
17846
  try {
17531
17847
  const decoded = JSON.parse(candidate);
17532
- if (isRecord6(decoded)) {
17848
+ if (isRecord7(decoded)) {
17533
17849
  return decoded;
17534
17850
  }
17535
17851
  if (typeof decoded === "string") {
17536
17852
  const nested = JSON.parse(decoded);
17537
- if (isRecord6(nested)) {
17853
+ if (isRecord7(nested)) {
17538
17854
  return nested;
17539
17855
  }
17540
17856
  }
@@ -17544,8 +17860,8 @@ function parseLegacyMetadataCell(value) {
17544
17860
  return null;
17545
17861
  }
17546
17862
  function mergeLegacyMetadataRecords(base, enriched) {
17547
- const baseColumns = isRecord6(base.columns) ? base.columns : null;
17548
- const enrichedColumns = isRecord6(enriched.columns) ? enriched.columns : null;
17863
+ const baseColumns = isRecord7(base.columns) ? base.columns : null;
17864
+ const enrichedColumns = isRecord7(enriched.columns) ? enriched.columns : null;
17549
17865
  const merged = {
17550
17866
  ...base,
17551
17867
  ...enriched
@@ -17747,7 +18063,7 @@ function registerEnrichCommand(program) {
17747
18063
  sourceCsvPath,
17748
18064
  rows
17749
18065
  }) : null;
17750
- const rowsForFailureReport = exportResult?.enrichedRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
18066
+ const rowsForFailureReport = exportResult?.enrichedDataRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
17751
18067
  if (options.json) {
17752
18068
  const failureReport2 = await maybeEmitEnrichFailureReport({
17753
18069
  config,
@@ -17756,10 +18072,22 @@ function registerEnrichCommand(program) {
17756
18072
  client: client2,
17757
18073
  outputPath: exportResult?.path ?? outputPath ?? null
17758
18074
  });
18075
+ const run = rewriteEnrichJsonStatus({
18076
+ status,
18077
+ config,
18078
+ forceAliases,
18079
+ output: exportResult,
18080
+ failureReport: failureReport2
18081
+ });
17759
18082
  printJson({
17760
18083
  ok: !failureReport2,
17761
- run: status,
17762
- output: exportResult ? { rows: exportResult.rows, path: exportResult.path } : null,
18084
+ run,
18085
+ output: exportResult ? {
18086
+ sourceCsvRows: exportResult.sourceCsvRows,
18087
+ selectedRows: exportResult.selectedRows,
18088
+ enrichedRows: exportResult.enrichedRows,
18089
+ path: exportResult.path
18090
+ } : null,
17763
18091
  ...failureReport2 ? {
17764
18092
  failure_report: {
17765
18093
  path: failureReport2.path,
@@ -17779,7 +18107,7 @@ function registerEnrichCommand(program) {
17779
18107
  );
17780
18108
  const waterfallSummaryLines = buildEnrichWaterfallSummaryLines(
17781
18109
  config,
17782
- exportResult.enrichedRows
18110
+ exportResult.enrichedDataRows
17783
18111
  );
17784
18112
  if (waterfallSummaryLines.length > 0) {
17785
18113
  process.stdout.write(`${waterfallSummaryLines.join("\n")}
@@ -17846,6 +18174,129 @@ Examples:
17846
18174
  ).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);
17847
18175
  }
17848
18176
 
18177
+ // src/cli/commands/legacy-noops.ts
18178
+ var SESSION_SUBCOMMANDS = [
18179
+ "start",
18180
+ "status",
18181
+ "output",
18182
+ "alert",
18183
+ "usage",
18184
+ "limit",
18185
+ "render",
18186
+ "send"
18187
+ ];
18188
+ var BACKEND_SUBCOMMANDS = [
18189
+ "start",
18190
+ "stop",
18191
+ "status",
18192
+ "refresh-runtime",
18193
+ "sync-runtime"
18194
+ ];
18195
+ function legacyNoopEnvelope(input2) {
18196
+ const command = [
18197
+ "deepline",
18198
+ input2.family,
18199
+ input2.subcommand
18200
+ ].filter(Boolean).join(" ");
18201
+ const subject = input2.family === "session" ? "Legacy Session UI/playground command" : "Legacy local playground backend command";
18202
+ 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.";
18203
+ return {
18204
+ ok: true,
18205
+ noop: true,
18206
+ command,
18207
+ compatibility: {
18208
+ family: "legacy_python_cli",
18209
+ sdk_behavior: "noop"
18210
+ },
18211
+ render: {
18212
+ sections: [
18213
+ {
18214
+ title: subject,
18215
+ lines: [note]
18216
+ }
18217
+ ]
18218
+ }
18219
+ };
18220
+ }
18221
+ function printLegacyNoop(input2) {
18222
+ printCommandEnvelope(legacyNoopEnvelope(input2), { json: input2.options.json });
18223
+ }
18224
+ function legacySubcommandFromArgv(family) {
18225
+ const args = process.argv.slice(2);
18226
+ const familyIndex = args.indexOf(family);
18227
+ const nextToken = familyIndex >= 0 ? args[familyIndex + 1] : void 0;
18228
+ return nextToken && !nextToken.startsWith("-") ? nextToken : void 0;
18229
+ }
18230
+ function addLegacyNoopSubcommand(parent, family, subcommand, description) {
18231
+ parent.command(subcommand).description(description).allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").action((_args, options) => {
18232
+ printLegacyNoop({ family, subcommand, options });
18233
+ });
18234
+ }
18235
+ function registerLegacyNoopCommands(program) {
18236
+ const session = program.command("session").description(
18237
+ "Compatibility no-ops for legacy Python Session UI commands."
18238
+ ).allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
18239
+ "after",
18240
+ `
18241
+ Notes:
18242
+ The SDK CLI accepts singular session commands from older agent skills so they
18243
+ do not fail, but it does not manage the legacy Python Session UI.
18244
+ Use "deepline sessions send" or "deepline sessions render" for real SDK
18245
+ transcript workflows.
18246
+
18247
+ Examples:
18248
+ deepline session start --steps '["Inspect CSV","Run pilot"]'
18249
+ deepline session status --message "Running pilot"
18250
+ deepline session output --csv ./results.csv --label "Results"
18251
+ `
18252
+ ).action((args, options) => {
18253
+ void args;
18254
+ printLegacyNoop({
18255
+ family: "session",
18256
+ subcommand: legacySubcommandFromArgv("session"),
18257
+ options
18258
+ });
18259
+ });
18260
+ for (const subcommand of SESSION_SUBCOMMANDS) {
18261
+ addLegacyNoopSubcommand(
18262
+ session,
18263
+ "session",
18264
+ subcommand,
18265
+ `Accept legacy "deepline session ${subcommand}" as an SDK no-op.`
18266
+ );
18267
+ }
18268
+ const backend = program.command("backend").description(
18269
+ "Compatibility no-ops for legacy Python local backend commands."
18270
+ ).allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
18271
+ "after",
18272
+ `
18273
+ Notes:
18274
+ The SDK CLI uses the configured Deepline host and V2 play runtime. It does not
18275
+ start, stop, or refresh the legacy Python local playground backend.
18276
+
18277
+ Examples:
18278
+ deepline backend start
18279
+ deepline backend stop --just-backend
18280
+ deepline backend status --json
18281
+ `
18282
+ ).action((args, options) => {
18283
+ void args;
18284
+ printLegacyNoop({
18285
+ family: "backend",
18286
+ subcommand: legacySubcommandFromArgv("backend"),
18287
+ options
18288
+ });
18289
+ });
18290
+ for (const subcommand of BACKEND_SUBCOMMANDS) {
18291
+ addLegacyNoopSubcommand(
18292
+ backend,
18293
+ "backend",
18294
+ subcommand,
18295
+ `Accept legacy "deepline backend ${subcommand}" as an SDK no-op.`
18296
+ );
18297
+ }
18298
+ }
18299
+
17849
18300
  // src/cli/commands/org.ts
17850
18301
  async function fetchOrganizations(http, apiKey) {
17851
18302
  return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
@@ -19761,11 +20212,13 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
19761
20212
  "deeplineUsdPerPricingUnit",
19762
20213
  "deepline_usd_per_pricing_unit"
19763
20214
  );
19764
- const starterScript = seedToolListScript({
19765
- toolId,
19766
- payload: samplePayloadForInputFields(inputFields),
19767
- rows: []
19768
- });
20215
+ const starterScript = extractedLists.length > 0 ? starterScriptJson(
20216
+ seedToolListScript({
20217
+ toolId,
20218
+ payload: samplePayloadForInputFields(inputFields),
20219
+ rows: []
20220
+ })
20221
+ ) : null;
19769
20222
  return {
19770
20223
  schemaVersion: 1,
19771
20224
  toolId,
@@ -19791,20 +20244,12 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
19791
20244
  extractedValues
19792
20245
  },
19793
20246
  executeCommand: `deepline tools execute ${toolId} --input '{...}' --json`,
19794
- starterScript: {
19795
- path: starterScript.path,
19796
- sourceCode: starterScript.sourceCode,
19797
- projectDir: starterScript.projectDir,
19798
- copyToProject: {
19799
- macosLinux: starterScript.macCopyCommand,
19800
- windowsPowerShell: starterScript.windowsCopyCommand
19801
- }
19802
- }
20247
+ ...starterScript ? { starterScript } : {}
19803
20248
  };
19804
20249
  }
19805
20250
  function extractionContractEntries(entries) {
19806
20251
  return entries.flatMap((entry) => {
19807
- if (!isRecord7(entry)) return [];
20252
+ if (!isRecord8(entry)) return [];
19808
20253
  const name = stringField(entry, "name");
19809
20254
  const expression = stringField(entry, "expression");
19810
20255
  return name && expression ? [{ name, expression }] : [];
@@ -19812,8 +20257,8 @@ function extractionContractEntries(entries) {
19812
20257
  }
19813
20258
  function printCompactToolContract(tool, requestedToolId) {
19814
20259
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
19815
- const cost = isRecord7(contract.cost) ? contract.cost : {};
19816
- const getters = isRecord7(contract.getters) ? contract.getters : {};
20260
+ const cost = isRecord8(contract.cost) ? contract.cost : {};
20261
+ const getters = isRecord8(contract.getters) ? contract.getters : {};
19817
20262
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
19818
20263
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
19819
20264
  const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
@@ -19830,7 +20275,7 @@ function printCompactToolContract(tool, requestedToolId) {
19830
20275
  console.log("");
19831
20276
  console.log("Inputs:");
19832
20277
  for (const field of inputFields) {
19833
- if (!isRecord7(field)) continue;
20278
+ if (!isRecord8(field)) continue;
19834
20279
  const name = stringField(field, "name");
19835
20280
  if (!name) continue;
19836
20281
  const required = field.required ? "*" : "";
@@ -19843,7 +20288,7 @@ function printCompactToolContract(tool, requestedToolId) {
19843
20288
  }
19844
20289
  console.log("");
19845
20290
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
19846
- const starterScript = isRecord7(contract.starterScript) ? contract.starterScript : {};
20291
+ const starterScript = isRecord8(contract.starterScript) ? contract.starterScript : {};
19847
20292
  const starterPath = stringField(starterScript, "path");
19848
20293
  if (starterPath) {
19849
20294
  console.log("");
@@ -19857,14 +20302,14 @@ function printCompactToolContract(tool, requestedToolId) {
19857
20302
  console.log("Getters:");
19858
20303
  if (listGetters.length) console.log("Lists:");
19859
20304
  for (const entry of listGetters) {
19860
- if (isRecord7(entry))
20305
+ if (isRecord8(entry))
19861
20306
  console.log(
19862
20307
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19863
20308
  );
19864
20309
  }
19865
20310
  if (valueGetters.length) console.log("Values:");
19866
20311
  for (const entry of valueGetters) {
19867
- if (isRecord7(entry))
20312
+ if (isRecord8(entry))
19868
20313
  console.log(
19869
20314
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19870
20315
  );
@@ -19877,7 +20322,7 @@ function printCompactToolContract(tool, requestedToolId) {
19877
20322
  }
19878
20323
  function printToolPricingOnly(tool, requestedToolId, options = {}) {
19879
20324
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
19880
- const cost = isRecord7(contract.cost) ? contract.cost : {};
20325
+ const cost = isRecord8(contract.cost) ? contract.cost : {};
19881
20326
  const pricingModel = stringField(cost, "pricingModel") || "unknown";
19882
20327
  const billingMode = stringField(cost, "billingMode") || "unknown";
19883
20328
  const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
@@ -19897,7 +20342,7 @@ function printToolSchemaOnly(tool, requestedToolId) {
19897
20342
  }
19898
20343
  console.log("Inputs:");
19899
20344
  for (const field of inputFields) {
19900
- if (!isRecord7(field)) continue;
20345
+ if (!isRecord8(field)) continue;
19901
20346
  const name = stringField(field, "name");
19902
20347
  if (!name) continue;
19903
20348
  const required = field.required ? "*" : "";
@@ -19923,10 +20368,10 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
19923
20368
  ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
19924
20369
  );
19925
20370
  console.log("});");
19926
- const getters = isRecord7(contract.getters) ? contract.getters : {};
20371
+ const getters = isRecord8(contract.getters) ? contract.getters : {};
19927
20372
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
19928
20373
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
19929
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord7);
20374
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord8);
19930
20375
  if (firstGetter) {
19931
20376
  const name = stringField(firstGetter, "name") || "value";
19932
20377
  const expression = stringField(firstGetter, "expression");
@@ -19943,7 +20388,7 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
19943
20388
  }
19944
20389
  function printToolGettersOnly(tool, requestedToolId) {
19945
20390
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
19946
- const getters = isRecord7(contract.getters) ? contract.getters : {};
20391
+ const getters = isRecord8(contract.getters) ? contract.getters : {};
19947
20392
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
19948
20393
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
19949
20394
  console.log(`Getters: ${contract.toolId}`);
@@ -19956,7 +20401,7 @@ function printToolGettersOnly(tool, requestedToolId) {
19956
20401
  if (listGetters.length) {
19957
20402
  console.log("Lists:");
19958
20403
  for (const entry of listGetters) {
19959
- if (isRecord7(entry))
20404
+ if (isRecord8(entry))
19960
20405
  console.log(
19961
20406
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19962
20407
  );
@@ -19965,7 +20410,7 @@ function printToolGettersOnly(tool, requestedToolId) {
19965
20410
  if (valueGetters.length) {
19966
20411
  console.log("Values:");
19967
20412
  for (const entry of valueGetters) {
19968
- if (isRecord7(entry))
20413
+ if (isRecord8(entry))
19969
20414
  console.log(
19970
20415
  `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
19971
20416
  );
@@ -19991,7 +20436,7 @@ function sampleValueForField(field) {
19991
20436
  function samplePayloadForInputFields(fields) {
19992
20437
  return Object.fromEntries(
19993
20438
  fields.slice(0, 4).flatMap((field) => {
19994
- if (!isRecord7(field)) return [];
20439
+ if (!isRecord8(field)) return [];
19995
20440
  const name = stringField(field, "name");
19996
20441
  if (!name) return [];
19997
20442
  return [[name, sampleValueForField(field)]];
@@ -20016,11 +20461,24 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
20016
20461
  const inputFields = toolInputFieldsForDisplay(
20017
20462
  recordField2(tool, "inputSchema", "input_schema")
20018
20463
  );
20019
- const starterScript = seedToolListScript({
20020
- toolId,
20021
- payload: samplePayloadForInputFields(inputFields),
20022
- rows: []
20023
- });
20464
+ const usageGuidance = usageGuidanceWithAccessDefaults(
20465
+ recordField2(tool, "usageGuidance", "usage_guidance")
20466
+ );
20467
+ const toolExecutionResult = recordField2(
20468
+ usageGuidance,
20469
+ "toolExecutionResult",
20470
+ "tool_execution_result"
20471
+ );
20472
+ const extractedLists = extractionContractEntries(
20473
+ arrayField(toolExecutionResult, "extractedLists", "extracted_lists")
20474
+ );
20475
+ const starterScript = extractedLists.length > 0 ? starterScriptJson(
20476
+ seedToolListScript({
20477
+ toolId,
20478
+ payload: samplePayloadForInputFields(inputFields),
20479
+ rows: []
20480
+ })
20481
+ ) : null;
20024
20482
  const {
20025
20483
  cost: _cost,
20026
20484
  deeplineCreditsPerPricingUnit: _deeplineCreditsPerPricingUnit,
@@ -20040,9 +20498,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
20040
20498
  toolId,
20041
20499
  provider: tool.provider,
20042
20500
  displayName: tool.displayName,
20043
- usageGuidance: usageGuidanceWithAccessDefaults(
20044
- recordField2(tool, "usageGuidance", "usage_guidance")
20045
- ),
20501
+ usageGuidance,
20046
20502
  runtimeOutputHelp: {
20047
20503
  contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
20048
20504
  getterScope: "extractedValues/extractedLists .get() only works for declared Deepline getters listed in usageGuidance.toolExecutionResult.",
@@ -20053,15 +20509,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
20053
20509
  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.",
20054
20510
  executeOutputFields: "tools execute JSON may include output_preview for this direct probe only; play debugging uses run output and returned dataset handles."
20055
20511
  },
20056
- starterScript: {
20057
- path: starterScript.path,
20058
- sourceCode: starterScript.sourceCode,
20059
- projectDir: starterScript.projectDir,
20060
- copyToProject: {
20061
- macosLinux: starterScript.macCopyCommand,
20062
- windowsPowerShell: starterScript.windowsCopyCommand
20063
- }
20064
- }
20512
+ ...starterScript ? { starterScript } : {}
20065
20513
  };
20066
20514
  }
20067
20515
  function usageGuidanceWithAccessDefaults(usageGuidance) {
@@ -20105,12 +20553,12 @@ function formatListedToolCost(tool) {
20105
20553
  }
20106
20554
  function toolInputFieldsForDisplay(inputSchema) {
20107
20555
  if (Array.isArray(inputSchema.fields))
20108
- return inputSchema.fields.filter(isRecord7);
20109
- const jsonSchema = isRecord7(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
20110
- const properties = isRecord7(jsonSchema.properties) ? jsonSchema.properties : {};
20556
+ return inputSchema.fields.filter(isRecord8);
20557
+ const jsonSchema = isRecord8(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
20558
+ const properties = isRecord8(jsonSchema.properties) ? jsonSchema.properties : {};
20111
20559
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
20112
20560
  return Object.entries(properties).map(([name, value]) => {
20113
- const property = isRecord7(value) ? value : {};
20561
+ const property = isRecord8(value) ? value : {};
20114
20562
  return {
20115
20563
  name,
20116
20564
  type: typeof property.type === "string" ? property.type : "unknown",
@@ -20139,15 +20587,15 @@ function printJsonPreview(label, payload) {
20139
20587
  }
20140
20588
  function samplePayload(samples, key) {
20141
20589
  const entry = samples[key];
20142
- if (!isRecord7(entry)) return void 0;
20590
+ if (!isRecord8(entry)) return void 0;
20143
20591
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
20144
20592
  }
20145
20593
  function commandEnvelopeFromRawResponse(rawResponse) {
20146
- return isRecord7(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
20594
+ return isRecord8(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
20147
20595
  }
20148
20596
  function listExtractorPathsFromUsageGuidance(tool) {
20149
20597
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
20150
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord7(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
20598
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord8(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
20151
20599
  return extractedLists.flatMap((entry) => {
20152
20600
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
20153
20601
  if (!Array.isArray(paths)) return [];
@@ -20163,7 +20611,7 @@ function formatDecimal(value) {
20163
20611
  function formatUsd(value) {
20164
20612
  return `$${formatDecimal(value)}`;
20165
20613
  }
20166
- function isRecord7(value) {
20614
+ function isRecord8(value) {
20167
20615
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
20168
20616
  }
20169
20617
  function stringField(source, ...keys) {
@@ -20190,7 +20638,7 @@ function arrayField(source, ...keys) {
20190
20638
  function recordField2(source, ...keys) {
20191
20639
  for (const key of keys) {
20192
20640
  const value = source[key];
20193
- if (isRecord7(value)) return value;
20641
+ if (isRecord8(value)) return value;
20194
20642
  }
20195
20643
  return {};
20196
20644
  }
@@ -20256,7 +20704,7 @@ function parseJsonObjectArgument(raw, flagName) {
20256
20704
  }
20257
20705
  throw invalidJsonError(flagName, message);
20258
20706
  }
20259
- if (!isRecord7(parsed)) {
20707
+ if (!isRecord8(parsed)) {
20260
20708
  throw invalidJsonError(flagName, "expected an object.");
20261
20709
  }
20262
20710
  return parsed;
@@ -20315,6 +20763,17 @@ function shellQuote2(value) {
20315
20763
  function powerShellQuote(value) {
20316
20764
  return `'${value.replace(/'/g, "''")}'`;
20317
20765
  }
20766
+ function starterScriptJson(script) {
20767
+ return {
20768
+ path: script.path,
20769
+ sourceCode: script.sourceCode,
20770
+ projectDir: script.projectDir,
20771
+ copyToProject: {
20772
+ macosLinux: script.macCopyCommand,
20773
+ windowsPowerShell: script.windowsCopyCommand
20774
+ }
20775
+ };
20776
+ }
20318
20777
  function seedToolListScript(input2) {
20319
20778
  const stem = safeFileStem(input2.toolId);
20320
20779
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
@@ -20379,7 +20838,7 @@ function buildToolExecuteBaseEnvelope(input2) {
20379
20838
  kind: summaryEntries.length > 0 ? "object" : "raw",
20380
20839
  summary: input2.summary
20381
20840
  };
20382
- const envelopeHasCanonicalOutput = isRecord7(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
20841
+ const envelopeHasCanonicalOutput = isRecord8(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
20383
20842
  const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote2(JSON.stringify(input2.params))} --json`;
20384
20843
  const actions = input2.listConversion ? [
20385
20844
  {
@@ -20488,7 +20947,7 @@ async function executeTool(args) {
20488
20947
  {
20489
20948
  ...baseEnvelope,
20490
20949
  local: {
20491
- ...isRecord7(baseEnvelope.local) ? baseEnvelope.local : {},
20950
+ ...isRecord8(baseEnvelope.local) ? baseEnvelope.local : {},
20492
20951
  payload_file: jsonPath
20493
20952
  }
20494
20953
  },
@@ -21248,10 +21707,6 @@ var command_compatibility_default = {
21248
21707
  label: "a legacy Python CLI workflow command",
21249
21708
  sdk_alternative: "Use `deepline plays ...` in the SDK CLI."
21250
21709
  },
21251
- backend: {
21252
- family: "python",
21253
- label: "a legacy Python CLI playground backend command"
21254
- },
21255
21710
  events: {
21256
21711
  family: "python",
21257
21712
  label: "a legacy Python CLI event command"
@@ -21487,7 +21942,11 @@ import { homedir as homedir7 } from "os";
21487
21942
  import { dirname as dirname12, join as join14 } from "path";
21488
21943
  var CHECK_TIMEOUT_MS2 = 3e3;
21489
21944
  var SDK_SKILL_NAME = "deepline-plays";
21490
- var SDK_SKILL_NAMES = [SDK_SKILL_NAME, "deepline-plays-quickstart"];
21945
+ var SDK_SKILL_NAMES = [
21946
+ SDK_SKILL_NAME,
21947
+ "deepline-plays-feedback",
21948
+ "deepline-plays-quickstart"
21949
+ ];
21491
21950
  var attemptedSync = false;
21492
21951
  function shouldSkipSkillsSync() {
21493
21952
  const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
@@ -21709,7 +22168,9 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
21709
22168
  if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
21710
22169
  return;
21711
22170
  }
21712
- writeSdkSkillsStatusLine("SDK skills changed; syncing Deepline SDK skills...");
22171
+ writeSdkSkillsStatusLine(
22172
+ "SDK skills changed; syncing Deepline SDK skills..."
22173
+ );
21713
22174
  const installed = await runSkillsInstall(baseUrl);
21714
22175
  if (!installed) return;
21715
22176
  if (installedSdkSkillHasStalePositionalExecuteExamples()) {
@@ -21749,6 +22210,19 @@ function shouldDeferSkillsSyncForCommand() {
21749
22210
  const subcommand = args[1];
21750
22211
  return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
21751
22212
  }
22213
+ function isLegacyNoopInvocation() {
22214
+ const command = process.argv.slice(2)[0];
22215
+ return command === "session" || command === "backend";
22216
+ }
22217
+ function topLevelCommandKnown(program, commandName) {
22218
+ const normalized = commandName.trim();
22219
+ if (!normalized || normalized.startsWith("-")) {
22220
+ return true;
22221
+ }
22222
+ return program.commands.some(
22223
+ (command) => command.name() === normalized || command.aliases().includes(normalized)
22224
+ );
22225
+ }
21752
22226
  async function runPlayRunnerHealthCheck() {
21753
22227
  const dir = await mkdtemp2(join15(tmpdir5(), "deepline-health-play-"));
21754
22228
  const file = join15(dir, "health-check.play.ts");
@@ -21968,7 +22442,7 @@ Exit codes:
21968
22442
  `
21969
22443
  );
21970
22444
  program.hook("preAction", async (_thisCommand, actionCommand) => {
21971
- if (actionCommand.name() === "version" || actionCommand.name() === "update") {
22445
+ if (actionCommand.name() === "version" || actionCommand.name() === "update" || isLegacyNoopInvocation()) {
21972
22446
  return;
21973
22447
  }
21974
22448
  if (printStartupPhase) {
@@ -21985,9 +22459,7 @@ Exit codes:
21985
22459
  if (compatibility.error) {
21986
22460
  return;
21987
22461
  }
21988
- const relaunched = await maybeAutoUpdateAndRelaunch(
21989
- compatibility.response
21990
- );
22462
+ const relaunched = await maybeAutoUpdateAndRelaunch(compatibility.response);
21991
22463
  if (relaunched) {
21992
22464
  return;
21993
22465
  }
@@ -22015,6 +22487,7 @@ Exit codes:
22015
22487
  registerCsvCommands(program);
22016
22488
  registerDbCommands(program);
22017
22489
  registerFeedbackCommands(program);
22490
+ registerLegacyNoopCommands(program);
22018
22491
  registerUpdateCommand(program);
22019
22492
  registerQuickstartCommands(program);
22020
22493
  program.command("preflight").description("Run compact health, auth, and Deepline billing checks.").option("--json", "Force JSON output.").addHelpText(
@@ -22115,6 +22588,20 @@ Examples:
22115
22588
  process.exitCode = 2;
22116
22589
  return;
22117
22590
  }
22591
+ const requestedTopLevelCommand = process.argv.slice(2)[0] ?? "";
22592
+ if (!topLevelCommandKnown(program, requestedTopLevelCommand)) {
22593
+ console.error(`error: unknown command '${requestedTopLevelCommand}'`);
22594
+ const hint = commandCompatibilityHint(
22595
+ "sdk",
22596
+ requestedTopLevelCommand,
22597
+ autoDetectBaseUrl()
22598
+ );
22599
+ if (hint && !process.argv.includes("--json")) {
22600
+ console.error(hint);
22601
+ }
22602
+ process.exitCode = 2;
22603
+ return;
22604
+ }
22118
22605
  try {
22119
22606
  await program.parseAsync(process.argv);
22120
22607
  recordCliTrace({