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.
@@ -160,7 +160,7 @@ configureProxyFromEnv();
160
160
  // src/cli/index.ts
161
161
  import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile5 } from "fs/promises";
162
162
  import { join as join14 } from "path";
163
- import { tmpdir as tmpdir3 } from "os";
163
+ import { tmpdir as tmpdir4 } from "os";
164
164
  import { Command as Command3 } from "commander";
165
165
 
166
166
  // src/config.ts
@@ -287,6 +287,15 @@ function sdkCliConfigDir(baseUrl) {
287
287
  const home = process.env.HOME?.trim() || homedir();
288
288
  return join(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL));
289
289
  }
290
+ function sdkCliStateDirPath(baseUrl, homeDir2 = process.env.HOME?.trim() || homedir()) {
291
+ return join(
292
+ homeDir2,
293
+ ".local",
294
+ "deepline",
295
+ baseUrlSlug(baseUrl || PROD_URL),
296
+ "sdk-cli"
297
+ );
298
+ }
290
299
  function sdkCliEnvFilePath(baseUrl) {
291
300
  return join(sdkCliConfigDir(baseUrl), ".env");
292
301
  }
@@ -381,10 +390,10 @@ var SDK_RELEASE = {
381
390
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
382
391
  // the SDK enrich generator's one-second stale policy.
383
392
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
384
- version: "0.1.129",
393
+ version: "0.1.131",
385
394
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
386
395
  supportPolicy: {
387
- latest: "0.1.129",
396
+ latest: "0.1.131",
388
397
  minimumSupported: "0.1.53",
389
398
  deprecatedBelow: "0.1.53",
390
399
  commandMinimumSupported: [
@@ -534,6 +543,10 @@ var HttpClient = class {
534
543
  if (explicit) return explicit;
535
544
  try {
536
545
  const versionPath = join2(
546
+ sdkCliStateDirPath(this.config.baseUrl),
547
+ "skills-version"
548
+ );
549
+ const legacyVersionPath = join2(
537
550
  process.env.HOME?.trim() || homedir3(),
538
551
  ".local",
539
552
  "deepline",
@@ -541,8 +554,9 @@ var HttpClient = class {
541
554
  "sdk-skills",
542
555
  ".version"
543
556
  );
544
- if (!existsSync2(versionPath)) return null;
545
- return this.cleanDiagnosticHeader(readFileSync2(versionPath, "utf-8"));
557
+ const resolvedPath = existsSync2(versionPath) ? versionPath : legacyVersionPath;
558
+ if (!existsSync2(resolvedPath)) return null;
559
+ return this.cleanDiagnosticHeader(readFileSync2(resolvedPath, "utf-8"));
546
560
  } catch {
547
561
  return null;
548
562
  }
@@ -3643,15 +3657,27 @@ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as rea
3643
3657
  import { homedir as homedir4 } from "os";
3644
3658
  import { dirname as dirname2, join as join3 } from "path";
3645
3659
  var CHECK_TIMEOUT_MS = 2e3;
3646
- var COMPAT_CACHE_TTL_MS = 5 * 60 * 1e3;
3660
+ var SDK_COMPATIBILITY_CACHE_TTL_MS = 5 * 60 * 1e3;
3647
3661
  function shouldSkipCompatibilityCheck() {
3648
3662
  const value = process.env.DEEPLINE_SKIP_SDK_COMPAT_CHECK?.trim().toLowerCase();
3649
3663
  return value === "1" || value === "true" || value === "yes";
3650
3664
  }
3651
- function compatibilityCachePath() {
3652
- return join3(homedir4(), ".cache", "deepline", "sdk-compat-cache.json");
3665
+ function sdkCompatibilityCachePath(baseUrl, homeDir2 = homedir4()) {
3666
+ return join3(sdkCliStateDirPath(baseUrl, homeDir2), "compat-cache.json");
3667
+ }
3668
+ function legacySdkCompatibilityCachePath(homeDir2 = homedir4()) {
3669
+ return join3(homeDir2, ".cache", "deepline", "sdk-compat-cache.json");
3670
+ }
3671
+ function compatibilityCacheKey(baseUrl, command, skillsVersion) {
3672
+ return JSON.stringify({
3673
+ baseUrl: baseUrl.replace(/\/$/, ""),
3674
+ version: SDK_VERSION,
3675
+ apiContract: SDK_API_CONTRACT,
3676
+ command: command?.trim() || null,
3677
+ skillsVersion: skillsVersion ?? null
3678
+ });
3653
3679
  }
3654
- function compatibilityCacheKey(baseUrl, command) {
3680
+ function legacyCompatibilityCacheKey(baseUrl, command) {
3655
3681
  return JSON.stringify({
3656
3682
  baseUrl: baseUrl.replace(/\/$/, ""),
3657
3683
  version: SDK_VERSION,
@@ -3659,15 +3685,20 @@ function compatibilityCacheKey(baseUrl, command) {
3659
3685
  command: command?.trim() || null
3660
3686
  });
3661
3687
  }
3662
- function readCachedCompatibility(baseUrl, command) {
3688
+ function readCachedCompatibility(baseUrl, command, skillsVersion) {
3663
3689
  try {
3664
- const path = compatibilityCachePath();
3665
- if (!existsSync3(path)) {
3690
+ const path = sdkCompatibilityCachePath(baseUrl);
3691
+ const legacyPath = legacySdkCompatibilityCachePath();
3692
+ const useLegacyCache = !existsSync3(path) && existsSync3(legacyPath);
3693
+ const cachePath = useLegacyCache ? legacyPath : path;
3694
+ if (!existsSync3(cachePath)) {
3666
3695
  return null;
3667
3696
  }
3668
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3669
- const entry = parsed.entries?.[compatibilityCacheKey(baseUrl, command)];
3670
- if (!entry || Date.now() - entry.savedAt > COMPAT_CACHE_TTL_MS) {
3697
+ const parsed = JSON.parse(
3698
+ readFileSync3(cachePath, "utf8")
3699
+ );
3700
+ const entry = parsed.entries?.[compatibilityCacheKey(baseUrl, command, skillsVersion)] ?? (useLegacyCache ? parsed.entries?.[legacyCompatibilityCacheKey(baseUrl, command)] : void 0);
3701
+ if (!entry || Date.now() - entry.savedAt > SDK_COMPATIBILITY_CACHE_TTL_MS) {
3671
3702
  return null;
3672
3703
  }
3673
3704
  return entry.response;
@@ -3675,12 +3706,12 @@ function readCachedCompatibility(baseUrl, command) {
3675
3706
  return null;
3676
3707
  }
3677
3708
  }
3678
- function writeCachedCompatibility(baseUrl, command, response) {
3709
+ function writeCachedCompatibility(baseUrl, command, skillsVersion, response) {
3679
3710
  try {
3680
- const path = compatibilityCachePath();
3711
+ const path = sdkCompatibilityCachePath(baseUrl);
3681
3712
  const existing = existsSync3(path) ? JSON.parse(readFileSync3(path, "utf8")) : {};
3682
3713
  const entries = existing.entries ?? {};
3683
- entries[compatibilityCacheKey(baseUrl, command)] = {
3714
+ entries[compatibilityCacheKey(baseUrl, command, skillsVersion)] = {
3684
3715
  savedAt: Date.now(),
3685
3716
  response
3686
3717
  };
@@ -3702,6 +3733,9 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
3702
3733
  if (options.command?.trim()) {
3703
3734
  url.searchParams.set("command", options.command.trim());
3704
3735
  }
3736
+ if (options.skillsVersion !== void 0) {
3737
+ url.searchParams.set("skills_version", options.skillsVersion ?? "");
3738
+ }
3705
3739
  const response = await fetch(url, {
3706
3740
  method: "GET",
3707
3741
  headers: {
@@ -3713,12 +3747,21 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
3713
3747
  });
3714
3748
  const data = await response.json().catch(() => null);
3715
3749
  if (data) {
3716
- writeCachedCompatibility(baseUrl, options.command, data);
3750
+ writeCachedCompatibility(
3751
+ baseUrl,
3752
+ options.command,
3753
+ options.skillsVersion,
3754
+ data
3755
+ );
3717
3756
  }
3718
3757
  return { response: data, error: null };
3719
3758
  } catch (error) {
3720
- const cached = readCachedCompatibility(baseUrl, options.command);
3721
- if (cached?.ok === false || cached?.status === "unsupported") {
3759
+ const cached = readCachedCompatibility(
3760
+ baseUrl,
3761
+ options.command,
3762
+ options.skillsVersion
3763
+ );
3764
+ if (cached) {
3722
3765
  return { response: cached, error: null };
3723
3766
  }
3724
3767
  return {
@@ -3754,6 +3797,7 @@ import { hostname } from "os";
3754
3797
  import { dirname as dirname4 } from "path";
3755
3798
 
3756
3799
  // src/cli/utils.ts
3800
+ import { createHash } from "crypto";
3757
3801
  import {
3758
3802
  existsSync as existsSync4,
3759
3803
  mkdirSync as mkdirSync3,
@@ -3762,12 +3806,13 @@ import {
3762
3806
  writeFileSync as writeFileSync3
3763
3807
  } from "fs";
3764
3808
  import { mkdir, writeFile } from "fs/promises";
3765
- import { homedir as homedir5 } from "os";
3809
+ import { homedir as homedir5, tmpdir, userInfo } from "os";
3766
3810
  import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
3767
3811
  import * as childProcess from "child_process";
3768
3812
  import { parse } from "csv-parse/sync";
3769
3813
  import { stringify } from "csv-stringify/sync";
3770
3814
  var BROWSER_OPEN_COOLDOWN_MS = 3e4;
3815
+ var SAME_URL_BROWSER_OPEN_COOLDOWN_MS = 5 * 6e4;
3771
3816
  var defaultBrowserCommandRunner = childProcess;
3772
3817
  function getAuthedHttpClient() {
3773
3818
  const config = resolveConfig();
@@ -3780,25 +3825,37 @@ async function writeOutputFile(filename, content) {
3780
3825
  await writeFile(fullPath, content, "utf-8");
3781
3826
  return fullPath;
3782
3827
  }
3783
- function browserOpenStateFile() {
3784
- const homeDir2 = process.env.HOME || homedir5();
3785
- return join4(
3786
- homeDir2,
3787
- ".local",
3788
- "deepline",
3789
- "runtime",
3790
- "state",
3791
- "browser-open.json"
3792
- );
3828
+ function stableOsUserId() {
3829
+ try {
3830
+ const info = userInfo();
3831
+ if (typeof info.uid === "number") return `uid-${info.uid}`;
3832
+ if (info.username) return `user-${info.username}`;
3833
+ } catch {
3834
+ }
3835
+ return "unknown-user";
3836
+ }
3837
+ function defaultBrowserOpenStateDir() {
3838
+ return join4(tmpdir(), `deepline-${stableOsUserId()}`, "runtime", "state");
3793
3839
  }
3794
- function claimBrowserOpen(now = Date.now()) {
3795
- const statePath = browserOpenStateFile();
3840
+ function browserOpenStateFile(stateDir = defaultBrowserOpenStateDir()) {
3841
+ return join4(stateDir, "browser-open.json");
3842
+ }
3843
+ function normalizeBrowserOpenTarget(raw) {
3844
+ return String(raw || "").trim();
3845
+ }
3846
+ function browserOpenTargetKey(raw) {
3847
+ const normalized = normalizeBrowserOpenTarget(raw);
3848
+ return normalized ? createHash("sha256").update(normalized).digest("hex") : "";
3849
+ }
3850
+ function claimBrowserOpen(now = Date.now(), stateDir, targetUrl) {
3851
+ const statePath = browserOpenStateFile(stateDir);
3796
3852
  const lockPath = `${statePath}.lock`;
3853
+ const targetKey = browserOpenTargetKey(targetUrl);
3797
3854
  let locked = false;
3798
3855
  try {
3799
- mkdirSync3(dirname3(statePath), { recursive: true });
3856
+ mkdirSync3(dirname3(statePath), { recursive: true, mode: 448 });
3800
3857
  try {
3801
- mkdirSync3(lockPath);
3858
+ mkdirSync3(lockPath, { mode: 448 });
3802
3859
  locked = true;
3803
3860
  } catch {
3804
3861
  return false;
@@ -3810,14 +3867,24 @@ function claimBrowserOpen(now = Date.now()) {
3810
3867
  if (typeof value === "number" && Number.isFinite(value)) {
3811
3868
  lastOpenedAt = value;
3812
3869
  }
3870
+ const targetValue = payload.targetKey ?? payload.target_key ?? payload.targetHash ?? payload.target_hash;
3871
+ const lastTargetKey = typeof targetValue === "string" ? targetValue.trim() : "";
3872
+ const cooldownMs = targetKey && targetKey === lastTargetKey ? SAME_URL_BROWSER_OPEN_COOLDOWN_MS : BROWSER_OPEN_COOLDOWN_MS;
3873
+ if (lastOpenedAt > now) {
3874
+ lastOpenedAt = 0;
3875
+ }
3876
+ if (now - lastOpenedAt < cooldownMs) {
3877
+ return false;
3878
+ }
3813
3879
  }
3814
- if (lastOpenedAt > now) {
3815
- lastOpenedAt = 0;
3816
- }
3817
- if (now - lastOpenedAt < BROWSER_OPEN_COOLDOWN_MS) {
3818
- return false;
3819
- }
3820
- writeFileSync3(statePath, JSON.stringify({ lastOpenedAt: now }), "utf-8");
3880
+ writeFileSync3(
3881
+ statePath,
3882
+ JSON.stringify({
3883
+ lastOpenedAt: now,
3884
+ ...targetKey ? { targetKey } : {}
3885
+ }),
3886
+ { encoding: "utf-8", mode: 384 }
3887
+ );
3821
3888
  return true;
3822
3889
  } catch {
3823
3890
  return true;
@@ -3849,6 +3916,30 @@ function browserAppNameFromBundleId(bundleId) {
3849
3916
  };
3850
3917
  return names[bundleId.toLowerCase()] ?? "";
3851
3918
  }
3919
+ function currentOsUsername() {
3920
+ try {
3921
+ return userInfo().username || "";
3922
+ } catch {
3923
+ return "";
3924
+ }
3925
+ }
3926
+ function readMacosUserHome(runner = defaultBrowserCommandRunner) {
3927
+ const username = currentOsUsername();
3928
+ if (process.platform === "darwin" && username) {
3929
+ try {
3930
+ const output2 = runner.execFileSync(
3931
+ "dscl",
3932
+ [".", "-read", `/Users/${username}`, "NFSHomeDirectory"],
3933
+ { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
3934
+ );
3935
+ const match = String(output2).match(/NFSHomeDirectory:\s*(.+)\s*$/m);
3936
+ const home = match?.[1]?.trim();
3937
+ if (home) return home;
3938
+ } catch {
3939
+ }
3940
+ }
3941
+ return homedir5();
3942
+ }
3852
3943
  function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
3853
3944
  try {
3854
3945
  const output2 = runner.execFileSync(
@@ -3858,7 +3949,7 @@ function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
3858
3949
  "json",
3859
3950
  "-o",
3860
3951
  "-",
3861
- `${homedir5()}/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist`
3952
+ `${readMacosUserHome(runner)}/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist`
3862
3953
  ],
3863
3954
  { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
3864
3955
  );
@@ -4005,7 +4096,7 @@ function openInBrowser(url) {
4005
4096
  if (browserOpeningDisabled()) return;
4006
4097
  const targetUrl = String(url || "").trim();
4007
4098
  if (!targetUrl) return;
4008
- if (!claimBrowserOpen()) return;
4099
+ if (!claimBrowserOpen(Date.now(), void 0, targetUrl)) return;
4009
4100
  const allowFocus = true;
4010
4101
  if (process.platform === "darwin") {
4011
4102
  openUrlMacos(targetUrl, allowFocus);
@@ -4107,12 +4198,15 @@ function flattenObjectColumns(row) {
4107
4198
  const hasMatchedEnvelope = Object.prototype.hasOwnProperty.call(record, "matched_result") || Object.prototype.hasOwnProperty.call(record, "matchedResult");
4108
4199
  if (hasMatchedEnvelope) {
4109
4200
  flattened[key] = JSON.stringify(record);
4201
+ continue;
4110
4202
  } else {
4111
4203
  const failureMessage = failureMessageFromRecord(record);
4112
4204
  if (failureMessage) {
4113
4205
  flattened[key] = failureMessage;
4206
+ continue;
4114
4207
  } else if (Object.prototype.hasOwnProperty.call(record, "result")) {
4115
4208
  flattened[key] = JSON.stringify(record);
4209
+ continue;
4116
4210
  }
4117
4211
  }
4118
4212
  for (const [nestedKey, nestedValue] of Object.entries(record)) {
@@ -6853,11 +6947,11 @@ import {
6853
6947
  stat,
6854
6948
  writeFile as writeFile3
6855
6949
  } from "fs/promises";
6856
- import { homedir as homedir6, tmpdir } from "os";
6950
+ import { homedir as homedir6, tmpdir as tmpdir2 } from "os";
6857
6951
  import { join as join6, resolve as resolve8 } from "path";
6858
6952
 
6859
6953
  // src/cli/commands/play.ts
6860
- import { createHash } from "crypto";
6954
+ import { createHash as createHash2 } from "crypto";
6861
6955
  import {
6862
6956
  existsSync as existsSync6,
6863
6957
  readFileSync as readFileSync6,
@@ -9488,7 +9582,7 @@ function stageFile(logicalPath, absolutePath) {
9488
9582
  return {
9489
9583
  logicalPath,
9490
9584
  contentBase64: buffer.toString("base64"),
9491
- contentHash: createHash("sha256").update(buffer).digest("hex"),
9585
+ contentHash: createHash2("sha256").update(buffer).digest("hex"),
9492
9586
  contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
9493
9587
  bytes: buffer.byteLength
9494
9588
  };
@@ -14843,9 +14937,7 @@ function renderExecuteStep(command, options = {
14843
14937
  const extractJs = command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
14844
14938
  ${indent(renderJavascriptBody(command.extract_js), 6)}
14845
14939
  }` : "null";
14846
- const runIfJs = command.run_if_js ? `(row) => { const input = row; const context = row;
14847
- ${indent(renderJavascriptBody(command.run_if_js), 6)}
14848
- }` : "null";
14940
+ const runIfJs = options.nativeRunIf ? "null" : renderRunIfFunction(command) ?? "null";
14849
14941
  const description = command.description ? `,
14850
14942
  description: ${stringLiteral(command.description)}` : "";
14851
14943
  const force = options.force ? `,
@@ -14870,13 +14962,35 @@ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14870
14962
  `}`
14871
14963
  ].join("\n");
14872
14964
  }
14965
+ function renderRunIfFunction(command) {
14966
+ return command.run_if_js ? `(row) => { const input = row; const context = row;
14967
+ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14968
+ }` : null;
14969
+ }
14970
+ function renderColumnRunIfFunction(command) {
14971
+ if (!command.run_if_js) {
14972
+ return null;
14973
+ }
14974
+ if (command.play) {
14975
+ return `(__dlRawRow) => { const row = __dlPrepareEnrichRow(__dlRawRow, [${stringLiteral(command.alias)}]); const input = row; const context = row;
14976
+ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14977
+ }`;
14978
+ }
14979
+ return renderRunIfFunction(command);
14980
+ }
14981
+ function renderCombinedRunIfFunction(precheck, runIfSource) {
14982
+ if (!runIfSource) {
14983
+ return null;
14984
+ }
14985
+ return precheck ? `(row) => { if (${precheck}) return false; return (${runIfSource})(row); }` : runIfSource;
14986
+ }
14873
14987
  function renderIdiomaticExecuteStep(command, options) {
14874
14988
  const callId = stringLiteral(commandCallId(command));
14875
14989
  const tool = stringLiteral(command.tool);
14876
14990
  const input2 = renderToolPayloadExpression(command.payload ?? {});
14877
14991
  const getter = getterFromLegacyExtractJs(command.extract_js, command.alias);
14878
14992
  const extraction = getter ? `${renderExtractedValueGetterExpression("result", getter)} ?? null` : "result";
14879
- const runIfLines = command.run_if_js ? [
14993
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14880
14994
  ` if (`,
14881
14995
  ` !((row: Record<string, any>) => {`,
14882
14996
  ` const input = row;`,
@@ -14910,10 +15024,8 @@ function renderPlayStep(command, options) {
14910
15024
  const callId = stringLiteral(commandCallId(command));
14911
15025
  const playRef = stringLiteral(command.play?.ref ?? command.tool);
14912
15026
  const payload = stableJson(command.payload ?? {});
14913
- const runIfJs = command.run_if_js ? `(row) => { const input = row; const context = row;
14914
- ${indent(renderJavascriptBody(command.run_if_js), 6)}
14915
- }` : "null";
14916
- const runIfLines = command.run_if_js ? [
15027
+ const runIfJs = renderRunIfFunction(command) ?? "null";
15028
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14917
15029
  ` const __dlRunIf = ${runIfJs};`,
14918
15030
  ` if (!__dlRunIf(templateRow)) return null;`
14919
15031
  ] : [];
@@ -14937,7 +15049,7 @@ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14937
15049
  }
14938
15050
  function renderInlineJavascriptStep(command, options) {
14939
15051
  const code = typeof command.payload?.code === "string" ? command.payload.code : "return null;";
14940
- const runIfLines = command.run_if_js ? [
15052
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14941
15053
  ` if (!((row: Record<string, any>) => { const input = row; const context = row;`,
14942
15054
  indent(renderJavascriptBody(command.run_if_js), 4),
14943
15055
  ` })(row as Record<string, any>)) return null;`
@@ -14967,7 +15079,8 @@ function renderColumnStep(alias, resolverSource, options = {}) {
14967
15079
  const resolver = indent(resolverSource, 8);
14968
15080
  const optionFields = [
14969
15081
  ...options.recompute === true ? ["recompute: true"] : [],
14970
- ...options.recomputeOnError === true ? ["recomputeOnError: true"] : []
15082
+ ...options.recomputeOnError === true ? ["recomputeOnError: true"] : [],
15083
+ ...options.runIfSource ? [`runIf: ${options.runIfSource}`] : []
14971
15084
  ];
14972
15085
  const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
14973
15086
  return [
@@ -15071,17 +15184,27 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15071
15184
  }
15072
15185
  const priorAliases = activeChildren.slice(0, stepIndex).map((prior) => prior.alias);
15073
15186
  const force = forceAliases.has(normalizeAlias(nested.alias));
15187
+ const precheck = priorAliases.length > 0 ? `__dlWaterfallSatisfied(row, ${stableJson(priorAliases)}, ${minResults})` : void 0;
15188
+ const runIfSource = renderCombinedRunIfFunction(
15189
+ precheck,
15190
+ renderColumnRunIfFunction(nested)
15191
+ );
15074
15192
  return renderColumnStep(
15075
15193
  nested.alias,
15076
15194
  renderExecuteStep(nested, {
15077
15195
  force,
15078
- precheck: priorAliases.length > 0 ? `__dlWaterfallSatisfied(row, ${stableJson(priorAliases)}, ${minResults})` : void 0,
15196
+ precheck,
15079
15197
  legacyEnvelope: Boolean(nested.extract_js),
15080
15198
  inlineRunJavascript,
15081
15199
  idiomaticGetters,
15082
- waterfallSoftFail: true
15200
+ waterfallSoftFail: true,
15201
+ nativeRunIf: Boolean(runIfSource)
15083
15202
  }),
15084
- { recompute: force, recomputeOnError: true }
15203
+ {
15204
+ recompute: force,
15205
+ recomputeOnError: true,
15206
+ runIfSource
15207
+ }
15085
15208
  );
15086
15209
  }).filter((line) => line !== null);
15087
15210
  const aliases = activeChildren.map((nested) => nested.alias);
@@ -15132,15 +15255,21 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15132
15255
  return;
15133
15256
  }
15134
15257
  const force = forceAliases.has(normalizeAlias(command.alias));
15258
+ const runIfSource = renderColumnRunIfFunction(command);
15135
15259
  columnSteps.push(
15136
15260
  renderColumnStep(
15137
15261
  command.alias,
15138
15262
  renderExecuteStep(command, {
15139
15263
  force,
15140
15264
  inlineRunJavascript,
15141
- idiomaticGetters
15265
+ idiomaticGetters,
15266
+ nativeRunIf: Boolean(runIfSource)
15142
15267
  }),
15143
- { recompute: force, recomputeOnError: true }
15268
+ {
15269
+ recompute: force,
15270
+ recomputeOnError: true,
15271
+ runIfSource
15272
+ }
15144
15273
  )
15145
15274
  );
15146
15275
  });
@@ -17002,7 +17131,7 @@ async function fetchBackingRowsForCsvExport(input2) {
17002
17131
  function mergeRowsForCsvExport(enrichedRows, options) {
17003
17132
  const rows = dataExportRows(normalizeEnrichRowsForCsvExport(enrichedRows));
17004
17133
  const range = options?.rows;
17005
- if (range?.rowStart === null || range?.rowStart === void 0) {
17134
+ if (!options?.inPlace && (range?.rowStart === null || range?.rowStart === void 0)) {
17006
17135
  return { rows, preferredColumns: [] };
17007
17136
  }
17008
17137
  if (!options?.sourceCsvPath) {
@@ -17013,9 +17142,15 @@ function mergeRowsForCsvExport(enrichedRows, options) {
17013
17142
  const baseRows = parsedBaseRows.map(
17014
17143
  (row) => ({ ...row })
17015
17144
  );
17016
- const start = Math.max(0, range.rowStart);
17145
+ const start = Math.max(0, range?.rowStart ?? 0);
17017
17146
  const maxEnd = Math.max(start, baseRows.length - 1);
17018
- const inclusiveEnd = range.rowEnd === null ? maxEnd : Math.min(maxEnd, range.rowEnd);
17147
+ const inclusiveEnd = range?.rowEnd === null || range?.rowEnd === void 0 ? maxEnd : Math.min(maxEnd, range.rowEnd);
17148
+ const expectedSelectedRows = baseRows.length === 0 ? 0 : Math.max(0, inclusiveEnd - start + 1);
17149
+ if (rows.length < expectedSelectedRows) {
17150
+ throw new Error(
17151
+ `Refusing to write a partial in-place CSV export: the run returned ${rows.length} row(s) for ${expectedSelectedRows} selected source row(s).`
17152
+ );
17153
+ }
17019
17154
  const merged = [...baseRows];
17020
17155
  let selectedIndex = 0;
17021
17156
  for (let rowIndex = start; rowIndex <= inclusiveEnd; rowIndex += 1) {
@@ -17329,7 +17464,7 @@ function registerEnrichCommand(program) {
17329
17464
  forceAliases,
17330
17465
  playName: options.name
17331
17466
  });
17332
- const tempDir = await mkdtemp(join6(tmpdir(), "deepline-enrich-play-"));
17467
+ const tempDir = await mkdtemp(join6(tmpdir2(), "deepline-enrich-play-"));
17333
17468
  const tempPlay = join6(tempDir, "deepline-enrich.play.ts");
17334
17469
  try {
17335
17470
  await writeFile3(tempPlay, playSource, "utf8");
@@ -17381,7 +17516,8 @@ function registerEnrichCommand(program) {
17381
17516
  client: client2,
17382
17517
  config,
17383
17518
  sourceCsvPath,
17384
- rows
17519
+ rows,
17520
+ inPlace: Boolean(options.inPlace)
17385
17521
  }) : null;
17386
17522
  const rowsForFailureReport = exportResult?.enrichedDataRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
17387
17523
  if (options.json) {
@@ -19132,7 +19268,7 @@ import {
19132
19268
  readFileSync as readFileSync9,
19133
19269
  writeFileSync as writeFileSync12
19134
19270
  } from "fs";
19135
- import { tmpdir as tmpdir2 } from "os";
19271
+ import { tmpdir as tmpdir3 } from "os";
19136
19272
  import { join as join10, resolve as resolve10 } from "path";
19137
19273
 
19138
19274
  // src/tool-output.ts
@@ -20440,7 +20576,7 @@ function starterScriptJson(script) {
20440
20576
  function seedToolListScript(input2) {
20441
20577
  const stem = safeFileStem(input2.toolId);
20442
20578
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
20443
- const scriptDir = mkdtempSync(join10(tmpdir2(), "deepline-workflow-seed-"));
20579
+ const scriptDir = mkdtempSync(join10(tmpdir3(), "deepline-workflow-seed-"));
20444
20580
  chmodSync(scriptDir, 448);
20445
20581
  const scriptPath = join10(scriptDir, fileName);
20446
20582
  const projectDir = `deepline/projects/${stem}-workflow`;
@@ -20748,7 +20884,7 @@ import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from
20748
20884
  import { dirname as dirname9, join as join11, resolve as resolve11 } from "path";
20749
20885
 
20750
20886
  // src/cli/workflow-to-play.ts
20751
- import { createHash as createHash2 } from "crypto";
20887
+ import { createHash as createHash3 } from "crypto";
20752
20888
 
20753
20889
  // ../shared_libs/plays/secret-guardrails.ts
20754
20890
  var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
@@ -20891,7 +21027,7 @@ function sanitizePlayNameSegment(value) {
20891
21027
  }
20892
21028
  function deriveWorkflowPlayName(workflowName) {
20893
21029
  const base = sanitizePlayNameSegment(workflowName) || "workflow";
20894
- const suffix = createHash2("sha256").update(workflowName).digest("hex").slice(0, 8);
21030
+ const suffix = createHash3("sha256").update(workflowName).digest("hex").slice(0, 8);
20895
21031
  const reserved = suffix.length + 1;
20896
21032
  const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
20897
21033
  let name = `${base.slice(0, allowedBase)}_${suffix}`;
@@ -21281,13 +21417,12 @@ import {
21281
21417
  unlinkSync,
21282
21418
  writeFileSync as writeFileSync14
21283
21419
  } from "fs";
21284
- import { homedir as homedir11 } from "os";
21420
+ import { homedir as homedir10 } from "os";
21285
21421
  import { dirname as dirname11, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve12 } from "path";
21286
21422
 
21287
21423
  // src/cli/skills-sync.ts
21288
21424
  import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
21289
21425
  import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync13 } from "fs";
21290
- import { homedir as homedir10 } from "os";
21291
21426
  import { dirname as dirname10, join as join12 } from "path";
21292
21427
 
21293
21428
  // ../shared_libs/cli/install-commands.json
@@ -21419,20 +21554,15 @@ function readPluginSkillsVersion() {
21419
21554
  }
21420
21555
  }
21421
21556
  function sdkSkillsVersionPath(baseUrl) {
21422
- const home = process.env.HOME?.trim() || homedir10();
21423
- return join12(
21424
- home,
21425
- ".local",
21426
- "deepline",
21427
- baseUrlSlug(baseUrl),
21428
- "sdk-skills",
21429
- ".version"
21430
- );
21557
+ return join12(sdkCliStateDirPath(baseUrl), "skills-version");
21431
21558
  }
21432
- function readLocalSkillsVersion(baseUrl) {
21559
+ function legacySdkSkillsVersionPath(baseUrl) {
21560
+ return join12(dirname10(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
21561
+ }
21562
+ function readSdkSkillsLocalVersion(baseUrl) {
21433
21563
  const pluginVersion = readPluginSkillsVersion();
21434
21564
  if (pluginVersion) return pluginVersion;
21435
- const path = sdkSkillsVersionPath(baseUrl);
21565
+ const path = existsSync10(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
21436
21566
  if (!existsSync10(path)) return "";
21437
21567
  try {
21438
21568
  return readFileSync10(path, "utf-8").trim();
@@ -21642,15 +21772,18 @@ function writeSdkSkillsStatusLine(line) {
21642
21772
  process.stderr.write(`${line}
21643
21773
  `);
21644
21774
  }
21645
- async function syncSdkSkillsIfNeeded(baseUrl) {
21775
+ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
21646
21776
  if (attemptedSync || shouldSkipSkillsSync()) return;
21647
21777
  attemptedSync = true;
21648
21778
  const usingPluginSkills = Boolean(activePluginSkillsDir());
21649
- const localVersion = readLocalSkillsVersion(baseUrl);
21650
- const update = await fetchSkillsUpdate(baseUrl, localVersion);
21651
21779
  if (usingPluginSkills) {
21652
21780
  return;
21653
21781
  }
21782
+ const localVersion = readSdkSkillsLocalVersion(baseUrl);
21783
+ const update = options.update === void 0 ? await fetchSkillsUpdate(baseUrl, localVersion) : options.update ? {
21784
+ needsUpdate: options.update.needs_update,
21785
+ remoteVersion: options.update.remote.version
21786
+ } : null;
21654
21787
  if (!update?.needsUpdate || !update.remoteVersion) {
21655
21788
  return;
21656
21789
  }
@@ -21768,7 +21901,7 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
21768
21901
  }
21769
21902
  function resolveUpdatePlan(options = {}) {
21770
21903
  const env = options.env ?? process.env;
21771
- const homeDir2 = options.homeDir ?? homedir11();
21904
+ const homeDir2 = options.homeDir ?? homedir10();
21772
21905
  const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve12(process.argv[1]) : "");
21773
21906
  const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname11(entrypoint)) : null;
21774
21907
  if (sourceRoot) {
@@ -21804,7 +21937,7 @@ function autoUpdateFailurePath(plan) {
21804
21937
  return join13(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
21805
21938
  }
21806
21939
  return join13(
21807
- homedir11(),
21940
+ homedir10(),
21808
21941
  ".local",
21809
21942
  "deepline",
21810
21943
  "sdk-cli",
@@ -22601,7 +22734,7 @@ function topLevelCommandKnown(program, commandName) {
22601
22734
  );
22602
22735
  }
22603
22736
  async function runPlayRunnerHealthCheck() {
22604
- const dir = await mkdtemp2(join14(tmpdir3(), "deepline-health-play-"));
22737
+ const dir = await mkdtemp2(join14(tmpdir4(), "deepline-health-play-"));
22605
22738
  const file = join14(dir, "health-check.play.ts");
22606
22739
  try {
22607
22740
  await writeFile5(
@@ -22829,11 +22962,18 @@ Exit codes:
22829
22962
  }
22830
22963
  const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
22831
22964
  const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
22965
+ const shouldDeferSkillsSync = shouldDeferSkillsSyncForCommand();
22966
+ const skillsVersion = shouldDeferSkillsSync ? void 0 : readSdkSkillsLocalVersion(baseUrl);
22832
22967
  const compatibility = await traceCliSpan(
22833
22968
  "cli.sdk_compatibility",
22834
- { baseUrl, command: compatibilityCommand },
22969
+ {
22970
+ baseUrl,
22971
+ command: compatibilityCommand,
22972
+ skillsVersion: skillsVersion ?? null
22973
+ },
22835
22974
  () => checkSdkCompatibility(baseUrl, {
22836
- command: compatibilityCommand
22975
+ command: compatibilityCommand,
22976
+ skillsVersion
22837
22977
  })
22838
22978
  );
22839
22979
  if (compatibility.error) {
@@ -22859,11 +22999,14 @@ Exit codes:
22859
22999
  if (printStartupPhase) {
22860
23000
  progress?.phase("checking sdk skills");
22861
23001
  }
22862
- if (!shouldDeferSkillsSyncForCommand()) {
23002
+ if (!shouldDeferSkillsSync) {
23003
+ const skillsUpdate = compatibility.response && Object.prototype.hasOwnProperty.call(compatibility.response, "skills") ? compatibility.response.skills ?? null : void 0;
22863
23004
  await traceCliSpan(
22864
23005
  "cli.sdk_skills_sync",
22865
23006
  { baseUrl },
22866
- () => syncSdkSkillsIfNeeded(baseUrl)
23007
+ () => syncSdkSkillsIfNeeded(baseUrl, {
23008
+ update: skillsUpdate
23009
+ })
22867
23010
  );
22868
23011
  }
22869
23012
  });