deepline 0.1.85 → 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.85",
232
+ version: "0.1.88",
233
233
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
234
234
  supportPolicy: {
235
- latest: "0.1.85",
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);
@@ -2420,7 +2542,7 @@ function buildCandidateUrls2(url) {
2420
2542
  }
2421
2543
  }
2422
2544
  function sleep3(ms) {
2423
- return new Promise((resolve13) => setTimeout(resolve13, ms));
2545
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
2424
2546
  }
2425
2547
  function printDeeplineLogo() {
2426
2548
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -4675,7 +4797,12 @@ function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
4675
4797
  return null;
4676
4798
  }
4677
4799
  function findPackageJsonPathFrom(startDir, packageName) {
4678
- 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;
4679
4806
  while (true) {
4680
4807
  const packageJsonPath = (0, import_node_path8.join)(
4681
4808
  current,
@@ -4695,17 +4822,15 @@ function findPackageJsonPathFrom(startDir, packageName) {
4695
4822
  }
4696
4823
  function findPackageJsonPath(packageName, fromFile, adapter) {
4697
4824
  const startDirs = [
4698
- (0, import_node_path8.dirname)(fromFile),
4699
- adapter.projectRoot,
4700
- (0, import_node_path8.dirname)(adapter.sdkPackageJson),
4701
- 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))
4702
4828
  ];
4703
4829
  const seen = /* @__PURE__ */ new Set();
4704
4830
  for (const startDir of startDirs) {
4705
- const normalized = (0, import_node_path8.resolve)(startDir);
4706
- if (seen.has(normalized)) continue;
4707
- seen.add(normalized);
4708
- const packageJsonPath = findPackageJsonPathFrom(normalized, packageName);
4831
+ if (seen.has(startDir)) continue;
4832
+ seen.add(startDir);
4833
+ const packageJsonPath = findPackageJsonPathFrom(startDir, packageName);
4709
4834
  if (packageJsonPath) return packageJsonPath;
4710
4835
  }
4711
4836
  const adapterNodeModulesPackageJson = (0, import_node_path8.join)(
@@ -5163,13 +5288,13 @@ async function writeArtifactCache(artifact, adapter) {
5163
5288
  "utf-8"
5164
5289
  );
5165
5290
  }
5166
- function normalizeSourceMapForRuntime(sourceMapText) {
5291
+ function normalizeSourceMapForRuntime(sourceMapText, projectRoot) {
5167
5292
  const parsed = JSON.parse(sourceMapText);
5168
5293
  parsed.sources = (parsed.sources ?? []).map((sourcePath) => {
5169
5294
  if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
5170
5295
  return sourcePath;
5171
5296
  }
5172
- return (0, import_node_path8.resolve)(process.cwd(), sourcePath);
5297
+ return (0, import_node_path8.join)(projectRoot, sourcePath);
5173
5298
  });
5174
5299
  parsed.sourceRoot = void 0;
5175
5300
  return JSON.stringify(parsed);
@@ -5435,7 +5560,10 @@ workers-harness:${harnessFingerprint}`
5435
5560
  };
5436
5561
  }
5437
5562
  const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
5438
- const normalizedSourceMap = normalizeSourceMapForRuntime(sourceMapText);
5563
+ const normalizedSourceMap = normalizeSourceMapForRuntime(
5564
+ sourceMapText,
5565
+ (0, import_node_path8.resolve)(adapter.projectRoot)
5566
+ );
5439
5567
  const virtualBaseName = exportName === "default" ? (0, import_node_path8.basename)(absolutePath).replace(/\.[^.]+$/, "") : `${(0, import_node_path8.basename)(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
5440
5568
  const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
5441
5569
  const executableCode = `${bundledCode}
@@ -7836,7 +7964,7 @@ function traceCliSync(phase, fields, run) {
7836
7964
  }
7837
7965
  }
7838
7966
  function sleep4(ms) {
7839
- return new Promise((resolve13) => setTimeout(resolve13, ms));
7967
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
7840
7968
  }
7841
7969
  function parseReferencedPlayTarget2(target) {
7842
7970
  const trimmed = target.trim();
@@ -8355,6 +8483,8 @@ var TERMINAL_PLAY_STATUSES2 = /* @__PURE__ */ new Set([
8355
8483
  "cancelled"
8356
8484
  ]);
8357
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;
8358
8488
  function getEventPayload(event) {
8359
8489
  return event.payload && typeof event.payload === "object" ? event.payload : {};
8360
8490
  }
@@ -8415,6 +8545,7 @@ function extractTableNamespaceFromLiveEvent(event) {
8415
8545
  const payload = getEventPayload(event);
8416
8546
  const candidates = [
8417
8547
  payload.artifactTableNamespace,
8548
+ payload.activeArtifactTableNamespace,
8418
8549
  payload.tableNamespace,
8419
8550
  payload.mapNodeId
8420
8551
  ];
@@ -8493,6 +8624,20 @@ function formatProgressCounts(input2) {
8493
8624
  const failed = typeof input2.failed === "number" && Number.isFinite(input2.failed) && input2.failed > 0 ? `, failed ${formatInteger(input2.failed)}` : "";
8494
8625
  return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
8495
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
+ }
8496
8641
  function getProgressLinesFromLiveEvent(event) {
8497
8642
  const payload = getEventPayload(event);
8498
8643
  if (event.type === "play.step.progress") {
@@ -8502,7 +8647,13 @@ function getProgressLinesFromLiveEvent(event) {
8502
8647
  failed: payload.failed
8503
8648
  });
8504
8649
  if (!counts) return [];
8505
- 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
+ ];
8506
8657
  }
8507
8658
  if (event.type !== "play.run.snapshot" && event.type !== "play.run.final_status") {
8508
8659
  return [];
@@ -8526,22 +8677,69 @@ function getProgressLinesFromLiveEvent(event) {
8526
8677
  if (!counts) {
8527
8678
  continue;
8528
8679
  }
8680
+ const messageSuffix = formatProgressMessageSuffix({
8681
+ message: progress.message,
8682
+ completed: progress.completed
8683
+ });
8529
8684
  lines.push(
8530
- `progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}`
8685
+ `progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
8531
8686
  );
8532
8687
  }
8533
8688
  return lines;
8534
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
+ }
8535
8696
  function printPlayProgressLines(input2) {
8536
8697
  for (const line of input2.lines) {
8537
8698
  const signature = line.trim();
8538
- 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
+ })) {
8539
8706
  continue;
8540
8707
  }
