deepline 0.1.129 → 0.1.130

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.130",
385
394
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
386
395
  supportPolicy: {
387
- latest: "0.1.129",
396
+ latest: "0.1.130",
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");
3839
+ }
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") : "";
3793
3849
  }
3794
- function claimBrowserOpen(now = Date.now()) {
3795
- const statePath = browserOpenStateFile();
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);
@@ -6853,11 +6944,11 @@ import {
6853
6944
  stat,
6854
6945
  writeFile as writeFile3
6855
6946
  } from "fs/promises";
6856
- import { homedir as homedir6, tmpdir } from "os";
6947
+ import { homedir as homedir6, tmpdir as tmpdir2 } from "os";
6857
6948
  import { join as join6, resolve as resolve8 } from "path";
6858
6949
 
6859
6950
  // src/cli/commands/play.ts
6860
- import { createHash } from "crypto";
6951
+ import { createHash as createHash2 } from "crypto";
6861
6952
  import {
6862
6953
  existsSync as existsSync6,
6863
6954
  readFileSync as readFileSync6,
@@ -9488,7 +9579,7 @@ function stageFile(logicalPath, absolutePath) {
9488
9579
  return {
9489
9580
  logicalPath,
9490
9581
  contentBase64: buffer.toString("base64"),
9491
- contentHash: createHash("sha256").update(buffer).digest("hex"),
9582
+ contentHash: createHash2("sha256").update(buffer).digest("hex"),
9492
9583
  contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
9493
9584
  bytes: buffer.byteLength
9494
9585
  };
@@ -14843,9 +14934,7 @@ function renderExecuteStep(command, options = {
14843
14934
  const extractJs = command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
14844
14935
  ${indent(renderJavascriptBody(command.extract_js), 6)}
14845
14936
  }` : "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";
14937
+ const runIfJs = options.nativeRunIf ? "null" : renderRunIfFunction(command) ?? "null";
14849
14938
  const description = command.description ? `,
14850
14939
  description: ${stringLiteral(command.description)}` : "";
14851
14940
  const force = options.force ? `,
@@ -14870,13 +14959,35 @@ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14870
14959
  `}`
14871
14960
  ].join("\n");
14872
14961
  }
14962
+ function renderRunIfFunction(command) {
14963
+ return command.run_if_js ? `(row) => { const input = row; const context = row;
14964
+ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14965
+ }` : null;
14966
+ }
14967
+ function renderColumnRunIfFunction(command) {
14968
+ if (!command.run_if_js) {
14969
+ return null;
14970
+ }
14971
+ if (command.play) {
14972
+ return `(__dlRawRow) => { const row = __dlPrepareEnrichRow(__dlRawRow, [${stringLiteral(command.alias)}]); const input = row; const context = row;
14973
+ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14974
+ }`;
14975
+ }
14976
+ return renderRunIfFunction(command);
14977
+ }
14978
+ function renderCombinedRunIfFunction(precheck, runIfSource) {
14979
+ if (!runIfSource) {
14980
+ return null;
14981
+ }
14982
+ return precheck ? `(row) => { if (${precheck}) return false; return (${runIfSource})(row); }` : runIfSource;
14983
+ }
14873
14984
  function renderIdiomaticExecuteStep(command, options) {
14874
14985
  const callId = stringLiteral(commandCallId(command));
14875
14986
  const tool = stringLiteral(command.tool);
14876
14987
  const input2 = renderToolPayloadExpression(command.payload ?? {});
14877
14988
  const getter = getterFromLegacyExtractJs(command.extract_js, command.alias);
14878
14989
  const extraction = getter ? `${renderExtractedValueGetterExpression("result", getter)} ?? null` : "result";
14879
- const runIfLines = command.run_if_js ? [
14990
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14880
14991
  ` if (`,
14881
14992
  ` !((row: Record<string, any>) => {`,
14882
14993
  ` const input = row;`,
@@ -14910,10 +15021,8 @@ function renderPlayStep(command, options) {
14910
15021
  const callId = stringLiteral(commandCallId(command));
14911
15022
  const playRef = stringLiteral(command.play?.ref ?? command.tool);
14912
15023
  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 ? [
15024
+ const runIfJs = renderRunIfFunction(command) ?? "null";
15025
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14917
15026
  ` const __dlRunIf = ${runIfJs};`,
14918
15027
  ` if (!__dlRunIf(templateRow)) return null;`
14919
15028
  ] : [];
@@ -14937,7 +15046,7 @@ ${indent(renderJavascriptBody(command.run_if_js), 6)}
14937
15046
  }
14938
15047
  function renderInlineJavascriptStep(command, options) {
14939
15048
  const code = typeof command.payload?.code === "string" ? command.payload.code : "return null;";
14940
- const runIfLines = command.run_if_js ? [
15049
+ const runIfLines = command.run_if_js && !options.nativeRunIf ? [
14941
15050
  ` if (!((row: Record<string, any>) => { const input = row; const context = row;`,
14942
15051
  indent(renderJavascriptBody(command.run_if_js), 4),
14943
15052
  ` })(row as Record<string, any>)) return null;`
@@ -14967,7 +15076,8 @@ function renderColumnStep(alias, resolverSource, options = {}) {
14967
15076
  const resolver = indent(resolverSource, 8);
14968
15077
  const optionFields = [
14969
15078
  ...options.recompute === true ? ["recompute: true"] : [],
14970
- ...options.recomputeOnError === true ? ["recomputeOnError: true"] : []
15079
+ ...options.recomputeOnError === true ? ["recomputeOnError: true"] : [],
15080
+ ...options.runIfSource ? [`runIf: ${options.runIfSource}`] : []
14971
15081
  ];
14972
15082
  const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
14973
15083
  return [
@@ -15071,17 +15181,27 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15071
15181
  }
15072
15182
  const priorAliases = activeChildren.slice(0, stepIndex).map((prior) => prior.alias);
15073
15183
  const force = forceAliases.has(normalizeAlias(nested.alias));
15184
+ const precheck = priorAliases.length > 0 ? `__dlWaterfallSatisfied(row, ${stableJson(priorAliases)}, ${minResults})` : void 0;
15185
+ const runIfSource = renderCombinedRunIfFunction(
15186
+ precheck,
15187
+ renderColumnRunIfFunction(nested)
15188
+ );
15074
15189
  return renderColumnStep(
15075
15190
  nested.alias,
15076
15191
  renderExecuteStep(nested, {
15077
15192
  force,
15078
- precheck: priorAliases.length > 0 ? `__dlWaterfallSatisfied(row, ${stableJson(priorAliases)}, ${minResults})` : void 0,
15193
+ precheck,
15079
15194
  legacyEnvelope: Boolean(nested.extract_js),
15080
15195
  inlineRunJavascript,
15081
15196
  idiomaticGetters,
15082
- waterfallSoftFail: true
15197
+ waterfallSoftFail: true,
15198
+ nativeRunIf: Boolean(runIfSource)
15083
15199
  }),
15084
- { recompute: force, recomputeOnError: true }
15200
+ {
15201
+ recompute: force,
15202
+ recomputeOnError: true,
15203
+ runIfSource
15204
+ }
15085
15205
  );
15086
15206
  }).filter((line) => line !== null);
15087
15207
  const aliases = activeChildren.map((nested) => nested.alias);
@@ -15132,15 +15252,21 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15132
15252
  return;
15133
15253
  }
15134
15254
  const force = forceAliases.has(normalizeAlias(command.alias));
15255
+ const runIfSource = renderColumnRunIfFunction(command);
15135
15256
  columnSteps.push(
15136
15257
  renderColumnStep(
15137
15258
  command.alias,
15138
15259
  renderExecuteStep(command, {
15139
15260
  force,
15140
15261
  inlineRunJavascript,
15141
- idiomaticGetters
15262
+ idiomaticGetters,
15263
+ nativeRunIf: Boolean(runIfSource)
15142
15264
  }),
15143
- { recompute: force, recomputeOnError: true }
15265
+ {
15266
+ recompute: force,
15267
+ recomputeOnError: true,
15268
+ runIfSource
15269
+ }
15144
15270
  )
15145
15271
  );
15146
15272
  });
@@ -17329,7 +17455,7 @@ function registerEnrichCommand(program) {
17329
17455
  forceAliases,
17330
17456
  playName: options.name
17331
17457
  });
17332
- const tempDir = await mkdtemp(join6(tmpdir(), "deepline-enrich-play-"));
17458
+ const tempDir = await mkdtemp(join6(tmpdir2(), "deepline-enrich-play-"));
17333
17459
  const tempPlay = join6(tempDir, "deepline-enrich.play.ts");
17334
17460
  try {
17335
17461
  await writeFile3(tempPlay, playSource, "utf8");
@@ -19132,7 +19258,7 @@ import {
19132
19258
  readFileSync as readFileSync9,
19133
19259
  writeFileSync as writeFileSync12
19134
19260
  } from "fs";
19135
- import { tmpdir as tmpdir2 } from "os";
19261
+ import { tmpdir as tmpdir3 } from "os";
19136
19262
  import { join as join10, resolve as resolve10 } from "path";
19137
19263
 
19138
19264
  // src/tool-output.ts
@@ -20440,7 +20566,7 @@ function starterScriptJson(script) {
20440
20566
  function seedToolListScript(input2) {
20441
20567
  const stem = safeFileStem(input2.toolId);
20442
20568
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
20443
- const scriptDir = mkdtempSync(join10(tmpdir2(), "deepline-workflow-seed-"));
20569
+ const scriptDir = mkdtempSync(join10(tmpdir3(), "deepline-workflow-seed-"));
20444
20570
  chmodSync(scriptDir, 448);
20445
20571
  const scriptPath = join10(scriptDir, fileName);
20446
20572
  const projectDir = `deepline/projects/${stem}-workflow`;
@@ -20748,7 +20874,7 @@ import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from
20748
20874
  import { dirname as dirname9, join as join11, resolve as resolve11 } from "path";
20749
20875
 
20750
20876
  // src/cli/workflow-to-play.ts
20751
- import { createHash as createHash2 } from "crypto";
20877
+ import { createHash as createHash3 } from "crypto";
20752
20878
 
20753
20879
  // ../shared_libs/plays/secret-guardrails.ts
20754
20880
  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 +21017,7 @@ function sanitizePlayNameSegment(value) {
20891
21017
  }
20892
21018
  function deriveWorkflowPlayName(workflowName) {
20893
21019
  const base = sanitizePlayNameSegment(workflowName) || "workflow";
20894
- const suffix = createHash2("sha256").update(workflowName).digest("hex").slice(0, 8);
21020
+ const suffix = createHash3("sha256").update(workflowName).digest("hex").slice(0, 8);
20895
21021
  const reserved = suffix.length + 1;
20896
21022
  const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
20897
21023
  let name = `${base.slice(0, allowedBase)}_${suffix}`;
@@ -21281,13 +21407,12 @@ import {
21281
21407
  unlinkSync,
21282
21408
  writeFileSync as writeFileSync14
21283
21409
  } from "fs";
21284
- import { homedir as homedir11 } from "os";
21410
+ import { homedir as homedir10 } from "os";
21285
21411
  import { dirname as dirname11, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve12 } from "path";
21286
21412
 
21287
21413
  // src/cli/skills-sync.ts
21288
21414
  import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
21289
21415
  import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync13 } from "fs";
21290
- import { homedir as homedir10 } from "os";
21291
21416
  import { dirname as dirname10, join as join12 } from "path";
21292
21417
 
21293
21418
  // ../shared_libs/cli/install-commands.json
@@ -21419,20 +21544,15 @@ function readPluginSkillsVersion() {
21419
21544
  }
21420
21545
  }
21421
21546
  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
- );
21547
+ return join12(sdkCliStateDirPath(baseUrl), "skills-version");
21431
21548
  }
21432
- function readLocalSkillsVersion(baseUrl) {
21549
+ function legacySdkSkillsVersionPath(baseUrl) {
21550
+ return join12(dirname10(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
21551
+ }
21552
+ function readSdkSkillsLocalVersion(baseUrl) {
21433
21553
  const pluginVersion = readPluginSkillsVersion();
21434
21554
  if (pluginVersion) return pluginVersion;
21435
- const path = sdkSkillsVersionPath(baseUrl);
21555
+ const path = existsSync10(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
21436
21556
  if (!existsSync10(path)) return "";
21437
21557
  try {
21438
21558
  return readFileSync10(path, "utf-8").trim();
@@ -21642,15 +21762,18 @@ function writeSdkSkillsStatusLine(line) {
21642
21762
  process.stderr.write(`${line}
21643
21763
  `);
21644
21764
  }
21645
- async function syncSdkSkillsIfNeeded(baseUrl) {
21765
+ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
21646
21766
  if (attemptedSync || shouldSkipSkillsSync()) return;
21647
21767
  attemptedSync = true;
21648
21768
  const usingPluginSkills = Boolean(activePluginSkillsDir());
21649
- const localVersion = readLocalSkillsVersion(baseUrl);
21650
- const update = await fetchSkillsUpdate(baseUrl, localVersion);
21651
21769
  if (usingPluginSkills) {
21652
21770
  return;
21653
21771
  }
21772
+ const localVersion = readSdkSkillsLocalVersion(baseUrl);
21773
+ const update = options.update === void 0 ? await fetchSkillsUpdate(baseUrl, localVersion) : options.update ? {
21774
+ needsUpdate: options.update.needs_update,
21775
+ remoteVersion: options.update.remote.version
21776
+ } : null;
21654
21777
  if (!update?.needsUpdate || !update.remoteVersion) {
21655
21778
  return;
21656
21779
  }
@@ -21768,7 +21891,7 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
21768
21891
  }
21769
21892
  function resolveUpdatePlan(options = {}) {
21770
21893
  const env = options.env ?? process.env;
21771
- const homeDir2 = options.homeDir ?? homedir11();
21894
+ const homeDir2 = options.homeDir ?? homedir10();
21772
21895
  const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve12(process.argv[1]) : "");
21773
21896
  const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname11(entrypoint)) : null;
21774
21897
  if (sourceRoot) {
@@ -21804,7 +21927,7 @@ function autoUpdateFailurePath(plan) {
21804
21927
  return join13(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
21805
21928
  }
21806
21929
  return join13(
21807
- homedir11(),
21930
+ homedir10(),
21808
21931
  ".local",
21809
21932
  "deepline",
21810
21933
  "sdk-cli",
@@ -22601,7 +22724,7 @@ function topLevelCommandKnown(program, commandName) {
22601
22724
  );
22602
22725
  }
22603
22726
  async function runPlayRunnerHealthCheck() {
22604
- const dir = await mkdtemp2(join14(tmpdir3(), "deepline-health-play-"));
22727
+ const dir = await mkdtemp2(join14(tmpdir4(), "deepline-health-play-"));
22605
22728
  const file = join14(dir, "health-check.play.ts");
22606
22729
  try {
22607
22730
  await writeFile5(
@@ -22829,11 +22952,18 @@ Exit codes:
22829
22952
  }
22830
22953
  const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
22831
22954
  const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
22955
+ const shouldDeferSkillsSync = shouldDeferSkillsSyncForCommand();
22956
+ const skillsVersion = shouldDeferSkillsSync ? void 0 : readSdkSkillsLocalVersion(baseUrl);
22832
22957
  const compatibility = await traceCliSpan(
22833
22958
  "cli.sdk_compatibility",
22834
- { baseUrl, command: compatibilityCommand },
22959
+ {
22960
+ baseUrl,
22961
+ command: compatibilityCommand,
22962
+ skillsVersion: skillsVersion ?? null
22963
+ },
22835
22964
  () => checkSdkCompatibility(baseUrl, {
22836
- command: compatibilityCommand
22965
+ command: compatibilityCommand,
22966
+ skillsVersion
22837
22967
  })
22838
22968
  );
22839
22969
  if (compatibility.error) {
@@ -22859,11 +22989,14 @@ Exit codes:
22859
22989
  if (printStartupPhase) {
22860
22990
  progress?.phase("checking sdk skills");
22861
22991
  }
22862
- if (!shouldDeferSkillsSyncForCommand()) {
22992
+ if (!shouldDeferSkillsSync) {
22993
+ const skillsUpdate = compatibility.response && Object.prototype.hasOwnProperty.call(compatibility.response, "skills") ? compatibility.response.skills ?? null : void 0;
22863
22994
  await traceCliSpan(
22864
22995
  "cli.sdk_skills_sync",
22865
22996
  { baseUrl },
22866
- () => syncSdkSkillsIfNeeded(baseUrl)
22997
+ () => syncSdkSkillsIfNeeded(baseUrl, {
22998
+ update: skillsUpdate
22999
+ })
22867
23000
  );
22868
23001
  }
22869
23002
  });