@rudderhq/cli 0.7.13 → 0.7.14

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/index.js CHANGED
@@ -7464,6 +7464,7 @@ import { execFile } from "node:child_process";
7464
7464
  import { existsSync as existsSync3 } from "node:fs";
7465
7465
  import fs6 from "node:fs/promises";
7466
7466
  import path8 from "node:path";
7467
+ import { performance } from "node:perf_hooks";
7467
7468
  import { fileURLToPath as fileURLToPath3 } from "node:url";
7468
7469
  import { promisify } from "node:util";
7469
7470
  function nativeTarget() {
@@ -7496,14 +7497,14 @@ function parseEnvelope(stdout, capability) {
7496
7497
  }
7497
7498
  return envelope;
7498
7499
  }
7499
- async function runNativePayload(capability, args, commandMayAccept) {
7500
+ async function runNativePayload(capability, args, commandMayAccept, timeoutMs = TIMEOUT_MS) {
7500
7501
  let stdout = "";
7501
7502
  let stderr = "";
7502
7503
  try {
7503
7504
  const command = resolveNativeCommand(resolveNativePayloadBinary(), args);
7504
7505
  const result = await execFileAsync(command.command, command.args, {
7505
7506
  encoding: "utf8",
7506
- timeout: TIMEOUT_MS,
7507
+ timeout: Math.max(1, Math.min(TIMEOUT_MS, timeoutMs)),
7507
7508
  maxBuffer: OUTPUT_LIMIT_BYTES,
7508
7509
  windowsHide: true
7509
7510
  });
@@ -7522,6 +7523,9 @@ async function runNativePayload(capability, args, commandMayAccept) {
7522
7523
  envelope2
7523
7524
  );
7524
7525
  }
7526
+ if (detail.code === "ETIMEDOUT" || detail.killed === true || detail.signal === "SIGTERM") {
7527
+ throw new NativePayloadError("deadline_exceeded", commandMayAccept, detail.code ?? detail.signal);
7528
+ }
7525
7529
  const failedBeforeSpawn = detail.code === "ENOENT" || detail.code === "EACCES";
7526
7530
  throw new NativePayloadError("process_failed", commandMayAccept && !failedBeforeSpawn, stderr || detail.code);
7527
7531
  }
@@ -7544,16 +7548,16 @@ function nativePayloadPolicy() {
7544
7548
  legacyToggleEnvs: ["RUDDER_NATIVE_RUNTIME_PAYLOAD"]
7545
7549
  });
7546
7550
  }
7547
- async function verifyNativePayload(archivePath, expectedSha256, maxArchiveBytes) {
7551
+ async function verifyNativePayload(archivePath, expectedSha256, maxArchiveBytes, timeoutMs) {
7548
7552
  return runNativePayload("payload.verify", [
7549
7553
  "payload",
7550
7554
  "verify",
7551
7555
  path8.resolve(archivePath),
7552
7556
  expectedSha256,
7553
7557
  String(maxArchiveBytes)
7554
- ], false);
7558
+ ], false, timeoutMs);
7555
7559
  }
7556
- async function extractNativePayload(archivePath, stagingPath, maxArchiveBytes) {
7560
+ async function extractNativePayload(archivePath, stagingPath, maxArchiveBytes, timeoutMs) {
7557
7561
  try {
7558
7562
  return await runNativePayload("payload.extract", [
7559
7563
  "payload",
@@ -7565,7 +7569,7 @@ async function extractNativePayload(archivePath, stagingPath, maxArchiveBytes) {
7565
7569
  String(maxArchiveBytes),
7566
7570
  String(maxArchiveBytes * 2),
7567
7571
  "0"
7568
- ], true);
7572
+ ], true, timeoutMs);
7569
7573
  } catch (error) {
7570
7574
  if (error instanceof NativePayloadError && error.code === "process_failed" && !existsSync3(stagingPath)) {
7571
7575
  throw new NativePayloadError("process_failed", false, error.message);
@@ -7573,24 +7577,53 @@ async function extractNativePayload(archivePath, stagingPath, maxArchiveBytes) {
7573
7577
  throw error;
7574
7578
  }
7575
7579
  }
7576
- async function probeNativePayloadVersion(rootPath, executable) {
7580
+ async function probeNativePayloadVersion(rootPath, executable, timeoutMs) {
7577
7581
  return runNativePayload("payload.probeVersion", [
7578
7582
  "payload",
7579
7583
  "probe-version",
7580
7584
  path8.resolve(rootPath),
7581
7585
  executable,
7582
7586
  "PostgreSQL 18.4"
7583
- ], true);
7587
+ ], true, timeoutMs);
7584
7588
  }
7585
- async function publishNativePayload(stagingPath, destinationPath) {
7589
+ async function publishNativePayload(stagingPath, destinationPath, timeoutMs) {
7586
7590
  return runNativePayload("payload.publish", [
7587
7591
  "payload",
7588
7592
  "publish",
7589
7593
  path8.resolve(stagingPath),
7590
7594
  path8.resolve(destinationPath)
7591
- ], true);
7595
+ ], true, timeoutMs);
7592
7596
  }
7593
7597
  async function tryInstallNativePayload(input) {
7598
+ const now = input.now ?? (() => performance.now());
7599
+ const expiresAt = input.timeoutMs === void 0 ? null : now() + input.timeoutMs;
7600
+ const remainingTimeout = (accepted) => {
7601
+ if (expiresAt === null) return void 0;
7602
+ const remaining = Math.ceil(expiresAt - now());
7603
+ if (remaining <= 0) throw new NativePayloadError("deadline_exceeded", accepted);
7604
+ return remaining;
7605
+ };
7606
+ const runCallbackWithinDeadline = async (accepted, callback) => {
7607
+ const controller = new AbortController();
7608
+ const timeoutMs = remainingTimeout(accepted);
7609
+ let timer;
7610
+ const timeoutPromise = timeoutMs === void 0 ? null : new Promise((_resolve, reject) => {
7611
+ timer = setTimeout(() => {
7612
+ controller.abort();
7613
+ reject(new NativePayloadError("deadline_exceeded", accepted));
7614
+ }, timeoutMs);
7615
+ });
7616
+ const context = {
7617
+ signal: controller.signal,
7618
+ remainingMs: () => remainingTimeout(accepted)
7619
+ };
7620
+ try {
7621
+ const operation = callback(context);
7622
+ return timeoutPromise ? await Promise.race([operation, timeoutPromise]) : await operation;
7623
+ } finally {
7624
+ if (timer) clearTimeout(timer);
7625
+ }
7626
+ };
7594
7627
  const policy = nativePayloadPolicy();
7595
7628
  if (!policy.enabled) return {
7596
7629
  installed: false,
@@ -7613,9 +7646,9 @@ async function tryInstallNativePayload(input) {
7613
7646
  }
7614
7647
  try {
7615
7648
  if (expectedSha256) {
7616
- await verifyNativePayload(input.archivePath, expectedSha256, input.maxArchiveBytes);
7649
+ await verifyNativePayload(input.archivePath, expectedSha256, input.maxArchiveBytes, remainingTimeout(false));
7617
7650
  }
7618
- await extractNativePayload(input.archivePath, input.extractPath, input.maxArchiveBytes);
7651
+ await extractNativePayload(input.archivePath, input.extractPath, input.maxArchiveBytes, remainingTimeout(false));
7619
7652
  } catch (error) {
7620
7653
  const fallbackSafe = error instanceof NativePayloadError && error.fallbackSafe;
7621
7654
  if (!policy.fallbackAllowed || !fallbackSafe) throw error;
@@ -7634,10 +7667,16 @@ async function tryInstallNativePayload(input) {
7634
7667
  };
7635
7668
  }
7636
7669
  try {
7637
- const versionExecutable = await input.preparePublish(input.extractPath, input.publishStagingPath);
7638
- await probeNativePayloadVersion(input.publishStagingPath, versionExecutable);
7639
- const published = await publishNativePayload(input.publishStagingPath, input.destinationPath);
7640
- await input.validatePublished(input.destinationPath);
7670
+ const versionExecutable = await runCallbackWithinDeadline(
7671
+ true,
7672
+ (context) => input.preparePublish(input.extractPath, input.publishStagingPath, context)
7673
+ );
7674
+ await probeNativePayloadVersion(input.publishStagingPath, versionExecutable, remainingTimeout(true));
7675
+ const published = await publishNativePayload(input.publishStagingPath, input.destinationPath, remainingTimeout(true));
7676
+ await runCallbackWithinDeadline(
7677
+ true,
7678
+ (context) => input.validatePublished(input.destinationPath, context)
7679
+ );
7641
7680
  return {
7642
7681
  installed: true,
7643
7682
  fallbackCode: null,
@@ -7651,7 +7690,9 @@ async function tryInstallNativePayload(input) {
7651
7690
  }
7652
7691
  };
7653
7692
  } finally {
7654
- await fs6.rm(input.publishStagingPath, { recursive: true, force: true });
7693
+ const cleanup = input.cleanupPublishStaging ?? ((publishStagingPath) => fs6.rm(publishStagingPath, { recursive: true, force: true }));
7694
+ void cleanup(input.publishStagingPath).catch(() => {
7695
+ });
7655
7696
  }
7656
7697
  }
7657
7698
  var execFileAsync, PROTOCOL_VERSION, OUTPUT_LIMIT_BYTES, TIMEOUT_MS, NativePayloadError;
@@ -7689,81 +7730,26 @@ var init_native_payload = __esm({
7689
7730
  }
7690
7731
  });
7691
7732
 
7692
- // src/runtime/postgres-payload.ts
7693
- import { cp, mkdir, stat } from "node:fs/promises";
7694
- import path9 from "node:path";
7695
- async function copyRuntimePostgresPayload(sourceRuntimeDir, targetRuntimeDir, sourceShareDir = path9.join(sourceRuntimeDir, "share")) {
7696
- await mkdir(targetRuntimeDir, { recursive: true });
7697
- for (const directoryName of ["bin", "lib"]) {
7698
- const sourceDirectory = path9.join(sourceRuntimeDir, directoryName);
7699
- if (!await stat(sourceDirectory).catch(() => null)) continue;
7700
- await cp(
7701
- sourceDirectory,
7702
- path9.join(targetRuntimeDir, directoryName),
7703
- { recursive: true, dereference: true }
7704
- );
7705
- }
7706
- await cp(
7707
- sourceShareDir,
7708
- path9.join(targetRuntimeDir, "share"),
7709
- { recursive: true, dereference: true }
7710
- );
7711
- }
7712
- var init_postgres_payload = __esm({
7713
- "src/runtime/postgres-payload.ts"() {
7714
- "use strict";
7715
- }
7716
- });
7717
-
7718
7733
  // src/runtime/postgres-runtime-download.ts
7719
7734
  import { createHash as createHash2 } from "node:crypto";
7720
7735
  import { createReadStream, createWriteStream } from "node:fs";
7721
- import { copyFile, stat as stat2 } from "node:fs/promises";
7722
7736
  import { Readable, Transform } from "node:stream";
7723
7737
  import { pipeline } from "node:stream/promises";
7724
7738
  import { fileURLToPath as fileURLToPath4 } from "node:url";