8541
8708
  input2.state.lastProgressSignature = signature;
8709
+ input2.state.lastProgressHeartbeatAt = now;
8542
8710
  input2.progress.writeLine(line);
8543
8711
  }
8544
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
+ }
8545
8743
  function buildPlayDashboardUrl(baseUrl, playName) {
8546
8744
  const trimmedBase = baseUrl.replace(/\/$/, "");
8547
8745
  const encodedPlayName = encodeURIComponent(playName);
@@ -8624,11 +8822,20 @@ async function waitForPlayCompletionByStream(input2) {
8624
8822
  progress: input2.progress
8625
8823
  });
8626
8824
  if (!input2.jsonOutput) {
8825
+ const progressLines = getProgressLinesFromLiveEvent(event);
8627
8826
  printPlayProgressLines({
8628
- lines: getProgressLinesFromLiveEvent(event),
8827
+ lines: progressLines,
8629
8828
  state: input2.state,
8630
8829
  progress: input2.progress
8631
8830
  });
8831
+ if (progressLines.length === 0) {
8832
+ printPlayStatusHeartbeat({
8833
+ event,
8834
+ playName: input2.playName,
8835
+ state: input2.state,
8836
+ progress: input2.progress
8837
+ });
8838
+ }
8632
8839
  }
8633
8840
  const finalStatus = getFinalStatusFromLiveEvent(event);
