deepline 0.1.129 → 0.1.131

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
@@ -183,7 +183,7 @@ configureProxyFromEnv();
183
183
  // src/cli/index.ts
184
184
  var import_promises5 = require("fs/promises");
185
185
  var import_node_path19 = require("path");
186
- var import_node_os15 = require("os");
186
+ var import_node_os14 = require("os");
187
187
  var import_commander3 = require("commander");
188
188
 
189
189
  // src/config.ts
@@ -310,6 +310,15 @@ function sdkCliConfigDir(baseUrl) {
310
310
  const home = process.env.HOME?.trim() || (0, import_node_os.homedir)();
311
311
  return (0, import_node_path.join)(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL));
312
312
  }
313
+ function sdkCliStateDirPath(baseUrl, homeDir2 = process.env.HOME?.trim() || (0, import_node_os.homedir)()) {
314
+ return (0, import_node_path.join)(
315
+ homeDir2,
316
+ ".local",
317
+ "deepline",
318
+ baseUrlSlug(baseUrl || PROD_URL),
319
+ "sdk-cli"
320
+ );
321
+ }
313
322
  function sdkCliEnvFilePath(baseUrl) {
314
323
  return (0, import_node_path.join)(sdkCliConfigDir(baseUrl), ".env");
315
324
  }