7725
- async function downloadRuntimePostgresArchive(url, targetPath, trustedSha256) {
7739
+ async function downloadRuntimePostgresArchive(url, targetPath, trustedSha256, options = {}) {
7726
7740
  const expectedSha256 = (trustedSha256 ?? process.env[RUDDER_POSTGRES_RUNTIME_ARCHIVE_SHA256_ENV])?.trim().toLowerCase() || null;
7727
7741
  if (expectedSha256 && !/^[a-f0-9]{64}$/.test(expectedSha256)) {
7728
7742
  throw new Error(`${RUDDER_POSTGRES_RUNTIME_ARCHIVE_SHA256_ENV} must be a 64-character SHA-256 digest`);
7729
7743
  }
7730
7744
  const configuredMaxBytes = Number.parseInt(process.env[RUDDER_POSTGRES_RUNTIME_ARCHIVE_MAX_BYTES_ENV] ?? "", 10);
7731
7745
  const maxBytes = Number.isSafeInteger(configuredMaxBytes) && configuredMaxBytes > 0 ? configuredMaxBytes : DEFAULT_RUNTIME_POSTGRES_ARCHIVE_MAX_BYTES;
7732
- async function verifyFile(filePath) {
7733
- if (!expectedSha256) return;
7734
- const hash = createHash2("sha256");
7735
- await new Promise((resolve, reject) => {
7736
- const stream = createReadStream(filePath);
7737
- stream.on("data", (chunk) => hash.update(chunk));
7738
- stream.on("error", reject);
7739
- stream.on("end", resolve);
7740
- });
7741
- const actual = hash.digest("hex");
7742
- if (actual !== expectedSha256) throw new Error(`PostgreSQL runtime archive SHA-256 mismatch: expected ${expectedSha256}, got ${actual}`);
7743
- }
7744
- if (url.startsWith("file://")) {
7745
- await copyFile(fileURLToPath4(url), targetPath);
7746
- const archiveStat = await stat2(targetPath);
7747
- if (archiveStat.size > maxBytes) throw new Error(`PostgreSQL runtime archive exceeds ${maxBytes} bytes`);
7748
- await verifyFile(targetPath);
7749
- return;
7750
- }
7751
7746
  const parsedTimeout = Number.parseInt(
7752
- process.env[RUDDER_POSTGRES_RUNTIME_DOWNLOAD_TIMEOUT_MS_ENV] ?? "600000",
7747
+ String(options.timeoutMs ?? process.env[RUDDER_POSTGRES_RUNTIME_DOWNLOAD_TIMEOUT_MS_ENV] ?? "600000"),
7753
7748
  10
7754
7749
  );
7755
7750
  const controller = new AbortController();
7756
7751
  const timeout = Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? setTimeout(() => controller.abort(), parsedTimeout) : null;
7757
7752
  try {
7758
- const response = await fetch(url, { signal: controller.signal });
7759
- if (!response.ok) {
7760
- throw new Error(`failed to download ${url}: ${response.status} ${response.statusText}`);
7761
- }
7762
- const contentLength = Number.parseInt(response.headers.get("content-length") ?? "", 10);
7763
- if (Number.isSafeInteger(contentLength) && contentLength > maxBytes) {
7764
- throw new Error(`PostgreSQL runtime archive exceeds ${maxBytes} bytes`);
7765
- }
7766
- if (!response.body) throw new Error("PostgreSQL runtime archive response has no body");
7767
7753
  const hash = createHash2("sha256");
7768
7754
  let bytes = 0;
7769
7755
  const monitor = new Transform({
@@ -7777,15 +7763,39 @@ async function downloadRuntimePostgresArchive(url, targetPath, trustedSha256) {
7777
7763
  callback(null, chunk);
7778
7764
  }
7779
7765
  });
7766
+ if (url.startsWith("file://")) {
7767
+ const readStream = (options.createReadStreamImpl ?? createReadStream)(fileURLToPath4(url));
7768
+ await pipeline(readStream, monitor, createWriteStream(targetPath), { signal: controller.signal });
7769
+ if (expectedSha256) {
7770
+ const actual = hash.digest("hex");
7771
+ if (actual !== expectedSha256) throw new Error(`PostgreSQL runtime archive SHA-256 mismatch: expected ${expectedSha256}, got ${actual}`);
7772
+ }
7773
+ return;
7774
+ }
7775
+ const response = await fetch(url, { signal: controller.signal });
7776
+ if (!response.ok) {
7777
+ throw new Error(`failed to download ${url}: ${response.status} ${response.statusText}`);
7778
+ }
7779
+ const contentLength = Number.parseInt(response.headers.get("content-length") ?? "", 10);
7780
+ if (Number.isSafeInteger(contentLength) && contentLength > maxBytes) {
7781
+ throw new Error(`PostgreSQL runtime archive exceeds ${maxBytes} bytes`);
7782
+ }
7783
+ if (!response.body) throw new Error("PostgreSQL runtime archive response has no body");
7780
7784
  await pipeline(
7781
7785
  Readable.fromWeb(response.body),
7782
7786
  monitor,
7783
- createWriteStream(targetPath, { flags: "wx" })
7787
+ createWriteStream(targetPath, { flags: "wx" }),
7788
+ { signal: controller.signal }
7784
7789
  );
7785
7790
  if (expectedSha256) {
7786
7791
  const actual = hash.digest("hex");
7787
7792
  if (actual !== expectedSha256) throw new Error(`PostgreSQL runtime archive SHA-256 mismatch: expected ${expectedSha256}, got ${actual}`);
7788
7793
  }
7794
+ } catch (error) {
7795
+ if (controller.signal.aborted) {
7796
+ throw new Error(`PostgreSQL runtime archive download timed out after ${parsedTimeout}ms`, { cause: error });
7797
+ }
7798
+ throw error;
7789
7799
  } finally {
7790
7800
  if (timeout) clearTimeout(timeout);
7791
7801
  }
@@ -7840,10 +7850,45 @@ var init_postgres_runtime_source = __esm({
7840
7850
 
7841
7851
  // src/runtime/install.ts
7842
7852
  import { execFileSync, spawnSync as spawnSync2 } from "node:child_process";
7843
- import { mkdir as mkdir2, mkdtemp, readFile, readdir, realpath, rename, rm, stat as stat3, symlink, writeFile } from "node:fs/promises";
7853
+ import { createReadStream as createReadStream2, createWriteStream as createWriteStream2 } from "node:fs";
7854
+ import { chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
7844
7855
  import { createRequire } from "node:module";
7845
- import path10 from "node:path";
7856
+ import path9 from "node:path";
7857
+ import { performance as performance2 } from "node:perf_hooks";
7858
+ import { pipeline as pipeline2 } from "node:stream/promises";
7846
7859
  import { pathToFileURL } from "node:url";
7860
+ function createRuntimeInstallDeadline(options) {
7861
+ if (options.timeoutMs === void 0) return void 0;
7862
+ if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0) {
7863
+ throw new Error("Runtime installation timeout must be a positive number of milliseconds.");
7864
+ }
7865
+ const now = options.now ?? (() => performance2.now());
7866
+ return { expiresAt: now() + options.timeoutMs, now };
7867
+ }
7868
+ function remainingRuntimeInstallMs(deadline, cacheDir, command) {
7869
+ if (!deadline) return void 0;
7870
+ const remaining = Math.ceil(deadline.expiresAt - deadline.now());
7871
+ if (remaining <= 0) {
7872
+ throw new RuntimeInstallError(
7873
+ `Timed out while preparing the Rudder runtime during ${command}`,
7874
+ { cacheDir, command }
7875
+ );
7876
+ }
7877
+ return remaining;
7878
+ }
7879
+ function runtimeInstallDeadlineError(cacheDir, command) {
7880
+ return new RuntimeInstallError(
7881
+ `Timed out while preparing the Rudder runtime during ${command}`,
7882
+ { cacheDir, command }
7883
+ );
7884
+ }
7885
+ function isRuntimeInstallDeadlineError(error) {
7886
+ return error instanceof RuntimeInstallError && error.message.startsWith("Timed out while preparing the Rudder runtime during ");
7887
+ }
7888
+ function isChildProcessTimeoutError(error) {
7889
+ const detail = error;
7890
+ return detail?.code === "ETIMEDOUT" || detail?.killed === true || detail?.signal === "SIGTERM";
7891
+ }
7847
7892
  function sanitizeRuntimeCacheSegment(value) {
7848
7893
  return encodeURIComponent(value.trim() || "latest").replaceAll("%", "_");
7849
7894
  }
@@ -7852,7 +7897,7 @@ function resolveRuntimePackageVersion(version) {
7852
7897
  return normalized.length > 0 ? normalized : "latest";
7853
7898
  }
7854
7899
  function resolveRuntimeCacheDir(version, homeDir = resolveRudderHomeDir()) {
7855
- return path10.join(homeDir, "runtimes", sanitizeRuntimeCacheSegment(resolveRuntimePackageVersion(version)));
7900
+ return path9.join(homeDir, "runtimes", sanitizeRuntimeCacheSegment(resolveRuntimePackageVersion(version)));
7856
7901
  }
7857
7902
  function resolveRuntimePackageSpec(version, packageName = RUNTIME_NPM_PACKAGE_NAME) {
7858
7903
  const packageVersion = resolveRuntimePackageVersion(version);
@@ -7860,7 +7905,7 @@ function resolveRuntimePackageSpec(version, packageName = RUNTIME_NPM_PACKAGE_NA
7860
7905
  }
7861
7906
  async function readRuntimeInstallMetadata(cacheDir) {
7862
7907
  try {
7863
- const raw = await readFile(path10.join(cacheDir, RUNTIME_METADATA_FILE), "utf8");
7908
+ const raw = await readFile(path9.join(cacheDir, RUNTIME_METADATA_FILE), "utf8");
7864
7909
  const parsed = JSON.parse(raw);
7865
7910
  if (parsed.version !== 1) return null;
7866
7911
  if (typeof parsed.packageName !== "string" || typeof parsed.packageVersion !== "string") return null;
@@ -7875,7 +7920,7 @@ async function readRuntimeInstallMetadata(cacheDir) {
7875
7920
  }
7876
7921
  }
7877
7922
  async function writeRuntimeInstallMetadata(cacheDir, metadata) {
7878
- await writeFile(path10.join(cacheDir, RUNTIME_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}
7923
+ await writeFile(path9.join(cacheDir, RUNTIME_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}
7879
7924
  `, "utf8");
7880
7925
  }
7881
7926
  async function touchRuntimeInstallMetadata(cacheDir, postgresRuntime) {
@@ -7903,27 +7948,28 @@ function resolveEmbeddedPostgresPlatformPackage(platform = process.platform, arc
7903
7948
  }
7904
7949
  async function canResolveRuntimePackage(cacheDir, packageName) {
7905
7950
  try {
7906
- await readFile(path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json"), "utf8");
7951
+ await readFile(path9.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json"), "utf8");
7907
7952
  return true;
7908
7953
  } catch {
7909
7954
  return false;
7910
7955
  }
7911
7956
  }
7912
- async function hasRequiredRuntimePlatformDependencies(cacheDir, metadata, postgresVersionProbe) {
7957
+ async function hasRequiredRuntimePlatformDependencies(cacheDir, metadata, postgresVersionProbe, deadline) {
7913
7958
  if (!await canResolveRuntimePackage(cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return true;
7914
7959
  const platformPackage = resolveEmbeddedPostgresPlatformPackage();
7915
7960
  if (!platformPackage) return true;
7916
7961
  if (await canResolveRuntimePackage(cacheDir, platformPackage)) return true;
7917
7962
  const expectedSharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(
7918
- path10.dirname(path10.dirname(cacheDir))
7963
+ path9.dirname(path9.dirname(cacheDir))
7919
7964
  );
7920
- return metadata.postgresRuntime?.scope === "shared" && metadata.postgresRuntime.platform === process.platform && metadata.postgresRuntime.arch === process.arch && path10.resolve(metadata.postgresRuntime.binDir) === path10.resolve(expectedSharedBinDir) && await isRuntimePostgresPayloadUsable(
7965
+ return metadata.postgresRuntime?.scope === "shared" && metadata.postgresRuntime.platform === process.platform && metadata.postgresRuntime.arch === process.arch && path9.resolve(metadata.postgresRuntime.binDir) === path9.resolve(expectedSharedBinDir) && await isRuntimePostgresPayloadUsable(
7921
7966
  cacheDir,
7922
7967
  metadata.postgresRuntime.binDir,
7923
- postgresVersionProbe
7968
+ postgresVersionProbe,
7969
+ deadline
7924
7970
  );
7925
7971
  }
7926
- async function isRuntimeCacheHit(options) {
7972
+ async function isRuntimeCacheHitWithinDeadline(options, deadline) {
7927
7973
  const packageName = options.packageName ?? RUNTIME_NPM_PACKAGE_NAME;
7928
7974
  const packageVersion = resolveRuntimePackageVersion(options.version);
7929
7975
  const metadata = await readRuntimeInstallMetadata(options.cacheDir);
@@ -7931,15 +7977,17 @@ async function isRuntimeCacheHit(options) {
7931
7977
  return false;
7932
7978
  }
7933
7979
  try {
7934
- const packageJsonPath = path10.join(options.cacheDir, "node_modules", ...packageName.split("/"), "package.json");
7980
+ const packageJsonPath = path9.join(options.cacheDir, "node_modules", ...packageName.split("/"), "package.json");
7935
7981
  const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
7936
7982
  const packageVersionMatches = packageVersion === "latest" || packageJson.version === packageVersion;
7937
7983
  return packageVersionMatches && await hasRequiredRuntimePlatformDependencies(
7938
7984
  options.cacheDir,
7939
7985
  metadata,
7940
- options.postgresVersionProbe ?? readPostgresVersion
7986
+ options.postgresVersionProbe ?? readPostgresVersion,
7987
+ deadline
7941
7988
  );
7942
- } catch {
7989
+ } catch (error) {
7990
+ if (isRuntimeInstallDeadlineError(error)) throw error;
7943
7991
  return false;
7944
7992
  }
7945
7993
  }
@@ -7947,15 +7995,45 @@ async function ensureRuntimeInstalled(options) {
7947
7995
  const packageVersion = resolveRuntimePackageVersion(options.version);
7948
7996
  const homeDir = options.homeDir ?? resolveRudderHomeDir();
7949
7997
  const cacheDir = resolveRuntimeCacheDir(packageVersion, homeDir);
7998
+ const deadline = createRuntimeInstallDeadline(options);
7950
7999
  return withRuntimeFilesystemLock(
7951
- path10.join(homeDir, "runtime-payloads", ".postgres-runtime.lifecycle.lock"),
8000
+ path9.join(homeDir, "runtime-payloads", ".postgres-runtime.lifecycle.lock"),
7952
8001
  async () => withRuntimeFilesystemLock(
7953
8002
  `${cacheDir}.install.lock`,
7954
- async () => ensureRuntimeInstalledUnlocked(options)
7955
- )
8003
+ async () => {
8004
+ try {
8005
+ return await ensureRuntimeInstalledUnlocked(options, deadline);
8006
+ } catch (error) {
8007
+ if (options.cleanupIncompleteOnFailure === true) {
8008
+ scheduleIncompleteRuntimeCacheCleanup({
8009
+ cacheDir,
8010
+ packageVersion,
8011
+ remove: options.removeIncompleteCache
8012
+ });
8013
+ }
8014
+ throw error;
8015
+ }
8016
+ },
8017
+ { deadline, cacheDir, command: "acquire target runtime install lock" }
8018
+ ),
8019
+ { deadline, cacheDir, command: "acquire PostgreSQL runtime lifecycle lock" }
7956
8020
  );
7957
8021
  }
7958
- async function ensureRuntimeInstalledUnlocked(options) {
8022
+ function scheduleIncompleteRuntimeCacheCleanup(options) {
8023
+ const remove = options.remove ?? ((cacheDir) => rm(cacheDir, { recursive: true, force: true }));
8024
+ void withRuntimeFilesystemLock(
8025
+ `${options.cacheDir}.install.lock`,
8026
+ async () => {
8027
+ const metadata = await readRuntimeInstallMetadata(options.cacheDir);
8028
+ if (!metadata || metadata.packageVersion !== options.packageVersion) {
8029
+ await remove(options.cacheDir);
8030
+ }
8031
+ },
8032
+ { cacheDir: options.cacheDir, command: "cleanup incomplete target runtime cache" }
8033
+ ).catch(() => {
8034
+ });
8035
+ }
8036
+ async function ensureRuntimeInstalledUnlocked(options, deadline) {
7959
8037
  const packageName = options.packageName ?? RUNTIME_NPM_PACKAGE_NAME;
7960
8038
  const packageVersion = resolveRuntimePackageVersion(options.version);
7961
8039
  const homeDir = options.homeDir ?? resolveRudderHomeDir();
@@ -7963,14 +8041,32 @@ async function ensureRuntimeInstalledUnlocked(options) {
7963
8041
  const packageSpec = resolveRuntimePackageSpec(packageVersion, packageName);
7964
8042
  const command = formatRuntimeInstallCommand(cacheDir, packageSpec);
7965
8043
  const preparePostgresPayload = options.preparePostgresPayload === true;
7966
- const postgresVersionProbe = options.postgresVersionProbe ?? readPostgresVersion;
7967
- if (await isRuntimeCacheHit({ cacheDir, version: packageVersion, packageName, postgresVersionProbe })) {
8044
+ const postgresVersionProbe = options.postgresVersionProbe ?? ((binaryPath) => {
8045
+ const probeCommand = `${binaryPath} --version`;
8046
+ try {
8047
+ return readPostgresVersion(
8048
+ binaryPath,
8049
+ remainingRuntimeInstallMs(deadline, cacheDir, probeCommand)
8050
+ );
8051
+ } catch (error) {
8052
+ if (isChildProcessTimeoutError(error)) {
8053
+ throw runtimeInstallDeadlineError(cacheDir, probeCommand);
8054
+ }
8055
+ throw error;
8056
+ }
8057
+ });
8058
+ if (await isRuntimeCacheHitWithinDeadline(
8059
+ { cacheDir, version: packageVersion, packageName, postgresVersionProbe },
8060
+ deadline
8061
+ )) {
7968
8062
  const postgresPayload2 = await stageRuntimePostgresPayload(
7969
8063
  cacheDir,
7970
8064
  homeDir,
7971
8065
  packageVersion,
7972
8066
  preparePostgresPayload,
7973
- postgresVersionProbe
8067
+ postgresVersionProbe,
8068
+ deadline,
8069
+ options.cleanupPostgresDownloadWorkDir
7974
8070
  );
7975
8071
  await touchRuntimeInstallMetadata(cacheDir, postgresPayload2.metadata);
7976
8072
  const prune2 = await maybePruneRuntimeCache({
@@ -7989,7 +8085,8 @@ async function ensureRuntimeInstalledUnlocked(options) {
7989
8085
  spawnSyncImpl,
7990
8086
  cacheDir,
7991
8087
  packageName,
7992
- packageVersion
8088
+ packageVersion,
8089
+ deadline
7993
8090
  });
7994
8091
  if (existingRuntimeOutput !== null) {
7995
8092
  const postgresPayload2 = await stageRuntimePostgresPayload(
@@ -7997,7 +8094,9 @@ async function ensureRuntimeInstalledUnlocked(options) {
7997
8094
  homeDir,
7998
8095
  packageVersion,
7999
8096
  preparePostgresPayload,
8000
- postgresVersionProbe
8097
+ postgresVersionProbe,
8098
+ deadline,
8099
+ options.cleanupPostgresDownloadWorkDir
8001
8100
  );
8002
8101
  const metadata2 = {
8003
8102
  version: 1,
@@ -8020,30 +8119,32 @@ async function ensureRuntimeInstalledUnlocked(options) {
8020
8119
  );
8021
8120
  }
8022
8121
  await rm(cacheDir, { recursive: true, force: true });
8023
- await mkdir2(cacheDir, { recursive: true });
8024
- await writeFile(path10.join(cacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
8122
+ await mkdir(cacheDir, { recursive: true });
8123
+ await writeFile(path9.join(cacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
8025
8124
  `, "utf8");
8026
- const result = runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec);
8125
+ const result = runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec, deadline);
8027
8126
  let output = collectSpawnOutput(result);
8028
- if (result.status !== 0 && packageVersion !== "latest" && isVersionNotFoundError(output)) {
8127
+ if (result.status !== 0 && packageVersion !== "latest" && options.allowLatestFallback !== false && isVersionNotFoundError(output)) {
8029
8128
  const fallbackVersion = "latest";
8030
8129
  const fallbackCacheDir = resolveRuntimeCacheDir(fallbackVersion, options.homeDir);
8031
8130
  const fallbackSpec = resolveRuntimePackageSpec(fallbackVersion, packageName);
8032
8131
  const fallbackInstallResult = await withRuntimeFilesystemLock(
8033
8132
  `${fallbackCacheDir}.install.lock`,
8034
8133
  async () => {
8035
- if (await isRuntimeCacheHit({
8134
+ if (await isRuntimeCacheHitWithinDeadline({
8036
8135
  cacheDir: fallbackCacheDir,
8037
8136
  version: fallbackVersion,
8038
8137
  packageName,
8039
8138
  postgresVersionProbe
8040
- })) {
8139
+ }, deadline)) {
8041
8140
  const fallbackPostgresPayload = await stageRuntimePostgresPayload(
8042
8141
  fallbackCacheDir,
8043
8142
  homeDir,
8044
8143
  fallbackVersion,
8045
8144
  preparePostgresPayload,
8046
- postgresVersionProbe
8145
+ postgresVersionProbe,
8146
+ deadline,
8147
+ options.cleanupPostgresDownloadWorkDir
8047
8148
  );
8048
8149
  await touchRuntimeInstallMetadata(fallbackCacheDir, fallbackPostgresPayload.metadata);
8049
8150
  return withPostgresPayload(
@@ -8058,22 +8159,24 @@ async function ensureRuntimeInstalledUnlocked(options) {
8058
8159
  );
8059
8160
  }
8060
8161
  await rm(fallbackCacheDir, { recursive: true, force: true });
8061
- await mkdir2(fallbackCacheDir, { recursive: true });
8062
- await writeFile(path10.join(fallbackCacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
8162
+ await mkdir(fallbackCacheDir, { recursive: true });
8163
+ await writeFile(path9.join(fallbackCacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
8063
8164
  `, "utf8");
8064
- const fallbackResult = runNpmRuntimeInstall(spawnSyncImpl, fallbackCacheDir, fallbackSpec);
8165
+ const fallbackResult = runNpmRuntimeInstall(spawnSyncImpl, fallbackCacheDir, fallbackSpec, deadline);
8065
8166
  let fallbackOutput = collectSpawnOutput(fallbackResult);
8066
8167
  if (fallbackResult.status !== 0) return null;
8067
8168
  fallbackOutput = collectOutputParts(
8068
8169
  fallbackOutput,
8069
- await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, fallbackCacheDir)
8170
+ await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, fallbackCacheDir, deadline)
8070
8171
  );
8071
8172
  const postgresPayload2 = await stageRuntimePostgresPayload(
8072
8173
  fallbackCacheDir,
8073
8174
  homeDir,
8074
8175
  fallbackVersion,
8075
8176
  preparePostgresPayload,
8076
- postgresVersionProbe
8177
+ postgresVersionProbe,
8178
+ deadline,
8179
+ options.cleanupPostgresDownloadWorkDir
8077
8180
  );
8078
8181
  const fallbackMetadata = {
8079
8182
  version: 1,
@@ -8094,7 +8197,8 @@ async function ensureRuntimeInstalledUnlocked(options) {
8094
8197
  },
8095
8198
  postgresPayload2
8096
8199
  );
8097
- }
8200
+ },
8201
+ { deadline, cacheDir: fallbackCacheDir, command: "acquire fallback runtime install lock" }
8098
8202
  );
8099
8203
  if (fallbackInstallResult) return fallbackInstallResult;
8100
8204
  }
@@ -8106,14 +8210,16 @@ async function ensureRuntimeInstalledUnlocked(options) {
8106
8210
  }
8107
8211
  output = collectOutputParts(
8108
8212
  output,
8109
- await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir)
8213
+ await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir, deadline)
8110
8214
  );
8111
8215
  const postgresPayload = await stageRuntimePostgresPayload(
8112
8216
  cacheDir,
8113
8217
  homeDir,
8114
8218
  packageVersion,
8115
8219
  preparePostgresPayload,
8116
- postgresVersionProbe
8220
+ postgresVersionProbe,
8221
+ deadline,
8222
+ options.cleanupPostgresDownloadWorkDir
8117
8223
  );
8118
8224
  const metadata = {
8119
8225
  version: 1,
@@ -8136,10 +8242,10 @@ async function ensureRuntimeInstalledUnlocked(options) {
8136
8242
  );
8137
8243
  }
8138
8244
  function resolveRuntimePostgresPayloadBinDir(cacheDir, platform = process.platform, arch = process.arch) {
8139
- return path10.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR, runtimePostgresPlatformSegment(platform, arch), "bin");
8245
+ return path9.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR, runtimePostgresPlatformSegment(platform, arch), "bin");
8140
8246
  }
8141
8247
  function resolveSharedRuntimePostgresPayloadBinDir(homeDir = resolveRudderHomeDir(), platform = process.platform, arch = process.arch) {
8142
- return path10.join(
8248
+ return path9.join(
8143
8249
  homeDir,
8144
8250
  "runtime-payloads",
8145
8251
  RUNTIME_POSTGRES_PAYLOAD_DIR,
@@ -8148,19 +8254,21 @@ function resolveSharedRuntimePostgresPayloadBinDir(homeDir = resolveRudderHomeDi
8148
8254
  );
8149
8255
  }
8150
8256
  function resolveRuntimeServerEntrypoint(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
8151
- return createRequire(path10.join(cacheDir, "package.json")).resolve(packageName);
8257
+ return createRequire(path9.join(cacheDir, "package.json")).resolve(packageName);
8152
8258
  }
8153
8259
  async function importRuntimeServerModule(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
8154
8260
  const entrypoint = resolveRuntimeServerEntrypoint(cacheDir, packageName);
8155
8261
  return await import(pathToFileURL(entrypoint).href);
8156
8262
  }
8157
- function runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec) {
8263
+ function runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec, deadline) {
8264
+ const timeout = remainingRuntimeInstallMs(deadline, cacheDir, `npm install ${packageSpec}`);
8158
8265
  return spawnSyncImpl(
8159
8266
  process.platform === "win32" ? "npm.cmd" : "npm",
8160
8267
  ["install", "--prefix", cacheDir, ...RUNTIME_NPM_INSTALL_FLAGS, packageSpec],
8161
8268
  {
8162
8269
  encoding: "utf8",
8163
8270
  stdio: ["ignore", "pipe", "pipe"],
8271
+ ...timeout === void 0 ? {} : { timeout },
8164
8272
  ...process.platform === "win32" ? { shell: true, windowsHide: true } : {}
8165
8273
  }
8166
8274
  );
@@ -8169,7 +8277,7 @@ function formatRuntimeInstallCommand(cacheDir, packageSpec) {
8169
8277
  return `npm install --prefix ${cacheDir} ${RUNTIME_NPM_INSTALL_FLAGS.join(" ")} ${packageSpec}`;
8170
8278
  }
8171
8279
  function formatRuntimePlatformRepairCommand(cacheDir, packageSpec) {
8172
- return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${path10.join(cacheDir, "node_modules")}`;
8280
+ return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${path9.join(cacheDir, "node_modules")}`;
8173
8281
  }
8174
8282
  function collectSpawnOutput(result) {
8175
8283
  return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
@@ -8186,7 +8294,7 @@ function withPostgresPayload(result, postgresPayload) {
8186
8294
  };
8187
8295
  }
8188
8296
  function runtimePackageJsonPath(cacheDir, packageName) {
8189
- return path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json");
8297
+ return path9.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json");
8190
8298
  }
8191
8299
  async function readRuntimePackageJson(cacheDir, packageName) {
8192
8300
  try {
@@ -8199,7 +8307,11 @@ async function tryRepairExistingRuntimePackage(options) {
8199
8307
  const runtimePackage = await readRuntimePackageJson(options.cacheDir, options.packageName);
8200
8308
  if (!runtimePackage) return null;
8201
8309
  if (options.packageVersion !== "latest" && runtimePackage.version !== options.packageVersion) return null;
8202
- const output = await ensureRequiredEmbeddedPostgresPlatformPackage(options.spawnSyncImpl, options.cacheDir);
8310
+ const output = await ensureRequiredEmbeddedPostgresPlatformPackage(
8311
+ options.spawnSyncImpl,
8312
+ options.cacheDir,
8313
+ options.deadline
8314
+ );
8203
8315
  if (!await canResolveRuntimePackage(options.cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return output;
8204
8316
  const platformPackage = resolveEmbeddedPostgresPlatformPackage();
8205
8317
  return !platformPackage || await canResolveRuntimePackage(options.cacheDir, platformPackage) ? output : null;
@@ -8213,13 +8325,19 @@ async function resolveEmbeddedPostgresPlatformPackageSpec(cacheDir) {
8213
8325
  const packageVersion = normalizeOptionalDependencyVersion(versionRange);
8214
8326
  return packageVersion ? `${packageName}@${packageVersion}` : packageName;
8215
8327
  }
8216
- async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir) {
8328
+ async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir, deadline) {
8217
8329
  const packageSpec = await resolveEmbeddedPostgresPlatformPackageSpec(cacheDir);
8218
8330
  if (!packageSpec) return "";
8219
8331
  const packageName = packageNameFromSpec(packageSpec);
8220
8332
  if (packageName && await canResolveRuntimePackage(cacheDir, packageName)) return "";
8221
8333
  await removeRuntimeInstallLocks(cacheDir);
8222
- const result = await installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName);
8334
+ const result = await installRuntimePackageInStaging(
8335
+ spawnSyncImpl,
8336
+ cacheDir,
8337
+ packageSpec,
8338
+ packageName,
8339
+ deadline
8340
+ );
8223
8341
  const output = collectSpawnOutput(result);
8224
8342
  if (result.status === 0 && packageName && await canResolveRuntimePackage(cacheDir, packageName)) {
8225
8343
  return output;
@@ -8230,28 +8348,29 @@ async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cach
8230
8348
  { cacheDir, command, output }
8231
8349
  );
8232
8350
  }
8233
- async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName) {
8234
- const stagingDir = path10.join(cacheDir, `.platform-repair-${process.pid}-${Date.now()}`);
8235
- await mkdir2(stagingDir, { recursive: true });
8351
+ async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName, deadline) {
8352
+ const stagingDir = path9.join(cacheDir, `.platform-repair-${process.pid}-${Date.now()}`);
8353
+ await mkdir(stagingDir, { recursive: true });
8236
8354
  try {
8237
- const packResult = runNpmPack(spawnSyncImpl, packageSpec, stagingDir);
8355
+ const packResult = runNpmPack(spawnSyncImpl, packageSpec, stagingDir, cacheDir, deadline);
8238
8356
  if (packResult.status !== 0) return packResult;
8239
8357
  const packFilename = parseNpmPackFilename(packResult.stdout);
8240
8358
  if (!packFilename) {
8241
8359
  return createSyntheticSpawnResult(1, "", `Unable to parse npm pack output for ${packageSpec}.`);
8242
8360
  }
8243
- const archivePath = path10.join(stagingDir, packFilename);
8244
- const targetDir = path10.dirname(runtimePackageJsonPath(cacheDir, packageName));
8245
- await mkdir2(path10.dirname(targetDir), { recursive: true });
8361
+ const archivePath = path9.join(stagingDir, packFilename);
8362
+ const targetDir = path9.dirname(runtimePackageJsonPath(cacheDir, packageName));
8363
+ await mkdir(path9.dirname(targetDir), { recursive: true });
8246
8364
  await rm(targetDir, { recursive: true, force: true });
8247
- await mkdir2(targetDir, { recursive: true });
8248
- const extractResult = runTarExtract(spawnSyncImpl, archivePath, targetDir);
8365
+ await mkdir(targetDir, { recursive: true });
8366
+ const extractResult = runTarExtract(spawnSyncImpl, archivePath, targetDir, cacheDir, deadline);
8249
8367
  return combineSpawnResults(packResult, extractResult);
8250
8368
  } finally {
8251
8369
  await rm(stagingDir, { recursive: true, force: true });
8252
8370
  }
8253
8371
  }
8254
- function runNpmPack(spawnSyncImpl, packageSpec, destinationDir) {
8372
+ function runNpmPack(spawnSyncImpl, packageSpec, destinationDir, cacheDir, deadline) {
8373
+ const timeout = remainingRuntimeInstallMs(deadline, cacheDir, `npm pack ${packageSpec}`);
8255
8374
  return spawnSyncImpl(
8256
8375
  process.platform === "win32" ? "npm.cmd" : "npm",
8257
8376
  ["pack", packageSpec, "--pack-destination", destinationDir, ...RUNTIME_NPM_PACK_FLAGS],
@@ -8259,17 +8378,20 @@ function runNpmPack(spawnSyncImpl, packageSpec, destinationDir) {
8259
8378
  encoding: "utf8",
8260
8379
  stdio: ["ignore", "pipe", "pipe"],
8261
8380
  env: { ...process.env, ...NPM_PLATFORM_REPAIR_ENV },
8381
+ ...timeout === void 0 ? {} : { timeout },
8262
8382
  ...process.platform === "win32" ? { shell: true, windowsHide: true } : {}
8263
8383
  }
8264
8384
  );
8265
8385
  }
8266
- function runTarExtract(spawnSyncImpl, archivePath, targetDir) {
8386
+ function runTarExtract(spawnSyncImpl, archivePath, targetDir, cacheDir, deadline) {
8387
+ const timeout = remainingRuntimeInstallMs(deadline, cacheDir, "extract runtime platform package");
8267
8388
  return spawnSyncImpl(
8268
8389
  "tar",
8269
8390
  ["-xzf", archivePath, "-C", targetDir, "--strip-components", "1"],
8270
8391
  {
8271
8392
  encoding: "utf8",
8272
8393
  stdio: ["ignore", "pipe", "pipe"],
8394
+ ...timeout === void 0 ? {} : { timeout },
8273
8395
  ...process.platform === "win32" ? { windowsHide: true } : {}
8274
8396
  }
8275
8397
  );
@@ -8293,8 +8415,8 @@ function combineSpawnResults(...results) {
8293
8415
  }
8294
8416
  async function removeRuntimeInstallLocks(cacheDir) {
8295
8417
  await Promise.all([
8296
- rm(path10.join(cacheDir, "package-lock.json"), { force: true }),
8297
- rm(path10.join(cacheDir, "node_modules", ".package-lock.json"), { force: true })
8418
+ rm(path9.join(cacheDir, "package-lock.json"), { force: true }),
8419
+ rm(path9.join(cacheDir, "node_modules", ".package-lock.json"), { force: true })
8298
8420
  ]);
8299
8421
  }
8300
8422
  function packageNameFromSpec(packageSpec) {
@@ -8318,77 +8440,95 @@ function runtimePostgresExecutableName(baseName) {
8318
8440
  return process.platform === "win32" ? `${baseName}.exe` : baseName;
8319
8441
  }
8320
8442
  function debianSharedirCandidate(binDir) {
8321
- const normalized = path10.resolve(binDir);
8322
- const parts = normalized.split(path10.sep);
8443
+ const normalized = path9.resolve(binDir);
8444
+ const parts = normalized.split(path9.sep);
8323
8445
  const libIndex = parts.lastIndexOf("lib");
8324
8446
  if (libIndex < 0) return null;
8325
8447
  if (parts[libIndex + 1] !== "postgresql") return null;
8326
8448
  const version = parts[libIndex + 2];
8327
8449
  if (!version || parts[libIndex + 3] !== "bin") return null;
8328
- const prefix = parts.slice(0, libIndex).join(path10.sep) || path10.sep;
8329
- return path10.join(prefix, "share", "postgresql", version);
8450
+ const prefix = parts.slice(0, libIndex).join(path9.sep) || path9.sep;
8451
+ return path9.join(prefix, "share", "postgresql", version);
8330
8452
  }
8331
- async function resolveRuntimePostgresTemplateDir(binDir) {
8453
+ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, deadline) {
8332
8454
  for (const candidatePath of [
8333
- path10.join(binDir, "..", "share", "postgresql", "postgres.bki"),
8334
- path10.join(binDir, "..", "share", "postgres.bki")
8455
+ path9.join(binDir, "..", "share", "postgresql", "postgres.bki"),
8456
+ path9.join(binDir, "..", "share", "postgres.bki")
8335
8457
  ]) {
8458
+ remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
8336
8459
  try {
8337
- await stat3(candidatePath);
8338
- return path10.dirname(candidatePath);
8460
+ await stat(candidatePath);
8461
+ return path9.dirname(candidatePath);
8339
8462
  } catch {
8340
8463
  }
8341
8464
  }
8342
8465
  const debianSharedir = debianSharedirCandidate(binDir);
8343
8466
  if (debianSharedir) {
8467
+ remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
8344
8468
  try {
8345
- await stat3(path10.join(debianSharedir, "postgres.bki"));
8469
+ await stat(path9.join(debianSharedir, "postgres.bki"));
8346
8470
  return debianSharedir;
8347
8471
  } catch {
8348
8472
  }
8349
8473
  }
8350
- const pgConfigPath = path10.join(binDir, process.platform === "win32" ? "pg_config.exe" : "pg_config");
8474
+ const pgConfigPath = path9.join(binDir, process.platform === "win32" ? "pg_config.exe" : "pg_config");
8351
8475
  try {
8352
- await stat3(pgConfigPath);
8353
- const sharedir = execFileSync(pgConfigPath, ["--sharedir"], { encoding: "utf8" }).trim();
8476
+ remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
8477
+ await stat(pgConfigPath);
8478
+ const timeout = remainingRuntimeInstallMs(deadline, cacheDir, `${pgConfigPath} --sharedir`);
8479
+ let sharedir;
8480
+ try {
8481
+ sharedir = execFileSync(pgConfigPath, ["--sharedir"], {
8482
+ encoding: "utf8",
8483
+ ...timeout === void 0 ? {} : { timeout }
8484
+ }).trim();
8485
+ } catch (error) {
8486
+ if (isChildProcessTimeoutError(error)) {
8487
+ throw runtimeInstallDeadlineError(cacheDir, `${pgConfigPath} --sharedir`);
8488
+ }
8489
+ throw error;
8490
+ }
8354
8491
  if (!sharedir) return null;
8355
- const candidatePath = path10.join(sharedir, "postgres.bki");
8356
- await stat3(candidatePath);
8492
+ remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime templates");
8493
+ const candidatePath = path9.join(sharedir, "postgres.bki");
8494
+ await stat(candidatePath);
8357
8495
  return sharedir;
8358
- } catch {
8496
+ } catch (error) {
8497
+ if (isRuntimeInstallDeadlineError(error)) throw error;
8359
8498
  return null;
8360
8499
  }
8361
8500
  }
8362
8501
  function resolveRuntimePostgresShareDir(binDir, templateDir) {
8363
- const adjacentShareDir = path10.resolve(binDir, "..", "share");
8502
+ const adjacentShareDir = path9.resolve(binDir, "..", "share");
8364
8503
  return pathIsInside(templateDir, adjacentShareDir) ? adjacentShareDir : templateDir;
8365
8504
  }
8366
- async function assertRuntimePostgresBinDirComplete(cacheDir, binDir) {
8505
+ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
8367
8506
  const requiredBinaries = ["initdb", "pg_ctl", "postgres"];
8368
8507
  const missing = [];
8369
8508
  for (const binary of requiredBinaries) {
8370
- const binaryPath = path10.join(binDir, runtimePostgresExecutableName(binary));
8509
+ remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime binaries");
8510
+ const binaryPath = path9.join(binDir, runtimePostgresExecutableName(binary));
8371
8511
  try {
8372
- await stat3(binaryPath);
8512
+ await stat(binaryPath);
8373
8513
  } catch {
8374
8514
  missing.push(binaryPath);
8375
8515
  }
8376
8516
  }
8377
- const templateDir = await resolveRuntimePostgresTemplateDir(binDir);
8517
+ const templateDir = await resolveRuntimePostgresTemplateDir(binDir, cacheDir, deadline);
8378
8518
  if (!templateDir) {
8379
- missing.push(path10.join(binDir, "..", "share", "postgresql", "postgres.bki"));
8519
+ missing.push(path9.join(binDir, "..", "share", "postgresql", "postgres.bki"));
8380
8520
  } else {
8381
8521
  try {
8382
- await stat3(path10.join(templateDir, "postgresql.conf.sample"));
8522
+ await stat(path9.join(templateDir, "postgresql.conf.sample"));
8383
8523
  } catch {
8384
- missing.push(path10.join(templateDir, "postgresql.conf.sample"));
8524
+ missing.push(path9.join(templateDir, "postgresql.conf.sample"));
8385
8525
  }
8386
8526
  const shareDir = resolveRuntimePostgresShareDir(binDir, templateDir);
8387
8527
  const hasTimezoneDir = (await Promise.all([
8388
- path10.join(templateDir, "timezone"),
8389
- path10.join(shareDir, "timezone")
8390
- ].map((candidate) => stat3(candidate).catch(() => null)))).some((candidate) => candidate?.isDirectory());
8391
- if (!hasTimezoneDir) missing.push(path10.join(shareDir, "timezone"));
8528
+ path9.join(templateDir, "timezone"),
8529
+ path9.join(shareDir, "timezone")
8530
+ ].map((candidate) => stat(candidate).catch(() => null)))).some((candidate) => candidate?.isDirectory());
8531
+ if (!hasTimezoneDir) missing.push(path9.join(shareDir, "timezone"));
8392
8532
  }
8393
8533
  if (missing.length > 0) {
8394
8534
  throw new RuntimeInstallError(
@@ -8397,31 +8537,124 @@ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir) {
8397
8537
  );
8398
8538
  }
8399
8539
  }
8400
- function readPostgresVersion(postgresBinary) {
8401
- return execFileSync(postgresBinary, ["--version"], { encoding: "utf8" });
8540
+ function readPostgresVersion(postgresBinary, timeout) {
8541
+ return execFileSync(postgresBinary, ["--version"], {
8542
+ encoding: "utf8",
8543
+ ...timeout === void 0 ? {} : { timeout }
8544
+ });
8402
8545
  }
8403
- async function isRuntimePostgresPayloadUsable(cacheDir, binDir, postgresVersionProbe) {
8546
+ async function isRuntimePostgresPayloadUsable(cacheDir, binDir, postgresVersionProbe, deadline) {
8404
8547
  try {
8405
- await validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionProbe);
8548
+ await validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionProbe, deadline);
8406
8549
  return true;
8407
- } catch {
8550
+ } catch (error) {
8551
+ if (isRuntimeInstallDeadlineError(error)) throw error;
8408
8552
  return false;
8409
8553
  }
8410
8554
  }
8411
8555
  function pathIsInside(candidatePath, rootPath) {
8412
- const relative = path10.relative(path10.resolve(rootPath), path10.resolve(candidatePath));
8413
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(relative);
8556
+ const relative = path9.relative(path9.resolve(rootPath), path9.resolve(candidatePath));
8557
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path9.sep}`) && !path9.isAbsolute(relative);
8558
+ }
8559
+ async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadline, signal, command) {
8560
+ if (signal.aborted) throw runtimeInstallDeadlineError(cacheDir, command);
8561
+ remainingRuntimeInstallMs(deadline, cacheDir, command);
8562
+ const sourceStats = await stat(sourcePath);
8563
+ if (signal.aborted) throw runtimeInstallDeadlineError(cacheDir, command);
8564
+ remainingRuntimeInstallMs(deadline, cacheDir, command);
8565
+ if (sourceStats.isDirectory()) {
8566
+ await mkdir(targetPath, { recursive: true });
8567
+ const entries = await readdir(sourcePath);
8568
+ for (const entry of entries) {
8569
+ await copyRuntimePayloadEntry(
8570
+ path9.join(sourcePath, entry),
8571
+ path9.join(targetPath, entry),
8572
+ cacheDir,
8573
+ deadline,
8574
+ signal,
8575
+ command
8576
+ );
8577
+ }
8578
+ return;
8579
+ }
8580
+ if (!sourceStats.isFile()) return;
8581
+ await mkdir(path9.dirname(targetPath), { recursive: true });
8582
+ try {
8583
+ await pipeline2(
8584
+ createReadStream2(sourcePath),
8585
+ createWriteStream2(targetPath, { flags: "w", mode: sourceStats.mode }),
8586
+ { signal }
8587
+ );
8588
+ await chmod(targetPath, sourceStats.mode);
8589
+ remainingRuntimeInstallMs(deadline, cacheDir, command);
8590
+ } catch (error) {
8591
+ await rm(targetPath, { force: true });
8592
+ if (signal.aborted || isRuntimeInstallDeadlineError(error)) {
8593
+ throw runtimeInstallDeadlineError(cacheDir, command);
8594
+ }
8595
+ throw error;
8596
+ }
8597
+ }
8598
+ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, targetRuntimeDir, sourceShareDir, cacheDir, deadline, externalSignal) {
8599
+ const command = "copy PostgreSQL runtime payload";
8600
+ const timeoutMs = remainingRuntimeInstallMs(deadline, cacheDir, command);
8601
+ const controller = new AbortController();
8602
+ const abortFromExternal = () => controller.abort(externalSignal?.reason);
8603
+ if (externalSignal?.aborted) abortFromExternal();
8604
+ else externalSignal?.addEventListener("abort", abortFromExternal, { once: true });
8605
+ let timer;
8606
+ const timeoutPromise = timeoutMs === void 0 ? null : new Promise((_resolve, reject) => {
8607
+ timer = setTimeout(() => {
8608
+ controller.abort();
8609
+ reject(runtimeInstallDeadlineError(cacheDir, command));
8610
+ }, timeoutMs);
8611
+ });
8612
+ const copyPromise = (async () => {
8613
+ await mkdir(targetRuntimeDir, { recursive: true });
8614
+ for (const directoryName of ["bin", "lib"]) {
8615
+ const sourceDirectory = path9.join(sourceRuntimeDir, directoryName);
8616
+ if (!await stat(sourceDirectory).catch(() => null)) continue;
8617
+ await copyRuntimePayloadEntry(
8618
+ sourceDirectory,
8619
+ path9.join(targetRuntimeDir, directoryName),
8620
+ cacheDir,
8621
+ deadline,
8622
+ controller.signal,
8623
+ command
8624
+ );
8625
+ }
8626
+ await copyRuntimePayloadEntry(
8627
+ sourceShareDir,
8628
+ path9.join(targetRuntimeDir, "share"),
8629
+ cacheDir,
8630
+ deadline,
8631
+ controller.signal,
8632
+ command
8633
+ );
8634
+ })();
8635
+ try {
8636
+ if (timeoutPromise) await Promise.race([copyPromise, timeoutPromise]);
8637
+ else await copyPromise;
8638
+ } finally {
8639
+ if (timer) clearTimeout(timer);
8640
+ externalSignal?.removeEventListener("abort", abortFromExternal);
8641
+ }
8414
8642
  }
8415
8643
  async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
8416
- const timeoutMs = options.timeoutMs ?? 3e4;
8644
+ const deadlineTimeout = remainingRuntimeInstallMs(
8645
+ options.deadline,
8646
+ options.cacheDir ?? path9.dirname(lockPath),
8647
+ options.command ?? `wait for runtime lock ${lockPath}`
8648
+ );
8649
+ const timeoutMs = Math.min(options.timeoutMs ?? 3e4, deadlineTimeout ?? Number.POSITIVE_INFINITY);
8417
8650
  const pollMs = options.pollMs ?? 50;
8418
8651
  const startedAt = Date.now();
8419
8652
  const lockId = `${process.pid}-${startedAt}-${Math.random().toString(16).slice(2)}`;
8420
- const ownerPath = path10.join(lockPath, "owner.json");
8421
- await mkdir2(path10.dirname(lockPath), { recursive: true });
8653
+ const ownerPath = path9.join(lockPath, "owner.json");
8654
+ await mkdir(path9.dirname(lockPath), { recursive: true });
8422
8655
  while (true) {
8423
8656
  try {
8424
- await mkdir2(lockPath);
8657
+ await mkdir(lockPath);
8425
8658
  await writeFile(
8426
8659
  ownerPath,
8427
8660
  `${JSON.stringify({ pid: process.pid, lockId, createdAt: (/* @__PURE__ */ new Date()).toISOString() })}
@@ -8438,7 +8671,7 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
8438
8671
  continue;
8439
8672
  }
8440
8673
  } catch {
8441
- const lockStats = await stat3(lockPath).catch(() => null);
8674
+ const lockStats = await stat(lockPath).catch(() => null);
8442
8675
  if (lockStats && Date.now() - lockStats.mtimeMs > 5e3) {
8443
8676
  await rm(lockPath, { recursive: true, force: true });
8444
8677
  continue;
@@ -8447,9 +8680,14 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
8447
8680
  if (Date.now() - startedAt >= timeoutMs) {
8448
8681
  throw new RuntimeInstallError(
8449
8682
  `Timed out waiting for PostgreSQL runtime install lock ${lockPath}`,
8450
- { cacheDir: path10.dirname(lockPath), command: "prepare shared PostgreSQL runtime", output: "" }
8683
+ { cacheDir: path9.dirname(lockPath), command: "prepare shared PostgreSQL runtime", output: "" }
8451
8684
  );
8452
8685
  }
8686
+ remainingRuntimeInstallMs(
8687
+ options.deadline,
8688
+ options.cacheDir ?? path9.dirname(lockPath),
8689
+ options.command ?? `wait for runtime lock ${lockPath}`
8690
+ );
8453
8691
  await new Promise((resolve) => setTimeout(resolve, pollMs));
8454
8692
  }
8455
8693
  }
@@ -8467,44 +8705,45 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
8467
8705
  }
8468
8706
  function isManagedRuntimePostgresBinDir(binDir, homeDir) {
8469
8707
  const managedBinDir = process.env[RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR_ENV]?.trim();
8470
- if (managedBinDir && path10.resolve(managedBinDir) === path10.resolve(binDir)) return true;
8471
- const runtimesRelative = path10.relative(
8472
- path10.join(homeDir, "runtimes"),
8473
- path10.resolve(binDir)
8708
+ if (managedBinDir && path9.resolve(managedBinDir) === path9.resolve(binDir)) return true;
8709
+ const runtimesRelative = path9.relative(
8710
+ path9.join(homeDir, "runtimes"),
8711
+ path9.resolve(binDir)
8474
8712
  );
8475
- const runtimeSegments = runtimesRelative.split(path10.sep);
8476
- if (runtimesRelative !== "" && runtimesRelative !== ".." && !runtimesRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(runtimesRelative) && runtimeSegments.length === 4 && runtimeSegments[0]?.length > 0 && runtimeSegments[1] === RUNTIME_POSTGRES_PAYLOAD_DIR && runtimeSegments[2] === `${process.platform}-${process.arch}` && runtimeSegments[3] === "bin") {
8713
+ const runtimeSegments = runtimesRelative.split(path9.sep);
8714
+ if (runtimesRelative !== "" && runtimesRelative !== ".." && !runtimesRelative.startsWith(`..${path9.sep}`) && !path9.isAbsolute(runtimesRelative) && runtimeSegments.length === 4 && runtimeSegments[0]?.length > 0 && runtimeSegments[1] === RUNTIME_POSTGRES_PAYLOAD_DIR && runtimeSegments[2] === `${process.platform}-${process.arch}` && runtimeSegments[3] === "bin") {
8477
8715
  return true;
8478
8716
  }
8479
- const payloadsRelative = path10.relative(
8480
- path10.join(homeDir, "runtime-payloads"),
8481
- path10.resolve(binDir)
8717
+ const payloadsRelative = path9.relative(
8718
+ path9.join(homeDir, "runtime-payloads"),
8719
+ path9.resolve(binDir)
8482
8720
  );
8483
- const payloadSegments = payloadsRelative.split(path10.sep);
8484
- return payloadsRelative !== "" && payloadsRelative !== ".." && !payloadsRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(payloadsRelative) && payloadSegments.length === 3 && payloadSegments[0] === RUNTIME_POSTGRES_PAYLOAD_DIR && payloadSegments[1] === `${process.platform}-${process.arch}` && payloadSegments[2] === "bin";
8721
+ const payloadSegments = payloadsRelative.split(path9.sep);
8722
+ return payloadsRelative !== "" && payloadsRelative !== ".." && !payloadsRelative.startsWith(`..${path9.sep}`) && !path9.isAbsolute(payloadsRelative) && payloadSegments.length === 3 && payloadSegments[0] === RUNTIME_POSTGRES_PAYLOAD_DIR && payloadSegments[1] === `${process.platform}-${process.arch}` && payloadSegments[2] === "bin";
8485
8723
  }
8486
- async function findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersionProbe) {
8487
- const runtimesRoot = path10.join(homeDir, "runtimes");
8724
+ async function findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersionProbe, deadline) {
8725
+ const runtimesRoot = path9.join(homeDir, "runtimes");
8488
8726
  const entries = await readdir(runtimesRoot, { withFileTypes: true }).catch(() => []);
8489
8727
  for (const entry of entries) {
8490
8728
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
8491
- const candidateCacheDir = path10.join(runtimesRoot, entry.name);
8492
- if (path10.resolve(candidateCacheDir) === path10.resolve(cacheDir)) continue;
8729
+ const candidateCacheDir = path9.join(runtimesRoot, entry.name);
8730
+ if (path9.resolve(candidateCacheDir) === path9.resolve(cacheDir)) continue;
8493
8731
  const candidateBinDir = resolveRuntimePostgresPayloadBinDir(candidateCacheDir);
8494
- if (await isRuntimePostgresPayloadUsable(cacheDir, candidateBinDir, postgresVersionProbe)) {
8732
+ remainingRuntimeInstallMs(deadline, cacheDir, "find cached PostgreSQL runtime payload");
8733
+ if (await isRuntimePostgresPayloadUsable(cacheDir, candidateBinDir, postgresVersionProbe, deadline)) {
8495
8734
  return candidateBinDir;
8496
8735
  }
8497
8736
  }
8498
8737
  return null;
8499
8738
  }
8500
8739
  async function readLiveRuntimeDescriptors(homeDir) {
8501
- const instancesRoot = path10.join(homeDir, "instances");
8740
+ const instancesRoot = path9.join(homeDir, "instances");
8502
8741
  const entries = await readdir(instancesRoot, { withFileTypes: true }).catch(() => []);
8503
8742
  const descriptors = [];
8504
8743
  for (const entry of entries) {
8505
8744
  if (!entry.isDirectory()) continue;
8506
8745
  try {
8507
- const raw = JSON.parse(await readFile(path10.join(instancesRoot, entry.name, "runtime", "server.json"), "utf8"));
8746
+ const raw = JSON.parse(await readFile(path9.join(instancesRoot, entry.name, "runtime", "server.json"), "utf8"));
8508
8747
  if (typeof raw.pid !== "number" || !Number.isInteger(raw.pid) || !isPidRunning(raw.pid) || typeof raw.version !== "string") {
8509
8748
  continue;
8510
8749
  }
@@ -8522,13 +8761,13 @@ async function assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDi
8522
8761
  const sharedPhysicalBinDir = await realpath(sharedBinDir).catch(() => null);
8523
8762
  const mayReferenceSharedPayload = await Promise.all(liveDescriptors.map(async (descriptor) => {
8524
8763
  if (descriptor.postgresBinDir === void 0) return true;
8525
- if (path10.resolve(descriptor.postgresBinDir) === path10.resolve(sharedBinDir)) return true;
8764
+ if (path9.resolve(descriptor.postgresBinDir) === path9.resolve(sharedBinDir)) return true;
8526
8765
  const descriptorPhysicalBinDir = await realpath(descriptor.postgresBinDir).catch(() => null);
8527
- if (descriptorPhysicalBinDir && sharedPhysicalBinDir && path10.resolve(descriptorPhysicalBinDir) === path10.resolve(sharedPhysicalBinDir)) {
8766
+ if (descriptorPhysicalBinDir && sharedPhysicalBinDir && path9.resolve(descriptorPhysicalBinDir) === path9.resolve(sharedPhysicalBinDir)) {
8528
8767
  return true;
8529
8768
  }
8530
8769
  if (!descriptorPhysicalBinDir) {
8531
- return pathIsInside(descriptor.postgresBinDir, path10.join(homeDir, "runtimes")) || pathIsInside(descriptor.postgresBinDir, path10.join(homeDir, "runtime-payloads"));
8770
+ return pathIsInside(descriptor.postgresBinDir, path9.join(homeDir, "runtimes")) || pathIsInside(descriptor.postgresBinDir, path9.join(homeDir, "runtime-payloads"));
8532
8771
  }
8533
8772
  return false;
8534
8773
  }));
@@ -8539,10 +8778,11 @@ async function assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDi
8539
8778
  );
8540
8779
  }
8541
8780
  }
8542
- async function validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionProbe) {
8543
- await assertRuntimePostgresBinDirComplete(cacheDir, binDir);
8781
+ async function validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionProbe, deadline) {
8782
+ await assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline);
8544
8783
  for (const binary of ["initdb", "pg_ctl", "postgres"]) {
8545
- const binaryPath = path10.join(binDir, runtimePostgresExecutableName(binary));
8784
+ remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime version");
8785
+ const binaryPath = path9.join(binDir, runtimePostgresExecutableName(binary));
8546
8786
  const result = postgresVersionProbe(binaryPath);
8547
8787
  if (!/\bPostgreSQL\)?\s+18\.4\b/i.test(result)) {
8548
8788
  throw new RuntimeInstallError(
@@ -8552,7 +8792,8 @@ async function validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionP
8552
8792
  }
8553
8793
  }
8554
8794
  }
8555
- function extractRuntimePostgresArchive(archivePath, extractDir) {
8795
+ function extractRuntimePostgresArchive(archivePath, extractDir, cacheDir, deadline) {
8796
+ const timeout = remainingRuntimeInstallMs(deadline, cacheDir, "extract PostgreSQL runtime archive");
8556
8797
  const result = process.platform === "win32" ? spawnSync2("powershell.exe", [
8557
8798
  "-NoProfile",
8558
8799
  "-NonInteractive",
@@ -8563,46 +8804,54 @@ function extractRuntimePostgresArchive(archivePath, extractDir) {
8563
8804
  ], {
8564
8805
  encoding: "utf8",
8565
8806
  env: { ...process.env, PG_ARCHIVE_PATH: archivePath, PG_EXTRACT_DIR: extractDir },
8566
- windowsHide: true
8567
- }) : spawnSync2("tar", ["-xf", archivePath, "-C", extractDir], { encoding: "utf8" });
8807
+ windowsHide: true,
8808
+ ...timeout === void 0 ? {} : { timeout }
8809
+ }) : spawnSync2("tar", ["-xf", archivePath, "-C", extractDir], {
8810
+ encoding: "utf8",
8811
+ ...timeout === void 0 ? {} : { timeout }
8812
+ });
8568
8813
  if (result.status !== 0) {
8569
8814
  throw new Error(`failed to extract PostgreSQL archive: ${result.stderr || result.stdout}`);
8570
8815
  }
8571
8816
  }
8572
- async function findRuntimePostgresBinDir(rootDir, cacheDir, postgresVersionProbe) {
8817
+ async function findRuntimePostgresBinDir(rootDir, cacheDir, postgresVersionProbe, deadline) {
8573
8818
  const queue = [rootDir];
8574
8819
  for (let index = 0; index < queue.length; index += 1) {
8575
8820
  const current = queue[index];
8576
- if (await isRuntimePostgresPayloadUsable(cacheDir, current, postgresVersionProbe)) return current;
8821
+ remainingRuntimeInstallMs(deadline, cacheDir, "find PostgreSQL runtime payload");
8822
+ if (await isRuntimePostgresPayloadUsable(cacheDir, current, postgresVersionProbe, deadline)) return current;
8577
8823
  const entries = await readdir(current, { withFileTypes: true }).catch(() => []);
8578
8824
  for (const entry of entries) {
8579
- if (entry.isDirectory()) queue.push(path10.join(current, entry.name));
8825
+ if (entry.isDirectory()) queue.push(path9.join(current, entry.name));
8580
8826
  }
8581
8827
  }
8582
8828
  return null;
8583
8829
  }
8584
- async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatformRoot, postgresVersionProbe, cleanupDownloads = false) {
8585
- const parentDir = path10.dirname(sharedPlatformRoot);
8586
- const baseName = path10.basename(sharedPlatformRoot);
8830
+ async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatformRoot, postgresVersionProbe, cleanupDownloads = false, deadline) {
8831
+ remainingRuntimeInstallMs(deadline, cacheDir, "reconcile shared PostgreSQL payload");
8832
+ const parentDir = path9.dirname(sharedPlatformRoot);
8833
+ const baseName = path9.basename(sharedPlatformRoot);
8587
8834
  const entries = await readdir(parentDir, { withFileTypes: true }).catch(() => []);
8588
- const temporaryRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.tmp-`)).map((entry) => path10.join(parentDir, entry.name));
8589
- const previousRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.previous-`)).map((entry) => path10.join(parentDir, entry.name)).sort().reverse();
8590
- const downloadsRoot = path10.join(
8591
- path10.dirname(path10.dirname(sharedPlatformRoot)),
8835
+ const temporaryRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.tmp-`)).map((entry) => path9.join(parentDir, entry.name));
8836
+ const previousRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.previous-`)).map((entry) => path9.join(parentDir, entry.name)).sort().reverse();
8837
+ const downloadsRoot = path9.join(
8838
+ path9.dirname(path9.dirname(sharedPlatformRoot)),
8592
8839
  ".downloads"
8593
8840
  );
8594
- const staleDownloadRoots = cleanupDownloads ? (await readdir(downloadsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.name.startsWith("postgres-18.4-")).map((entry) => path10.join(downloadsRoot, entry.name)) : [];
8595
- const canonicalBinDir = path10.join(sharedPlatformRoot, "bin");
8841
+ const staleDownloadRoots = cleanupDownloads ? (await readdir(downloadsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.name.startsWith("postgres-18.4-")).map((entry) => path9.join(downloadsRoot, entry.name)) : [];
8842
+ const canonicalBinDir = path9.join(sharedPlatformRoot, "bin");
8596
8843
  if (!await isRuntimePostgresPayloadUsable(
8597
8844
  cacheDir,
8598
8845
  canonicalBinDir,
8599
- postgresVersionProbe
8846
+ postgresVersionProbe,
8847
+ deadline
8600
8848
  )) {
8601
8849
  for (const previousRoot of previousRoots) {
8602
8850
  if (!await isRuntimePostgresPayloadUsable(
8603
8851
  cacheDir,
8604
- path10.join(previousRoot, "bin"),
8605
- postgresVersionProbe
8852
+ path9.join(previousRoot, "bin"),
8853
+ postgresVersionProbe,
8854
+ deadline
8606
8855
  )) {
8607
8856
  continue;
8608
8857
  }
@@ -8617,12 +8866,12 @@ async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatfor
8617
8866
  ...staleDownloadRoots.map((candidate) => rm(candidate, { recursive: true, force: true }))
8618
8867
  ]);
8619
8868
  }
8620
- async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinDir, postgresVersionProbe) {
8869
+ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinDir, postgresVersionProbe, deadline) {
8621
8870
  const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
8622
- const sharedRuntimeDir = path10.dirname(sharedBinDir);
8871
+ const sharedRuntimeDir = path9.dirname(sharedBinDir);
8623
8872
  const sharedPlatformRoot = sharedRuntimeDir;
8624
- const sourceRuntimeDir = path10.dirname(sourceBinDir);
8625
- const sourceTemplateDir = await resolveRuntimePostgresTemplateDir(sourceBinDir);
8873
+ const sourceRuntimeDir = path9.dirname(sourceBinDir);
8874
+ const sourceTemplateDir = await resolveRuntimePostgresTemplateDir(sourceBinDir, cacheDir, deadline);
8626
8875
  if (!sourceTemplateDir) {
8627
8876
  throw new RuntimeInstallError(
8628
8877
  `${RUDDER_POSTGRES_BIN_DIR_ENV} must contain PostgreSQL 18.4 initdb template files`,
@@ -8634,13 +8883,15 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
8634
8883
  await reconcileSharedPostgresPayloadGenerations(
8635
8884
  cacheDir,
8636
8885
  sharedPlatformRoot,
8637
- postgresVersionProbe
8886
+ postgresVersionProbe,
8887
+ false,
8888
+ deadline
8638
8889
  );
8639
- if (await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe)) {
8890
+ if (await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe, deadline)) {
8640
8891
  return sharedBinDir;
8641
8892
  }
8642
8893
  await assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDir);
8643
- await mkdir2(path10.dirname(sharedPlatformRoot), { recursive: true });
8894
+ await mkdir(path9.dirname(sharedPlatformRoot), { recursive: true });
8644
8895
  const temporaryPlatformRoot = `${sharedPlatformRoot}.tmp-${process.pid}-${Date.now()}`;
8645
8896
  const previousPlatformRoot = `${sharedPlatformRoot}.previous-${process.pid}-${Date.now()}`;
8646
8897
  let previousMoved = false;
@@ -8650,13 +8901,15 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
8650
8901
  try {
8651
8902
  const temporaryRuntimeDir = temporaryPlatformRoot;
8652
8903
  const sourceShareDir = resolveRuntimePostgresShareDir(sourceBinDir, sourceTemplateDir);
8653
- await copyRuntimePostgresPayload(
8904
+ await copyRuntimePostgresPayloadWithinDeadline(
8654
8905
  sourceRuntimeDir,
8655
8906
  temporaryRuntimeDir,
8656
- sourceShareDir
8907
+ sourceShareDir,
8908
+ cacheDir,
8909
+ deadline
8657
8910
  );
8658
- const temporaryBinDir = path10.join(temporaryRuntimeDir, "bin");
8659
- await validateRuntimePostgresVersion(cacheDir, temporaryBinDir, postgresVersionProbe);
8911
+ const temporaryBinDir = path9.join(temporaryRuntimeDir, "bin");
8912
+ await validateRuntimePostgresVersion(cacheDir, temporaryBinDir, postgresVersionProbe, deadline);
8660
8913
  try {
8661
8914
  await rename(sharedPlatformRoot, previousPlatformRoot);
8662
8915
  previousMoved = true;
@@ -8684,30 +8937,35 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
8684
8937
  }
8685
8938
  }
8686
8939
  return sharedBinDir;
8687
- });
8940
+ }, { deadline, cacheDir, command: "acquire shared PostgreSQL install lock" });
8688
8941
  }
8689
- async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresVersionProbe) {
8942
+ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresVersionProbe, deadline, cleanupWorkDir) {
8690
8943
  const archiveSource = resolvePostgresRuntimeArchiveSource();
8691
8944
  const archiveUrl = archiveSource?.url ?? null;
8692
8945
  if (!archiveUrl) return null;
8693
8946
  const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
8694
- const sharedPlatformRoot = path10.dirname(sharedBinDir);
8947
+ const sharedPlatformRoot = path9.dirname(sharedBinDir);
8695
8948
  const downloadLockPath = `${sharedPlatformRoot}.download.lock`;
8696
8949
  return withRuntimeFilesystemLock(downloadLockPath, async () => {
8697
- if (await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe)) {
8950
+ if (await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe, deadline)) {
8698
8951
  return sharedBinDir;
8699
8952
  }
8700
- const workRoot = path10.join(homeDir, "runtime-payloads", ".downloads");
8701
- await mkdir2(workRoot, { recursive: true });
8702
- const workDir = await mkdtemp(path10.join(workRoot, "postgres-18.4-"));
8703
- const archivePath = path10.join(workDir, "postgresql-18.4.zip");
8704
- const extractDir = path10.join(workDir, "extract");
8953
+ const workRoot = path9.join(homeDir, "runtime-payloads", ".downloads");
8954
+ await mkdir(workRoot, { recursive: true });
8955
+ const workDir = await mkdtemp(path9.join(workRoot, "postgres-18.4-"));
8956
+ const archivePath = path9.join(workDir, "postgresql-18.4.zip");
8957
+ const extractDir = path9.join(workDir, "extract");
8705
8958
  try {
8706
- await downloadRuntimePostgresArchive(archiveUrl, archivePath, archiveSource?.expectedSha256);
8959
+ await downloadRuntimePostgresArchive(
8960
+ archiveUrl,
8961
+ archivePath,
8962
+ archiveSource?.expectedSha256,
8963
+ { timeoutMs: remainingRuntimeInstallMs(deadline, cacheDir, "download PostgreSQL runtime archive") }
8964
+ );
8707
8965
  const configuredMaxBytes = Number.parseInt(process.env[RUDDER_POSTGRES_RUNTIME_ARCHIVE_MAX_BYTES_ENV2] ?? "", 10);
8708
8966
  const maxArchiveBytes = Number.isSafeInteger(configuredMaxBytes) && configuredMaxBytes > 0 ? configuredMaxBytes : DEFAULT_RUNTIME_POSTGRES_ARCHIVE_MAX_BYTES2;
8709
8967
  const nativePublishStaging = `${sharedPlatformRoot}.tmp-native-${process.pid}-${Date.now()}`;
8710
- await mkdir2(path10.dirname(sharedPlatformRoot), { recursive: true });
8968
+ await mkdir(path9.dirname(sharedPlatformRoot), { recursive: true });
8711
8969
  const nativeInstall = await tryInstallNativePayload({
8712
8970
  archivePath,
8713
8971
  extractPath: extractDir,
@@ -8715,11 +8973,14 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
8715
8973
  destinationPath: sharedPlatformRoot,
8716
8974
  maxArchiveBytes,
8717
8975
  expectedSha256: archiveSource?.expectedSha256,
8718
- preparePublish: async (nativeExtractPath, publishStagingPath) => {
8976
+ timeoutMs: remainingRuntimeInstallMs(deadline, cacheDir, "prepare native PostgreSQL runtime payload"),
8977
+ now: deadline?.now,
8978
+ preparePublish: async (nativeExtractPath, publishStagingPath, context) => {
8719
8979
  const extractedBinDir2 = await findRuntimePostgresBinDir(
8720
8980
  nativeExtractPath,
8721
8981
  cacheDir,
8722
- postgresVersionProbe
8982
+ postgresVersionProbe,
8983
+ deadline
8723
8984
  );
8724
8985
  if (!extractedBinDir2) {
8725
8986
  throw new RuntimeInstallError(
@@ -8727,41 +8988,46 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
8727
8988
  { cacheDir, command: "prepare native PostgreSQL runtime payload", output: "" }
8728
8989
  );
8729
8990
  }
8730
- await validateRuntimePostgresVersion(cacheDir, extractedBinDir2, postgresVersionProbe);
8731
- const templateDir = await resolveRuntimePostgresTemplateDir(extractedBinDir2);
8991
+ await validateRuntimePostgresVersion(cacheDir, extractedBinDir2, postgresVersionProbe, deadline);
8992
+ const templateDir = await resolveRuntimePostgresTemplateDir(extractedBinDir2, cacheDir, deadline);
8732
8993
  if (!templateDir) {
8733
8994
  throw new RuntimeInstallError(
8734
8995
  "PostgreSQL 18.4 archive did not contain initdb template files",
8735
8996
  { cacheDir, command: "prepare native PostgreSQL runtime payload", output: "" }
8736
8997
  );
8737
8998
  }
8738
- await copyRuntimePostgresPayload(
8739
- path10.dirname(extractedBinDir2),
8999
+ await copyRuntimePostgresPayloadWithinDeadline(
9000
+ path9.dirname(extractedBinDir2),
8740
9001
  publishStagingPath,
8741
- resolveRuntimePostgresShareDir(extractedBinDir2, templateDir)
9002
+ resolveRuntimePostgresShareDir(extractedBinDir2, templateDir),
9003
+ cacheDir,
9004
+ deadline,
9005
+ context.signal
8742
9006
  );
8743
- return path10.relative(
9007
+ return path9.relative(
8744
9008
  publishStagingPath,
8745
- path10.join(publishStagingPath, "bin", runtimePostgresExecutableName("postgres"))
9009
+ path9.join(publishStagingPath, "bin", runtimePostgresExecutableName("postgres"))
8746
9010
  );
8747
9011
  },
8748
9012
  validatePublished: async (destinationPath) => {
8749
9013
  await validateRuntimePostgresVersion(
8750
9014
  cacheDir,
8751
- path10.join(destinationPath, "bin"),
8752
- postgresVersionProbe
9015
+ path9.join(destinationPath, "bin"),
9016
+ postgresVersionProbe,
9017
+ deadline
8753
9018
  );
8754
9019
  }
8755
9020
  });
8756
9021
  if (nativeInstall.installed) {
8757
9022
  return sharedBinDir;
8758
9023
  }
8759
- await mkdir2(extractDir, { recursive: true });
8760
- extractRuntimePostgresArchive(archivePath, extractDir);
9024
+ await mkdir(extractDir, { recursive: true });
9025
+ extractRuntimePostgresArchive(archivePath, extractDir, cacheDir, deadline);
8761
9026
  const extractedBinDir = await findRuntimePostgresBinDir(
8762
9027
  extractDir,
8763
9028
  cacheDir,
8764
- postgresVersionProbe
9029
+ postgresVersionProbe,
9030
+ deadline
8765
9031
  );
8766
9032
  if (!extractedBinDir) {
8767
9033
  throw new RuntimeInstallError(
@@ -8773,28 +9039,31 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
8773
9039
  cacheDir,
8774
9040
  homeDir,
8775
9041
  extractedBinDir,
8776
- postgresVersionProbe
9042
+ postgresVersionProbe,
9043
+ deadline
8777
9044
  );
8778
9045
  } finally {
8779
- await rm(workDir, { recursive: true, force: true });
9046
+ const cleanup = cleanupWorkDir ?? ((candidate) => rm(candidate, { recursive: true, force: true }));
9047
+ void cleanup(workDir).catch(() => {
9048
+ });
8780
9049
  }
8781
- });
9050
+ }, { deadline, cacheDir, command: "acquire shared PostgreSQL download lock" });
8782
9051
  }
8783
9052
  async function ensureRuntimePostgresCompatibilityLink(cacheDir, homeDir, packageVersion) {
8784
- const compatibilityRoot = path10.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR);
8785
- const sharedPayloadRoot = path10.join(homeDir, "runtime-payloads", RUNTIME_POSTGRES_PAYLOAD_DIR);
9053
+ const compatibilityRoot = path9.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR);
9054
+ const sharedPayloadRoot = path9.join(homeDir, "runtime-payloads", RUNTIME_POSTGRES_PAYLOAD_DIR);
8786
9055
  const runtimeMetadata = await readRuntimeInstallMetadata(cacheDir);
8787
9056
  const liveDescriptors = await readLiveRuntimeDescriptors(homeDir);
8788
9057
  const compatibilityBinDir = resolveRuntimePostgresPayloadBinDir(cacheDir);
8789
9058
  const isProtected = liveDescriptors.some((descriptor) => descriptor.postgresBinDir && pathIsInside(descriptor.postgresBinDir, compatibilityRoot) || !descriptor.postgresBinDir && descriptor.version === (runtimeMetadata?.packageVersion ?? packageVersion));
8790
9059
  if (isProtected) return;
8791
- await mkdir2(path10.dirname(compatibilityRoot), { recursive: true });
9060
+ await mkdir(path9.dirname(compatibilityRoot), { recursive: true });
8792
9061
  const temporaryRoot = `${compatibilityRoot}.next-${process.pid}-${Date.now()}`;
8793
9062
  const previousRoot = `${compatibilityRoot}.previous-${process.pid}-${Date.now()}`;
8794
9063
  await rm(temporaryRoot, { recursive: true, force: true });
8795
9064
  await rm(previousRoot, { recursive: true, force: true });
8796
9065
  await symlink(
8797
- process.platform === "win32" ? sharedPayloadRoot : path10.relative(path10.dirname(compatibilityRoot), sharedPayloadRoot),
9066
+ process.platform === "win32" ? sharedPayloadRoot : path9.relative(path9.dirname(compatibilityRoot), sharedPayloadRoot),
8798
9067
  temporaryRoot,
8799
9068
  process.platform === "win32" ? "junction" : "dir"
8800
9069
  );
@@ -8824,15 +9093,16 @@ async function ensureRuntimePostgresCompatibilityLink(cacheDir, homeDir, package
8824
9093
  if (!previousMoved) await rm(previousRoot, { recursive: true, force: true });
8825
9094
  }
8826
9095
  }
8827
- async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, enabled, postgresVersionProbe) {
9096
+ async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, enabled, postgresVersionProbe, deadline, cleanupDownloadWorkDir) {
8828
9097
  if (!enabled) return { output: "" };
8829
9098
  const explicitSourceBinDir = process.env[RUDDER_POSTGRES_BIN_DIR_ENV]?.trim();
8830
- const resolvedExplicitSourceBinDir = explicitSourceBinDir ? path10.resolve(explicitSourceBinDir) : null;
9099
+ const resolvedExplicitSourceBinDir = explicitSourceBinDir ? path9.resolve(explicitSourceBinDir) : null;
8831
9100
  if (resolvedExplicitSourceBinDir && !isManagedRuntimePostgresBinDir(resolvedExplicitSourceBinDir, homeDir)) {
8832
9101
  await validateRuntimePostgresVersion(
8833
9102
  cacheDir,
8834
9103
  resolvedExplicitSourceBinDir,
8835
- postgresVersionProbe
9104
+ postgresVersionProbe,
9105
+ deadline
8836
9106
  );
8837
9107
  return {
8838
9108
  output: "",
@@ -8847,35 +9117,41 @@ async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, en
8847
9117
  };
8848
9118
  }
8849
9119
  const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
8850
- const sharedPlatformRoot = path10.dirname(sharedBinDir);
9120
+ const sharedPlatformRoot = path9.dirname(sharedBinDir);
8851
9121
  await withRuntimeFilesystemLock(
8852
9122
  `${sharedPlatformRoot}.install.lock`,
8853
9123
  async () => reconcileSharedPostgresPayloadGenerations(
8854
9124
  cacheDir,
8855
9125
  sharedPlatformRoot,
8856
9126
  postgresVersionProbe,
8857
- true
8858
- )
9127
+ true,
9128
+ deadline
9129
+ ),
9130
+ { deadline, cacheDir, command: "reconcile shared PostgreSQL payload" }
8859
9131
  );
8860
9132
  let output = "";
8861
- if (!await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe)) {
8862
- const sourceBinDir = resolvedExplicitSourceBinDir ?? await findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersionProbe);
9133
+ if (!await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe, deadline)) {
9134
+ const sourceBinDir = resolvedExplicitSourceBinDir ?? await findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersionProbe, deadline);
8863
9135
  if (sourceBinDir) {
8864
9136
  await validateRuntimePostgresVersion(
8865
9137
  cacheDir,
8866
9138
  sourceBinDir,
8867
- postgresVersionProbe
9139
+ postgresVersionProbe,
9140
+ deadline
8868
9141
  );
8869
9142
  await installSharedRuntimePostgresPayload(
8870
9143
  cacheDir,
8871
9144
  homeDir,
8872
9145
  sourceBinDir,
8873
- postgresVersionProbe
9146
+ postgresVersionProbe,
9147
+ deadline
8874
9148
  );
8875
9149
  } else if (!await downloadSharedRuntimePostgresPayload(
8876
9150
  cacheDir,
8877
9151
  homeDir,
8878
- postgresVersionProbe
9152
+ postgresVersionProbe,
9153
+ deadline,
9154
+ cleanupDownloadWorkDir
8879
9155
  )) {
8880
9156
  return { output: "" };
8881
9157
  }
@@ -8953,13 +9229,13 @@ async function pruneRuntimeCache(options = {}) {
8953
9229
  };
8954
9230
  }
8955
9231
  async function scanRuntimeCacheEntries(homeDir) {
8956
- const runtimesDir = path10.join(homeDir, "runtimes");
9232
+ const runtimesDir = path9.join(homeDir, "runtimes");
8957
9233
  const dirents = await readdir(runtimesDir, { withFileTypes: true }).catch(() => null);
8958
9234
  if (!dirents) return [];
8959
9235
  const entries = [];
8960
9236
  for (const dirent of dirents) {
8961
9237
  if (!dirent.isDirectory()) continue;
8962
- const cacheDir = path10.join(runtimesDir, dirent.name);
9238
+ const cacheDir = path9.join(runtimesDir, dirent.name);
8963
9239
  const metadata = await readRuntimeInstallMetadata(cacheDir);
8964
9240
  if (!metadata) continue;
8965
9241
  const fallbackStat = await safeStat(cacheDir);
@@ -8982,7 +9258,7 @@ function parseTimestampMs(value) {
8982
9258
  }
8983
9259
  async function safeStat(targetPath) {
8984
9260
  try {
8985
- return await stat3(targetPath);
9261
+ return await stat(targetPath);
8986
9262
  } catch {
8987
9263
  return null;
8988
9264
  }
@@ -8992,7 +9268,7 @@ async function directorySizeBytes(targetPath) {
8992
9268
  if (!dirents) return 0;
8993
9269
  let total = 0;
8994
9270
  for (const dirent of dirents) {
8995
- const entryPath = path10.join(targetPath, dirent.name);
9271
+ const entryPath = path9.join(targetPath, dirent.name);
8996
9272
  if (dirent.isSymbolicLink()) continue;
8997
9273
  if (dirent.isDirectory()) {
8998
9274
  total += await directorySizeBytes(entryPath);
@@ -9004,14 +9280,14 @@ async function directorySizeBytes(targetPath) {
9004
9280
  return total;
9005
9281
  }
9006
9282
  async function readActiveRuntimeVersions(homeDir) {
9007
- const instancesDir = path10.join(homeDir, "instances");
9283
+ const instancesDir = path9.join(homeDir, "instances");
9008
9284
  const dirents = await readdir(instancesDir, { withFileTypes: true }).catch(() => null);
9009
9285
  if (!dirents) return [];
9010
9286
  const versions = /* @__PURE__ */ new Set();
9011
9287
  for (const dirent of dirents) {
9012
9288
  if (!dirent.isDirectory()) continue;
9013
9289
  try {
9014
- const descriptorPath = path10.join(instancesDir, dirent.name, "runtime", "server.json");
9290
+ const descriptorPath = path9.join(instancesDir, dirent.name, "runtime", "server.json");
9015
9291
  const parsed = JSON.parse(await readFile(descriptorPath, "utf8"));
9016
9292
  if (typeof parsed.version !== "string") continue;
9017
9293
  if (typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0 && isPidRunning(parsed.pid)) {
@@ -9126,7 +9402,6 @@ var init_install = __esm({
9126
9402
  "use strict";
9127
9403
  init_home();
9128
9404
  init_native_payload();
9129
- init_postgres_payload();
9130
9405
  init_postgres_runtime_download();
9131
9406
  init_postgres_runtime_source();
9132
9407
  RUNTIME_NPM_PACKAGE_NAME = "@rudderhq/server";
@@ -9172,7 +9447,7 @@ var init_install = __esm({
9172
9447
 
9173
9448
  // src/runtime/server-entry.ts
9174
9449
  import fs7 from "node:fs";
9175
- import path11 from "node:path";
9450
+ import path10 from "node:path";
9176
9451
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL2 } from "node:url";
9177
9452
  function formatError(err) {
9178
9453
  if (err instanceof Error) {
@@ -9194,8 +9469,8 @@ function maybeEnableUiDevMiddleware(entrypoint) {
9194
9469
  }
9195
9470
  }
9196
9471
  function resolveDevServerEntry() {
9197
- const projectRoot = path11.resolve(path11.dirname(fileURLToPath5(import.meta.url)), "../../..");
9198
- return path11.resolve(projectRoot, "server/src/index.ts");
9472
+ const projectRoot = path10.resolve(path10.dirname(fileURLToPath5(import.meta.url)), "../../..");
9473
+ return path10.resolve(projectRoot, "server/src/index.ts");
9199
9474
  }
9200
9475
  async function loadServerRuntimeModule(options) {
9201
9476
  const devEntry = resolveDevServerEntry();
@@ -9335,21 +9610,21 @@ var init_auth_bootstrap_ceo = __esm({
9335
9610
 
9336
9611
  // src/utils/path-resolver.ts
9337
9612
  import fs10 from "node:fs";
9338
- import path19 from "node:path";
9613
+ import path18 from "node:path";
9339
9614
  function unique(items) {
9340
9615
  return Array.from(new Set(items));
9341
9616
  }
9342
9617
  function resolveRuntimeLikePath(value, configPath) {
9343
9618
  const expanded = expandHomePrefix(value);
9344
- if (path19.isAbsolute(expanded)) return path19.resolve(expanded);
9619
+ if (path18.isAbsolute(expanded)) return path18.resolve(expanded);
9345
9620
  const cwd = process.cwd();
9346
- const configDir = configPath ? path19.dirname(configPath) : null;
9347
- const workspaceRoot = configDir ? path19.resolve(configDir, "..") : cwd;
9621
+ const configDir = configPath ? path18.dirname(configPath) : null;
9622
+ const workspaceRoot = configDir ? path18.resolve(configDir, "..") : cwd;
9348
9623
  const candidates = unique([
9349
- ...configDir ? [path19.resolve(configDir, expanded)] : [],
9350
- path19.resolve(workspaceRoot, "server", expanded),
9351
- path19.resolve(workspaceRoot, expanded),
9352
- path19.resolve(cwd, expanded)
9624
+ ...configDir ? [path18.resolve(configDir, expanded)] : [],
9625
+ path18.resolve(workspaceRoot, "server", expanded),
9626
+ path18.resolve(workspaceRoot, expanded),
9627
+ path18.resolve(cwd, expanded)
9353
9628
  ]);
9354
9629
  return candidates.find((candidate) => fs10.existsSync(candidate)) ?? candidates[0];
9355
9630
  }
@@ -9363,7 +9638,7 @@ var init_path_resolver = __esm({
9363
9638
  // src/config/secrets-key.ts
9364
9639
  import { randomBytes as randomBytes2 } from "node:crypto";
9365
9640
  import fs11 from "node:fs";
9366
- import path20 from "node:path";
9641
+ import path19 from "node:path";
9367
9642
  function ensureLocalSecretsKeyFile(config, configPath) {
9368
9643
  if (config.secrets.provider !== "local_encrypted") {
9369
9644
  return { status: "skipped_provider", path: null };
@@ -9378,7 +9653,7 @@ function ensureLocalSecretsKeyFile(config, configPath) {
9378
9653
  if (fs11.existsSync(keyFilePath)) {
9379
9654
  return { status: "existing", path: keyFilePath };
9380
9655
  }
9381
- fs11.mkdirSync(path20.dirname(keyFilePath), { recursive: true });
9656
+ fs11.mkdirSync(path19.dirname(keyFilePath), { recursive: true });
9382
9657
  fs11.writeFileSync(keyFilePath, randomBytes2(32).toString("base64"), {
9383
9658
  encoding: "utf8",
9384
9659
  mode: 384
@@ -10464,7 +10739,7 @@ var init_port_check = __esm({
10464
10739
  // src/checks/secrets-check.ts
10465
10740
  import { randomBytes as randomBytes3 } from "node:crypto";
10466
10741
  import fs14 from "node:fs";
10467
- import path21 from "node:path";
10742
+ import path20 from "node:path";
10468
10743
  function decodeMasterKey(raw) {
10469
10744
  const trimmed = raw.trim();
10470
10745
  if (!trimmed) return null;
@@ -10534,7 +10809,7 @@ function secretsCheck(config, configPath) {
10534
10809
  message: `Secrets key file does not exist yet: ${keyFilePath}`,
10535
10810
  canRepair: true,
10536
10811
  repair: () => {
10537
- fs14.mkdirSync(path21.dirname(keyFilePath), { recursive: true });
10812
+ fs14.mkdirSync(path20.dirname(keyFilePath), { recursive: true });
10538
10813
  fs14.writeFileSync(keyFilePath, randomBytes3(32).toString("base64"), {
10539
10814
  encoding: "utf8",
10540
10815
  mode: 384
@@ -11107,7 +11382,7 @@ var init_run = __esm({
11107
11382
 
11108
11383
  // src/commands/onboard.ts
11109
11384
  import * as p14 from "@clack/prompts";
11110
- import path22 from "node:path";
11385
+ import path21 from "node:path";
11111
11386
  import pc13 from "picocolors";
11112
11387
  function parseBooleanFromEnv(rawValue) {
11113
11388
  if (rawValue === void 0) return null;
@@ -11140,7 +11415,7 @@ function parseEnumFromEnv(rawValue, allowedValues) {
11140
11415
  }
11141
11416
  function resolvePathFromEnv(rawValue) {
11142
11417
  if (!rawValue || rawValue.trim().length === 0) return null;
11143
- return path22.resolve(expandHomePrefix(rawValue.trim()));
11418
+ return path21.resolve(expandHomePrefix(rawValue.trim()));
11144
11419
  }
11145
11420
  function quickstartDefaultsFromEnv() {
11146
11421
  const instanceId = resolveRudderInstanceId();
@@ -11572,7 +11847,7 @@ var init_onboard = __esm({
11572
11847
  });
11573
11848
 
11574
11849
  // src/program.ts
11575
- import { Command, CommanderError } from "commander";
11850
+ import { Command, CommanderError, Option } from "commander";
11576
11851
 
11577
11852
  // src/agent-v1-mcp-server.ts
11578
11853
  init_dist();
@@ -13105,41 +13380,41 @@ var RudderApiClient = class {
13105
13380
  this.signal = opts.signal;
13106
13381
  this.recoverAuth = opts.recoverAuth;
13107
13382
  }
13108
- get(path26, opts) {
13109
- return this.request(path26, { method: "GET" }, opts);
13383
+ get(path25, opts) {
13384
+ return this.request(path25, { method: "GET" }, opts);
13110
13385
  }
13111
- post(path26, body, opts) {
13112
- return this.request(path26, {
13386
+ post(path25, body, opts) {
13387
+ return this.request(path25, {
13113
13388
  method: "POST",
13114
13389
  body: body === void 0 ? void 0 : JSON.stringify(body)
13115
13390
  }, opts);
13116
13391
  }
13117
- postForm(path26, form, opts) {
13118
- return this.request(path26, {
13392
+ postForm(path25, form, opts) {
13393
+ return this.request(path25, {
13119
13394
  method: "POST",
13120
13395
  body: form
13121
13396
  }, opts);
13122
13397
  }
13123
- patch(path26, body, opts) {
13124
- return this.request(path26, {
13398
+ patch(path25, body, opts) {
13399
+ return this.request(path25, {
13125
13400
  method: "PATCH",
13126
13401
  body: body === void 0 ? void 0 : JSON.stringify(body)
13127
13402
  }, opts);
13128
13403
  }
13129
- put(path26, body, opts) {
13130
- return this.request(path26, {
13404
+ put(path25, body, opts) {
13405
+ return this.request(path25, {
13131
13406
  method: "PUT",
13132
13407
  body: body === void 0 ? void 0 : JSON.stringify(body)
13133
13408
  }, opts);
13134
13409
  }
13135
- delete(path26, opts) {
13136
- return this.request(path26, { method: "DELETE" }, opts);
13410
+ delete(path25, opts) {
13411
+ return this.request(path25, { method: "DELETE" }, opts);
13137
13412
  }
13138
13413
  setApiKey(apiKey) {
13139
13414
  this.apiKey = apiKey?.trim() || void 0;
13140
13415
  }
13141
- async request(path26, init, opts, hasRetriedAuth = false) {
13142
- const url = buildUrl(this.apiBase, path26);
13416
+ async request(path25, init, opts, hasRetriedAuth = false) {
13417
+ const url = buildUrl(this.apiBase, path25);
13143
13418
  const headers = {
13144
13419
  accept: "application/json",
13145
13420
  ...toStringRecord(init.headers)
@@ -13170,13 +13445,13 @@ var RudderApiClient = class {
13170
13445
  const apiError = await toApiError(response);
13171
13446
  if (!hasRetriedAuth && this.recoverAuth) {
13172
13447
  const recoveredToken = await this.recoverAuth({
13173
- path: path26,
13448
+ path: path25,
13174
13449
  method: String(init.method ?? "GET").toUpperCase(),
13175
13450
  error: apiError
13176
13451
  });
13177
13452
  if (recoveredToken) {
13178
13453
  this.setApiKey(recoveredToken);
13179
- return this.request(path26, init, opts, true);
13454
+ return this.request(path25, init, opts, true);
13180
13455
  }
13181
13456
  }
13182
13457
  throw apiError;
@@ -13195,8 +13470,8 @@ function shouldAttachAgentContext(method) {
13195
13470
  const normalized = String(method ?? "GET").toUpperCase();
13196
13471
  return normalized !== "GET" && normalized !== "HEAD";
13197
13472
  }
13198
- function buildUrl(apiBase, path26) {
13199
- const normalizedPath = path26.startsWith("/") ? path26 : `/${path26}`;
13473
+ function buildUrl(apiBase, path25) {
13474
+ const normalizedPath = path25.startsWith("/") ? path25 : `/${path25}`;
13200
13475
  const [pathname, query] = normalizedPath.split("?");
13201
13476
  const url = new URL2(apiBase);
13202
13477
  url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
@@ -14359,7 +14634,7 @@ async function callToolDirectlyIfSupported(toolName, rawArgs, env, signal) {
14359
14634
  if (hasLocalImageInputs(input.images)) return null;
14360
14635
  const api = mcpApiClient(env, signal);
14361
14636
  const success = (data) => mcpSuccess(
14362
- toCliShortIdOutput(data),
14637
+ capabilityId.startsWith("browser.") ? data : toCliShortIdOutput(data),
14363
14638
  capabilityId.startsWith("browser.") ? RUDDER_BROWSER_MCP_MAX_TOOL_RESULT_BYTES : RUDDER_MCP_MAX_TOOL_RESULT_BYTES
14364
14639
  );
14365
14640
  switch (capabilityId) {
@@ -15786,8 +16061,8 @@ function registerActivityCommands(program) {
15786
16061
  if (opts.entityType) params.set("entityType", opts.entityType);
15787
16062
  if (opts.entityId) params.set("entityId", opts.entityId);
15788
16063
  const query = params.toString();
15789
- const path26 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
15790
- const rows = await ctx.api.get(path26) ?? [];
16064
+ const path25 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
16065
+ const rows = await ctx.api.get(path25) ?? [];
15791
16066
  if (ctx.json) {
15792
16067
  printOutput(rows, { json: true });
15793
16068
  return;
@@ -15819,7 +16094,7 @@ function registerActivityCommands(program) {
15819
16094
 
15820
16095
  // ../packages/agent-runtime-utils/dist/server-utils.cli.js
15821
16096
  import { promises as fs8 } from "node:fs";
15822
- import path12 from "node:path";
16097
+ import path11 from "node:path";
15823
16098
 
15824
16099
  // ../packages/agent-runtime-utils/dist/native-process-runner.js
15825
16100
  init_dist2();
@@ -16093,12 +16368,11 @@ The prior Run has already persisted the checkpoint named above. Reconstruct the
16093
16368
 
16094
16369
  If the checkpoint instead records a wait or human decision, this wake is unexpected: do not invent authorization or execute the waiting action. Refresh managed Goal context, report the mismatch, and leave the Goal waiting for its named actor or external trigger. If a ready Result Proposal exists, stop and wait for human Acceptance.`;
16095
16370
  var ISSUE_ASSIGNEE_EXECUTION_RAIL = "Before doing issue-scoped execution as the assignee, check out the assigned issue. If checkout returns `409`, do not retry; stop and report the ownership conflict.";
16096
- var ISSUE_ASSIGN_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}). You have been assigned to work on an issue.
16371
+ var ISSUE_ASSIGN_PROMPT_TEMPLATE = `<wake_context>
16372
+ You are agent {{agent.id}} ({{agent.name}}). You have been assigned to work on an issue.
16097
16373
 
16098
16374
  {{context.rudderWorkspace.orgResourcesPrompt}}
16099
16375
 
16100
- ## Task Context
16101
-
16102
16376
  **Issue:** {{issue.title}}
16103
16377
  **ID:** {{issue.id}}
16104
16378
  **Status:** {{issue.status}}
@@ -16107,21 +16381,23 @@ var ISSUE_ASSIGN_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}).
16107
16381
  **Reviewer:** {{issue.reviewerLabel}}
16108
16382
  **Created At:** {{issue.createdAt}}
16109
16383
  **Updated At:** {{issue.updatedAt}}
16384
+ </wake_context>
16110
16385
 
16386
+ <quoted_issue_context>
16111
16387
  **Description:**
16112
16388
  {{issue.description}}
16389
+ </quoted_issue_context>
16113
16390
 
16114
16391
 
16115
16392
  Your task is to review this issue, understand what kind of work it asks for, and take the appropriate next action.
16116
16393
 
16117
16394
  Do not assume every issue is a codebase task. If the issue is a question, screenshot check, review, planning request, coordination task, or another non-code request, answer or handle that request directly. Inspect the codebase and implement a change only when the issue actually asks for engineering work or when the relevant project resources make code changes necessary.
16118
16395
  ${ISSUE_ASSIGNEE_EXECUTION_RAIL}`;
16119
- var ISSUE_COMMENTED_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}). There is a new comment on an issue you own.
16396
+ var ISSUE_COMMENTED_PROMPT_TEMPLATE = `<wake_context>
16397
+ You are agent {{agent.id}} ({{agent.name}}). There is a new comment on an issue you own.
16120
16398
 
16121
16399
  {{context.rudderWorkspace.orgResourcesPrompt}}
16122
16400
 
16123
- ## Context
16124
-
16125
16401
  **Issue:** {{issue.title}}
16126
16402
  **ID:** {{issue.id}}
16127
16403
  **Status:** {{issue.status}}
@@ -16129,7 +16405,9 @@ var ISSUE_COMMENTED_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}
16129
16405
  **Reviewer:** {{issue.reviewerLabel}}
16130
16406
  **Created At:** {{issue.createdAt}}
16131
16407
  **Updated At:** {{issue.updatedAt}}
16408
+ </wake_context>
16132
16409
 
16410
+ <quoted_issue_context>
16133
16411
  **Issue Description:**
16134
16412
  {{issue.description}}
16135
16413
 
@@ -16138,15 +16416,15 @@ var ISSUE_COMMENTED_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}
16138
16416
  From: {{comment.authorLabel}} ({{comment.authorKind}})
16139
16417
 
16140
16418
  {{comment.body}}
16419
+ </quoted_issue_context>
16141
16420
 
16142
16421
  Review the new comment and continue the issue from the current state. Respond or take action as needed.
16143
16422
  ${ISSUE_ASSIGNEE_EXECUTION_RAIL}`;
16144
- var ISSUE_CHANGES_REQUESTED_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}). A reviewer requested changes on an issue you own.
16423
+ var ISSUE_CHANGES_REQUESTED_PROMPT_TEMPLATE = `<wake_context>
16424
+ You are agent {{agent.id}} ({{agent.name}}). A reviewer requested changes on an issue you own.
16145
16425
 
16146
16426
  {{context.rudderWorkspace.orgResourcesPrompt}}
16147
16427
 
16148
- ## Context
16149
-
16150
16428
  **Issue:** {{issue.title}}
16151
16429
  **ID:** {{issue.id}}
16152
16430
  **Status:** {{issue.status}}
@@ -16154,7 +16432,9 @@ var ISSUE_CHANGES_REQUESTED_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{age
16154
16432
  **Reviewer:** {{issue.reviewerLabel}}
16155
16433
  **Created At:** {{issue.createdAt}}
16156
16434
  **Updated At:** {{issue.updatedAt}}
16435
+ </wake_context>
16157
16436
 
16437
+ <quoted_issue_context>
16158
16438
  **Issue Description:**
16159
16439
  {{issue.description}}
16160
16440
 
@@ -16163,10 +16443,12 @@ var ISSUE_CHANGES_REQUESTED_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{age
16163
16443
  From: {{comment.authorLabel}} ({{comment.authorKind}})
16164
16444
 
16165
16445
  {{comment.body}}
16446
+ </quoted_issue_context>
16166
16447
 
16167
16448
  Review the requested changes and continue the issue from the current state. Address the reviewer feedback before handing it back for review.
16168
16449
  ${ISSUE_ASSIGNEE_EXECUTION_RAIL}`;
16169
- var ISSUE_RECOVERY_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}). This is a recovery run, not a fresh task.
16450
+ var ISSUE_RECOVERY_PROMPT_TEMPLATE = `<wake_context>
16451
+ You are agent {{agent.id}} ({{agent.name}}). This is a recovery run, not a fresh task.
16170
16452
 
16171
16453
  {{context.rudderWorkspace.orgResourcesPrompt}}
16172
16454
 
@@ -16188,14 +16470,18 @@ var ISSUE_RECOVERY_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}
16188
16470
  - Reviewer: {{issue.reviewerLabel}}
16189
16471
  - Created At: {{issue.createdAt}}
16190
16472
  - Updated At: {{issue.updatedAt}}
16473
+ </wake_context>
16191
16474
 
16475
+ <quoted_issue_context>
16192
16476
  - Description:
16193
16477
  {{issue.description}}
16478
+ </quoted_issue_context>
16194
16479
 
16195
16480
 
16196
16481
  Before doing anything else, inspect what the previous run already completed and any side effects it may have caused. Continue the remaining work from the current state. Avoid blindly re-running the whole task.
16197
16482
  ${ISSUE_ASSIGNEE_EXECUTION_RAIL}`;
16198
- var ISSUE_PASSIVE_FOLLOWUP_PROMPT_TEMPLATE = `You are agent {{agent.id}} ({{agent.name}}). This is a passive issue follow-up, not a fresh assignment and not a failure recovery.
16483
+ var ISSUE_PASSIVE_FOLLOWUP_PROMPT_TEMPLATE = `<wake_context>
16484
+ You are agent {{agent.id}} ({{agent.name}}). This is a passive issue follow-up, not a fresh assignment and not a failure recovery.
16199
16485
 
16200
16486
  {{context.rudderWorkspace.orgResourcesPrompt}}
16201
16487
 
@@ -16218,16 +16504,17 @@ Reason: {{context.passiveFollowup.reason}}
16218
16504
  - Reviewer: {{issue.reviewerLabel}}
16219
16505
  - Created At: {{issue.createdAt}}
16220
16506
  - Updated At: {{issue.updatedAt}}
16507
+ </wake_context>
16221
16508
 
16509
+ <quoted_issue_context>
16222
16510
  - Description:
16223
16511
  {{issue.description}}
16512
+ </quoted_issue_context>
16224
16513
 
16225
16514
 
16226
16515
  Before changing the issue, continue to progress the current issue, then inspect the current issue state and any side effects from the previous run. Finally, do exactly one close-out action: add a progress comment, mark the issue done, block it with a reason, or hand it off explicitly with explanation.
16227
16516
  ${ISSUE_ASSIGNEE_EXECUTION_RAIL}`;
16228
16517
  var RUDDER_AGENT_OPERATING_CONTRACT = [
16229
- "# Rudder Agent Operating Contract",
16230
- "",
16231
16518
  "You are a helpful assistant running inside Rudder. Your home directory is `$AGENT_HOME`. Everything personal to you -- life, memory, knowledge -- lives there. Other agents may have their own folders and you may update them when necessary.",
16232
16519
  "",
16233
16520
  "Read Rudder mcp tools to firstly.",
@@ -16288,8 +16575,6 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
16288
16575
  "- When the user explicitly mentions previously handled issue, tasks or conversations, you need to retrieve the relevant tasks first before proceeding with the next action."
16289
16576
  ].join("\n");
16290
16577
  var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
16291
- "# Rudder Heartbeat Instruction",
16292
- "",
16293
16578
  "This section is injected by Rudder only for heartbeat scene runs. It is the platform-owned heartbeat/self-check pipeline.",
16294
16579
  "",
16295
16580
  "## Heartbeat Pipeline",
@@ -16315,8 +16600,8 @@ var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
16315
16600
  // ../packages/agent-runtime-utils/dist/server-utils.cli.js
16316
16601
  async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
16317
16602
  const candidates = [
16318
- ...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path12.resolve(moduleDir, relativePath)),
16319
- ...additionalCandidates.map((candidate) => path12.resolve(candidate))
16603
+ ...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path11.resolve(moduleDir, relativePath)),
16604
+ ...additionalCandidates.map((candidate) => path11.resolve(candidate))
16320
16605
  ];
16321
16606
  const seenRoots = /* @__PURE__ */ new Set();
16322
16607
  for (const root of candidates) {
@@ -16333,26 +16618,26 @@ async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames)
16333
16618
  return removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames);
16334
16619
  }
16335
16620
  async function readRudderMaterializedSkillSource(target) {
16336
- const manifestPath = path12.join(target, ".rudder", "materialized-skill.json");
16621
+ const manifestPath = path11.join(target, ".rudder", "materialized-skill.json");
16337
16622
  const raw = await fs8.readFile(manifestPath, "utf8").catch(() => null);
16338
16623
  if (!raw)
16339
16624
  return null;
16340
16625
  try {
16341
16626
  const parsed = parseObject(JSON.parse(raw));
16342
16627
  const sourcePath = asString(parsed.sourcePath, "").trim();
16343
- return sourcePath.length > 0 ? path12.resolve(sourcePath) : null;
16628
+ return sourcePath.length > 0 ? path11.resolve(sourcePath) : null;
16344
16629
  } catch {
16345
16630
  return null;
16346
16631
  }
16347
16632
  }
16348
16633
  async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames, knownSkillSources = []) {
16349
16634
  const allowed = new Set(Array.from(allowedSkillNames));
16350
- const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) => path12.resolve(value)));
16635
+ const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) => path11.resolve(value)));
16351
16636
  try {
16352
16637
  const entries = await fs8.readdir(skillsHome, { withFileTypes: true });
16353
16638
  const removed = [];
16354
16639
  for (const entry of entries) {
16355
- const target = path12.join(skillsHome, entry.name);
16640
+ const target = path11.join(skillsHome, entry.name);
16356
16641
  const existing = await fs8.lstat(target).catch(() => null);
16357
16642
  if (!existing)
16358
16643
  continue;
@@ -16361,8 +16646,8 @@ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames
16361
16646
  const linkedPath = await fs8.readlink(target).catch(() => null);
16362
16647
  if (!linkedPath)
16363
16648
  continue;
16364
- const resolvedLinkedPath = path12.isAbsolute(linkedPath) ? linkedPath : path12.resolve(path12.dirname(target), linkedPath);
16365
- isRudderManagedSkill = knownSources.has(path12.resolve(resolvedLinkedPath)) || isMaintainerOnlySkillTarget(linkedPath) || isMaintainerOnlySkillTarget(resolvedLinkedPath);
16649
+ const resolvedLinkedPath = path11.isAbsolute(linkedPath) ? linkedPath : path11.resolve(path11.dirname(target), linkedPath);
16650
+ isRudderManagedSkill = knownSources.has(path11.resolve(resolvedLinkedPath)) || isMaintainerOnlySkillTarget(linkedPath) || isMaintainerOnlySkillTarget(resolvedLinkedPath);
16366
16651
  } else if (existing.isDirectory()) {
16367
16652
  const materializedSource = await readRudderMaterializedSkillSource(target);
16368
16653
  isRudderManagedSkill = materializedSource !== null && knownSources.has(materializedSource);
@@ -16384,7 +16669,7 @@ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames
16384
16669
  init_dist2();
16385
16670
  import fs9 from "node:fs/promises";
16386
16671
  import os3 from "node:os";
16387
- import path13 from "node:path";
16672
+ import path12 from "node:path";
16388
16673
  import { fileURLToPath as fileURLToPath6 } from "node:url";
16389
16674
 
16390
16675
  // src/commands/client/help.ts
@@ -16408,16 +16693,16 @@ function formatHelpExample(example) {
16408
16693
  }
16409
16694
 
16410
16695
  // src/commands/client/agent.ts
16411
- var __moduleDir = path13.dirname(fileURLToPath6(import.meta.url));
16696
+ var __moduleDir = path12.dirname(fileURLToPath6(import.meta.url));
16412
16697
  function codexSkillsHome() {
16413
16698
  const fromEnv = process.env.CODEX_HOME?.trim();
16414
- const base = fromEnv && fromEnv.length > 0 ? fromEnv : path13.join(os3.homedir(), ".codex");
16415
- return path13.join(base, "skills");
16699
+ const base = fromEnv && fromEnv.length > 0 ? fromEnv : path12.join(os3.homedir(), ".codex");
16700
+ return path12.join(base, "skills");
16416
16701
  }
16417
16702
  function claudeSkillsHome() {
16418
16703
  const fromEnv = process.env.CLAUDE_HOME?.trim();
16419
- const base = fromEnv && fromEnv.length > 0 ? fromEnv : path13.join(os3.homedir(), ".claude");
16420
- return path13.join(base, "skills");
16704
+ const base = fromEnv && fromEnv.length > 0 ? fromEnv : path12.join(os3.homedir(), ".claude");
16705
+ return path12.join(base, "skills");
16421
16706
  }
16422
16707
  async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
16423
16708
  const summary = {
@@ -16436,8 +16721,8 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
16436
16721
  );
16437
16722
  for (const entry of entries) {
16438
16723
  if (!entry.isDirectory()) continue;
16439
- const source = path13.join(sourceSkillsDir, entry.name);
16440
- const target = path13.join(targetSkillsDir, entry.name);
16724
+ const source = path12.join(sourceSkillsDir, entry.name);
16725
+ const target = path12.join(targetSkillsDir, entry.name);
16441
16726
  const existing = await fs9.lstat(target).catch(() => null);
16442
16727
  if (existing) {
16443
16728
  if (existing.isSymbolicLink()) {
@@ -16458,7 +16743,7 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
16458
16743
  continue;
16459
16744
  }
16460
16745
  }
16461
- const resolvedLinkedPath = path13.isAbsolute(linkedPath) ? linkedPath : path13.resolve(path13.dirname(target), linkedPath);
16746
+ const resolvedLinkedPath = path12.isAbsolute(linkedPath) ? linkedPath : path12.resolve(path12.dirname(target), linkedPath);
16462
16747
  const linkedTargetExists = await fs9.stat(resolvedLinkedPath).then(() => true).catch(() => false);
16463
16748
  if (!linkedTargetExists) {
16464
16749
  await fs9.unlink(target);
@@ -16683,7 +16968,7 @@ function registerAgentCommands(program) {
16683
16968
  if (opts.markdown && opts.markdownFile) {
16684
16969
  throw new Error("Pass only one of --markdown or --markdown-file.");
16685
16970
  }
16686
- const markdown = opts.markdownFile ? await fs9.readFile(path13.resolve(opts.markdownFile), "utf8") : opts.markdown;
16971
+ const markdown = opts.markdownFile ? await fs9.readFile(path12.resolve(opts.markdownFile), "utf8") : opts.markdown;
16687
16972
  const payload = organizationSkillCreateSchema.parse({
16688
16973
  name: opts.name,
16689
16974
  slug: opts.slug?.trim() || null,
@@ -16862,7 +17147,7 @@ function registerAgentCommands(program) {
16862
17147
  }
16863
17148
  const installSummaries = [];
16864
17149
  if (opts.installSkills !== false) {
16865
- const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path13.resolve(process.cwd(), "skills")]);
17150
+ const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path12.resolve(process.cwd(), "skills")]);
16866
17151
  if (!skillsDir) {
16867
17152
  throw new Error(
16868
17153
  "Could not locate local Rudder skills directory. Expected ./skills in the repo checkout."
@@ -16950,10 +17235,10 @@ async function buildAgentUpdatePatch(opts) {
16950
17235
  if (opts.capabilities !== void 0) rawPatch.capabilities = opts.capabilities;
16951
17236
  if (opts.description !== void 0) rawPatch.capabilities = opts.description;
16952
17237
  if (opts.capabilitiesFile !== void 0) {
16953
- rawPatch.capabilities = await fs9.readFile(path13.resolve(opts.capabilitiesFile), "utf8");
17238
+ rawPatch.capabilities = await fs9.readFile(path12.resolve(opts.capabilitiesFile), "utf8");
16954
17239
  }
16955
17240
  if (opts.descriptionFile !== void 0) {
16956
- rawPatch.capabilities = await fs9.readFile(path13.resolve(opts.descriptionFile), "utf8");
17241
+ rawPatch.capabilities = await fs9.readFile(path12.resolve(opts.descriptionFile), "utf8");
16957
17242
  }
16958
17243
  if (clearCapabilities) rawPatch.capabilities = null;
16959
17244
  return updateAgentSchema.parse(rawPatch);
@@ -16977,7 +17262,7 @@ function parseJsonObject(value, name) {
16977
17262
  // src/commands/client/approval.ts
16978
17263
  init_dist2();
16979
17264
  import { readFile as readFile2 } from "node:fs/promises";
16980
- import path14 from "node:path";
17265
+ import path13 from "node:path";
16981
17266
  function registerApprovalCommands(program) {
16982
17267
  const approval = program.command("approval").description("Approval operations");
16983
17268
  addCommonClientOptions(
@@ -17168,7 +17453,7 @@ async function readTextInputFile(inputPath, optionName) {
17168
17453
  if (inputPath === "-") {
17169
17454
  return readStdinText();
17170
17455
  }
17171
- const resolvedPath = path14.resolve(process.cwd(), inputPath);
17456
+ const resolvedPath = path13.resolve(process.cwd(), inputPath);
17172
17457
  return readFile2(resolvedPath, "utf8").catch((err) => {
17173
17458
  throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
17174
17459
  });
@@ -18005,12 +18290,12 @@ async function readStdin() {
18005
18290
 
18006
18291
  // src/commands/client/company.ts
18007
18292
  import * as p3 from "@clack/prompts";
18008
- import { mkdir as mkdir3, readdir as readdir2, readFile as readFile3, stat as stat4, writeFile as writeFile2 } from "node:fs/promises";
18009
- import path16 from "node:path";
18293
+ import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
18294
+ import path15 from "node:path";
18010
18295
  import pc5 from "picocolors";
18011
18296
 
18012
18297
  // src/commands/client/zip.ts
18013
- import path15 from "node:path";
18298
+ import path14 from "node:path";
18014
18299
  import { inflateRawSync } from "node:zlib";
18015
18300
  var textDecoder = new TextDecoder();
18016
18301
  var binaryContentTypeByExtension = {
@@ -18038,7 +18323,7 @@ function sharedArchiveRoot(paths) {
18038
18323
  return firstSegments.every((parts) => parts.length > 1 && parts[0] === candidate) ? candidate : null;
18039
18324
  }
18040
18325
  function bytesToPortableFileEntry(pathValue, bytes) {
18041
- const contentType = binaryContentTypeByExtension[path15.extname(pathValue).toLowerCase()];
18326
+ const contentType = binaryContentTypeByExtension[path14.extname(pathValue).toLowerCase()];
18042
18327
  if (!contentType) return textDecoder.decode(bytes);
18043
18328
  return {
18044
18329
  encoding: "base64",
@@ -18126,7 +18411,7 @@ var IMPORT_INCLUDE_OPTIONS = [
18126
18411
  ];
18127
18412
  var IMPORT_PREVIEW_SAMPLE_LIMIT = 6;
18128
18413
  function readPortableFileEntry(filePath, contents) {
18129
- const contentType = binaryContentTypeByExtension[path16.extname(filePath).toLowerCase()];
18414
+ const contentType = binaryContentTypeByExtension[path15.extname(filePath).toLowerCase()];
18130
18415
  if (!contentType) return contents.toString("utf8");
18131
18416
  return {
18132
18417
  encoding: "base64",
@@ -18181,10 +18466,10 @@ function normalizePortablePath(filePath) {
18181
18466
  return filePath.replace(/\\/g, "/");
18182
18467
  }
18183
18468
  function shouldIncludePortableFile(filePath) {
18184
- const baseName = path16.basename(filePath);
18469
+ const baseName = path15.basename(filePath);
18185
18470
  const isMarkdown = baseName.endsWith(".md");
18186
18471
  const isPaperclipYaml = baseName === ".rudder.yaml" || baseName === ".rudder.yml";
18187
- const contentType = binaryContentTypeByExtension[path16.extname(baseName).toLowerCase()];
18472
+ const contentType = binaryContentTypeByExtension[path15.extname(baseName).toLowerCase()];
18188
18473
  return isMarkdown || isPaperclipYaml || Boolean(contentType);
18189
18474
  }
18190
18475
  function findPortableExtensionPath(files) {
@@ -18739,7 +19024,7 @@ function normalizeGithubImportSource(input, refOverride) {
18739
19024
  }
18740
19025
  async function pathExists(inputPath) {
18741
19026
  try {
18742
- await stat4(path16.resolve(inputPath));
19027
+ await stat2(path15.resolve(inputPath));
18743
19028
  return true;
18744
19029
  } catch {
18745
19030
  return false;
@@ -18749,45 +19034,45 @@ async function collectPackageFiles(root, current, files) {
18749
19034
  const entries = await readdir2(current, { withFileTypes: true });
18750
19035
  for (const entry of entries) {
18751
19036
  if (entry.name.startsWith(".git")) continue;
18752
- const absolutePath = path16.join(current, entry.name);
19037
+ const absolutePath = path15.join(current, entry.name);
18753
19038
  if (entry.isDirectory()) {
18754
19039
  await collectPackageFiles(root, absolutePath, files);
18755
19040
  continue;
18756
19041
  }
18757
19042
  if (!entry.isFile()) continue;
18758
- const relativePath = path16.relative(root, absolutePath).replace(/\\/g, "/");
19043
+ const relativePath = path15.relative(root, absolutePath).replace(/\\/g, "/");
18759
19044
  if (!shouldIncludePortableFile(relativePath)) continue;
18760
19045
  files[relativePath] = readPortableFileEntry(relativePath, await readFile3(absolutePath));
18761
19046
  }
18762
19047
  }
18763
19048
  async function resolveInlineSourceFromPath(inputPath) {
18764
- const resolved = path16.resolve(inputPath);
18765
- const resolvedStat = await stat4(resolved);
18766
- if (resolvedStat.isFile() && path16.extname(resolved).toLowerCase() === ".zip") {
19049
+ const resolved = path15.resolve(inputPath);
19050
+ const resolvedStat = await stat2(resolved);
19051
+ if (resolvedStat.isFile() && path15.extname(resolved).toLowerCase() === ".zip") {
18767
19052
  const archive = await readZipArchive(await readFile3(resolved));
18768
19053
  const filteredFiles = Object.fromEntries(
18769
19054
  Object.entries(archive.files).filter(([relativePath]) => shouldIncludePortableFile(relativePath))
18770
19055
  );
18771
19056
  return {
18772
- rootPath: archive.rootPath ?? path16.basename(resolved, ".zip"),
19057
+ rootPath: archive.rootPath ?? path15.basename(resolved, ".zip"),
18773
19058
  files: filteredFiles
18774
19059
  };
18775
19060
  }
18776
- const rootDir = resolvedStat.isDirectory() ? resolved : path16.dirname(resolved);
19061
+ const rootDir = resolvedStat.isDirectory() ? resolved : path15.dirname(resolved);
18777
19062
  const files = {};
18778
19063
  await collectPackageFiles(rootDir, rootDir, files);
18779
19064
  return {
18780
- rootPath: path16.basename(rootDir),
19065
+ rootPath: path15.basename(rootDir),
18781
19066
  files
18782
19067
  };
18783
19068
  }
18784
19069
  async function writeExportToFolder(outDir, exported) {
18785
- const root = path16.resolve(outDir);
18786
- await mkdir3(root, { recursive: true });
19070
+ const root = path15.resolve(outDir);
19071
+ await mkdir2(root, { recursive: true });
18787
19072
  for (const [relativePath, content] of Object.entries(exported.files)) {
18788
19073
  const normalized = relativePath.replace(/\\/g, "/");
18789
- const filePath = path16.join(root, normalized);
18790
- await mkdir3(path16.dirname(filePath), { recursive: true });
19074
+ const filePath = path15.join(root, normalized);
19075
+ await mkdir2(path15.dirname(filePath), { recursive: true });
18791
19076
  const writeValue = portableFileEntryToWriteValue(content);
18792
19077
  if (typeof writeValue === "string") {
18793
19078
  await writeFile2(filePath, writeValue, "utf8");
@@ -18797,8 +19082,8 @@ async function writeExportToFolder(outDir, exported) {
18797
19082
  }
18798
19083
  }
18799
19084
  async function confirmOverwriteExportDirectory(outDir) {
18800
- const root = path16.resolve(outDir);
18801
- const stats = await stat4(root).catch(() => null);
19085
+ const root = path15.resolve(outDir);
19086
+ const stats = await stat2(root).catch(() => null);
18802
19087
  if (!stats) return;
18803
19088
  if (!stats.isDirectory()) {
18804
19089
  throw new Error(`Export output path ${root} exists and is not a directory.`);
@@ -18979,7 +19264,7 @@ function registerCompanyCommands(program) {
18979
19264
  printOutput(
18980
19265
  {
18981
19266
  ok: true,
18982
- out: path16.resolve(opts.out),
19267
+ out: path15.resolve(opts.out),
18983
19268
  rootPath: exported.rootPath,
18984
19269
  filesWritten: Object.keys(exported.files).length,
18985
19270
  rudderExtensionPath: exported.rudderExtensionPath,
@@ -19477,8 +19762,8 @@ function parseResultValue(value) {
19477
19762
 
19478
19763
  // src/commands/client/issue.ts
19479
19764
  init_dist2();
19480
- import { readFile as readFile4, stat as stat5 } from "node:fs/promises";
19481
- import path17 from "node:path";
19765
+ import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
19766
+ import path16 from "node:path";
19482
19767
  function registerIssueCommands(program) {
19483
19768
  const issue = program.command("issue").description("Issue operations");
19484
19769
  addCommonClientOptions(
@@ -19842,7 +20127,7 @@ async function readTextInputFile2(inputPath, optionName) {
19842
20127
  if (inputPath === "-") {
19843
20128
  return readStdinText2();
19844
20129
  }
19845
- const resolvedPath = path17.resolve(process.cwd(), inputPath);
20130
+ const resolvedPath = path16.resolve(process.cwd(), inputPath);
19846
20131
  return readFile4(resolvedPath, "utf8").catch((err) => {
19847
20132
  throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
19848
20133
  });
@@ -19899,14 +20184,14 @@ async function appendUploadedIssueImages(ctx, issueId, body, imagePaths) {
19899
20184
  ${imageBlock}` : imageBlock;
19900
20185
  }
19901
20186
  async function uploadIssueCommentImage(ctx, issue, imagePath) {
19902
- const resolvedPath = path17.resolve(process.cwd(), imagePath);
19903
- const stats = await stat5(resolvedPath).catch((err) => {
20187
+ const resolvedPath = path16.resolve(process.cwd(), imagePath);
20188
+ const stats = await stat3(resolvedPath).catch((err) => {
19904
20189
  throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
19905
20190
  });
19906
20191
  if (!stats.isFile()) {
19907
20192
  throw new Error(`Image path must be a file: ${imagePath}`);
19908
20193
  }
19909
- const filename = path17.basename(resolvedPath);
20194
+ const filename = path16.basename(resolvedPath);
19910
20195
  const contentType = inferCommentImageContentType(filename);
19911
20196
  const buffer = await readFile4(resolvedPath);
19912
20197
  if (buffer.length <= 0) {
@@ -19925,7 +20210,7 @@ async function uploadIssueCommentImage(ctx, issue, imagePath) {
19925
20210
  return attachment;
19926
20211
  }
19927
20212
  function inferCommentImageContentType(filename) {
19928
- const ext = path17.extname(filename).toLowerCase();
20213
+ const ext = path16.extname(filename).toLowerCase();
19929
20214
  switch (ext) {
19930
20215
  case ".png":
19931
20216
  return "image/png";
@@ -20029,7 +20314,7 @@ function formatIssueSearchMatch(match) {
20029
20314
 
20030
20315
  // src/commands/client/library.ts
20031
20316
  import { readFile as readFile5 } from "node:fs/promises";
20032
- import path18 from "node:path";
20317
+ import path17 from "node:path";
20033
20318
  function toLibraryFileLinkResult(detail) {
20034
20319
  return {
20035
20320
  filePath: detail.filePath,
@@ -20174,7 +20459,7 @@ async function resolveBodyFileInput(inputPath) {
20174
20459
  if (inputPath === "-") {
20175
20460
  return readStdinText3();
20176
20461
  }
20177
- const resolvedPath = path18.resolve(process.cwd(), inputPath);
20462
+ const resolvedPath = path17.resolve(process.cwd(), inputPath);
20178
20463
  return readFile5(resolvedPath, "utf8").catch((err) => {
20179
20464
  throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
20180
20465
  });
@@ -20933,8 +21218,8 @@ function registerUserCommands(program) {
20933
21218
  appendParam(params, "limit", opts.limit);
20934
21219
  appendParam(params, "cursor", opts.cursor);
20935
21220
  const query = params.toString();
20936
- const path26 = `/api/orgs/${ctx.orgId}/users/${encodeURIComponent(userId)}/activity-ledger${query ? `?${query}` : ""}`;
20937
- const result = await ctx.api.get(path26);
21221
+ const path25 = `/api/orgs/${ctx.orgId}/users/${encodeURIComponent(userId)}/activity-ledger${query ? `?${query}` : ""}`;
21222
+ const result = await ctx.api.get(path25);
20938
21223
  if (ctx.json) {
20939
21224
  printOutput(result, { json: true });
20940
21225
  return;
@@ -21751,9 +22036,9 @@ import * as p15 from "@clack/prompts";
21751
22036
  import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
21752
22037
  import { createHash as createHash4, randomUUID } from "node:crypto";
21753
22038
  import { constants as fsConstants, mkdirSync as mkdirSync2, readFileSync as readFileSync2 } from "node:fs";
21754
- import { access, chmod, copyFile as copyFile2, cp as cp2, lstat, mkdir as mkdir4, mkdtemp as mkdtemp2, readdir as readdir3, readFile as readFile6, rm as rm3, stat as stat6, utimes, writeFile as writeFile3 } from "node:fs/promises";
22039
+ import { access, chmod as chmod2, copyFile, cp, lstat, mkdir as mkdir3, mkdtemp as mkdtemp2, readdir as readdir3, readFile as readFile6, rm as rm3, stat as stat4, utimes, writeFile as writeFile3 } from "node:fs/promises";
21755
22040
  import { homedir, tmpdir } from "node:os";
21756
- import path24 from "node:path";
22041
+ import path23 from "node:path";
21757
22042
  import { clearTimeout as clearTimeout3, setTimeout as setTimeout3 } from "node:timers";
21758
22043
  import { setTimeout as delay2 } from "node:timers/promises";
21759
22044
  import pc14 from "picocolors";
@@ -21782,11 +22067,11 @@ init_home();
21782
22067
 
21783
22068
  // src/desktop-download.ts
21784
22069
  import { createHash as createHash3 } from "node:crypto";
21785
- import { createWriteStream as createWriteStream2, mkdirSync } from "node:fs";
22070
+ import { createWriteStream as createWriteStream3, mkdirSync } from "node:fs";
21786
22071
  import { rm as rm2 } from "node:fs/promises";
21787
- import path23 from "node:path";
22072
+ import path22 from "node:path";
21788
22073
  import { Readable as Readable2, Transform as Transform2 } from "node:stream";
21789
- import { pipeline as pipeline2 } from "node:stream/promises";
22074
+ import { pipeline as pipeline3 } from "node:stream/promises";
21790
22075
  import { clearTimeout as clearTimeout2, setTimeout as setTimeout2 } from "node:timers";
21791
22076
 
21792
22077
  // src/utils/progress.ts
@@ -22024,7 +22309,7 @@ async function resolveDesktopDownloadOrigins(options) {
22024
22309
  }
22025
22310
  async function downloadAsset(asset, outputDir, progressFactory = createByteProgress, expectedChecksum, timeouts = {}) {
22026
22311
  mkdirSync(outputDir, { recursive: true });
22027
- const outputPath = path23.join(outputDir, path23.basename(asset.name));
22312
+ const outputPath = path22.join(outputDir, path22.basename(asset.name));
22028
22313
  const idleTimeoutMs = timeouts.idleMs ?? DESKTOP_ASSET_IDLE_TIMEOUT_MS;
22029
22314
  const responseTimeoutMs = timeouts.responseMs ?? DESKTOP_ASSET_RESPONSE_TIMEOUT_MS;
22030
22315
  const failures = [];
@@ -22064,7 +22349,7 @@ async function downloadAsset(asset, outputDir, progressFactory = createByteProgr
22064
22349
  });
22065
22350
  progress.start(totalBytes);
22066
22351
  armIdleTimeout();
22067
- await pipeline2(Readable2.fromWeb(response.body), monitor, createWriteStream2(outputPath));
22352
+ await pipeline3(Readable2.fromWeb(response.body), monitor, createWriteStream3(outputPath));
22068
22353
  if (idleTimeout) clearTimeout2(idleTimeout);
22069
22354
  idleTimeout = null;
22070
22355
  const actualChecksum = hash.digest("hex");
@@ -22128,6 +22413,15 @@ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES = 768 * 1024 * 1024;
22128
22413
  var DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS = 1;
22129
22414
  var DESKTOP_INSTALL_LOCK_TIMEOUT_MS = 60 * 60 * 1e3;
22130
22415
  var DESKTOP_INSTALL_LOCK_POLL_MS = 250;
22416
+ var DESKTOP_RUNTIME_PREPARE_TIMEOUT_MS = 9e4;
22417
+ async function waitForDesktopRuntimeSmokeEvidence(envName) {
22418
+ if (process.env.RUDDER_DESKTOP_SMOKE_AUTO_UPDATE_PUBLIC !== "1") return;
22419
+ const value = Number(process.env[envName]);
22420
+ if (!Number.isFinite(value) || value <= 0) return;
22421
+ await delay2(Math.min(value, 1e4));
22422
+ }
22423
+ var DEFAULT_GITHUB_API_BASE_URL = "https://api.github.com";
22424
+ var DEFAULT_GITHUB_DOWNLOAD_BASE_URL = "https://github.com";
22131
22425
  function normalizeProgressTotal(totalBytes) {
22132
22426
  return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
22133
22427
  }
@@ -22351,38 +22645,38 @@ function resolveDesktopAssetTarget(platform = process.platform, arch = process.a
22351
22645
  throw new Error(`Rudder Desktop does not publish portable assets for ${platform}.`);
22352
22646
  }
22353
22647
  function resolveDefaultDesktopInstallRoot(target, env = process.env, homeDir = homedir()) {
22354
- if (target.platform === "macos") return path24.join(homeDir, "Applications");
22648
+ if (target.platform === "macos") return path23.join(homeDir, "Applications");
22355
22649
  if (target.platform === "windows") {
22356
- const localAppData = env.LOCALAPPDATA?.trim() || path24.join(homeDir, "AppData", "Local");
22357
- return path24.join(localAppData, "Programs", DESKTOP_APP_NAME);
22650
+ const localAppData = env.LOCALAPPDATA?.trim() || path23.join(homeDir, "AppData", "Local");
22651
+ return path23.join(localAppData, "Programs", DESKTOP_APP_NAME);
22358
22652
  }
22359
- return path24.join(homeDir, ".local", "share", "rudder");
22653
+ return path23.join(homeDir, ".local", "share", "rudder");
22360
22654
  }
22361
22655
  function resolveDesktopInstallPaths(target, installRoot) {
22362
- const root = path24.resolve(installRoot);
22656
+ const root = path23.resolve(installRoot);
22363
22657
  if (target.platform === "macos") {
22364
- const appPath2 = path24.join(root, `${DESKTOP_APP_NAME}.app`);
22658
+ const appPath2 = path23.join(root, `${DESKTOP_APP_NAME}.app`);
22365
22659
  return {
22366
22660
  installRoot: root,
22367
22661
  appPath: appPath2,
22368
- executablePath: path24.join(appPath2, "Contents", "MacOS", DESKTOP_APP_NAME),
22369
- metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
22662
+ executablePath: path23.join(appPath2, "Contents", "MacOS", DESKTOP_APP_NAME),
22663
+ metadataPath: path23.join(root, DESKTOP_METADATA_FILE)
22370
22664
  };
22371
22665
  }
22372
22666
  if (target.platform === "windows") {
22373
22667
  return {
22374
22668
  installRoot: root,
22375
22669
  appPath: root,
22376
- executablePath: path24.join(root, `${DESKTOP_APP_NAME}.exe`),
22377
- metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
22670
+ executablePath: path23.join(root, `${DESKTOP_APP_NAME}.exe`),
22671
+ metadataPath: path23.join(root, DESKTOP_METADATA_FILE)
22378
22672
  };
22379
22673
  }
22380
- const appPath = path24.join(root, `${DESKTOP_APP_NAME}.AppImage`);
22674
+ const appPath = path23.join(root, `${DESKTOP_APP_NAME}.AppImage`);
22381
22675
  return {
22382
22676
  installRoot: root,
22383
22677
  appPath,
22384
22678
  executablePath: appPath,
22385
- metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
22679
+ metadataPath: path23.join(root, DESKTOP_METADATA_FILE)
22386
22680
  };
22387
22681
  }
22388
22682
  function normalizeAssetName(name) {
@@ -22441,10 +22735,20 @@ function resolveDesktopAssetCandidates(options) {
22441
22735
  const candidates = [];
22442
22736
  const deterministicShellName = options.directReleaseVersion ? resolveDesktopShellAssetName(options.directReleaseVersion, options.target) : null;
22443
22737
  if (options.allowShellAssets !== false) {
22444
- const shellAsset = selectDesktopShellAsset(options.releaseAssets, options.target) ?? (options.releaseAssets.length === 0 && deterministicShellName ? buildGithubReleaseAsset(options.repo, options.tag, deterministicShellName) : null);
22738
+ const shellAsset = selectDesktopShellAsset(options.releaseAssets, options.target) ?? (options.releaseAssets.length === 0 && deterministicShellName ? buildGithubReleaseAsset(
22739
+ options.repo,
22740
+ options.tag,
22741
+ deterministicShellName,
22742
+ options.downloadBaseUrl
22743
+ ) : null);
22445
22744
  if (shellAsset) candidates.push({ asset: shellAsset, kind: "shell" });
22446
22745
  }
22447
- const fullAsset = selectDesktopAsset(options.releaseAssets, options.target) ?? (options.directReleaseVersion ? buildGithubReleaseAsset(options.repo, options.tag, resolveDesktopAssetName(options.directReleaseVersion, options.target)) : null);
22746
+ const fullAsset = selectDesktopAsset(options.releaseAssets, options.target) ?? (options.directReleaseVersion ? buildGithubReleaseAsset(
22747
+ options.repo,
22748
+ options.tag,
22749
+ resolveDesktopAssetName(options.directReleaseVersion, options.target),
22750
+ options.downloadBaseUrl
22751
+ ) : null);
22448
22752
  if (fullAsset) candidates.push({ asset: fullAsset, kind: "full" });
22449
22753
  return candidates;
22450
22754
  }
@@ -22488,8 +22792,35 @@ function githubApiHeaders() {
22488
22792
  };
22489
22793
  }
22490
22794
  var GITHUB_API_TIMEOUT_MS = 15e3;
22491
- async function fetchGithubRelease(repo, tag) {
22492
- const endpoint = tag === "latest" ? `https://api.github.com/repos/${repo}/releases/latest` : `https://api.github.com/repos/${repo}/releases/tags/${encodeURIComponent(tag)}`;
22795
+ function resolveDesktopSmokeReleaseBaseUrls(env = process.env) {
22796
+ if (env.RUDDER_DESKTOP_SMOKE_AUTO_UPDATE_PUBLIC !== "1") {
22797
+ return {
22798
+ apiBaseUrl: DEFAULT_GITHUB_API_BASE_URL,
22799
+ downloadBaseUrl: DEFAULT_GITHUB_DOWNLOAD_BASE_URL
22800
+ };
22801
+ }
22802
+ const normalizeBaseUrl = (value, fallback) => {
22803
+ const configured = value?.trim();
22804
+ if (!configured) return fallback;
22805
+ const parsed = new URL(configured);
22806
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
22807
+ throw new Error(`Desktop smoke release base URL must use HTTP or HTTPS: ${configured}`);
22808
+ }
22809
+ return configured.replace(/\/+$/u, "");
22810
+ };
22811
+ return {
22812
+ apiBaseUrl: normalizeBaseUrl(
22813
+ env.RUDDER_DESKTOP_SMOKE_RELEASE_API_BASE_URL,
22814
+ DEFAULT_GITHUB_API_BASE_URL
22815
+ ),
22816
+ downloadBaseUrl: normalizeBaseUrl(
22817
+ env.RUDDER_DESKTOP_SMOKE_RELEASE_DOWNLOAD_BASE_URL,
22818
+ DEFAULT_GITHUB_DOWNLOAD_BASE_URL
22819
+ )
22820
+ };
22821
+ }
22822
+ async function fetchGithubRelease(repo, tag, apiBaseUrl = DEFAULT_GITHUB_API_BASE_URL) {
22823
+ const endpoint = tag === "latest" ? `${apiBaseUrl}/repos/${repo}/releases/latest` : `${apiBaseUrl}/repos/${repo}/releases/tags/${encodeURIComponent(tag)}`;
22493
22824
  const response = await fetchWithTimeout2(endpoint, { headers: githubApiHeaders() }, GITHUB_API_TIMEOUT_MS);
22494
22825
  if (!response.ok) {
22495
22826
  throw new Error(`GitHub Release ${tag} was not found in ${repo} (${response.status}).`);
@@ -22517,14 +22848,14 @@ function resolveDesktopShellAssetName(version, target) {
22517
22848
  function encodeReleaseTagForDownloadUrl2(tag) {
22518
22849
  return tag.split("/").map((segment) => encodeURIComponent(segment)).join("/");
22519
22850
  }
22520
- function buildGithubReleaseAssetDownloadUrl(repo, tag, assetName) {
22851
+ function buildGithubReleaseAssetDownloadUrl(repo, tag, assetName, downloadBaseUrl = DEFAULT_GITHUB_DOWNLOAD_BASE_URL) {
22521
22852
  const encodedTag = encodeReleaseTagForDownloadUrl2(tag);
22522
- return `https://github.com/${repo}/releases/download/${encodedTag}/${encodeURIComponent(assetName)}`;
22853
+ return `${downloadBaseUrl}/${repo}/releases/download/${encodedTag}/${encodeURIComponent(assetName)}`;
22523
22854
  }
22524
- function buildGithubReleaseAsset(repo, tag, assetName) {
22855
+ function buildGithubReleaseAsset(repo, tag, assetName, downloadBaseUrl) {
22525
22856
  return {
22526
22857
  name: assetName,
22527
- browser_download_url: buildGithubReleaseAssetDownloadUrl(repo, tag, assetName)
22858
+ browser_download_url: buildGithubReleaseAssetDownloadUrl(repo, tag, assetName, downloadBaseUrl)
22528
22859
  };
22529
22860
  }
22530
22861
  function checksumForFile(filePath) {
@@ -22533,16 +22864,16 @@ function checksumForFile(filePath) {
22533
22864
  return hash.digest("hex");
22534
22865
  }
22535
22866
  function resolveAssetChecksum(checksums, assetName) {
22536
- const expected = checksums.get(path24.basename(assetName));
22867
+ const expected = checksums.get(path23.basename(assetName));
22537
22868
  if (!expected) {
22538
- throw new Error(`Desktop release checksums do not include ${path24.basename(assetName)}.`);
22869
+ throw new Error(`Desktop release checksums do not include ${path23.basename(assetName)}.`);
22539
22870
  }
22540
22871
  return expected;
22541
22872
  }
22542
22873
  function assertChecksumMatch(filePath, expected) {
22543
22874
  const actual = checksumForFile(filePath);
22544
22875
  if (actual !== expected.toLowerCase()) {
22545
- throw new Error(`Checksum mismatch for ${path24.basename(filePath)}.`);
22876
+ throw new Error(`Checksum mismatch for ${path23.basename(filePath)}.`);
22546
22877
  }
22547
22878
  return actual;
22548
22879
  }
@@ -22561,10 +22892,10 @@ function normalizeDesktopAssetChecksum(checksum) {
22561
22892
  return normalized;
22562
22893
  }
22563
22894
  function resolveDesktopAssetCacheDir(assetChecksum, homeDir = resolveRudderHomeDir()) {
22564
- return path24.join(homeDir, DESKTOP_ASSET_CACHE_DIR, normalizeDesktopAssetChecksum(assetChecksum));
22895
+ return path23.join(homeDir, DESKTOP_ASSET_CACHE_DIR, normalizeDesktopAssetChecksum(assetChecksum));
22565
22896
  }
22566
22897
  function resolveDesktopCachedAssetPath(assetName, assetChecksum, homeDir = resolveRudderHomeDir()) {
22567
- return path24.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path24.basename(assetName));
22898
+ return path23.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path23.basename(assetName));
22568
22899
  }
22569
22900
  async function pruneDesktopAssetCache(options = {}) {
22570
22901
  const homeDir = options.homeDir ?? resolveRudderHomeDir();
@@ -22610,7 +22941,7 @@ async function maybePruneDesktopAssetCache(options) {
22610
22941
  return result.deleted.length > 0 || result.warnings.length > 0 ? result : null;
22611
22942
  }
22612
22943
  async function scanDesktopAssetCacheEntries(homeDir) {
22613
- const cacheRoot = path24.join(homeDir, DESKTOP_ASSET_CACHE_DIR);
22944
+ const cacheRoot = path23.join(homeDir, DESKTOP_ASSET_CACHE_DIR);
22614
22945
  const dirents = await readdir3(cacheRoot, { withFileTypes: true }).catch(() => null);
22615
22946
  if (!dirents) return [];
22616
22947
  const entries = [];
@@ -22622,7 +22953,7 @@ async function scanDesktopAssetCacheEntries(homeDir) {
22622
22953
  } catch {
22623
22954
  continue;
22624
22955
  }
22625
- const cacheDir = path24.join(cacheRoot, dirent.name);
22956
+ const cacheDir = path23.join(cacheRoot, dirent.name);
22626
22957
  const stats = await desktopCacheDirectoryStats(cacheDir);
22627
22958
  entries.push({
22628
22959
  cacheDir,
@@ -22634,7 +22965,7 @@ async function scanDesktopAssetCacheEntries(homeDir) {
22634
22965
  return entries;
22635
22966
  }
22636
22967
  async function desktopCacheDirectoryStats(targetPath) {
22637
- const fallbackStat = await stat6(targetPath).catch(() => null);
22968
+ const fallbackStat = await stat4(targetPath).catch(() => null);
22638
22969
  const dirents = await readdir3(targetPath, { withFileTypes: true }).catch(() => null);
22639
22970
  if (!dirents) {
22640
22971
  return {
@@ -22646,8 +22977,8 @@ async function desktopCacheDirectoryStats(targetPath) {
22646
22977
  let lastUsedAtMs = Number(fallbackStat?.mtimeMs ?? 0);
22647
22978
  for (const dirent of dirents) {
22648
22979
  if (dirent.isSymbolicLink()) continue;
22649
- const entryPath = path24.join(targetPath, dirent.name);
22650
- const entryStat = await stat6(entryPath).catch(() => null);
22980
+ const entryPath = path23.join(targetPath, dirent.name);
22981
+ const entryStat = await stat4(entryPath).catch(() => null);
22651
22982
  if (!entryStat) continue;
22652
22983
  lastUsedAtMs = Math.max(lastUsedAtMs, Number(entryStat.mtimeMs ?? 0));
22653
22984
  if (dirent.isDirectory()) {
@@ -22723,14 +23054,14 @@ async function downloadDesktopAssetWithCache(asset, expectedChecksum, options =
22723
23054
  await rm3(cachePath, { force: true });
22724
23055
  }
22725
23056
  }
22726
- const outputDir = options.outputDir ?? await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-installer."));
23057
+ const outputDir = options.outputDir ?? await mkdtemp2(path23.join(tmpdir(), "rudder-desktop-installer."));
22727
23058
  const removeOutputDir = options.outputDir ? false : true;
22728
23059
  try {
22729
23060
  const downloadedPath = await downloadAsset(asset, outputDir, options.progressFactory, normalizedChecksum);
22730
23061
  const checksum = assertChecksumMatch(downloadedPath, normalizedChecksum);
22731
- await mkdir4(path24.dirname(cachePath), { recursive: true });
22732
- if (path24.resolve(downloadedPath) !== path24.resolve(cachePath)) {
22733
- await copyFile2(downloadedPath, cachePath);
23062
+ await mkdir3(path23.dirname(cachePath), { recursive: true });
23063
+ if (path23.resolve(downloadedPath) !== path23.resolve(cachePath)) {
23064
+ await copyFile(downloadedPath, cachePath);
22734
23065
  }
22735
23066
  return { path: cachePath, checksum, cacheStatus: "miss" };
22736
23067
  } finally {
@@ -22746,8 +23077,8 @@ async function pathExists2(targetPath) {
22746
23077
  }
22747
23078
  }
22748
23079
  function resolveDesktopInstallLockPath(paths) {
22749
- const installRootHash = createHash4("sha256").update(path24.resolve(paths.installRoot)).digest("hex").slice(0, 16);
22750
- return path24.join(path24.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
23080
+ const installRootHash = createHash4("sha256").update(path23.resolve(paths.installRoot)).digest("hex").slice(0, 16);
23081
+ return path23.join(path23.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
22751
23082
  }
22752
23083
  async function readDesktopInstallLock(lockPath) {
22753
23084
  try {
@@ -22767,17 +23098,17 @@ async function readDesktopInstallLock(lockPath) {
22767
23098
  }
22768
23099
  async function withDesktopInstallLock(paths, fn, options = {}) {
22769
23100
  const lockPath = resolveDesktopInstallLockPath(paths);
22770
- const lockDir = path24.dirname(lockPath);
23101
+ const lockDir = path23.dirname(lockPath);
22771
23102
  const timeoutMs = options.timeoutMs ?? DESKTOP_INSTALL_LOCK_TIMEOUT_MS;
22772
23103
  const pollMs = options.pollMs ?? DESKTOP_INSTALL_LOCK_POLL_MS;
22773
23104
  const startedAt = Date.now();
22774
23105
  const payload = {
22775
23106
  lockId: randomUUID(),
22776
23107
  pid: process.pid,
22777
- installRoot: path24.resolve(paths.installRoot),
23108
+ installRoot: path23.resolve(paths.installRoot),
22778
23109
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
22779
23110
  };
22780
- await mkdir4(lockDir, { recursive: true });
23111
+ await mkdir3(lockDir, { recursive: true });
22781
23112
  while (true) {
22782
23113
  try {
22783
23114
  await writeFile3(lockPath, `${JSON.stringify(payload, null, 2)}
@@ -22834,7 +23165,7 @@ function isSuccessfulRobocopyExitCode(status) {
22834
23165
  }
22835
23166
  async function extractZip(zipPath, outputDir, target) {
22836
23167
  await rm3(outputDir, { recursive: true, force: true });
22837
- await mkdir4(outputDir, { recursive: true });
23168
+ await mkdir3(outputDir, { recursive: true });
22838
23169
  if (target.platform === "macos") {
22839
23170
  runChecked("ditto", ["-x", "-k", zipPath, outputDir]);
22840
23171
  return;
@@ -22850,7 +23181,7 @@ async function findPath(root, predicate, maxDepth = 5) {
22850
23181
  async function visit(dir, depth) {
22851
23182
  const entries = await readdir3(dir, { withFileTypes: true });
22852
23183
  for (const entry of entries) {
22853
- const fullPath = path24.join(dir, entry.name);
23184
+ const fullPath = path23.join(dir, entry.name);
22854
23185
  if (predicate(fullPath, entry.isDirectory())) return fullPath;
22855
23186
  if (entry.isDirectory() && depth < maxDepth) {
22856
23187
  const nested = await visit(fullPath, depth + 1);
@@ -22862,18 +23193,18 @@ async function findPath(root, predicate, maxDepth = 5) {
22862
23193
  return await visit(root, 0);
22863
23194
  }
22864
23195
  async function findMacApp(extractDir) {
22865
- const direct = path24.join(extractDir, `${DESKTOP_APP_NAME}.app`);
23196
+ const direct = path23.join(extractDir, `${DESKTOP_APP_NAME}.app`);
22866
23197
  if (await pathExists2(direct)) return direct;
22867
- const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory && path24.basename(filePath) === `${DESKTOP_APP_NAME}.app`);
23198
+ const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory && path23.basename(filePath) === `${DESKTOP_APP_NAME}.app`);
22868
23199
  if (!found) throw new Error(`Portable macOS archive did not contain ${DESKTOP_APP_NAME}.app.`);
22869
23200
  return found;
22870
23201
  }
22871
23202
  async function findWindowsAppDir(extractDir) {
22872
- const direct = path24.join(extractDir, `${DESKTOP_APP_NAME}.exe`);
23203
+ const direct = path23.join(extractDir, `${DESKTOP_APP_NAME}.exe`);
22873
23204
  if (await pathExists2(direct)) return extractDir;
22874
- const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory && path24.basename(filePath).toLowerCase() === `${DESKTOP_APP_NAME.toLowerCase()}.exe`);
23205
+ const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory && path23.basename(filePath).toLowerCase() === `${DESKTOP_APP_NAME.toLowerCase()}.exe`);
22875
23206
  if (!executable) throw new Error(`Portable Windows archive did not contain ${DESKTOP_APP_NAME}.exe.`);
22876
- return path24.dirname(executable);
23207
+ return path23.dirname(executable);
22877
23208
  }
22878
23209
  async function readInstallMetadata(metadataPath) {
22879
23210
  try {
@@ -22941,7 +23272,7 @@ async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
22941
23272
  }
22942
23273
  async function requestDesktopQuit(executablePath, target, options = {}) {
22943
23274
  if (!await pathExists2(executablePath)) return { ok: true, status: "not_running" };
22944
- const responsePath = path24.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
23275
+ const responsePath = path23.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
22945
23276
  const result = spawnSync4(executablePath, [
22946
23277
  `${DESKTOP_UPDATE_QUIT_ARG}=${responsePath}`,
22947
23278
  ...options.forceUpdate ? [DESKTOP_UPDATE_FORCE_ARG] : []
@@ -23099,13 +23430,13 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
23099
23430
  throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
23100
23431
  }
23101
23432
  async function installPortableDesktop(installerPath, paths, target) {
23102
- await mkdir4(paths.installRoot, { recursive: true });
23433
+ await mkdir3(paths.installRoot, { recursive: true });
23103
23434
  if (target.platform === "linux") {
23104
- await copyFile2(installerPath, paths.appPath);
23105
- await chmod(paths.appPath, 493);
23435
+ await copyFile(installerPath, paths.appPath);
23436
+ await chmod2(paths.appPath, 493);
23106
23437
  return;
23107
23438
  }
23108
- const extractDir = await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-extract."));
23439
+ const extractDir = await mkdtemp2(path23.join(tmpdir(), "rudder-desktop-extract."));
23109
23440
  try {
23110
23441
  await extractZip(installerPath, extractDir, target);
23111
23442
  if (target.platform === "macos") {
@@ -23114,7 +23445,7 @@ async function installPortableDesktop(installerPath, paths, target) {
23114
23445
  return;
23115
23446
  }
23116
23447
  const appSource = await findWindowsAppDir(extractDir);
23117
- await mkdir4(path24.dirname(paths.installRoot), { recursive: true });
23448
+ await mkdir3(path23.dirname(paths.installRoot), { recursive: true });
23118
23449
  await copyPortableAppBundle(appSource, paths.installRoot);
23119
23450
  } finally {
23120
23451
  await rm3(extractDir, { recursive: true, force: true });
@@ -23122,7 +23453,7 @@ async function installPortableDesktop(installerPath, paths, target) {
23122
23453
  }
23123
23454
  async function copyPortableAppBundle(sourcePath, destinationPath) {
23124
23455
  if (process.platform === "win32") {
23125
- await mkdir4(destinationPath, { recursive: true });
23456
+ await mkdir3(destinationPath, { recursive: true });
23126
23457
  const command = buildWindowsRobocopyMirrorCommand(sourcePath, destinationPath);
23127
23458
  const result = spawnSync4(command.command, command.args, {
23128
23459
  encoding: "utf8",
@@ -23131,7 +23462,7 @@ async function copyPortableAppBundle(sourcePath, destinationPath) {
23131
23462
  if (isSuccessfulRobocopyExitCode(result.status)) return;
23132
23463
  throw new Error(formatCommandFailure(command.command, command.args, result.stdout, result.stderr));
23133
23464
  }
23134
- await cp2(sourcePath, destinationPath, { recursive: true, verbatimSymlinks: true });
23465
+ await cp(sourcePath, destinationPath, { recursive: true, verbatimSymlinks: true });
23135
23466
  }
23136
23467
  async function removeMacQuarantine(paths, target) {
23137
23468
  if (target.platform !== "macos") return;
@@ -23155,26 +23486,26 @@ function buildLinuxDesktopEntry(executablePath) {
23155
23486
  ].join("\n");
23156
23487
  }
23157
23488
  async function writeLinuxLaunchers(paths) {
23158
- const desktopDir = path24.join(homedir(), ".local", "share", "applications");
23159
- await mkdir4(desktopDir, { recursive: true });
23160
- await writeFile3(path24.join(desktopDir, "rudder.desktop"), buildLinuxDesktopEntry(paths.executablePath), "utf8");
23161
- const binDir = path24.join(homedir(), ".local", "bin");
23162
- await mkdir4(binDir, { recursive: true });
23163
- const wrapperPath = path24.join(binDir, "rudder-desktop");
23489
+ const desktopDir = path23.join(homedir(), ".local", "share", "applications");
23490
+ await mkdir3(desktopDir, { recursive: true });
23491
+ await writeFile3(path23.join(desktopDir, "rudder.desktop"), buildLinuxDesktopEntry(paths.executablePath), "utf8");
23492
+ const binDir = path23.join(homedir(), ".local", "bin");
23493
+ await mkdir3(binDir, { recursive: true });
23494
+ const wrapperPath = path23.join(binDir, "rudder-desktop");
23164
23495
  const escaped = paths.executablePath.replaceAll("'", `'"'"'`);
23165
23496
  await writeFile3(wrapperPath, `#!/bin/sh
23166
23497
  exec '${escaped}' "$@"
23167
23498
  `, "utf8");
23168
- await chmod(wrapperPath, 493);
23499
+ await chmod2(wrapperPath, 493);
23169
23500
  }
23170
23501
  function buildWindowsShortcutScript(executablePath) {
23171
- const appData = process.env.APPDATA?.trim() || path24.join(homedir(), "AppData", "Roaming");
23172
- const shortcutPath = path24.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
23502
+ const appData = process.env.APPDATA?.trim() || path23.join(homedir(), "AppData", "Roaming");
23503
+ const shortcutPath = path23.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
23173
23504
  return [
23174
23505
  "$shell = New-Object -ComObject WScript.Shell",
23175
23506
  `$shortcut = $shell.CreateShortcut(${powershellQuote(shortcutPath)})`,
23176
23507
  `$shortcut.TargetPath = ${powershellQuote(executablePath)}`,
23177
- `$shortcut.WorkingDirectory = ${powershellQuote(path24.dirname(executablePath))}`,
23508
+ `$shortcut.WorkingDirectory = ${powershellQuote(path23.dirname(executablePath))}`,
23178
23509
  "$shortcut.Save()"
23179
23510
  ].join("; ");
23180
23511
  }
@@ -23206,7 +23537,7 @@ function launchDesktop(paths, target) {
23206
23537
  spawn3(paths.executablePath, [], { detached: true, stdio: "ignore" }).unref();
23207
23538
  }
23208
23539
  async function writeInstallMetadata(paths, releaseTag, assetName, assetChecksum, assetKind = "full") {
23209
- mkdirSync2(path24.dirname(paths.metadataPath), { recursive: true });
23540
+ mkdirSync2(path23.dirname(paths.metadataPath), { recursive: true });
23210
23541
  const metadata = {
23211
23542
  version: 1,
23212
23543
  releaseTag,
@@ -23253,6 +23584,7 @@ async function startCommand(opts) {
23253
23584
  const version = opts.targetVersion?.trim() || opts.version?.trim() || resolveCurrentCliVersion();
23254
23585
  const dryRun = opts.dryRun === true;
23255
23586
  const desktopProgressJson = opts.desktopProgressJson === true;
23587
+ const desktopRuntimeBestEffort = opts.desktopRuntimeBestEffort === true && installDesktop;
23256
23588
  const exactDesktopAssetPath = opts.desktopAssetPath?.trim() || null;
23257
23589
  const exactDesktopAssetChecksum = opts.desktopAssetChecksum?.trim() || null;
23258
23590
  const exactDesktopAssetName = opts.desktopAssetName?.trim() || null;
@@ -23261,7 +23593,7 @@ async function startCommand(opts) {
23261
23593
  if (!exactDesktopAssetPath || !exactDesktopAssetChecksum || !exactDesktopAssetName || !exactDesktopReleaseDigest) {
23262
23594
  throw new Error("Exact Desktop asset mode requires path, checksum, asset name, and release digest.");
23263
23595
  }
23264
- if (!path24.isAbsolute(exactDesktopAssetPath) || exactDesktopAssetName.includes("/") || !/^[a-f0-9]{64}$/iu.test(exactDesktopAssetChecksum) || !/^[a-f0-9]{64}$/iu.test(exactDesktopReleaseDigest)) {
23596
+ if (!path23.isAbsolute(exactDesktopAssetPath) || exactDesktopAssetName.includes("/") || !/^[a-f0-9]{64}$/iu.test(exactDesktopAssetChecksum) || !/^[a-f0-9]{64}$/iu.test(exactDesktopReleaseDigest)) {
23265
23597
  throw new Error("Exact Desktop asset mode received invalid candidate identity.");
23266
23598
  }
23267
23599
  if (opts.desktopAssetKind && opts.desktopAssetKind !== "full" && opts.desktopAssetKind !== "shell") {
@@ -23284,13 +23616,29 @@ async function startCommand(opts) {
23284
23616
  }
23285
23617
  if (installRuntime) {
23286
23618
  p15.log.step("Preparing Rudder runtime");
23619
+ if (desktopProgressJson && desktopRuntimeBestEffort) {
23620
+ writeDesktopProgress({
23621
+ phase: "preparing_runtime",
23622
+ message: "Preparing the lightweight Desktop update runtime; the full package will be used if this takes too long."
23623
+ });
23624
+ await waitForDesktopRuntimeSmokeEvidence("RUDDER_DESKTOP_SMOKE_RUNTIME_PREPARING_DELAY_MS");
23625
+ }
23287
23626
  if (dryRun) {
23288
23627
  p15.log.message(`[dry-run] Would install or reuse ${pc14.cyan(`@rudderhq/server@${version}`)} in the Rudder runtime cache.`);
23289
23628
  } else {
23290
23629
  const spinner3 = p15.spinner();
23291
23630
  spinner3.start("Installing or reusing Rudder runtime...");
23292
23631
  try {
23293
- const runtime = await ensureRuntimeInstalled({ version, preparePostgresPayload: true });
23632
+ const runtime = await ensureRuntimeInstalled({
23633
+ version,
23634
+ preparePostgresPayload: true,
23635
+ ...desktopRuntimeBestEffort ? {
23636
+ timeoutMs: DESKTOP_RUNTIME_PREPARE_TIMEOUT_MS,
23637
+ cleanupIncompleteOnFailure: true,
23638
+ pruneRuntimeCache: false,
23639
+ allowLatestFallback: false
23640
+ } : {}
23641
+ });
23294
23642
  runtimeSupportsShellAssets = runtimeSupportsDesktopShellAssets(version, runtime);
23295
23643
  spinner3.stop(
23296
23644
  runtime.status === "hit" ? `Rudder runtime cache hit at ${pc14.cyan(runtime.cacheDir)}.` : `Rudder runtime installed at ${pc14.cyan(runtime.cacheDir)}.`
@@ -23301,12 +23649,27 @@ async function startCommand(opts) {
23301
23649
  if (!runtimeSupportsShellAssets && installDesktop) {
23302
23650
  p15.log.warn("Rudder runtime did not resolve to the exact Desktop version; the full portable Desktop asset will be used.");
23303
23651
  }
23652
+ if (desktopProgressJson && desktopRuntimeBestEffort) {
23653
+ writeDesktopProgress({
23654
+ phase: "preparing_runtime",
23655
+ message: runtimeSupportsShellAssets ? "Lightweight Desktop update runtime is ready." : "Lightweight runtime is unavailable; continuing with the full Desktop package."
23656
+ });
23657
+ }
23304
23658
  } catch (error) {
23305
23659
  spinner3.stop(pc14.red("Rudder runtime installation failed."));
23306
23660
  if (error instanceof RuntimeInstallError && error.output) {
23307
23661
  p15.log.message(pc14.dim(error.output));
23308
23662
  }
23309
- throw error;
23663
+ if (!desktopRuntimeBestEffort) throw error;
23664
+ const detail = error instanceof Error ? error.message : String(error);
23665
+ p15.log.warn(`Lightweight Desktop update runtime preparation failed; continuing with the full portable asset. ${detail}`);
23666
+ if (desktopProgressJson) {
23667
+ writeDesktopProgress({
23668
+ phase: "preparing_runtime",
23669
+ message: "Lightweight runtime preparation did not finish; continuing with the full Desktop package."
23670
+ });
23671
+ await waitForDesktopRuntimeSmokeEvidence("RUDDER_DESKTOP_SMOKE_RUNTIME_FALLBACK_DELAY_MS");
23672
+ }
23310
23673
  }
23311
23674
  }
23312
23675
  }
@@ -23341,11 +23704,12 @@ async function startCommand(opts) {
23341
23704
  if (installDesktop) {
23342
23705
  const downloadSource = resolveDesktopDownloadSource(opts.downloadSource);
23343
23706
  const mirrorBaseUrl = resolveDesktopReleaseMirrorBaseUrl(repo);
23707
+ const smokeReleaseBaseUrls = resolveDesktopSmokeReleaseBaseUrls();
23344
23708
  const target = resolveDesktopAssetTarget();
23345
23709
  const tag = resolveDesktopReleaseTag(version);
23346
- const installRoot = opts.desktopInstallDir ? path24.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
23710
+ const installRoot = opts.desktopInstallDir ? path23.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
23347
23711
  const installPaths = resolveDesktopInstallPaths(target, installRoot);
23348
- const outputDir = opts.outputDir ? path24.resolve(opts.outputDir) : await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-installer."));
23712
+ const outputDir = opts.outputDir ? path23.resolve(opts.outputDir) : await mkdtemp2(path23.join(tmpdir(), "rudder-desktop-installer."));
23349
23713
  p15.log.step("Installing desktop app");
23350
23714
  p15.log.message(`Release: ${pc14.cyan(`${repo}@${tag}`)}`);
23351
23715
  p15.log.message(`Target: ${pc14.cyan(`${target.platform}/${target.arch}`)}`);
@@ -23385,13 +23749,13 @@ async function startCommand(opts) {
23385
23749
  if (computedReleaseDigest !== exactDesktopReleaseDigest.toLowerCase()) {
23386
23750
  throw new Error("Exact Desktop asset release digest does not match the candidate identity.");
23387
23751
  }
23388
- const descriptor = await stat6(exactDesktopAssetPath);
23752
+ const descriptor = await stat4(exactDesktopAssetPath);
23389
23753
  if (!descriptor.isFile()) throw new Error("Exact Desktop asset must be a regular file.");
23390
23754
  const linkDescriptor = await lstat(exactDesktopAssetPath);
23391
23755
  if (linkDescriptor.isSymbolicLink()) throw new Error("Exact Desktop asset must not be a symbolic link.");
23392
23756
  const checksum = await runStartPhase(
23393
23757
  "Verifying staged Desktop checksum...",
23394
- `Verified ${pc14.cyan(path24.basename(exactDesktopAssetPath))}.`,
23758
+ `Verified ${pc14.cyan(path23.basename(exactDesktopAssetPath))}.`,
23395
23759
  () => assertChecksumMatch(exactDesktopAssetPath, expectedChecksum),
23396
23760
  desktopProgressJson ? "verifying_checksum" : null
23397
23761
  );
@@ -23403,7 +23767,7 @@ async function startCommand(opts) {
23403
23767
  release = await runStartPhase(
23404
23768
  "Resolving Desktop release...",
23405
23769
  "Desktop release resolved.",
23406
- () => fetchGithubRelease(repo, tag),
23770
+ () => fetchGithubRelease(repo, tag, smokeReleaseBaseUrls.apiBaseUrl),
23407
23771
  desktopProgressJson ? "resolving_release" : null
23408
23772
  );
23409
23773
  } catch (error) {
@@ -23420,12 +23784,18 @@ async function startCommand(opts) {
23420
23784
  repo,
23421
23785
  tag,
23422
23786
  directReleaseVersion,
23423
- allowShellAssets: runtimeSupportsShellAssets
23787
+ allowShellAssets: runtimeSupportsShellAssets,
23788
+ downloadBaseUrl: smokeReleaseBaseUrls.downloadBaseUrl
23424
23789
  });
23425
23790
  if (assetCandidates.length === 0) {
23426
23791
  throw new Error(`No Rudder Desktop portable asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
23427
23792
  }
23428
- const checksumAsset = selectChecksumAsset(release?.assets ?? []) ?? (directReleaseVersion ? buildGithubReleaseAsset(repo, tag, DESKTOP_CHECKSUM_ASSET_NAME) : null);
23793
+ const checksumAsset = selectChecksumAsset(release?.assets ?? []) ?? (directReleaseVersion ? buildGithubReleaseAsset(
23794
+ repo,
23795
+ tag,
23796
+ DESKTOP_CHECKSUM_ASSET_NAME,
23797
+ smokeReleaseBaseUrls.downloadBaseUrl
23798
+ ) : null);
23429
23799
  if (!checksumAsset) {
23430
23800
  throw new Error("Desktop release is missing SHASUMS256.txt.");
23431
23801
  }
@@ -23504,7 +23874,7 @@ async function startCommand(opts) {
23504
23874
  }
23505
23875
  const checksum = await runStartPhase(
23506
23876
  "Verifying Desktop checksum...",
23507
- `Verified ${pc14.cyan(path24.basename(verifiedAsset.path))}.`,
23877
+ `Verified ${pc14.cyan(path23.basename(verifiedAsset.path))}.`,
23508
23878
  () => assertChecksumMatch(verifiedAsset.path, expectedChecksum),
23509
23879
  desktopProgressJson ? "verifying_checksum" : null
23510
23880
  );
@@ -23515,7 +23885,8 @@ async function startCommand(opts) {
23515
23885
  percent: 100,
23516
23886
  assetName: selectedAsset.name,
23517
23887
  assetChecksum: checksum,
23518
- stagedArtifactPath: path24.resolve(verifiedAsset.path),
23888
+ assetKind: selectedAssetKind,
23889
+ stagedArtifactPath: path23.resolve(verifiedAsset.path),
23519
23890
  stagedArtifactDigest: checksum,
23520
23891
  releaseDigest: createHash4("sha256").update(JSON.stringify({
23521
23892
  releaseTag,
@@ -23608,11 +23979,11 @@ async function startCommand(opts) {
23608
23979
 
23609
23980
  // src/config/data-dir.ts
23610
23981
  init_home();
23611
- import path25 from "node:path";
23982
+ import path24 from "node:path";
23612
23983
  function applyDataDirOverride(options, support = {}) {
23613
23984
  const rawDataDir = options.dataDir?.trim();
23614
23985
  if (!rawDataDir) return null;
23615
- const resolvedDataDir = path25.resolve(expandHomePrefix(rawDataDir));
23986
+ const resolvedDataDir = path24.resolve(expandHomePrefix(rawDataDir));
23616
23987
  process.env.RUDDER_HOME = resolvedDataDir;
23617
23988
  if (support.hasConfigOption) {
23618
23989
  const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
@@ -23672,7 +24043,7 @@ function createProgram() {
23672
24043
  });
23673
24044
  loadRudderEnvFile(options.config);
23674
24045
  });
23675
- program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--server-only", "Prepare the Rudder server runtime and persistent CLI without installing Desktop").option("--no-cli", "Skip persistent CLI installation").option("--no-runtime", "Skip Rudder runtime installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--target-version <version>", "Rudder version to start; avoids the root CLI version flag").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--download-source <source>", "Desktop download source: auto, cn, or global").option("--output-dir <path>", "Directory for downloaded desktop release assets").option("--desktop-install-dir <path>", "Directory for the portable Desktop install").option("--no-open", "Install Desktop without launching it").option("--wait-for-active-runs", "Wait for active Rudder runs to finish before replacing Desktop", false).option("--desktop-progress-json", "Emit newline-delimited Desktop update progress events").option("--desktop-wait-for-apply", "Wait for an apply signal after downloading and verifying the Desktop update", false).option("--desktop-prepare-only", "Download and verify the Desktop update without installing or launching it", false).option("--desktop-asset-path <path>", "Use one previously staged, exact Desktop asset path").option("--desktop-asset-checksum <sha256>", "SHA-256 for the exact staged Desktop asset").option("--desktop-asset-name <name>", "Asset name bound to the exact staged Desktop candidate").option("--desktop-asset-kind <kind>", "Asset kind bound to the exact staged Desktop candidate (full or shell)").option("--desktop-release-digest <sha256>", "Release digest bound to the exact staged Desktop candidate").option("--no-version-check", "Skip checking npm for a newer Rudder CLI version").option("--dry-run", "Print the start actions without changing the machine", false).action(startCommand);
24046
+ program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--server-only", "Prepare the Rudder server runtime and persistent CLI without installing Desktop").option("--no-cli", "Skip persistent CLI installation").option("--no-runtime", "Skip Rudder runtime installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--target-version <version>", "Rudder version to start; avoids the root CLI version flag").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--download-source <source>", "Desktop download source: auto, cn, or global").option("--output-dir <path>", "Directory for downloaded desktop release assets").option("--desktop-install-dir <path>", "Directory for the portable Desktop install").option("--no-open", "Install Desktop without launching it").option("--wait-for-active-runs", "Wait for active Rudder runs to finish before replacing Desktop", false).option("--desktop-progress-json", "Emit newline-delimited Desktop update progress events").option("--desktop-wait-for-apply", "Wait for an apply signal after downloading and verifying the Desktop update", false).option("--desktop-prepare-only", "Download and verify the Desktop update without installing or launching it", false).option("--desktop-asset-path <path>", "Use one previously staged, exact Desktop asset path").option("--desktop-asset-checksum <sha256>", "SHA-256 for the exact staged Desktop asset").option("--desktop-asset-name <name>", "Asset name bound to the exact staged Desktop candidate").option("--desktop-asset-kind <kind>", "Asset kind bound to the exact staged Desktop candidate (full or shell)").option("--desktop-release-digest <sha256>", "Release digest bound to the exact staged Desktop candidate").addOption(new Option("--desktop-runtime-best-effort").hideHelp()).option("--no-version-check", "Skip checking npm for a newer Rudder CLI version").option("--dry-run", "Print the start actions without changing the machine", false).action(startCommand);
23676
24047
  program.command("onboard").description("Interactive first-run setup wizard").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("-y, --yes", "Accept defaults (quickstart + start immediately)", false).option("--run", "Start Rudder immediately after saving config", false).action(onboard);
23677
24048
  program.command("doctor").description("Run diagnostic checks on your Rudder setup").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--repair", "Attempt to repair issues automatically").alias("--fix").option("-y, --yes", "Skip repair confirmation prompts").action(async (opts) => {
23678
24049
  await doctor(opts);