8634
8841
  if (finalStatus) {
@@ -8706,7 +8913,9 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8706
8913
  const state = {
8707
8914
  lastLogIndex: 0,
8708
8915
  emittedRunnerStarted: false,
8709
- lastProgressSignature: null
8916
+ lastProgressSignature: null,
8917
+ lastProgressHeartbeatAt: 0,
8918
+ lastStatusHeartbeatAt: 0
8710
8919
  };
8711
8920
  const controller = new AbortController();
8712
8921
  let timedOut = false;
@@ -8747,7 +8956,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8747
8956
  dashboardUrl,
8748
8957
  noOpen: input2.noOpen
8749
8958
  });
8750
- input2.progress.phase(`loading play on ${dashboardUrl}`);
8959
+ input2.progress.phase("running");
8751
8960
  emittedDashboardUrl = true;
8752
8961
  }
8753
8962
  assertPlayWaitNotTimedOut({
@@ -8778,11 +8987,20 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8778
8987
  progress: input2.progress
8779
8988
  });
8780
8989
  if (!input2.jsonOutput) {
8990
+ const progressLines = getProgressLinesFromLiveEvent(event);
8781
8991
  printPlayProgressLines({
8782
- lines: getProgressLinesFromLiveEvent(event),
8992
+ lines: progressLines,
8783
8993
  state,
8784
8994
  progress: input2.progress
8785
8995
  });
8996
+ if (progressLines.length === 0) {
8997
+ printPlayStatusHeartbeat({
8998
+ event,
8999
+ playName: input2.playName,
9000
+ state,
9001
+ progress: input2.progress
9002
+ });
9003
+ }
8786
9004
  }
8787
9005
  const finalStatus = getFinalStatusFromLiveEvent(event);