@@ -404,10 +413,10 @@ var SDK_RELEASE = {
404
413
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
405
414
  // the SDK enrich generator's one-second stale policy.
406
415
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
407
- version: "0.1.129",
416
+ version: "0.1.131",
408
417
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
409
418
  supportPolicy: {
410
- latest: "0.1.129",
419
+ latest: "0.1.131",
411
420
  minimumSupported: "0.1.53",
412
421
  deprecatedBelow: "0.1.53",
413
422
  commandMinimumSupported: [
@@ -557,6 +566,10 @@ var HttpClient = class {
557
566
  if (explicit) return explicit;
558
567
  try {
559
568
  const versionPath = (0, import_node_path2.join)(
569
+ sdkCliStateDirPath(this.config.baseUrl),
570
+ "skills-version"
571
+ );
572
+ const legacyVersionPath = (0, import_node_path2.join)(
560
573
  process.env.HOME?.trim() || (0, import_node_os3.homedir)(),
561
574
  ".local",
562
575
  "deepline",
@@ -564,8 +577,9 @@ var HttpClient = class {
564
577
  "sdk-skills",
565
578
  ".version"
566
579
  );
567
- if (!(0, import_node_fs2.existsSync)(versionPath)) return null;
568
- return this.cleanDiagnosticHeader((0, import_node_fs2.readFileSync)(versionPath, "utf-8"));
580
+ const resolvedPath = (0, import_node_fs2.existsSync)(versionPath) ? versionPath : legacyVersionPath;
581
+ if (!(0, import_node_fs2.existsSync)(resolvedPath)) return null;
582
+ return this.cleanDiagnosticHeader((0, import_node_fs2.readFileSync)(resolvedPath, "utf-8"));
569
583
  } catch {
570
584
  return null;
571
585
  }
@@ -3666,15 +3680,27 @@ var import_node_fs3 = require("fs");
3666
3680
  var import_node_os4 = require("os");
3667
3681
  var import_node_path3 = require("path");
3668
3682
  var CHECK_TIMEOUT_MS = 2e3;
3669
- var COMPAT_CACHE_TTL_MS = 5 * 60 * 1e3;
3683
+ var SDK_COMPATIBILITY_CACHE_TTL_MS = 5 * 60 * 1e3;
3670
3684
  function shouldSkipCompatibilityCheck() {
3671
3685
  const value = process.env.DEEPLINE_SKIP_SDK_COMPAT_CHECK?.trim().toLowerCase();
3672
3686
  return value === "1" || value === "true" || value === "yes";
3673
3687
  }
3674
- function compatibilityCachePath() {
3675
- return (0, import_node_path3.join)((0, import_node_os4.homedir)(), ".cache", "deepline", "sdk-compat-cache.json");
3688
+ function sdkCompatibilityCachePath(baseUrl, homeDir2 = (0, import_node_os4.homedir)()) {
3689
+ return (0, import_node_path3.join)(sdkCliStateDirPath(baseUrl, homeDir2), "compat-cache.json");
3676
3690
  }
3677
- function compatibilityCacheKey(baseUrl, command) {
3691
+ function legacySdkCompatibilityCachePath(homeDir2 = (0, import_node_os4.homedir)()) {
3692
+ return (0, import_node_path3.join)(homeDir2, ".cache", "deepline", "sdk-compat-cache.json");
3693
+ }
3694
+ function compatibilityCacheKey(baseUrl, command, skillsVersion) {
3695
+ return JSON.stringify({
3696
+ baseUrl: baseUrl.replace(/\/$/, ""),
3697
+ version: SDK_VERSION,
3698
+ apiContract: SDK_API_CONTRACT,
3699
+ command: command?.trim() || null,
3700
+ skillsVersion: skillsVersion ?? null
3701
+ });
3702
+ }
3703
+ function legacyCompatibilityCacheKey(baseUrl, command) {
3678
3704
  return JSON.stringify({
3679
3705
  baseUrl: baseUrl.replace(/\/$/, ""),
3680
3706
  version: SDK_VERSION,
@@ -3682,15 +3708,20 @@ function compatibilityCacheKey(baseUrl, command) {
3682
3708
  command: command?.trim() || null
3683
3709
  });
3684
3710
  }
3685
- function readCachedCompatibility(baseUrl, command) {
3711
+ function readCachedCompatibility(baseUrl, command, skillsVersion) {
3686
3712
  try {
3687
- const path = compatibilityCachePath();
3688
- if (!(0, import_node_fs3.existsSync)(path)) {
3713
+ const path = sdkCompatibilityCachePath(baseUrl);
3714
+ const legacyPath = legacySdkCompatibilityCachePath();
3715
+ const useLegacyCache = !(0, import_node_fs3.existsSync)(path) && (0, import_node_fs3.existsSync)(legacyPath);
3716
+ const cachePath = useLegacyCache ? legacyPath : path;
3717
+ if (!(0, import_node_fs3.existsSync)(cachePath)) {
3689
3718
  return null;
3690
3719
  }
3691
- const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
3692
- const entry = parsed.entries?.[compatibilityCacheKey(baseUrl, command)];
3693
- if (!entry || Date.now() - entry.savedAt > COMPAT_CACHE_TTL_MS) {
3720
+ const parsed = JSON.parse(
3721
+ (0, import_node_fs3.readFileSync)(cachePath, "utf8")
3722
+ );
3723
+ const entry = parsed.entries?.[compatibilityCacheKey(baseUrl, command, skillsVersion)] ?? (useLegacyCache ? parsed.entries?.[legacyCompatibilityCacheKey(baseUrl, command)] : void 0);
3724
+ if (!entry || Date.now() - entry.savedAt > SDK_COMPATIBILITY_CACHE_TTL_MS) {
3694
3725
  return null;
3695
3726
  }
3696
3727
  return entry.response;
@@ -3698,12 +3729,12 @@ function readCachedCompatibility(baseUrl, command) {
3698
3729
  return null;
3699
3730
  }
3700
3731
  }
3701
- function writeCachedCompatibility(baseUrl, command, response) {
3732
+ function writeCachedCompatibility(baseUrl, command, skillsVersion, response) {
3702
3733
  try {
3703
- const path = compatibilityCachePath();
3734
+ const path = sdkCompatibilityCachePath(baseUrl);
3704
3735
  const existing = (0, import_node_fs3.existsSync)(path) ? JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8")) : {};
3705
3736
  const entries = existing.entries ?? {};
3706
- entries[compatibilityCacheKey(baseUrl, command)] = {
3737
+ entries[compatibilityCacheKey(baseUrl, command, skillsVersion)] = {
3707
3738
  savedAt: Date.now(),
3708
3739
  response
3709
3740
  };
@@ -3725,6 +3756,9 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
3725
3756
  if (options.command?.trim()) {
3726
3757
  url.searchParams.set("command", options.command.trim());
3727
3758
  }
3759
+ if (options.skillsVersion !== void 0) {
3760
+ url.searchParams.set("skills_version", options.skillsVersion ?? "");
3761
+ }
3728
3762
  const response = await fetch(url, {
3729
3763
  method: "GET",
3730
3764
  headers: {
@@ -3736,12 +3770,21 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
3736
3770
  });
3737
3771
  const data = await response.json().catch(() => null);
3738
3772
  if (data) {
3739
- writeCachedCompatibility(baseUrl, options.command, data);
3773
+ writeCachedCompatibility(
3774
+ baseUrl,
3775
+ options.command,
3776
+ options.skillsVersion,
3777
+ data
3778
+ );
3740
3779
  }
3741
3780
  return { response: data, error: null };
3742
3781
  } catch (error) {
3743
- const cached = readCachedCompatibility(baseUrl, options.command);
3744
- if (cached?.ok === false || cached?.status === "unsupported") {
3782
+ const cached = readCachedCompatibility(
3783
+ baseUrl,
3784
+ options.command,
3785
+ options.skillsVersion
3786
+ );
3787
+ if (cached) {
3745
3788
  return { response: cached, error: null };
3746
3789
  }
3747
3790
  return {
@@ -3771,6 +3814,7 @@ var import_node_os6 = require("os");
3771
3814
  var import_node_path5 = require("path");
3772
3815
 
3773
3816
  // src/cli/utils.ts
3817
+ var import_node_crypto = require("crypto");
3774
3818
  var import_node_fs4 = require("fs");
3775
3819
  var import_promises = require("fs/promises");
3776
3820
  var import_node_os5 = require("os");
@@ -3779,6 +3823,7 @@ var childProcess = __toESM(require("child_process"));
3779
3823
  var import_sync = require("csv-parse/sync");
3780
3824
  var import_sync2 = require("csv-stringify/sync");
3781
3825
  var BROWSER_OPEN_COOLDOWN_MS = 3e4;
3826
+ var SAME_URL_BROWSER_OPEN_COOLDOWN_MS = 5 * 6e4;
3782
3827
  var defaultBrowserCommandRunner = childProcess;
3783
3828
  function getAuthedHttpClient() {
3784
3829
  const config = resolveConfig();
@@ -3791,25 +3836,37 @@ async function writeOutputFile(filename, content) {
3791
3836
  await (0, import_promises.writeFile)(fullPath, content, "utf-8");
3792
3837
  return fullPath;
3793
3838
  }
3794
- function browserOpenStateFile() {
3795
- const homeDir2 = process.env.HOME || (0, import_node_os5.homedir)();
3796
- return (0, import_node_path4.join)(
3797
- homeDir2,
3798
- ".local",
3799
- "deepline",
3800
- "runtime",
3801
- "state",
3802
- "browser-open.json"
3803
- );
3839
+ function stableOsUserId() {
3840
+ try {
3841
+ const info = (0, import_node_os5.userInfo)();
3842
+ if (typeof info.uid === "number") return `uid-${info.uid}`;
3843
+ if (info.username) return `user-${info.username}`;
3844
+ } catch {
3845
+ }
3846
+ return "unknown-user";
3847
+ }
3848
+ function defaultBrowserOpenStateDir() {
3849
+ return (0, import_node_path4.join)((0, import_node_os5.tmpdir)(), `deepline-${stableOsUserId()}`, "runtime", "state");
3850
+ }
3851
+ function browserOpenStateFile(stateDir = defaultBrowserOpenStateDir()) {
3852
+ return (0, import_node_path4.join)(stateDir, "browser-open.json");
3853
+ }
3854
+ function normalizeBrowserOpenTarget(raw) {
3855
+ return String(raw || "").trim();
3804
3856
  }
3805
- function claimBrowserOpen(now = Date.now()) {
3806
- const statePath = browserOpenStateFile();
3857
+ function browserOpenTargetKey(raw) {
3858
+ const normalized = normalizeBrowserOpenTarget(raw);
3859
+ return normalized ? (0, import_node_crypto.createHash)("sha256").update(normalized).digest("hex") : "";
3860
+ }
3861
+ function claimBrowserOpen(now = Date.now(), stateDir, targetUrl) {
3862
+ const statePath = browserOpenStateFile(stateDir);
3807
3863
  const lockPath = `${statePath}.lock`;
3864
+ const targetKey = browserOpenTargetKey(targetUrl);
3808
3865
  let locked = false;
3809
3866
  try {
3810
- (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(statePath), { recursive: true });
3867
+ (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(statePath), { recursive: true, mode: 448 });
3811
3868
  try {
3812
- (0, import_node_fs4.mkdirSync)(lockPath);
3869
+ (0, import_node_fs4.mkdirSync)(lockPath, { mode: 448 });
3813
3870
  locked = true;
3814
3871
  } catch {
3815
3872
  return false;
@@ -3821,14 +3878,24 @@ function claimBrowserOpen(now = Date.now()) {
3821
3878
  if (typeof value === "number" && Number.isFinite(value)) {
3822
3879
  lastOpenedAt = value;
3823
3880
  }
3881
+ const targetValue = payload.targetKey ?? payload.target_key ?? payload.targetHash ?? payload.target_hash;
3882
+ const lastTargetKey = typeof targetValue === "string" ? targetValue.trim() : "";
3883
+ const cooldownMs = targetKey && targetKey === lastTargetKey ? SAME_URL_BROWSER_OPEN_COOLDOWN_MS : BROWSER_OPEN_COOLDOWN_MS;
3884
+ if (lastOpenedAt > now) {
3885
+ lastOpenedAt = 0;
3886
+ }
3887
+ if (now - lastOpenedAt < cooldownMs) {
3888
+ return false;
3889
+ }
3824
3890
  }
3825
- if (lastOpenedAt > now) {
3826
- lastOpenedAt = 0;
3827
- }
3828
- if (now - lastOpenedAt < BROWSER_OPEN_COOLDOWN_MS) {
3829
- return false;
3830
- }
3831
- (0, import_node_fs4.writeFileSync)(statePath, JSON.stringify({ lastOpenedAt: now }), "utf-8");
3891
+ (0, import_node_fs4.writeFileSync)(
3892
+ statePath,
3893
+ JSON.stringify({
3894
+ lastOpenedAt: now,
3895
+ ...targetKey ? { targetKey } : {}
3896
+ }),
3897
+ { encoding: "utf-8", mode: 384 }
3898
+ );
3832
3899
  return true;
3833
3900
  } catch {
3834
3901
  return true;
@@ -3860,6 +3927,30 @@ function browserAppNameFromBundleId(bundleId) {
3860
3927
  };
3861
3928
  return names[bundleId.toLowerCase()] ?? "";
3862
3929
  }
3930
+ function currentOsUsername() {
3931
+ try {
3932
+ return (0, import_node_os5.userInfo)().username || "";
3933
+ } catch {
3934
+ return "";
3935
+ }
3936
+ }
3937
+ function readMacosUserHome(runner = defaultBrowserCommandRunner) {
3938
+ const username = currentOsUsername();
3939
+ if (process.platform === "darwin" && username) {
3940
+ try {
3941
+ const output2 = runner.execFileSync(
3942
+ "dscl",
3943
+ [".", "-read", `/Users/${username}`, "NFSHomeDirectory"],
3944
+ { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
3945
+ );
3946
+ const match = String(output2).match(/NFSHomeDirectory:\s*(.+)\s*$/m);
3947
+ const home = match?.[1]?.trim();
3948
+ if (home) return home;
3949
+ } catch {
3950
+ }
3951
+ }
3952
+ return (0, import_node_os5.homedir)();
3953
+ }
3863
3954
  function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
3864
3955
  try {
3865
3956
  const output2 = runner.execFileSync(
@@ -3869,7 +3960,7 @@ function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
3869
3960
  "json",
3870
3961
  "-o",
3871
3962
  "-",
3872
- `${(0, import_node_os5.homedir)()}/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist`
3963
+ `${readMacosUserHome(runner)}/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist`
3873
3964
  ],
3874
3965
  { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
3875
3966
  );
@@ -4016,7 +4107,7 @@ function openInBrowser(url) {
4016
4107
  if (browserOpeningDisabled()) return;
4017
4108
  const targetUrl = String(url || "").trim();
4018
4109
  if (!targetUrl) return;
4019
- if (!claimBrowserOpen()) return;
4110
+ if (!claimBrowserOpen(Date.now(), void 0, targetUrl)) return;
4020
4111
  const allowFocus = true;
4021
4112
  if (process.platform === "darwin") {
4022
4113
  openUrlMacos(targetUrl, allowFocus);
@@ -4118,12 +4209,15 @@ function flattenObjectColumns(row) {
4118
4209
  const hasMatchedEnvelope = Object.prototype.hasOwnProperty.call(record, "matched_result") || Object.prototype.hasOwnProperty.call(record, "matchedResult");
4119
4210
  if (hasMatchedEnvelope) {
4120
4211
  flattened[key] = JSON.stringify(record);
4212
+ continue;
4121
4213
  } else {
4122
4214
  const failureMessage = failureMessageFromRecord(record);
4123
4215
  if (failureMessage) {
4124
4216
  flattened[key] = failureMessage;
4217
+ continue;
4125
4218
  } else if (Object.prototype.hasOwnProperty.call(record, "result")) {
4126
4219
  flattened[key] = JSON.stringify(record);
4220
+ continue;
4127
4221
  }
4128
4222
  }
4129
4223
  for (const [nestedKey, nestedValue] of Object.entries(record)) {
@@ -6861,7 +6955,7 @@ var import_node_os7 = require("os");
6861
6955
  var import_node_path11 = require("path");
6862
6956
 
6863
6957
  // src/cli/commands/play.ts
6864
- var import_node_crypto = require("crypto");
6958
+ var import_node_crypto2 = require("crypto");
6865
6959
  var import_node_fs9 = require("fs");
6866
6960
  var import_node_path10 = require("path");
6867
6961
  var import_sync5 = require("csv-parse/sync");
@@ -9479,7 +9573,7 @@ function stageFile(logicalPath, absolutePath) {
9479
9573
  return {
9480
9574
  logicalPath,
9481
9575
  contentBase64: buffer.toString("base64"),
9482
- contentHash: (0, import_node_crypto.createHash)("sha256").update(buffer).digest("hex"),
9576
+ contentHash: (0, import_node_crypto2.createHash)("sha256").update(buffer).digest("hex"),
9483
9577
  contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
9484
9578
  bytes: buffer.byteLength
9485
9579
  };
@@ -14834,9 +14928,7 @@ function renderExecuteStep(command, options = {
14834
14928
  const extractJs = command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
14835
14929
  ${indent(renderJavascriptBody(command.extract_js), 6)}
14836
14930
  }` : "null";
14837
- const runIfJs = command.run_if_js ? `(row) => { const input = row; const context = row;
14838
- ${indent(renderJavascriptBody(command.run_if_js), 6)}
14839
- }` : "null";
14931
+ const runIfJs = options.nativeRunIf ? "null" : renderRunIfFunction(command) ?? "null";
14840
14932
  const description = command.description ? `,
14841
14933
  description: ${stringLiteral(command.description)}` : "";
14842
14934
  const force = options.force ? `,
@@ -14861,13 +14953,35 @@ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14861
14953
  `}`
14862
14954
  ].join("\n");
14863
14955
  }
14956
+ function renderRunIfFunction(command) {
14957
+ return command.run_if_js ? `(row) => { const input = row; const context = row;
14958
+ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14959
+ }` : null;
14960
+ }
14961
+ function renderColumnRunIfFunction(command) {
14962
+ if (!command.run_if_js) {
14963
+ return null;
14964
+ }
14965
+ if (command.play) {
14966
+ return `(__dlRawRow) => { const row = __dlPrepareEnrichRow(__dlRawRow, [${stringLiteral(command.alias)}]); const input = row; const context = row;
14967
+ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14968
+ }`;
14969
+ }
14970
+ return renderRunIfFunction(command);
14971
+ }
14972
+ function renderCombinedRunIfFunction(precheck, runIfSource) {
14973
+ if (!runIfSource) {
14974
+ return null;
14975
+ }
14976
+ return precheck ? `(row) => { if (${precheck}) return false; return (${runIfSource})(row); }` : runIfSource;
14977
+ }
14864
14978
  function renderIdiomaticExecuteStep(command, options) {
14865
14979
  const callId = stringLiteral(commandCallId(command));
14866
14980
  const tool = stringLiteral(command.tool);
14867
14981
  const input2 = renderToolPayloadExpression(command.payload ?? {});
14868
14982
  const getter = getterFromLegacyExtractJs(command.extract_js, command.alias);
14869
14983
  const extraction = getter ? `${renderExtractedValueGetterExpression("result", getter)} ?? null` : "result";
14870
- const runIfLines = command.run_if_js ? [
14984
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14871
14985
  ` if (`,
14872
14986
  ` !((row: Record<string, any>) => {`,
14873
14987
  ` const input = row;`,
@@ -14901,10 +15015,8 @@ function renderPlayStep(command, options) {
14901
15015
  const callId = stringLiteral(commandCallId(command));
14902
15016
  const playRef = stringLiteral(command.play?.ref ?? command.tool);
14903
15017
  const payload = stableJson(command.payload ?? {});
14904
- const runIfJs = command.run_if_js ? `(row) => { const input = row; const context = row;
14905
- ${indent(renderJavascriptBody(command.run_if_js), 6)}
14906
- }` : "null";
14907
- const runIfLines = command.run_if_js ? [
15018
+ const runIfJs = renderRunIfFunction(command) ?? "null";
15019
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14908
15020
  ` const __dlRunIf = ${runIfJs};`,
14909
15021
  ` if (!__dlRunIf(templateRow)) return null;`
14910
15022
  ] : [];
@@ -14928,7 +15040,7 @@ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14928
15040
  }
14929
15041
  function renderInlineJavascriptStep(command, options) {
14930
15042
  const code = typeof command.payload?.code === "string" ? command.payload.code : "return null;";
14931
- const runIfLines = command.run_if_js ? [
15043
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14932
15044
  ` if (!((row: Record<string, any>) => { const input = row; const context = row;`,
14933
15045
  indent(renderJavascriptBody(command.run_if_js), 4),
14934
15046
  ` })(row as Record<string, any>)) return null;`
@@ -14958,7 +15070,8 @@ function renderColumnStep(alias, resolverSource, options = {}) {
14958
15070
  const resolver = indent(resolverSource, 8);
14959
15071
  const optionFields = [
14960
15072
  ...options.recompute === true ? ["recompute: true"] : [],
14961
- ...options.recomputeOnError === true ? ["recomputeOnError: true"] : []
15073
+ ...options.recomputeOnError === true ? ["recomputeOnError: true"] : [],
15074
+ ...options.runIfSource ? [`runIf: ${options.runIfSource}`] : []
14962
15075
  ];
14963
15076
  const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
14964
15077
  return [
@@ -15062,17 +15175,27 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15062
15175
  }
15063
15176
  const priorAliases = activeChildren.slice(0, stepIndex).map((prior) => prior.alias);
15064
15177
  const force = forceAliases.has(normalizeAlias(nested.alias));
15178
+ const precheck = priorAliases.length > 0 ? `__dlWaterfallSatisfied(row, ${stableJson(priorAliases)}, ${minResults})` : void 0;
15179
+ const runIfSource = renderCombinedRunIfFunction(
15180
+ precheck,
15181
+ renderColumnRunIfFunction(nested)
15182
+ );
15065
15183
  return renderColumnStep(
15066
15184
  nested.alias,
15067
15185
  renderExecuteStep(nested, {
15068
15186
  force,
15069
- precheck: priorAliases.length > 0 ? `__dlWaterfallSatisfied(row, ${stableJson(priorAliases)}, ${minResults})` : void 0,
15187
+ precheck,
15070
15188
  legacyEnvelope: Boolean(nested.extract_js),
15071
15189
  inlineRunJavascript,
15072
15190
  idiomaticGetters,
15073
- waterfallSoftFail: true
15191
+ waterfallSoftFail: true,
15192
+ nativeRunIf: Boolean(runIfSource)
15074
15193
  }),
15075
- { recompute: force, recomputeOnError: true }
15194
+ {
15195
+ recompute: force,
15196
+ recomputeOnError: true,
15197
+ runIfSource
15198
+ }
15076
15199
  );
15077
15200
  }).filter((line) => line !== null);
15078
15201
  const aliases = activeChildren.map((nested) => nested.alias);
@@ -15123,15 +15246,21 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15123
15246
  return;
15124
15247
  }
15125
15248
  const force = forceAliases.has(normalizeAlias(command.alias));
15249
+ const runIfSource = renderColumnRunIfFunction(command);
15126
15250
  columnSteps.push(
15127
15251
  renderColumnStep(
15128
15252
  command.alias,
15129
15253
  renderExecuteStep(command, {
15130
15254
  force,
15131
15255
  inlineRunJavascript,
15132
- idiomaticGetters
15256
+ idiomaticGetters,
15257
+ nativeRunIf: Boolean(runIfSource)
15133
15258
  }),
15134
- { recompute: force, recomputeOnError: true }
15259
+ {
15260
+ recompute: force,
15261
+ recomputeOnError: true,
15262
+ runIfSource
15263
+ }
15135
15264
  )
15136
15265
  );
15137
15266
  });
@@ -16993,7 +17122,7 @@ async function fetchBackingRowsForCsvExport(input2) {
16993
17122
  function mergeRowsForCsvExport(enrichedRows, options) {
16994
17123
  const rows = dataExportRows(normalizeEnrichRowsForCsvExport(enrichedRows));
16995
17124
  const range = options?.rows;
16996
- if (range?.rowStart === null || range?.rowStart === void 0) {
17125
+ if (!options?.inPlace && (range?.rowStart === null || range?.rowStart === void 0)) {
16997
17126
  return { rows, preferredColumns: [] };
16998
17127
  }
16999
17128
  if (!options?.sourceCsvPath) {
@@ -17004,9 +17133,15 @@ function mergeRowsForCsvExport(enrichedRows, options) {
17004
17133
  const baseRows = parsedBaseRows.map(
17005
17134
  (row) => ({ ...row })
17006
17135
  );
17007
- const start = Math.max(0, range.rowStart);
17136
+ const start = Math.max(0, range?.rowStart ?? 0);
17008
17137
  const maxEnd = Math.max(start, baseRows.length - 1);
17009
- const inclusiveEnd = range.rowEnd === null ? maxEnd : Math.min(maxEnd, range.rowEnd);
17138
+ const inclusiveEnd = range?.rowEnd === null || range?.rowEnd === void 0 ? maxEnd : Math.min(maxEnd, range.rowEnd);
17139
+ const expectedSelectedRows = baseRows.length === 0 ? 0 : Math.max(0, inclusiveEnd - start + 1);
17140
+ if (rows.length < expectedSelectedRows) {
17141
+ throw new Error(
17142
+ `Refusing to write a partial in-place CSV export: the run returned ${rows.length} row(s) for ${expectedSelectedRows} selected source row(s).`
17143
+ );
17144
+ }
17010
17145
  const merged = [...baseRows];
17011
17146
  let selectedIndex = 0;
17012
17147
  for (let rowIndex = start; rowIndex <= inclusiveEnd; rowIndex += 1) {
@@ -17372,7 +17507,8 @@ function registerEnrichCommand(program) {
17372
17507
  client: client2,
17373
17508
  config,
17374
17509
  sourceCsvPath,
17375
- rows
17510
+ rows,
17511
+ inPlace: Boolean(options.inPlace)
17376
17512
  }) : null;
17377
17513
  const rowsForFailureReport = exportResult?.enrichedDataRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
17378
17514
  if (options.json) {
@@ -17490,7 +17626,7 @@ var import_node_fs10 = require("fs");
17490
17626
  var import_node_os8 = require("os");
17491
17627
  var import_node_path12 = require("path");
17492
17628
  var import_node_zlib = require("zlib");
17493
- var import_node_crypto2 = require("crypto");
17629
+ var import_node_crypto3 = require("crypto");
17494
17630
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
17495
17631
  var UUID_IN_TEXT_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
17496
17632
  var MAX_SESSION_UPLOAD_BYTES = 35e5;
@@ -17852,7 +17988,7 @@ async function uploadPayload(path, payload) {
17852
17988
  return await http.post(path, payload);
17853
17989
  }
17854
17990
  async function uploadChunkedSessions(sessions, options) {
17855
- const uploadId = (0, import_node_crypto2.randomUUID)();
17991
+ const uploadId = (0, import_node_crypto3.randomUUID)();
17856
17992
  for (const session of sessions) {
17857
17993
  const bytes = Buffer.from(session.encodedContent, "base64");
17858
17994
  const chunks = [];
@@ -18497,7 +18633,7 @@ Examples:
18497
18633
 
18498
18634
  // src/cli/commands/quickstart.ts
18499
18635
  var import_node_child_process = require("child_process");
18500
- var import_node_crypto3 = require("crypto");
18636
+ var import_node_crypto4 = require("crypto");
18501
18637
  var import_node_http = require("http");
18502
18638
  var EXIT_OK2 = 0;
18503
18639
  var EXIT_AUTH2 = 1;
@@ -18626,7 +18762,7 @@ async function handleQuickstart(options) {
18626
18762
  return EXIT_AUTH2;
18627
18763
  }
18628
18764
  }
18629
- const state = (0, import_node_crypto3.randomBytes)(32).toString("hex");
18765
+ const state = (0, import_node_crypto4.randomBytes)(32).toString("hex");
18630
18766
  let resolveSelection;
18631
18767
  const selectionPromise = new Promise((resolve13) => {
18632
18768
  resolveSelection = resolve13;
@@ -20726,7 +20862,7 @@ var import_promises4 = require("fs/promises");
20726
20862
  var import_node_path16 = require("path");
20727
20863
 
20728
20864
  // src/cli/workflow-to-play.ts
20729
- var import_node_crypto4 = require("crypto");
20865
+ var import_node_crypto5 = require("crypto");
20730
20866
 
20731
20867
  // ../shared_libs/plays/secret-guardrails.ts
20732
20868
  var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
@@ -20869,7 +21005,7 @@ function sanitizePlayNameSegment(value) {
20869
21005
  }
20870
21006
  function deriveWorkflowPlayName(workflowName) {
20871
21007
  const base = sanitizePlayNameSegment(workflowName) || "workflow";
20872
- const suffix = (0, import_node_crypto4.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
21008
+ const suffix = (0, import_node_crypto5.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
20873
21009
  const reserved = suffix.length + 1;
20874
21010
  const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
20875
21011
  let name = `${base.slice(0, allowedBase)}_${suffix}`;
@@ -21250,13 +21386,12 @@ Notes:
21250
21386
  // src/cli/commands/update.ts
21251
21387
  var import_node_child_process3 = require("child_process");
21252
21388
  var import_node_fs15 = require("fs");
21253
- var import_node_os13 = require("os");
21389
+ var import_node_os12 = require("os");
21254
21390
  var import_node_path18 = require("path");
21255
21391
 
21256
21392
  // src/cli/skills-sync.ts
21257
21393
  var import_node_child_process2 = require("child_process");
21258
21394
  var import_node_fs14 = require("fs");
21259
- var import_node_os12 = require("os");
21260
21395
  var import_node_path17 = require("path");
21261
21396
 
21262
21397
  // ../shared_libs/cli/install-commands.json
@@ -21388,20 +21523,15 @@ function readPluginSkillsVersion() {
21388
21523
  }
21389
21524
  }
21390
21525
  function sdkSkillsVersionPath(baseUrl) {
21391
- const home = process.env.HOME?.trim() || (0, import_node_os12.homedir)();
21392
- return (0, import_node_path17.join)(
21393
- home,
21394
- ".local",
21395
- "deepline",
21396
- baseUrlSlug(baseUrl),
21397
- "sdk-skills",
21398
- ".version"
21399
- );
21526
+ return (0, import_node_path17.join)(sdkCliStateDirPath(baseUrl), "skills-version");
21527
+ }
21528
+ function legacySdkSkillsVersionPath(baseUrl) {
21529
+ return (0, import_node_path17.join)((0, import_node_path17.dirname)(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
21400
21530
  }
21401
- function readLocalSkillsVersion(baseUrl) {
21531
+ function readSdkSkillsLocalVersion(baseUrl) {
21402
21532
  const pluginVersion = readPluginSkillsVersion();
21403
21533
  if (pluginVersion) return pluginVersion;
21404
- const path = sdkSkillsVersionPath(baseUrl);
21534
+ const path = (0, import_node_fs14.existsSync)(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
21405
21535
  if (!(0, import_node_fs14.existsSync)(path)) return "";
21406
21536
  try {
21407
21537
  return (0, import_node_fs14.readFileSync)(path, "utf-8").trim();
@@ -21611,15 +21741,18 @@ function writeSdkSkillsStatusLine(line) {
21611
21741
  process.stderr.write(`${line}
21612
21742
  `);
21613
21743
  }
21614
- async function syncSdkSkillsIfNeeded(baseUrl) {
21744
+ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
21615
21745
  if (attemptedSync || shouldSkipSkillsSync()) return;
21616
21746
  attemptedSync = true;
21617
21747
  const usingPluginSkills = Boolean(activePluginSkillsDir());
21618
- const localVersion = readLocalSkillsVersion(baseUrl);
21619
- const update = await fetchSkillsUpdate(baseUrl, localVersion);
21620
21748
  if (usingPluginSkills) {
21621
21749
  return;
21622
21750
  }
21751
+ const localVersion = readSdkSkillsLocalVersion(baseUrl);
21752
+ const update = options.update === void 0 ? await fetchSkillsUpdate(baseUrl, localVersion) : options.update ? {
21753
+ needsUpdate: options.update.needs_update,
21754
+ remoteVersion: options.update.remote.version
21755
+ } : null;
21623
21756
  if (!update?.needsUpdate || !update.remoteVersion) {
21624
21757
  return;
21625
21758
  }
@@ -21737,7 +21870,7 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
21737
21870
  }
21738
21871
  function resolveUpdatePlan(options = {}) {
21739
21872
  const env = options.env ?? process.env;
21740
- const homeDir2 = options.homeDir ?? (0, import_node_os13.homedir)();
21873
+ const homeDir2 = options.homeDir ?? (0, import_node_os12.homedir)();
21741
21874
  const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path18.resolve)(process.argv[1]) : "");
21742
21875
  const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path18.dirname)(entrypoint)) : null;
21743
21876
  if (sourceRoot) {
@@ -21773,7 +21906,7 @@ function autoUpdateFailurePath(plan) {
21773
21906
  return (0, import_node_path18.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
21774
21907
  }
21775
21908
  return (0, import_node_path18.join)(
21776
- (0, import_node_os13.homedir)(),
21909
+ (0, import_node_os12.homedir)(),
21777
21910
  ".local",
21778
21911
  "deepline",
21779
21912
  "sdk-cli",
@@ -22273,7 +22406,7 @@ async function maybeAutoUpdateAndRelaunch(response) {
22273
22406
  }
22274
22407
 
22275
22408
  // src/cli/failure-reporting.ts
22276
- var import_node_os14 = require("os");
22409
+ var import_node_os13 = require("os");
22277
22410
  var FAILURE_REPORT_DISABLE_ENV = "DEEPLINE_DISABLE_FAILURE_REPORTING";
22278
22411
  var REPORT_FAILURE_TIMEOUT_MS = 1e4;
22279
22412
  var MAX_FAILURE_TEXT_CHARS = 4e3;
@@ -22375,12 +22508,12 @@ function isNetworkFailure(error) {
22375
22508
  }
22376
22509
  function buildEnvironmentContext() {
22377
22510
  const context = {
22378
- os: (0, import_node_os14.platform)(),
22379
- os_release: (0, import_node_os14.release)(),
22380
- platform: `${(0, import_node_os14.platform)()}-${(0, import_node_os14.release)()}-${process.arch}`,
22511
+ os: (0, import_node_os13.platform)(),
22512
+ os_release: (0, import_node_os13.release)(),
22513
+ platform: `${(0, import_node_os13.platform)()}-${(0, import_node_os13.release)()}-${process.arch}`,
22381
22514
  node_version: process.version,
22382
22515
  runtime: "Node.js",
22383
- hostname: (0, import_node_os14.hostname)(),
22516
+ hostname: (0, import_node_os13.hostname)(),
22384
22517
  agent_runtime: detectAgentRuntime()
22385
22518
  };
22386
22519
  for (const key of ["CLAUDE_CODE_REMOTE", "DEEPLINE_PLUGIN_MODE"]) {
@@ -22570,7 +22703,7 @@ function topLevelCommandKnown(program, commandName) {
22570
22703
  );
22571
22704
  }
22572
22705
  async function runPlayRunnerHealthCheck() {
22573
- const dir = await (0, import_promises5.mkdtemp)((0, import_node_path19.join)((0, import_node_os15.tmpdir)(), "deepline-health-play-"));
22706
+ const dir = await (0, import_promises5.mkdtemp)((0, import_node_path19.join)((0, import_node_os14.tmpdir)(), "deepline-health-play-"));
22574
22707
  const file = (0, import_node_path19.join)(dir, "health-check.play.ts");
22575
22708
  try {
22576
22709
  await (0, import_promises5.writeFile)(
@@ -22798,11 +22931,18 @@ Exit codes:
22798
22931
  }
22799
22932
  const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
22800
22933
  const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
22934
+ const shouldDeferSkillsSync = shouldDeferSkillsSyncForCommand();
22935
+ const skillsVersion = shouldDeferSkillsSync ? void 0 : readSdkSkillsLocalVersion(baseUrl);
22801
22936
  const compatibility = await traceCliSpan(
22802
22937
  "cli.sdk_compatibility",
22803
- { baseUrl, command: compatibilityCommand },
22938
+ {
22939
+ baseUrl,
22940
+ command: compatibilityCommand,
22941
+ skillsVersion: skillsVersion ?? null
22942
+ },
22804
22943
  () => checkSdkCompatibility(baseUrl, {
22805
- command: compatibilityCommand
22944
+ command: compatibilityCommand,
22945
+ skillsVersion
22806
22946
  })
22807
22947
  );
22808
22948
  if (compatibility.error) {
@@ -22828,11 +22968,14 @@ Exit codes:
22828
22968
  if (printStartupPhase) {
22829
22969
  progress?.phase("checking sdk skills");
22830
22970
  }
22831
- if (!shouldDeferSkillsSyncForCommand()) {
22971
+ if (!shouldDeferSkillsSync) {
22972
+ const skillsUpdate = compatibility.response && Object.prototype.hasOwnProperty.call(compatibility.response, "skills") ? compatibility.response.skills ?? null : void 0;
22832
22973
  await traceCliSpan(
22833
22974
  "cli.sdk_skills_sync",
22834
22975
  { baseUrl },
22835
- () => syncSdkSkillsIfNeeded(baseUrl)
22976
+ () => syncSdkSkillsIfNeeded(baseUrl, {
22977
+ update: skillsUpdate
22978
+ })
22836
22979
  );
22837
22980
  }
22838
22981
  });