deepline 0.1.83 → 0.1.88

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
@@ -229,10 +229,10 @@ var import_node_path2 = require("path");
229
229
 
230
230
  // src/release.ts
231
231
  var SDK_RELEASE = {
232
- version: "0.1.83",
232
+ version: "0.1.88",
233
233
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
234
234
  supportPolicy: {
235
- latest: "0.1.83",
235
+ latest: "0.1.88",
236
236
  minimumSupported: "0.1.53",
237
237
  deprecatedBelow: "0.1.53"
238
238
  }
@@ -246,6 +246,7 @@ var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
246
246
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
247
247
  var COORDINATOR_URL_OVERRIDE_HEADER = "x-deepline-coordinator-url";
248
248
  var WORKER_CALLBACK_URL_OVERRIDE_HEADER = "x-deepline-worker-callback-url";
249
+ var SYNTHETIC_RUN_HEADER = "x-deepline-synthetic-run";
249
250
 
250
251
  // src/http.ts
251
252
  var MAX_DIAGNOSTIC_HEADER_LENGTH = 120;
@@ -313,6 +314,10 @@ var HttpClient = class {
313
314
  if (workerCallbackUrl?.trim()) {
314
315
  headers[WORKER_CALLBACK_URL_OVERRIDE_HEADER] = workerCallbackUrl.trim();
315
316
  }
317
+ const syntheticRun = typeof process !== "undefined" ? process.env?.DEEPLINE_SYNTHETIC_RUN : void 0;
318
+ if (syntheticRun && syntheticRun.trim() && syntheticRun.trim() !== "0") {
319
+ headers[SYNTHETIC_RUN_HEADER] = "1";
320
+ }
316
321
  return headers;
317
322
  }
318
323
  /**
@@ -579,7 +584,7 @@ function decodeSseFrame(frame) {
579
584
  return parsed;
580
585
  }
581
586
  function sleep(ms) {
582
- return new Promise((resolve13) => setTimeout(resolve13, ms));
587
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
583
588
  }
584
589
 
585
590
  // src/client.ts
@@ -589,7 +594,7 @@ var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
589
594
  var V2_EXECUTE_RESPONSE_CONTRACT = "v2-tool-response";
590
595
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
591
596
  function sleep2(ms) {
592
- return new Promise((resolve13) => setTimeout(resolve13, ms));
597
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
593
598
  }
594
599
  function isTransientCompileManifestError(error) {
595
600
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -603,6 +608,21 @@ function isTransientCompileManifestError(error) {
603
608
  function isRecord(value) {
604
609
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
605
610
  }
611
+ function isPrebuiltPlayDescription(play) {
612
+ return play.origin === "prebuilt" || play.ownerType === "deepline";
613
+ }
614
+ function preferPrebuiltPlayDescriptions(plays) {
615
+ const prebuilt = [];
616
+ const owned = [];
617
+ for (const play of plays) {
618
+ if (isPrebuiltPlayDescription(play)) {
619
+ prebuilt.push(play);
620
+ } else {
621
+ owned.push(play);
622
+ }
623
+ }
624
+ return [...prebuilt, ...owned];
625
+ }
606
626
  function isPlayRunPackage(value) {
607
627
  return Boolean(
608
628
  value && typeof value === "object" && !Array.isArray(value) && value.kind === "play_run" && value.run && typeof value.run?.id === "string"
@@ -726,8 +746,14 @@ function playRunStatusFromState(state) {
726
746
  var DeeplineClient = class {
727
747
  http;
728
748
  config;
749
+ /** Canonical run lifecycle namespace backed by `/api/v2/runs`. */
729
750
  runs;
730
751
  /**
752
+ * Create a low-level SDK client.
753
+ *
754
+ * Most callers can omit options and let the SDK resolve auth/config from
755
+ * environment variables and CLI-managed credentials.
756
+ *
731
757
  * @param options - Optional overrides for API key, base URL, timeout, and retries.
732
758
  * @throws {@link ConfigError} if no API key can be resolved from any source.
733
759
  */
@@ -829,12 +855,19 @@ var DeeplineClient = class {
829
855
  // ——————————————————————————————————————————————————————————
830
856
  // Secrets
831
857
  // ——————————————————————————————————————————————————————————
858
+ /** List secret metadata visible to the current workspace. */
832
859
  async listSecrets() {
833
860
  const response = await this.http.get(
834
861
  "/api/v2/secrets"
835
862
  );
836
863
  return Array.isArray(response.secrets) ? response.secrets : [];
837
864
  }
865
+ /**
866
+ * Check whether a named secret exists, is active, and has a stored value.
867
+ *
868
+ * @param name - Secret name. It is normalized to uppercase before lookup.
869
+ * @returns Matching active secret metadata, or `null`.
870
+ */
838
871
  async checkSecret(name) {
839
872
  const normalized = name.trim().toUpperCase();
840
873
  const secrets = await this.listSecrets();
@@ -947,9 +980,21 @@ var DeeplineClient = class {
947
980
  headers
948
981
  );
949
982
  }
983
+ /**
984
+ * Back-compatible alias for {@link executeTool}.
985
+ *
986
+ * Retained for callers that still use the older raw naming while the response
987
+ * envelope remains the same.
988
+ */
950
989
  async executeToolRaw(toolId, input2, options) {
951
990
  return this.executeTool(toolId, input2, options);
952
991
  }
992
+ /**
993
+ * Run a bounded SQL query against the customer data plane.
994
+ *
995
+ * Use this from trusted backend or agent contexts only. The API enforces
996
+ * workspace scoping and row limits.
997
+ */
953
998
  async queryCustomerDb(input2) {
954
999
  return this.http.post("/api/v2/db/query", {
955
1000
  sql: input2.sql,
@@ -1021,6 +1066,17 @@ var DeeplineClient = class {
1021
1066
  );
1022
1067
  return normalizePlayRunStart(response);
1023
1068
  }
1069
+ /**
1070
+ * Start a play run and stream live runtime events from the same request.
1071
+ *
1072
+ * Use this when a caller wants low-level event handling instead of submitting
1073
+ * first and then connecting to `streamPlayRunEvents(runId)`.
1074
+ *
1075
+ * @param request - Play run configuration.
1076
+ * @param options - Optional streaming options.
1077
+ * @param options.signal - Optional abort signal for the streaming request.
1078
+ * @returns Async stream of play-scoped live events.
1079
+ */
1024
1080
  async *startPlayRunStream(request, options) {
1025
1081
  const body = {
1026
1082
  ...request.name ? { name: request.name } : {},
@@ -1073,6 +1129,12 @@ var DeeplineClient = class {
1073
1129
  compilerManifest
1074
1130
  });
1075
1131
  }
1132
+ /**
1133
+ * Register multiple bundled play artifacts in one request.
1134
+ *
1135
+ * Used by packaging and prebuilt publication flows. Each artifact is compiled
1136
+ * first when a compiler manifest is not already supplied.
1137
+ */
1076
1138
  async registerPlayArtifacts(artifacts) {
1077
1139
  const compiledArtifacts = await Promise.all(
1078
1140
  artifacts.map(async (artifact) => ({
@@ -1089,6 +1151,13 @@ var DeeplineClient = class {
1089
1151
  artifacts: compiledArtifacts
1090
1152
  });
1091
1153
  }
1154
+ /**
1155
+ * Compile a bundled play artifact into the server-side compiler manifest.
1156
+ *
1157
+ * The manifest records imports, trigger bindings, static pipeline shape, and
1158
+ * runtime metadata needed before a play artifact can be checked, registered,
1159
+ * or run.
1160
+ */
1092
1161
  async compilePlayManifest(input2) {
1093
1162
  const retryDelays = COMPILE_MANIFEST_RETRY_DELAYS_MS.slice(
1094
1163
  0,
@@ -1117,9 +1186,21 @@ var DeeplineClient = class {
1117
1186
  async checkPlayArtifact(input2) {
1118
1187
  return this.http.post("/api/v2/plays/check", input2);
1119
1188
  }
1189
+ /**
1190
+ * Compile legacy enrich command arguments into a runtime plan.
1191
+ *
1192
+ * This is primarily used by CLI compatibility paths that translate older
1193
+ * enrichment commands onto the play runtime.
1194
+ */
1120
1195
  async compileEnrichPlan(input2) {
1121
1196
  return this.http.post("/api/v2/enrich/compile", input2);
1122
1197
  }
1198
+ /**
1199
+ * Register an already-bundled play artifact and start a run from it.
1200
+ *
1201
+ * This is the low-level file-backed run path used by SDK/CLI packaging
1202
+ * wrappers after local bundling has produced the runtime artifact.
1203
+ */
1123
1204
  async startPlayRunFromBundle(input2) {
1124
1205
  const compilerManifest = input2.compilerManifest ?? await this.compilePlayManifest({
1125
1206
  name: input2.name,
@@ -1277,6 +1358,12 @@ var DeeplineClient = class {
1277
1358
  const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
1278
1359
  return response.files;
1279
1360
  }
1361
+ /**
1362
+ * Resolve staged play files by content hash without uploading bytes.
1363
+ *
1364
+ * Missing files are returned so callers can upload only the files the server
1365
+ * does not already have.
1366
+ */
1280
1367
  async resolveStagedPlayFiles(files) {
1281
1368
  return this.http.post("/api/v2/plays/files/stage", { files });
1282
1369
  }
@@ -1493,6 +1580,12 @@ var DeeplineClient = class {
1493
1580
  entries
1494
1581
  };
1495
1582
  }
1583
+ /**
1584
+ * Export persisted runtime-sheet rows for a play dataset/table namespace.
1585
+ *
1586
+ * This is the SDK form of exporting `ctx.dataset(...).run()` output for a
1587
+ * specific play and optional run id.
1588
+ */
1496
1589
  async getPlaySheetRows(input2) {
1497
1590
  const params = new URLSearchParams({
1498
1591
  tableNamespace: input2.tableNamespace,
@@ -1521,6 +1614,12 @@ var DeeplineClient = class {
1521
1614
  options?.reason ? { reason: options.reason } : {}
1522
1615
  );
1523
1616
  }
1617
+ /**
1618
+ * List callable plays visible to the workspace.
1619
+ *
1620
+ * Pass `origin: "prebuilt"` for Deepline-managed prebuilts or
1621
+ * `origin: "owned"` for org-owned plays.
1622
+ */
1524
1623
  async listPlays(options) {
1525
1624
  const params = new URLSearchParams();
1526
1625
  if (options?.origin) params.set("origin", options.origin);
@@ -1535,15 +1634,32 @@ var DeeplineClient = class {
1535
1634
  );
1536
1635
  return response.plays ?? [];
1537
1636
  }
1637
+ /**
1638
+ * Search callable plays and return compact play descriptions.
1639
+ *
1640
+ * Prebuilt plays are preferred by default because they have maintained
1641
+ * contracts and stable run behavior.
1642
+ */
1538
1643
  async searchPlays(options) {
1539
1644
  const params = new URLSearchParams();
1540
1645
  params.set("search", options.query.trim());
1646
+ const scope = options.scope ?? "prebuilt";
1647
+ if (scope !== "all") {
1648
+ params.set("origin", scope);
1649
+ }
1541
1650
  const response = await this.http.get(
1542
1651
  `/api/v2/plays?${params.toString()}`
1543
1652
  );
1544
- return (response.plays ?? []).map(
1653
+ const plays = (response.plays ?? []).map(
1545
1654
  (play) => this.summarizePlayListItem(play, options)
1546
1655
  );
1656
+ if (scope === "prebuilt") {
1657
+ return plays.filter(isPrebuiltPlayDescription);
1658
+ }
1659
+ if (scope === "owned") {
1660
+ return plays.filter((play) => !isPrebuiltPlayDescription(play));
1661
+ }
1662
+ return preferPrebuiltPlayDescriptions(plays);
1547
1663
  }
1548
1664
  /**
1549
1665
  * Get the full definition and state of a named play.
@@ -1566,6 +1682,12 @@ var DeeplineClient = class {
1566
1682
  const encodedName = encodeURIComponent(name);
1567
1683
  return this.http.get(`/api/v2/plays/${encodedName}`);
1568
1684
  }
1685
+ /**
1686
+ * Get a normalized play description suitable for agents and CLIs.
1687
+ *
1688
+ * The description includes runnable examples, input/output summaries, clone
1689
+ * guidance, revision state, and latest run metadata when available.
1690
+ */
1569
1691
  async describePlay(name, options) {
1570
1692
  const detail = await this.getPlay(name);
1571
1693
  return this.summarizePlayDetail(detail, options);
@@ -2136,6 +2258,9 @@ function readCsvRows(csvPath) {
2136
2258
  function csvStringFromRows(rows, columns) {
2137
2259
  return (0, import_sync2.stringify)(rows, {
2138
2260
  header: true,
2261
+ cast: {
2262
+ boolean: (value) => value ? "true" : "false"
2263
+ },
2139
2264
  ...columns?.length ? { columns } : {}
2140
2265
  });
2141
2266
  }
@@ -2417,7 +2542,7 @@ function buildCandidateUrls2(url) {
2417
2542
  }
2418
2543
  }
2419
2544
  function sleep3(ms) {
2420
- return new Promise((resolve13) => setTimeout(resolve13, ms));
2545
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
2421
2546
  }
2422
2547
  function printDeeplineLogo() {
2423
2548
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -4672,7 +4797,12 @@ function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
4672
4797
  return null;
4673
4798
  }
4674
4799
  function findPackageJsonPathFrom(startDir, packageName) {
4675
- let current = (0, import_node_path8.resolve)(startDir);
4800
+ if (!(0, import_node_path8.isAbsolute)(startDir)) {
4801
+ throw new Error(
4802
+ `Package resolution requires an absolute start directory, got ${startDir}`
4803
+ );
4804
+ }
4805
+ let current = startDir;
4676
4806
  while (true) {
4677
4807
  const packageJsonPath = (0, import_node_path8.join)(
4678
4808
  current,
@@ -4692,17 +4822,15 @@ function findPackageJsonPathFrom(startDir, packageName) {
4692
4822
  }
4693
4823
  function findPackageJsonPath(packageName, fromFile, adapter) {
4694
4824
  const startDirs = [
4695
- (0, import_node_path8.dirname)(fromFile),
4696
- adapter.projectRoot,
4697
- (0, import_node_path8.dirname)(adapter.sdkPackageJson),
4698
- process.cwd()
4825
+ (0, import_node_path8.resolve)((0, import_node_path8.dirname)(fromFile)),
4826
+ (0, import_node_path8.resolve)(adapter.projectRoot),
4827
+ (0, import_node_path8.resolve)((0, import_node_path8.dirname)(adapter.sdkPackageJson))
4699
4828
  ];
4700
4829
  const seen = /* @__PURE__ */ new Set();
4701
4830
  for (const startDir of startDirs) {
4702
- const normalized = (0, import_node_path8.resolve)(startDir);
4703
- if (seen.has(normalized)) continue;
4704
- seen.add(normalized);
4705
- const packageJsonPath = findPackageJsonPathFrom(normalized, packageName);
4831
+ if (seen.has(startDir)) continue;
4832
+ seen.add(startDir);
4833
+ const packageJsonPath = findPackageJsonPathFrom(startDir, packageName);
4706
4834
  if (packageJsonPath) return packageJsonPath;
4707
4835
  }
4708
4836
  const adapterNodeModulesPackageJson = (0, import_node_path8.join)(
@@ -5160,13 +5288,13 @@ async function writeArtifactCache(artifact, adapter) {
5160
5288
  "utf-8"
5161
5289
  );
5162
5290
  }
5163
- function normalizeSourceMapForRuntime(sourceMapText) {
5291
+ function normalizeSourceMapForRuntime(sourceMapText, projectRoot) {
5164
5292
  const parsed = JSON.parse(sourceMapText);
5165
5293
  parsed.sources = (parsed.sources ?? []).map((sourcePath) => {
5166
5294
  if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
5167
5295
  return sourcePath;
5168
5296
  }
5169
- return (0, import_node_path8.resolve)(process.cwd(), sourcePath);
5297
+ return (0, import_node_path8.join)(projectRoot, sourcePath);
5170
5298
  });
5171
5299
  parsed.sourceRoot = void 0;
5172
5300
  return JSON.stringify(parsed);
@@ -5432,7 +5560,10 @@ workers-harness:${harnessFingerprint}`
5432
5560
  };
5433
5561
  }
5434
5562
  const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
5435
- const normalizedSourceMap = normalizeSourceMapForRuntime(sourceMapText);
5563
+ const normalizedSourceMap = normalizeSourceMapForRuntime(
5564
+ sourceMapText,
5565
+ (0, import_node_path8.resolve)(adapter.projectRoot)
5566
+ );
5436
5567
  const virtualBaseName = exportName === "default" ? (0, import_node_path8.basename)(absolutePath).replace(/\.[^.]+$/, "") : `${(0, import_node_path8.basename)(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
5437
5568
  const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
5438
5569
  const executableCode = `${bundledCode}
@@ -5506,12 +5637,16 @@ var PLAY_DEDUP_BACKENDS = {
5506
5637
  var PLAY_SCHEDULER_BACKENDS = {
5507
5638
  temporal: "temporal",
5508
5639
  cfWorkflows: "cf-workflows",
5640
+ postgres: "postgres",
5509
5641
  inProcess: "in-process"
5510
5642
  };
5511
5643
 
5512
5644
  // ../shared_libs/play-runtime/providers.ts
5513
5645
  var PLAY_RUNTIME_PROVIDER_IDS = {
5514
5646
  workersEdge: "workers_edge",
5647
+ postgresFast: "postgres_fast",
5648
+ postgresFastSandbox: "postgres_fast_sandbox",
5649
+ postgresFastWorkers: "postgres_fast_workers",
5515
5650
  local: "local"
5516
5651
  };
5517
5652
  var PLAY_RUNTIME_PROVIDERS = {
@@ -5523,6 +5658,30 @@ var PLAY_RUNTIME_PROVIDERS = {
5523
5658
  artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
5524
5659
  label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
5525
5660
  },
5661
+ postgres_fast: {
5662
+ id: PLAY_RUNTIME_PROVIDER_IDS.postgresFast,
5663
+ scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
5664
+ runner: PLAY_RUNTIME_BACKENDS.daytona,
5665
+ dedup: PLAY_DEDUP_BACKENDS.durableObject,
5666
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
5667
+ label: "Experimental Postgres Scheduler + warm sandbox runner + DO dedup"
5668
+ },
5669
+ postgres_fast_sandbox: {
5670
+ id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastSandbox,
5671
+ scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
5672
+ runner: PLAY_RUNTIME_BACKENDS.daytona,
5673
+ dedup: PLAY_DEDUP_BACKENDS.durableObject,
5674
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
5675
+ label: "Experimental Postgres Scheduler + warm sandbox runner + DO dedup"
5676
+ },
5677
+ postgres_fast_workers: {
5678
+ id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastWorkers,
5679
+ scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
5680
+ runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
5681
+ dedup: PLAY_DEDUP_BACKENDS.durableObject,
5682
+ artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
5683
+ label: "Experimental Postgres Scheduler + Queue/DO-woken Workers + DO dedup"
5684
+ },
5526
5685
  local: {
5527
5686
  id: PLAY_RUNTIME_PROVIDER_IDS.local,
5528
5687
  scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
@@ -7805,7 +7964,7 @@ function traceCliSync(phase, fields, run) {
7805
7964
  }
7806
7965
  }
7807
7966
  function sleep4(ms) {
7808
- return new Promise((resolve13) => setTimeout(resolve13, ms));
7967
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
7809
7968
  }
7810
7969
  function parseReferencedPlayTarget2(target) {
7811
7970
  const trimmed = target.trim();
@@ -8143,9 +8302,10 @@ function formatUnresolvedPackagedFiles(filePath, unresolvedFileReferences) {
8143
8302
  const details = unresolvedFileReferences.map((unresolved) => `${unresolved.sourceFragment}: ${unresolved.message}`).join("; ");
8144
8303
  return `Failed to package local ctx.csv(...) files in ${filePath}: ${details}`;
8145
8304
  }
8146
- async function collectBundledPlayGraph(entryFile) {
8305
+ async function collectBundledPlayGraph(entryFile, profile = null) {
8147
8306
  const nodes = /* @__PURE__ */ new Map();
8148
8307
  const visiting = /* @__PURE__ */ new Set();
8308
+ const artifactKind = resolveExecutionProfile(profile).artifactKind;
8149
8309
  const visit = async (filePath) => {
8150
8310
  const absolutePath = normalizePlayPath(filePath);
8151
8311
  const cached = nodes.get(absolutePath);
@@ -8160,7 +8320,7 @@ async function collectBundledPlayGraph(entryFile) {
8160
8320
  visiting.add(absolutePath);
8161
8321
  try {
8162
8322
  const bundleResult = await bundlePlayFile2(absolutePath, {
8163
- target: "esm_workers"
8323
+ target: artifactKind
8164
8324
  });
8165
8325
  if (bundleResult.success === false) {
8166
8326
  throw new Error(
@@ -8275,7 +8435,8 @@ function formatTimestamp(value) {
8275
8435
  return date.toISOString();
8276
8436
  }
8277
8437
  function formatRunLine(run) {
8278
- return `${run.workflowId} ${run.status} ${formatTimestamp(run.startTime)}`;
8438
+ const credits = typeof run.billingTotalCredits === "number" && Number.isFinite(run.billingTotalCredits) ? `${formatCreditAmount(run.billingTotalCredits)} credits` : "\u2014";
8439
+ return `${run.workflowId} ${run.status} ${formatTimestamp(run.startTime)} ${credits}`;
8279
8440
  }
8280
8441
  function isTransientPlayStreamError(error) {
8281
8442
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -8322,6 +8483,8 @@ var TERMINAL_PLAY_STATUSES2 = /* @__PURE__ */ new Set([
8322
8483
  "cancelled"
8323
8484
  ]);
8324
8485
  var PLAY_START_TRANSIENT_RETRY_DELAYS_MS = [500, 1500];
8486
+ var PLAY_PROGRESS_HEARTBEAT_INTERVAL_MS = 15e3;
8487
+ var PLAY_STATUS_HEARTBEAT_INTERVAL_MS = 15e3;
8325
8488
  function getEventPayload(event) {
8326
8489
  return event.payload && typeof event.payload === "object" ? event.payload : {};
8327
8490
  }
@@ -8382,6 +8545,7 @@ function extractTableNamespaceFromLiveEvent(event) {
8382
8545
  const payload = getEventPayload(event);
8383
8546
  const candidates = [
8384
8547
  payload.artifactTableNamespace,
8548
+ payload.activeArtifactTableNamespace,
8385
8549
  payload.tableNamespace,
8386
8550
  payload.mapNodeId
8387
8551
  ];
@@ -8460,6 +8624,20 @@ function formatProgressCounts(input2) {
8460
8624
  const failed = typeof input2.failed === "number" && Number.isFinite(input2.failed) && input2.failed > 0 ? `, failed ${formatInteger(input2.failed)}` : "";
8461
8625
  return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
8462
8626
  }
8627
+ function formatProgressMessageSuffix(input2) {
8628
+ const message = typeof input2.message === "string" ? input2.message.trim() : "";
8629
+ if (!message) {
8630
+ return "";
8631
+ }
8632
+ const completed = typeof input2.completed === "number" && Number.isFinite(input2.completed) ? input2.completed : null;
8633
+ if (/^[\d,]+\s*\/\s*[\d,]+\s+rows processed$/i.test(message)) {
8634
+ return "";
8635
+ }
8636
+ if (completed !== null && completed > 0 && /rows?\s+queued\b/i.test(message)) {
8637
+ return "";
8638
+ }
8639
+ return ` - ${message}`;
8640
+ }
8463
8641
  function getProgressLinesFromLiveEvent(event) {
8464
8642
  const payload = getEventPayload(event);
8465
8643
  if (event.type === "play.step.progress") {
@@ -8469,7 +8647,13 @@ function getProgressLinesFromLiveEvent(event) {
8469
8647
  failed: payload.failed
8470
8648
  });
8471
8649
  if (!counts) return [];
8472
- return [`progress ${formatProgressLabel(payload.stepId)}: ${counts}`];
8650
+ const messageSuffix = formatProgressMessageSuffix({
8651
+ message: payload.message,
8652
+ completed: payload.completed
8653
+ });
8654
+ return [
8655
+ `progress ${formatProgressLabel(payload.stepId)}: ${counts}${messageSuffix}`
8656
+ ];
8473
8657
  }
8474
8658
  if (event.type !== "play.run.snapshot" && event.type !== "play.run.final_status") {
8475
8659
  return [];
@@ -8493,22 +8677,69 @@ function getProgressLinesFromLiveEvent(event) {
8493
8677
  if (!counts) {
8494
8678
  continue;
8495
8679
  }
8680
+ const messageSuffix = formatProgressMessageSuffix({
8681
+ message: progress.message,
8682
+ completed: progress.completed
8683
+ });
8496
8684
  lines.push(
8497
- `progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}`
8685
+ `progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
8498
8686
  );
8499
8687
  }
8500
8688
  return lines;
8501
8689
  }
8690
+ function shouldPrintPlayProgressLine(input2) {
8691
+ if (!input2.signature) {
8692
+ return false;
8693
+ }
8694
+ return input2.lastProgressSignature !== input2.signature || input2.nowMs - input2.lastProgressHeartbeatAt >= PLAY_PROGRESS_HEARTBEAT_INTERVAL_MS;
8695
+ }
8502
8696
  function printPlayProgressLines(input2) {
8503
8697
  for (const line of input2.lines) {
8504
8698
  const signature = line.trim();
8505
- if (!signature || input2.state.lastProgressSignature === signature) {
8699
+ const now = Date.now();
8700
+ if (!shouldPrintPlayProgressLine({
8701
+ signature,
8702
+ lastProgressSignature: input2.state.lastProgressSignature,
8703
+ lastProgressHeartbeatAt: input2.state.lastProgressHeartbeatAt,
8704
+ nowMs: now
8705
+ })) {
8506
8706
  continue;
8507
8707
  }
8508
8708
  input2.state.lastProgressSignature = signature;
8709
+ input2.state.lastProgressHeartbeatAt = now;
8509
8710
  input2.progress.writeLine(line);
8510
8711
  }
8511
8712
  }
8713
+ function getRunningHeartbeatLine(input2) {
8714
+ const status = getStatusFromLiveEvent(input2.event);
8715
+ if (status !== "queued" && status !== "running" && status !== "waiting") {
8716
+ return null;
8717
+ }
8718
+ const tableNamespace = extractTableNamespaceFromLiveEvent(input2.event);
8719
+ const target = tableNamespace ? formatProgressLabel(tableNamespace) : input2.playName;
8720
+ if (status === "queued") {
8721
+ return `queued ${target}: waiting for worker capacity`;
8722
+ }
8723
+ if (status === "waiting") {
8724
+ return `waiting ${target}: waiting on external work`;
8725
+ }
8726
+ return `running ${target}: still processing`;
8727
+ }
8728
+ function printPlayStatusHeartbeat(input2) {
8729
+ const now = Date.now();
8730
+ if (now - input2.state.lastStatusHeartbeatAt < PLAY_STATUS_HEARTBEAT_INTERVAL_MS) {
8731
+ return;
8732
+ }
8733
+ const line = getRunningHeartbeatLine({
8734
+ event: input2.event,
8735
+ playName: input2.playName
8736
+ });
8737
+ if (!line) {
8738
+ return;
8739
+ }
8740
+ input2.state.lastStatusHeartbeatAt = now;
8741
+ input2.progress.writeLine(line);
8742
+ }
8512
8743
  function buildPlayDashboardUrl(baseUrl, playName) {
8513
8744
  const trimmedBase = baseUrl.replace(/\/$/, "");
8514
8745
  const encodedPlayName = encodeURIComponent(playName);
@@ -8591,11 +8822,20 @@ async function waitForPlayCompletionByStream(input2) {
8591
8822
  progress: input2.progress
8592
8823
  });
8593
8824
  if (!input2.jsonOutput) {
8825
+ const progressLines = getProgressLinesFromLiveEvent(event);
8594
8826
  printPlayProgressLines({
8595
- lines: getProgressLinesFromLiveEvent(event),
8827
+ lines: progressLines,
8596
8828
  state: input2.state,
8597
8829
  progress: input2.progress
8598
8830
  });
8831
+ if (progressLines.length === 0) {
8832
+ printPlayStatusHeartbeat({
8833
+ event,
8834
+ playName: input2.playName,
8835
+ state: input2.state,
8836
+ progress: input2.progress
8837
+ });
8838
+ }
8599
8839
  }
8600
8840
  const finalStatus = getFinalStatusFromLiveEvent(event);
8601
8841
  if (finalStatus) {
@@ -8673,7 +8913,9 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8673
8913
  const state = {
8674
8914
  lastLogIndex: 0,
8675
8915
  emittedRunnerStarted: false,
8676
- lastProgressSignature: null
8916
+ lastProgressSignature: null,
8917
+ lastProgressHeartbeatAt: 0,
8918
+ lastStatusHeartbeatAt: 0
8677
8919
  };
8678
8920
  const controller = new AbortController();
8679
8921
  let timedOut = false;
@@ -8714,7 +8956,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8714
8956
  dashboardUrl,
8715
8957
  noOpen: input2.noOpen
8716
8958
  });
8717
- input2.progress.phase(`loading play on ${dashboardUrl}`);
8959
+ input2.progress.phase("running");
8718
8960
  emittedDashboardUrl = true;
8719
8961
  }
8720
8962
  assertPlayWaitNotTimedOut({
@@ -8745,11 +8987,20 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8745
8987
  progress: input2.progress
8746
8988
  });
8747
8989
  if (!input2.jsonOutput) {
8990
+ const progressLines = getProgressLinesFromLiveEvent(event);
8748
8991
  printPlayProgressLines({
8749
- lines: getProgressLinesFromLiveEvent(event),
8992
+ lines: progressLines,
8750
8993
  state,
8751
8994
  progress: input2.progress
8752
8995
  });
8996
+ if (progressLines.length === 0) {
8997
+ printPlayStatusHeartbeat({
8998
+ event,
8999
+ playName: input2.playName,
9000
+ state,
9001
+ progress: input2.progress
9002
+ });
9003
+ }
8753
9004
  }
8754
9005
  const finalStatus = getFinalStatusFromLiveEvent(event);
8755
9006
  if (finalStatus) {
@@ -9349,6 +9600,17 @@ function getPlayRunPackage(status) {
9349
9600
  const packaged = status.package;
9350
9601
  return isPlayRunPackageValue(packaged) ? packaged : null;
9351
9602
  }
9603
+ function withTerminalPlayIdentity(status, playName) {
9604
+ if (!playName.trim() || getPlayRunPackage(status)) {
9605
+ return status;
9606
+ }
9607
+ const record = status;
9608
+ const hasIdentity = typeof record.playName === "string" && record.playName.trim().length > 0 || typeof record.name === "string" && record.name.trim().length > 0 || Boolean(getStringField(record.run, "playName"));
9609
+ if (hasIdentity) {
9610
+ return status;
9611
+ }
9612
+ return { ...status, playName };
9613
+ }
9352
9614
  function compactPlayStatus(status) {
9353
9615
  const packaged = getPlayRunPackage(status);
9354
9616
  if (packaged) {
@@ -9525,6 +9787,9 @@ function actionToCommand(action) {
9525
9787
  if (record.kind === "deepline_run_inspect" && typeof record.runId === "string") {
9526
9788
  return `deepline runs get ${record.runId} --json`;
9527
9789
  }
9790
+ if (record.kind === "deepline_run_billing" && typeof record.runId === "string") {
9791
+ return `deepline runs get ${record.runId} --full --json | jq '.billing'`;
9792
+ }
9528
9793
  if (record.kind === "deepline_run_export" && typeof record.runId === "string" && typeof record.datasetPath === "string") {
9529
9794
  return `deepline runs export ${record.runId} --dataset ${shellSingleQuote(
9530
9795
  record.datasetPath
@@ -9557,6 +9822,12 @@ function buildRunPackageTextLines(packaged) {
9557
9822
  if (playName) {
9558
9823
  lines.push(` play: ${playName}`);
9559
9824
  }
9825
+ const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
9826
+ const billingCommand = actionToCommand(next.billing);
9827
+ if (billingCommand) {
9828
+ const costState = status === "completed" || status === "failed" || status === "cancelled" ? "finalizing" : "pending";
9829
+ lines.push(` cost: ${costState}`);
9830
+ }
9560
9831
  for (const step of readRecordArray(packaged.steps).slice(0, 8)) {
9561
9832
  const id = typeof step.id === "string" ? step.id : "step";
9562
9833
  const kind = typeof step.kind === "string" ? step.kind : "step";
@@ -9573,12 +9844,12 @@ function buildRunPackageTextLines(packaged) {
9573
9844
  );
9574
9845
  }
9575
9846
  }
9576
- const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
9577
9847
  const datasetActions = readFirstDatasetActions(packaged);
9578
9848
  const inspectCommand = actionToCommand(next.inspect);
9579
9849
  const queryCommand = actionToCommand(next.query) ?? actionToCommand(datasetActions.query);
9580
9850
  const exportCommand = actionToCommand(next.export) ?? actionToCommand(datasetActions.exportCsv);
9581
9851
  if (inspectCommand) lines.push(` inspect: ${inspectCommand}`);
9852
+ if (billingCommand) lines.push(` billing: ${billingCommand}`);
9582
9853
  if (queryCommand) lines.push(` query: ${queryCommand}`);
9583
9854
  if (exportCommand) lines.push(` export CSV: ${exportCommand}`);
9584
9855
  return lines;
@@ -10127,7 +10398,7 @@ function writeStartedPlayRun(input2) {
10127
10398
  );
10128
10399
  }
10129
10400
  function parsePlayRunOptions(args) {
10130
- 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 '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\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.";
10401
+ 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 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.";
10131
10402
  let filePath = null;
10132
10403
  let playName = null;
10133
10404
  let input2 = null;
@@ -10140,6 +10411,7 @@ function parsePlayRunOptions(args) {
10140
10411
  const force = args.includes("--force");
10141
10412
  const noOpen = args.includes("--no-open");
10142
10413
  let waitTimeoutMs = null;
10414
+ let profile = null;
10143
10415
  for (let index = 0; index < args.length; index += 1) {
10144
10416
  const arg = args[index];
10145
10417
  if (arg === "--file" && args[index + 1]) {
@@ -10158,6 +10430,16 @@ function parsePlayRunOptions(args) {
10158
10430
  revisionId = args[++index];
10159
10431
  continue;
10160
10432
  }
10433
+ if (arg === "--profile") {
10434
+ const value = args[index + 1];
10435
+ if (!value) {
10436
+ throw new Error("--profile requires an execution profile id.");
10437
+ }
10438
+ profile = value.trim();
10439
+ resolveExecutionProfile(profile);
10440
+ index += 1;
10441
+ continue;
10442
+ }
10161
10443
  if (arg === "--live") {
10162
10444
  revisionSelector = "live";
10163
10445
  continue;
@@ -10245,7 +10527,8 @@ function parsePlayRunOptions(args) {
10245
10527
  fullJson,
10246
10528
  waitTimeoutMs,
10247
10529
  force,
10248
- noOpen
10530
+ noOpen,
10531
+ profile
10249
10532
  };
10250
10533
  }
10251
10534
  function parsePlayCheckOptions(args) {
@@ -10522,7 +10805,7 @@ async function handleFileBackedRun(options) {
10522
10805
  graph = await traceCliSpan(
10523
10806
  "cli.play_file_bundle_graph",
10524
10807
  { targetKind: "file" },
10525
- () => collectBundledPlayGraph(absolutePlayPath)
10808
+ () => collectBundledPlayGraph(absolutePlayPath, options.profile)
10526
10809
  );
10527
10810
  await traceCliSpan(
10528
10811
  "cli.play_file_compile_manifests",
@@ -10582,7 +10865,8 @@ async function handleFileBackedRun(options) {
10582
10865
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
10583
10866
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
10584
10867
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
10585
- ...options.force ? { force: true } : {}
10868
+ ...options.force ? { force: true } : {},
10869
+ ...options.profile ? { profile: options.profile } : {}
10586
10870
  };
10587
10871
  if (options.watch) {
10588
10872
  progress.phase("starting run");
@@ -10607,11 +10891,14 @@ async function handleFileBackedRun(options) {
10607
10891
  } else {
10608
10892
  progress.fail();
10609
10893
  }
10610
- const outputStatus = await resolvePlayRunOutputStatus({
10611
- client,
10612
- status: finalStatus,
10613
- fullJson: options.fullJson
10614
- });
10894
+ const outputStatus = withTerminalPlayIdentity(
10895
+ await resolvePlayRunOutputStatus({
10896
+ client,
10897
+ status: finalStatus,
10898
+ fullJson: options.fullJson
10899
+ }),
10900
+ playName
10901
+ );
10615
10902
  traceCliSync(
10616
10903
  "cli.play_write_result",
10617
10904
  { targetKind: "file", playName },
@@ -10634,7 +10921,7 @@ async function handleFileBackedRun(options) {
10634
10921
  dashboardUrl: resolvedDashboardUrl,
10635
10922
  noOpen: options.noOpen
10636
10923
  });
10637
- progress.phase(`loading play on ${resolvedDashboardUrl}`);
10924
+ progress.phase("started run");
10638
10925
  progress.complete();
10639
10926
  writeStartedPlayRun({
10640
10927
  runId: started.workflowId,
@@ -10728,7 +11015,8 @@ async function handleNamedRun(options) {
10728
11015
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
10729
11016
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
10730
11017
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
10731
- ...options.force ? { force: true } : {}
11018
+ ...options.force ? { force: true } : {},
11019
+ ...options.profile ? { profile: options.profile } : {}
10732
11020
  };
10733
11021
  if (options.watch) {
10734
11022
  progress.phase("starting run");
@@ -10753,11 +11041,14 @@ async function handleNamedRun(options) {
10753
11041
  } else {
10754
11042
  progress.fail();
10755
11043
  }
10756
- const outputStatus = await resolvePlayRunOutputStatus({
10757
- client,
10758
- status: finalStatus,
10759
- fullJson: options.fullJson
10760
- });
11044
+ const outputStatus = withTerminalPlayIdentity(
11045
+ await resolvePlayRunOutputStatus({
11046
+ client,
11047
+ status: finalStatus,
11048
+ fullJson: options.fullJson
11049
+ }),
11050
+ playName
11051
+ );
10761
11052
  traceCliSync(
10762
11053
  "cli.play_write_result",
10763
11054
  { targetKind: "name", playName },
@@ -10780,7 +11071,7 @@ async function handleNamedRun(options) {
10780
11071
  dashboardUrl: resolvedDashboardUrl,
10781
11072
  noOpen: options.noOpen
10782
11073
  });
10783
- progress.phase(`loading play on ${resolvedDashboardUrl}`);
11074
+ progress.phase("started run");
10784
11075
  progress.complete();
10785
11076
  writeStartedPlayRun({
10786
11077
  runId: started.workflowId,
@@ -10892,10 +11183,12 @@ async function handleRunsList(args) {
10892
11183
  startedAt: run.startTime,
10893
11184
  finishedAt: run.closeTime,
10894
11185
  executionTime: run.executionTime,
11186
+ billingTotalCredits: run.billingTotalCredits,
11187
+ billingMaxCreditsPerRun: run.billingMaxCreditsPerRun,
10895
11188
  playName: run.memo?.playName ?? playName
10896
11189
  }));
10897
11190
  const lines = runs.length === 0 ? [`No runs found for ${playName}.`] : runs.map(
10898
- (run) => `${run.runId} ${run.status} ${formatTimestamp(run.startedAt)}`
11191
+ (run) => `${run.runId} ${run.status} ${formatTimestamp(run.startedAt)} ${typeof run.billingTotalCredits === "number" && Number.isFinite(run.billingTotalCredits) ? `${formatCreditAmount(run.billingTotalCredits)} credits` : "\u2014"}`
10899
11192
  );
10900
11193
  printCommandEnvelope(
10901
11194
  {
@@ -11266,16 +11559,19 @@ function parsePlaySearchOptions(args) {
11266
11559
  const query = args[0]?.trim();
11267
11560
  if (!query) {
11268
11561
  throw new Error(
11269
- "Usage: deepline plays search <query> [--compact] [--json]"
11562
+ "Usage: deepline plays search <query> [--all] [--compact] [--json]"
11270
11563
  );
11271
11564
  }
11272
11565
  return {
11273
11566
  query,
11274
11567
  jsonOutput: argsWantJson(args),
11275
11568
  compact: args.includes("--compact"),
11276
- prebuiltOnly: args.includes("--prebuilt")
11569
+ scope: args.includes("--all") && !args.includes("--prebuilt") ? "all" : "prebuilt"
11277
11570
  };
11278
11571
  }
11572
+ function playSearchDisclaimer(scope) {
11573
+ return scope === "all" ? "Prebuilt-first search: Deepline-managed prebuilts are trusted, robust plays with maintained contracts, so they are listed before plays you created. Use created-play results only when you are specifically looking for one." : "Prebuilt-first search: Deepline-managed prebuilts are trusted, robust plays with maintained contracts. Plays you created are omitted by default; add --all only when you are specifically looking for one.";
11574
+ }
11279
11575
  function printPlayDescription(play) {
11280
11576
  const reference = formatPlayListReference(play);
11281
11577
  const labels = [
@@ -11417,19 +11713,26 @@ async function handlePlaySearch(args) {
11417
11713
  return 1;
11418
11714
  }
11419
11715
  const client = new DeeplineClient();
11420
- const plays = (await client.searchPlays({
11716
+ const plays = await client.searchPlays({
11421
11717
  query: options.query,
11422
- compact: options.compact
11423
- })).filter(
11424
- (play) => options.prebuiltOnly ? play.origin === "prebuilt" || play.ownerType === "deepline" : true
11425
- );
11718
+ compact: options.compact,
11719
+ scope: options.scope
11720
+ });
11721
+ const disclaimer = playSearchDisclaimer(options.scope);
11426
11722
  if (options.jsonOutput) {
11427
- const jsonPlays = options.prebuiltOnly ? plays.map((play) => ({
11723
+ const jsonPlays = options.scope === "prebuilt" ? plays.map((play) => ({
11428
11724
  ...play,
11429
11725
  inputSchema: compactPlaySchema(play.inputSchema)
11430
11726
  })) : plays;
11431
11727
  process.stdout.write(
11432
11728
  `${JSON.stringify({
11729
+ disclaimer,
11730
+ search_policy: {
11731
+ default_scope: "prebuilt",
11732
+ included_origins: options.scope === "all" ? ["prebuilt", "owned"] : ["prebuilt"],
11733
+ owned_plays_omitted: options.scope === "prebuilt",
11734
+ include_owned_flag: "--all"
11735
+ },
11433
11736
  plays: jsonPlays,
11434
11737
  total: jsonPlays.length,
11435
11738
  truncated: false
@@ -11438,21 +11741,23 @@ async function handlePlaySearch(args) {
11438
11741
  );
11439
11742
  return 0;
11440
11743
  }
11441
- const displayPlays = options.prebuiltOnly ? plays.slice(0, 5) : plays;
11744
+ const displayPlays = options.scope === "prebuilt" ? plays.slice(0, 5) : plays;
11745
+ process.stdout.write(`${disclaimer}
11746
+ `);
11442
11747
  process.stdout.write(
11443
- `${plays.length} plays found${options.prebuiltOnly && plays.length > displayPlays.length ? `; showing top ${displayPlays.length}` : ""}:
11748
+ `${plays.length} plays found${options.scope === "prebuilt" && plays.length > displayPlays.length ? `; showing top ${displayPlays.length}` : ""}:
11444
11749
 
11445
11750
  `
11446
11751
  );
11447
11752
  for (const play of displayPlays) {
11448
- if (options.prebuiltOnly) {
11753
+ if (options.scope === "prebuilt") {
11449
11754
  printCompactPlaySearchResult(play);
11450
11755
  } else {
11451
11756
  printPlayDescription(play);
11452
11757
  }
11453
11758
  console.log("");
11454
11759
  }
11455
- if (options.prebuiltOnly && plays.length > displayPlays.length) {
11760
+ if (options.scope === "prebuilt" && plays.length > displayPlays.length) {
11456
11761
  console.log("Use --json for the full machine-readable result set.");
11457
11762
  }
11458
11763
  return 0;
@@ -11816,6 +12121,9 @@ Examples:
11816
12121
  ).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("-i, --input <json>", "Input JSON object or @file path").option("--live", "Run the current live revision explicitly").option("--latest", "Run the newest saved revision, even if it is not live").option(
11817
12122
  "--revision-id <id>",
11818
12123
  "Run a specific saved revision instead of the live revision"
12124
+ ).option(
12125
+ "--profile <id>",
12126
+ "Internal/testing: override the execution profile for this run"
11819
12127
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
11820
12128
  "--logs",
11821
12129
  "When output is non-interactive, stream play logs to stderr while waiting"
@@ -11849,6 +12157,7 @@ Pass-through input flags:
11849
12157
  ...options.live ? ["--live"] : [],
11850
12158
  ...options.latest ? ["--latest"] : [],
11851
12159
  ...options.revisionId ? ["--revision-id", options.revisionId] : [],
12160
+ ...options.profile ? ["--profile", options.profile] : [],
11852
12161
  ...options.wait === false ? ["--no-wait"] : [],
11853
12162
  ...options.watch || options.wait ? ["--watch"] : [],
11854
12163
  ...options.logs ? ["--logs"] : [],
@@ -11902,18 +12211,26 @@ Examples:
11902
12211
  ...options.json ? ["--json"] : []
11903
12212
  ]);
11904
12213
  });
11905
- const addPlaySearchCommand = (command) => command.description("Search saved and prebuilt plays.").option("--prebuilt", "Only show Deepline-managed prebuilt plays").addHelpText(
12214
+ const addPlaySearchCommand = (command) => command.description("Search Deepline prebuilt plays by task.").option(
12215
+ "--prebuilt",
12216
+ "Only show Deepline-managed prebuilt plays (default)"
12217
+ ).option(
12218
+ "--all",
12219
+ "Also include plays you created after Deepline-managed prebuilts"
12220
+ ).addHelpText(
11906
12221
  "after",
11907
12222
  `
11908
12223
  Notes:
11909
- Ranked discovery for workflows. Use describe on a result before running it.
11910
- Prefer --prebuilt for new GTM tasks so old workspace scratchpads do not
11911
- outrank Deepline-managed routes unless the user names one explicitly.
12224
+ Ranked discovery for workflows. Search defaults to Deepline-managed prebuilts
12225
+ because they are trusted, robust plays with maintained contracts. Use describe
12226
+ on a result before running it.
12227
+ Add --all only when you are specifically looking for a play you created.
11912
12228
  The grep alias is the same ranked retrieval surface with a more literal name
11913
12229
  for agents that are filtering the play registry.
11914
12230
 
11915
12231
  Examples:
11916
12232
  deepline plays search email
12233
+ deepline plays search email --all
11917
12234
  deepline plays grep "linkedin to email" --compact --json
11918
12235
  deepline plays describe person-linkedin-to-email --json
11919
12236
  `
@@ -11921,6 +12238,7 @@ Examples:
11921
12238
  process.exitCode = await handlePlaySearch([
11922
12239
  query,
11923
12240
  ...options.prebuilt ? ["--prebuilt"] : [],
12241
+ ...options.all ? ["--all"] : [],
11924
12242
  ...options.compact ? ["--compact"] : [],
11925
12243
  ...options.json ? ["--json"] : []
11926
12244
  ]);
@@ -13688,7 +14006,7 @@ async function readHiddenLine(prompt) {
13688
14006
  if (typeof import_node_process.stdin.setRawMode === "function") import_node_process.stdin.setRawMode(true);
13689
14007
  let value = "";
13690
14008
  import_node_process.stdin.resume();
13691
- return await new Promise((resolve13, reject) => {
14009
+ return await new Promise((resolve14, reject) => {
13692
14010
  let settled = false;
13693
14011
  const cleanup = () => {
13694
14012
  import_node_process.stdin.off("data", onData);
@@ -13703,7 +14021,7 @@ async function readHiddenLine(prompt) {
13703
14021
  settled = true;
13704
14022
  import_node_process.stdout.write("\n");
13705
14023
  cleanup();
13706
- resolve13(line);
14024
+ resolve14(line);
13707
14025
  };
13708
14026
  const fail = (error) => {
13709
14027
  if (settled) return;
@@ -14468,7 +14786,13 @@ Examples:
14468
14786
  ).option(
14469
14787
  "--json [payload]",
14470
14788
  "Emit JSON output. Use `--input` or `--payload` for passing JSON params."
14471
- ).option("--input <payload>", "Merge a JSON object into the tool params").option("--payload <payload>", "Merge a JSON object into the tool params").option(
14789
+ ).option(
14790
+ "--input <payload>",
14791
+ "Merge a JSON object or @file path into the tool params"
14792
+ ).option(
14793
+ "--payload <payload>",
14794
+ "Merge a JSON object or @file path into the tool params"
14795
+ ).option(
14472
14796
  "--output-format <format>",
14473
14797
  "Output format: auto, csv, csv_file, json, or json_file"
14474
14798
  ).option(
@@ -15039,6 +15363,57 @@ function normalizeOutputFormat(raw) {
15039
15363
  throw new Error(`Invalid value for --output-format: ${raw}`);
15040
15364
  }
15041
15365
  }
15366
+ function resolveAtFilePath(rawPath) {
15367
+ const trimmed = rawPath.trim();
15368
+ const resolved = (0, import_node_path15.resolve)(trimmed);
15369
+ if ((0, import_node_fs12.existsSync)(resolved)) return resolved;
15370
+ if (process.platform !== "win32" && trimmed.includes("\\")) {
15371
+ const normalized = (0, import_node_path15.resolve)(trimmed.replace(/\\/g, "/"));
15372
+ if ((0, import_node_fs12.existsSync)(normalized)) return normalized;
15373
+ }
15374
+ return resolved;
15375
+ }
15376
+ function readJsonArgument(raw, flagName) {
15377
+ if (!raw.startsWith("@")) return raw.replace(/^\uFEFF/, "");
15378
+ const filePath = raw.slice(1).trim();
15379
+ if (!filePath) {
15380
+ throw new Error(`Invalid ${flagName} value: empty @file path.`);
15381
+ }
15382
+ try {
15383
+ return (0, import_node_fs12.readFileSync)(resolveAtFilePath(filePath), "utf8").replace(
15384
+ /^\uFEFF/,
15385
+ ""
15386
+ );
15387
+ } catch (error) {
15388
+ const message = error instanceof Error ? error.message : String(error);
15389
+ throw new Error(
15390
+ `Failed to read ${flagName} file '${filePath}': ${message}`
15391
+ );
15392
+ }
15393
+ }
15394
+ function invalidJsonError(flagName, message) {
15395
+ const error = new Error(
15396
+ `Invalid JSON in ${flagName}: ${message}`
15397
+ );
15398
+ error.code = "INVALID_JSON";
15399
+ return error;
15400
+ }
15401
+ function parseJsonObjectArgument(raw, flagName) {
15402
+ let parsed;
15403
+ try {
15404
+ parsed = JSON.parse(readJsonArgument(raw, flagName));
15405
+ } catch (error) {
15406
+ const message = error instanceof Error ? error.message : String(error);
15407
+ if (message.startsWith("Failed to read ") || message.startsWith("Invalid ")) {
15408
+ throw error;
15409
+ }
15410
+ throw invalidJsonError(flagName, message);
15411
+ }
15412
+ if (!isRecord5(parsed)) {
15413
+ throw invalidJsonError(flagName, "expected an object.");
15414
+ }
15415
+ return parsed;
15416
+ }
15042
15417
  function parseExecuteOptions(args) {
15043
15418
  const toolId = args[0];
15044
15419
  if (!toolId) {
@@ -15061,12 +15436,15 @@ function parseExecuteOptions(args) {
15061
15436
  const next = args[index + 1];
15062
15437
  outputFormat = "json";
15063
15438
  if (next && !next.startsWith("--")) {
15064
- Object.assign(params, JSON.parse(args[++index]));
15439
+ Object.assign(
15440
+ params,
15441
+ parseJsonObjectArgument(args[++index], "--json")
15442
+ );
15065
15443
  }
15066
15444
  continue;
15067
15445
  }
15068
15446
  if ((arg === "--input" || arg === "--payload") && args[index + 1]) {
15069
- Object.assign(params, JSON.parse(args[++index]));
15447
+ Object.assign(params, parseJsonObjectArgument(args[++index], arg));
15070
15448
  continue;
15071
15449
  }
15072
15450
  if (arg === "--output-format" && args[index + 1]) {
@@ -15651,7 +16029,7 @@ function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
15651
16029
  lines.push(
15652
16030
  "",
15653
16031
  " To stay on the SDK CLI, install the SDK agent skill:",
15654
- ` ${skillsInstallCommand(baseUrl, "deepline-sdk")}`,
16032
+ ` ${skillsInstallCommand(baseUrl, "deepline-plays")}`,
15655
16033
  " To use the legacy Python CLI instead:",
15656
16034
  ` ${legacyPythonInstallCommand(baseUrl)}`,
15657
16035
  " `deepline update` updates this SDK CLI, but it will not switch CLI families."
@@ -15664,7 +16042,7 @@ function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
15664
16042
  "",
15665
16043
  " To use SDK commands, install the SDK CLI and SDK agent skill:",
15666
16044
  ` ${sdkNpmGlobalInstallCommand()}`,
15667
- ` ${skillsInstallCommand(baseUrl, "deepline-sdk")}`,
16045
+ ` ${skillsInstallCommand(baseUrl, "deepline-plays")}`,
15668
16046
  " `deepline update` updates this Python CLI and its skills, but it will not switch CLI families."
15669
16047
  );
15670
16048
  if (compatibility.python_alternative) {
@@ -15685,12 +16063,29 @@ var import_node_fs14 = require("fs");
15685
16063
  var import_node_os10 = require("os");
15686
16064
  var import_node_path17 = require("path");
15687
16065
  var CHECK_TIMEOUT_MS2 = 3e3;
15688
- var SDK_SKILL_NAME = "deepline-sdk";
16066
+ var SDK_SKILL_NAME = "deepline-plays";
15689
16067
  var attemptedSync = false;
15690
16068
  function shouldSkipSkillsSync() {
15691
16069
  const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
15692
16070
  return value === "1" || value === "true" || value === "yes" || value === "on";
15693
16071
  }
16072
+ function activePluginSkillsDir() {
16073
+ const pluginMode = process.env.DEEPLINE_PLUGIN_MODE?.trim().toLowerCase();
16074
+ if (pluginMode !== "true" && pluginMode !== "1" && pluginMode !== "yes" && pluginMode !== "on") {
16075
+ return "";
16076
+ }
16077
+ const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
16078
+ return dir && (0, import_node_fs14.existsSync)(dir) ? dir : "";
16079
+ }
16080
+ function readPluginSkillsVersion() {
16081
+ const dir = activePluginSkillsDir();
16082
+ if (!dir) return "";
16083
+ try {
16084
+ return (0, import_node_fs14.readFileSync)((0, import_node_path17.join)(dir, ".version"), "utf-8").trim();
16085
+ } catch {
16086
+ return "";
16087
+ }
16088
+ }
15694
16089
  function sdkSkillsVersionPath(baseUrl) {
15695
16090
  const home = process.env.HOME?.trim() || (0, import_node_os10.homedir)();
15696
16091
  return (0, import_node_path17.join)(
@@ -15703,6 +16098,8 @@ function sdkSkillsVersionPath(baseUrl) {
15703
16098
  );
15704
16099
  }
15705
16100
  function readLocalSkillsVersion(baseUrl) {
16101
+ const pluginVersion = readPluginSkillsVersion();
16102
+ if (pluginVersion) return pluginVersion;
15706
16103
  const path = sdkSkillsVersionPath(baseUrl);
15707
16104
  if (!(0, import_node_fs14.existsSync)(path)) return "";
15708
16105
  try {
@@ -15719,7 +16116,8 @@ function writeLocalSkillsVersion(baseUrl, version) {
15719
16116
  }
15720
16117
  function installedSdkSkillHasStalePositionalExecuteExamples() {
15721
16118
  const home = process.env.HOME?.trim() || (0, import_node_os10.homedir)();
15722
- const roots = [
16119
+ const pluginSkillsDir = activePluginSkillsDir();
16120
+ const roots = pluginSkillsDir ? [(0, import_node_path17.join)(pluginSkillsDir, SDK_SKILL_NAME)] : [
15723
16121
  (0, import_node_path17.join)(home, ".claude", "skills", SDK_SKILL_NAME),
15724
16122
  (0, import_node_path17.join)(home, ".agents", "skills", SDK_SKILL_NAME)
15725
16123
  ];
@@ -15818,7 +16216,7 @@ function resolveSkillsInstallCommands(baseUrl) {
15818
16216
  return [npxInstall];
15819
16217
  }
15820
16218
  function runOneSkillsInstall(install) {
15821
- return new Promise((resolve13) => {
16219
+ return new Promise((resolve14) => {
15822
16220
  const child = (0, import_node_child_process2.spawn)(install.command, install.args, {
15823
16221
  stdio: ["ignore", "ignore", "pipe"],
15824
16222
  env: process.env
@@ -15828,7 +16226,7 @@ function runOneSkillsInstall(install) {
15828
16226
  stderr += chunk.toString("utf-8");
15829
16227
  });
15830
16228
  child.on("error", (error) => {
15831
- resolve13({
16229
+ resolve14({
15832
16230
  ok: false,
15833
16231
  detail: `failed to start ${install.command}: ${error.message}`,
15834
16232
  manualCommand: install.manualCommand
@@ -15836,11 +16234,11 @@ function runOneSkillsInstall(install) {
15836
16234
  });
15837
16235
  child.on("close", (code) => {
15838
16236
  if (code === 0) {
15839
- resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
16237
+ resolve14({ ok: true, detail: "", manualCommand: install.manualCommand });
15840
16238
  return;
15841
16239
  }
15842
16240
  const detail = stderr.trim();
15843
- resolve13({
16241
+ resolve14({
15844
16242
  ok: false,
15845
16243
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
15846
16244
  manualCommand: install.manualCommand
@@ -15877,18 +16275,22 @@ function writeSdkSkillsStatusLine(line) {
15877
16275
  async function syncSdkSkillsIfNeeded(baseUrl) {
15878
16276
  if (attemptedSync || shouldSkipSkillsSync()) return;
15879
16277
  attemptedSync = true;
16278
+ const usingPluginSkills = Boolean(activePluginSkillsDir());
15880
16279
  const localVersion = readLocalSkillsVersion(baseUrl);
15881
16280
  const update = await fetchSkillsUpdate(baseUrl, localVersion);
15882
16281
  const hasStaleInstalledSkill = installedSdkSkillHasStalePositionalExecuteExamples();
16282
+ if (usingPluginSkills) {
16283
+ return;
16284
+ }
15883
16285
  if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
15884
16286
  return;
15885
16287
  }
15886
- writeSdkSkillsStatusLine("SDK skills changed; syncing deepline-sdk skill...");
16288
+ writeSdkSkillsStatusLine("SDK skills changed; syncing deepline-plays skill...");
15887
16289
  const installed = await runSkillsInstall(baseUrl);
15888
16290
  if (!installed) return;
15889
16291
  if (installedSdkSkillHasStalePositionalExecuteExamples()) {
15890
16292
  process.stderr.write(
15891
- "SDK skills sync completed, but installed deepline-sdk docs still contain stale positional ctx.tools.execute examples.\n"
16293
+ "SDK skills sync completed, but installed deepline-plays docs still contain stale positional ctx.tools.execute examples.\n"
15892
16294
  );
15893
16295
  return;
15894
16296
  }