8788
9006
  if (finalStatus) {
@@ -9382,6 +9600,17 @@ function getPlayRunPackage(status) {
9382
9600
  const packaged = status.package;
9383
9601
  return isPlayRunPackageValue(packaged) ? packaged : null;
9384
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
+ }
9385
9614
  function compactPlayStatus(status) {
9386
9615
  const packaged = getPlayRunPackage(status);
9387
9616
  if (packaged) {
@@ -9558,6 +9787,9 @@ function actionToCommand(action) {
9558
9787
  if (record.kind === "deepline_run_inspect" && typeof record.runId === "string") {
9559
9788
  return `deepline runs get ${record.runId} --json`;
9560
9789
  }
9790
+ if (record.kind === "deepline_run_billing" && typeof record.runId === "string") {
9791
+ return `deepline runs get ${record.runId} --full --json | jq '.billing'`;
9792
+ }
9561
9793
  if (record.kind === "deepline_run_export" && typeof record.runId === "string" && typeof record.datasetPath === "string") {
9562
9794
  return `deepline runs export ${record.runId} --dataset ${shellSingleQuote(
9563
9795
  record.datasetPath
@@ -9590,6 +9822,12 @@ function buildRunPackageTextLines(packaged) {
9590
9822
  if (playName) {
9591
9823
  lines.push(` play: ${playName}`);
9592
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
+ }
9593
9831
  for (const step of readRecordArray(packaged.steps).slice(0, 8)) {
9594
9832
  const id = typeof step.id === "string" ? step.id : "step";
9595
9833
  const kind = typeof step.kind === "string" ? step.kind : "step";
@@ -9606,12 +9844,12 @@ function buildRunPackageTextLines(packaged) {
9606
9844
  );
9607
9845
  }
9608
9846
  }
9609
- const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
9610
9847
  const datasetActions = readFirstDatasetActions(packaged);
9611
9848
  const inspectCommand = actionToCommand(next.inspect);
9612
9849
  const queryCommand = actionToCommand(next.query) ?? actionToCommand(datasetActions.query);
9613
9850
  const exportCommand = actionToCommand(next.export) ?? actionToCommand(datasetActions.exportCsv);
9614
9851
  if (inspectCommand) lines.push(` inspect: ${inspectCommand}`);
9852
+ if (billingCommand) lines.push(` billing: ${billingCommand}`);
9615
9853
  if (queryCommand) lines.push(` query: ${queryCommand}`);
9616
9854
  if (exportCommand) lines.push(` export CSV: ${exportCommand}`);
9617
9855
  return lines;
@@ -10653,11 +10891,14 @@ async function handleFileBackedRun(options) {
10653
10891
  } else {
10654
10892
  progress.fail();
10655
10893
  }
10656
- const outputStatus = await resolvePlayRunOutputStatus({
10657
- client,
10658
- status: finalStatus,
10659
- fullJson: options.fullJson
10660
- });
10894
+ const outputStatus = withTerminalPlayIdentity(
10895
+ await resolvePlayRunOutputStatus({
10896
+ client,
10897
+ status: finalStatus,
10898
+ fullJson: options.fullJson
10899
+ }),
10900
+ playName
10901
+ );
10661
10902
  traceCliSync(
10662
10903
  "cli.play_write_result",
10663
10904
  { targetKind: "file", playName },
@@ -10680,7 +10921,7 @@ async function handleFileBackedRun(options) {
10680
10921
  dashboardUrl: resolvedDashboardUrl,
10681
10922
  noOpen: options.noOpen
10682
10923
  });
10683
- progress.phase(`loading play on ${resolvedDashboardUrl}`);
10924
+ progress.phase("started run");
10684
10925
  progress.complete();
10685
10926
  writeStartedPlayRun({
10686
10927
  runId: started.workflowId,
@@ -10800,11 +11041,14 @@ async function handleNamedRun(options) {
10800
11041
  } else {
10801
11042
  progress.fail();
10802
11043
  }
10803
- const outputStatus = await resolvePlayRunOutputStatus({
10804
- client,
10805
- status: finalStatus,
10806
- fullJson: options.fullJson
10807
- });
11044
+ const outputStatus = withTerminalPlayIdentity(
11045
+ await resolvePlayRunOutputStatus({
11046
+ client,
11047
+ status: finalStatus,
11048
+ fullJson: options.fullJson
11049
+ }),
11050
+ playName
11051
+ );
10808
11052
  traceCliSync(
10809
11053
  "cli.play_write_result",
10810
11054
  { targetKind: "name", playName },
@@ -10827,7 +11071,7 @@ async function handleNamedRun(options) {
10827
11071
  dashboardUrl: resolvedDashboardUrl,
10828
11072
  noOpen: options.noOpen
10829
11073
  });
10830
- progress.phase(`loading play on ${resolvedDashboardUrl}`);
11074
+ progress.phase("started run");
10831
11075
  progress.complete();
10832
11076
  writeStartedPlayRun({
10833
11077
  runId: started.workflowId,
@@ -11315,16 +11559,19 @@ function parsePlaySearchOptions(args) {
11315
11559
  const query = args[0]?.trim();
11316
11560
  if (!query) {
11317
11561
  throw new Error(
11318
- "Usage: deepline plays search <query> [--compact] [--json]"
11562
+ "Usage: deepline plays search <query> [--all] [--compact] [--json]"
11319
11563
  );
11320
11564
  }
11321
11565
  return {
11322
11566
  query,
11323
11567
  jsonOutput: argsWantJson(args),
11324
11568
  compact: args.includes("--compact"),
11325
- prebuiltOnly: args.includes("--prebuilt")
11569
+ scope: args.includes("--all") && !args.includes("--prebuilt") ? "all" : "prebuilt"
11326
11570
  };
11327
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
+ }
11328
11575
  function printPlayDescription(play) {
11329
11576
  const reference = formatPlayListReference(play);
11330
11577
  const labels = [
@@ -11466,19 +11713,26 @@ async function handlePlaySearch(args) {
11466
11713
  return 1;
11467
11714
  }
11468
11715
  const client = new DeeplineClient();
11469
- const plays = (await client.searchPlays({
11716
+ const plays = await client.searchPlays({
11470
11717
  query: options.query,
11471
- compact: options.compact
11472
- })).filter(
11473
- (play) => options.prebuiltOnly ? play.origin === "prebuilt" || play.ownerType === "deepline" : true
11474
- );
11718
+ compact: options.compact,
11719
+ scope: options.scope
11720
+ });
11721
+ const disclaimer = playSearchDisclaimer(options.scope);
11475
11722
  if (options.jsonOutput) {
11476
- const jsonPlays = options.prebuiltOnly ? plays.map((play) => ({
11723
+ const jsonPlays = options.scope === "prebuilt" ? plays.map((play) => ({
11477
11724
  ...play,
11478
11725
  inputSchema: compactPlaySchema(play.inputSchema)
11479
11726
  })) : plays;
11480
11727
  process.stdout.write(
11481
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
+ },
11482
11736
  plays: jsonPlays,
11483
11737
  total: jsonPlays.length,
11484
11738
  truncated: false
@@ -11487,21 +11741,23 @@ async function handlePlaySearch(args) {
11487
11741
  );
11488
11742
  return 0;
11489
11743
  }
11490
- 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
+ `);
11491
11747
  process.stdout.write(
11492
- `${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}` : ""}:
11493
11749
 
11494
11750
  `
11495
11751
  );
11496
11752
  for (const play of displayPlays) {
11497
- if (options.prebuiltOnly) {
11753
+ if (options.scope === "prebuilt") {
11498
11754
  printCompactPlaySearchResult(play);
11499
11755
  } else {
11500
11756
  printPlayDescription(play);
11501
11757
  }
11502
11758
  console.log("");
11503
11759
  }
11504
- if (options.prebuiltOnly && plays.length > displayPlays.length) {
11760
+ if (options.scope === "prebuilt" && plays.length > displayPlays.length) {
11505
11761
  console.log("Use --json for the full machine-readable result set.");
11506
11762
  }
11507
11763
  return 0;
@@ -11955,18 +12211,26 @@ Examples:
11955
12211
  ...options.json ? ["--json"] : []
11956
12212
  ]);
11957
12213
  });
11958
- 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(
11959
12221
  "after",
11960
12222
  `
11961
12223
  Notes:
11962
- Ranked discovery for workflows. Use describe on a result before running it.
11963
- Prefer --prebuilt for new GTM tasks so old workspace scratchpads do not
11964
- 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.
11965
12228
  The grep alias is the same ranked retrieval surface with a more literal name
11966
12229
  for agents that are filtering the play registry.
11967
12230
 
11968
12231
  Examples:
11969
12232
  deepline plays search email
12233
+ deepline plays search email --all
11970
12234
  deepline plays grep "linkedin to email" --compact --json
11971
12235
  deepline plays describe person-linkedin-to-email --json
11972
12236
  `
@@ -11974,6 +12238,7 @@ Examples:
11974
12238
  process.exitCode = await handlePlaySearch([
11975
12239
  query,
11976
12240
  ...options.prebuilt ? ["--prebuilt"] : [],
12241
+ ...options.all ? ["--all"] : [],
11977
12242
  ...options.compact ? ["--compact"] : [],
11978
12243
  ...options.json ? ["--json"] : []
11979
12244
  ]);
@@ -13741,7 +14006,7 @@ async function readHiddenLine(prompt) {
13741
14006
  if (typeof import_node_process.stdin.setRawMode === "function") import_node_process.stdin.setRawMode(true);
13742
14007
  let value = "";
13743
14008
  import_node_process.stdin.resume();
13744
- return await new Promise((resolve13, reject) => {
14009
+ return await new Promise((resolve14, reject) => {
13745
14010
  let settled = false;
13746
14011
  const cleanup = () => {
13747
14012
  import_node_process.stdin.off("data", onData);
@@ -13756,7 +14021,7 @@ async function readHiddenLine(prompt) {
13756
14021
  settled = true;
13757
14022
  import_node_process.stdout.write("\n");
13758
14023
  cleanup();
13759
- resolve13(line);
14024
+ resolve14(line);
13760
14025
  };
13761
14026
  const fail = (error) => {
13762
14027
  if (settled) return;
@@ -14521,7 +14786,13 @@ Examples:
14521
14786
  ).option(
14522
14787
  "--json [payload]",
14523
14788
  "Emit JSON output. Use `--input` or `--payload` for passing JSON params."
14524
- ).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(
14525
14796
  "--output-format <format>",
14526
14797
  "Output format: auto, csv, csv_file, json, or json_file"
14527
14798
  ).option(
@@ -15092,6 +15363,57 @@ function normalizeOutputFormat(raw) {
15092
15363
  throw new Error(`Invalid value for --output-format: ${raw}`);
15093
15364
  }
15094
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
+ }
15095
15417
  function parseExecuteOptions(args) {
15096
15418
  const toolId = args[0];
15097
15419
  if (!toolId) {
@@ -15114,12 +15436,15 @@ function parseExecuteOptions(args) {
15114
15436
  const next = args[index + 1];
15115
15437
  outputFormat = "json";
15116
15438
  if (next && !next.startsWith("--")) {
15117
- Object.assign(params, JSON.parse(args[++index]));
15439
+ Object.assign(
15440
+ params,
15441
+ parseJsonObjectArgument(args[++index], "--json")
15442
+ );
15118
15443
  }
15119
15444
  continue;
15120
15445
  }
15121
15446
  if ((arg === "--input" || arg === "--payload") && args[index + 1]) {
15122
- Object.assign(params, JSON.parse(args[++index]));
15447
+ Object.assign(params, parseJsonObjectArgument(args[++index], arg));
15123
15448
  continue;
15124
15449
  }
15125
15450
  if (arg === "--output-format" && args[index + 1]) {
@@ -15704,7 +16029,7 @@ function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
15704
16029
  lines.push(
15705
16030
  "",
15706
16031
  " To stay on the SDK CLI, install the SDK agent skill:",
15707
- ` ${skillsInstallCommand(baseUrl, "deepline-sdk")}`,
16032
+ ` ${skillsInstallCommand(baseUrl, "deepline-plays")}`,
15708
16033
  " To use the legacy Python CLI instead:",
15709
16034
  ` ${legacyPythonInstallCommand(baseUrl)}`,
15710
16035
  " `deepline update` updates this SDK CLI, but it will not switch CLI families."
@@ -15717,7 +16042,7 @@ function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
15717
16042
  "",
15718
16043
  " To use SDK commands, install the SDK CLI and SDK agent skill:",
15719
16044
  ` ${sdkNpmGlobalInstallCommand()}`,
15720
- ` ${skillsInstallCommand(baseUrl, "deepline-sdk")}`,
16045
+ ` ${skillsInstallCommand(baseUrl, "deepline-plays")}`,
15721
16046
  " `deepline update` updates this Python CLI and its skills, but it will not switch CLI families."
15722
16047
  );
15723
16048
  if (compatibility.python_alternative) {
@@ -15738,12 +16063,29 @@ var import_node_fs14 = require("fs");
15738
16063
  var import_node_os10 = require("os");
15739
16064
  var import_node_path17 = require("path");
15740
16065
  var CHECK_TIMEOUT_MS2 = 3e3;
15741
- var SDK_SKILL_NAME = "deepline-sdk";
16066
+ var SDK_SKILL_NAME = "deepline-plays";
15742
16067
  var attemptedSync = false;
15743
16068
  function shouldSkipSkillsSync() {
15744
16069
  const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
15745
16070
  return value === "1" || value === "true" || value === "yes" || value === "on";
15746
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
+ }
15747
16089
  function sdkSkillsVersionPath(baseUrl) {
15748
16090
  const home = process.env.HOME?.trim() || (0, import_node_os10.homedir)();
15749
16091
  return (0, import_node_path17.join)(
@@ -15756,6 +16098,8 @@ function sdkSkillsVersionPath(baseUrl) {
15756
16098
  );
15757
16099
  }
15758
16100
  function readLocalSkillsVersion(baseUrl) {
16101
+ const pluginVersion = readPluginSkillsVersion();
16102
+ if (pluginVersion) return pluginVersion;
15759
16103
  const path = sdkSkillsVersionPath(baseUrl);
15760
16104
  if (!(0, import_node_fs14.existsSync)(path)) return "";
15761
16105
  try {
@@ -15772,7 +16116,8 @@ function writeLocalSkillsVersion(baseUrl, version) {
15772
16116
  }
15773
16117
  function installedSdkSkillHasStalePositionalExecuteExamples() {
15774
16118
  const home = process.env.HOME?.trim() || (0, import_node_os10.homedir)();
15775
- const roots = [
16119
+ const pluginSkillsDir = activePluginSkillsDir();
16120
+ const roots = pluginSkillsDir ? [(0, import_node_path17.join)(pluginSkillsDir, SDK_SKILL_NAME)] : [
15776
16121
  (0, import_node_path17.join)(home, ".claude", "skills", SDK_SKILL_NAME),
15777
16122
  (0, import_node_path17.join)(home, ".agents", "skills", SDK_SKILL_NAME)
15778
16123
  ];
@@ -15871,7 +16216,7 @@ function resolveSkillsInstallCommands(baseUrl) {
15871
16216
  return [npxInstall];
15872
16217
  }
15873
16218
  function runOneSkillsInstall(install) {
15874
- return new Promise((resolve13) => {
16219
+ return new Promise((resolve14) => {
15875
16220
  const child = (0, import_node_child_process2.spawn)(install.command, install.args, {
15876
16221
  stdio: ["ignore", "ignore", "pipe"],
15877
16222
  env: process.env
@@ -15881,7 +16226,7 @@ function runOneSkillsInstall(install) {
15881
16226
  stderr += chunk.toString("utf-8");
15882
16227
  });
15883
16228
  child.on("error", (error) => {
15884
- resolve13({
16229
+ resolve14({
15885
16230
  ok: false,
15886
16231
  detail: `failed to start ${install.command}: ${error.message}`,
15887
16232
  manualCommand: install.manualCommand
@@ -15889,11 +16234,11 @@ function runOneSkillsInstall(install) {
15889
16234
  });
15890
16235
  child.on("close", (code) => {
15891
16236
  if (code === 0) {
15892
- resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
16237
+ resolve14({ ok: true, detail: "", manualCommand: install.manualCommand });
15893
16238
  return;
15894
16239
  }
15895
16240
  const detail = stderr.trim();
15896
- resolve13({
16241
+ resolve14({
15897
16242
  ok: false,
15898
16243
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
15899
16244
  manualCommand: install.manualCommand
@@ -15930,18 +16275,22 @@ function writeSdkSkillsStatusLine(line) {
15930
16275
  async function syncSdkSkillsIfNeeded(baseUrl) {
15931
16276
  if (attemptedSync || shouldSkipSkillsSync()) return;
15932
16277
  attemptedSync = true;
16278
+ const usingPluginSkills = Boolean(activePluginSkillsDir());
15933
16279
  const localVersion = readLocalSkillsVersion(baseUrl);
15934
16280
  const update = await fetchSkillsUpdate(baseUrl, localVersion);
15935
16281
  const hasStaleInstalledSkill = installedSdkSkillHasStalePositionalExecuteExamples();
16282
+ if (usingPluginSkills) {
16283
+ return;
16284
+ }
15936
16285
  if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
15937
16286
  return;
15938
16287
  }
15939
- writeSdkSkillsStatusLine("SDK skills changed; syncing deepline-sdk skill...");
16288
+ writeSdkSkillsStatusLine("SDK skills changed; syncing deepline-plays skill...");
15940
16289
  const installed = await runSkillsInstall(baseUrl);
15941
16290
  if (!installed) return;
15942
16291
  if (installedSdkSkillHasStalePositionalExecuteExamples()) {
15943
16292
  process.stderr.write(
15944
- "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"
15945
16294
  );
15946
16295
  return;
15947
16296
  }