@pipelab/core-node 1.0.0-beta.0 → 1.0.0-beta.10

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.mjs CHANGED
@@ -2,13 +2,13 @@ import { createRequire } from "node:module";
2
2
  import path, { delimiter, dirname, isAbsolute, join, resolve } from "node:path";
3
3
  import { homedir, platform, tmpdir } from "node:os";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
- import fs, { createWriteStream, existsSync } from "node:fs";
5
+ import fs, { createWriteStream, existsSync, readdirSync, statSync } from "node:fs";
6
6
  import { WebSocket, WebSocketServer as WebSocketServer$1 } from "ws";
7
7
  import http from "node:http";
8
8
  import { nanoid } from "nanoid";
9
9
  import { SubscriptionRequiredError, WebSocketError, appSettingsMigrator, configRegistry, fileRepoMigrations, isRequired, isSupabaseAvailable, isWebSocketRequestMessage, processGraph, savedFileMigrator, supabase, useLogger, usePlugins } from "@pipelab/shared";
10
10
  import { getUiDevServerMissingWarning, uiDevPort, websocketPort } from "@pipelab/constants";
11
- import fs$1, { access, chmod, cp, mkdir, mkdtemp, readFile, readdir, realpath, rm, stat, unlink, writeFile } from "node:fs/promises";
11
+ import fs$1, { access, chmod, cp, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
12
12
  import { execa } from "execa";
13
13
  import tar from "tar";
14
14
  import yauzl from "yauzl";
@@ -55,14 +55,16 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
55
55
  //#region src/context.ts
56
56
  const _dirname = typeof __dirname !== "undefined" ? __dirname : typeof import.meta !== "undefined" && import.meta.url ? dirname(fileURLToPath(import.meta.url)) : process.cwd();
57
57
  const isDev = process.env.NODE_ENV === "development";
58
- const getDefaultUserDataPath = () => {
59
- return join((() => {
58
+ const getDefaultUserDataPath = (env) => {
59
+ const base = (() => {
60
60
  switch (platform()) {
61
61
  case "win32": return process.env.APPDATA || join(homedir(), "AppData", "Roaming");
62
62
  case "darwin": return join(homedir(), "Library", "Application Support");
63
63
  default: return process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
64
64
  }
65
- })(), "@pipelab", isDev ? "app-dev" : "app");
65
+ })();
66
+ const mode = env ?? (isDev ? "dev" : "prod");
67
+ return join(base, "@pipelab", mode === "dev" ? "app-dev" : mode === "beta" ? "app-beta" : "app");
66
68
  };
67
69
  /**
68
70
  * Finds the monorepo root by looking for pnpm-workspace.yaml.
@@ -78,8 +80,10 @@ function findProjectRoot(startDir) {
78
80
  const projectRoot = findProjectRoot(_dirname);
79
81
  var PipelabContext = class {
80
82
  userDataPath;
83
+ releaseTag;
81
84
  constructor(options) {
82
85
  this.userDataPath = options.userDataPath;
86
+ this.releaseTag = options.releaseTag || "latest";
83
87
  }
84
88
  getPackagesPath(...subpaths) {
85
89
  return join(this.userDataPath, "packages", ...subpaths);
@@ -628,25 +632,24 @@ const setupConfigFile = async (name, options) => {
628
632
  }
629
633
  let json = void 0;
630
634
  try {
631
- json = await migrator.migrate(originalJson, { debug: false });
635
+ json = await migrator.migrate(originalJson, {
636
+ debug: false,
637
+ onStep: async (state, version) => {
638
+ const parsedPath = path.parse(filesPath);
639
+ const versionedPath = path.join(parsedPath.dir, `${parsedPath.name}.v${version}.json`);
640
+ try {
641
+ await fs$1.writeFile(versionedPath, JSON.stringify(state));
642
+ logger().info(`Intermediate backup created for ${name} at ${versionedPath}`);
643
+ } catch (e) {
644
+ logger().error(`Failed to create intermediate backup for ${name} at v${version}:`, e);
645
+ }
646
+ }
647
+ });
632
648
  } catch (e) {
633
649
  logger().error(`Error migrating config ${name}:`, e);
634
650
  json = migrator.defaultValue;
635
651
  }
636
- const originalVersion = originalJson?.version;
637
- const newVersion = json?.version;
638
- if (originalVersion !== newVersion && content !== void 0) {
639
- const parsedPath = path.parse(filesPath);
640
- const versionSuffix = originalVersion || "unknown";
641
- const backupPath = path.join(parsedPath.dir, `${parsedPath.name}.${versionSuffix}.bak`);
642
- try {
643
- await fs$1.copyFile(filesPath, backupPath);
644
- logger().info(`Backup created for ${name} at ${backupPath} (version ${versionSuffix})`);
645
- } catch (e) {
646
- logger().error(`Failed to create backup for ${name}:`, e);
647
- }
648
- }
649
- if (originalVersion !== newVersion || content === void 0) try {
652
+ if (originalJson?.version !== json?.version || content === void 0) try {
650
653
  await fs$1.writeFile(filesPath, JSON.stringify(json));
651
654
  } catch (e) {
652
655
  logger().error(`Error saving migrated config ${name}:`, e);
@@ -8832,9 +8835,13 @@ const sendStartupReady = () => {
8832
8835
  };
8833
8836
  async function serveCommand(options, version, _dirname) {
8834
8837
  if (!options.userData) throw new Error("userDataPath is required for serveCommand");
8835
- const context = new PipelabContext({ userDataPath: options.userData });
8838
+ const releaseTag = version.includes("beta") ? "beta" : "latest";
8839
+ const context = new PipelabContext({
8840
+ userDataPath: options.userData,
8841
+ releaseTag
8842
+ });
8836
8843
  let rawAssetFolder;
8837
- if (!isDev) rawAssetFolder = await fetchPipelabAsset("@pipelab/ui", "latest", { context });
8844
+ if (!isDev) rawAssetFolder = await fetchPipelabAsset("@pipelab/ui", releaseTag, { context });
8838
8845
  const server = http$1.createServer(async (request, response) => {
8839
8846
  if (isDev) {
8840
8847
  response.writeHead(200, { "Content-Type": "text/html" });
@@ -8874,6 +8881,25 @@ async function serveCommand(options, version, _dirname) {
8874
8881
  //#region src/utils/remote.ts
8875
8882
  const DEFAULT_NODE_VERSION = "24.14.1";
8876
8883
  const DEFAULT_PNPM_VERSION = "10.12.0";
8884
+ function isPackageComplete(packageDir) {
8885
+ return existsSync(join(packageDir, "package.json"));
8886
+ }
8887
+ function isNodeJSComplete(nodePath) {
8888
+ try {
8889
+ return existsSync(nodePath) && statSync(nodePath).size > 0;
8890
+ } catch {
8891
+ return false;
8892
+ }
8893
+ }
8894
+ function isDependenciesInstalledSync(packageDir) {
8895
+ const nodeModulesPath = join(packageDir, "node_modules");
8896
+ if (!existsSync(nodeModulesPath)) return false;
8897
+ try {
8898
+ return readdirSync(nodeModulesPath).length > 0;
8899
+ } catch {
8900
+ return false;
8901
+ }
8902
+ }
8877
8903
  /**
8878
8904
  * In-memory lock to prevent concurrent operations on the same resource (e.g., downloading Node.js).
8879
8905
  */
@@ -8938,15 +8964,35 @@ async function fetchPackage(packageName, versionOrRange, options) {
8938
8964
  }
8939
8965
  const cachePath = join(ctx.userDataPath, "cache", "pacote");
8940
8966
  const packageDir = join(baseDir, resolvedVersion);
8941
- if (existsSync(packageDir) && !options?.installDeps) return {
8967
+ if (options?.installDeps ? isPackageComplete(packageDir) && isDependenciesInstalledSync(packageDir) : isPackageComplete(packageDir)) return {
8942
8968
  packageDir,
8943
8969
  resolvedVersion
8944
8970
  };
8945
8971
  return withLock(`package:${packageName}:${resolvedVersion}`, async () => {
8946
- if (!existsSync(packageDir)) {
8972
+ if (!isPackageComplete(packageDir)) {
8947
8973
  console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Downloading to ${packageDir}...`);
8948
- await mkdir(packageDir, { recursive: true });
8949
- await pacote.extract(`${packageName}@${resolvedVersion}`, packageDir, { cache: cachePath });
8974
+ const tempDir = join(baseDir, `.tmp-${resolvedVersion}-${Math.random().toString(36).slice(2)}`);
8975
+ await mkdir(tempDir, { recursive: true });
8976
+ try {
8977
+ await pacote.extract(`${packageName}@${resolvedVersion}`, tempDir, { cache: cachePath });
8978
+ await resolveEntryPoint(tempDir, packageName);
8979
+ if (existsSync(packageDir)) await rm(packageDir, {
8980
+ recursive: true,
8981
+ force: true
8982
+ }).catch(() => {});
8983
+ try {
8984
+ await rename(tempDir, packageDir);
8985
+ } catch (err) {
8986
+ if (isPackageComplete(packageDir)) console.log(`[Fetcher] Destination ${packageDir} already exists and is valid.`);
8987
+ else throw err;
8988
+ }
8989
+ } catch (err) {
8990
+ await rm(tempDir, {
8991
+ recursive: true,
8992
+ force: true
8993
+ }).catch(() => {});
8994
+ throw err;
8995
+ }
8950
8996
  }
8951
8997
  const entryPoint = await resolveEntryPoint(packageDir, packageName);
8952
8998
  if (options?.installDeps) await installDependencies(packageDir, packageName, options);
@@ -8991,9 +9037,9 @@ async function ensureNodeJS(context, version = DEFAULT_NODE_VERSION) {
8991
9037
  const isWindows = process.platform === "win32";
8992
9038
  const nodeDir = context.getThirdPartyPath("node", version);
8993
9039
  const finalNodePath = join(nodeDir, isWindows ? "node.exe" : "bin/node");
8994
- if (existsSync(finalNodePath)) return finalNodePath;
9040
+ if (isNodeJSComplete(finalNodePath)) return finalNodePath;
8995
9041
  return withLock(`node:${version}`, async () => {
8996
- if (existsSync(finalNodePath)) return finalNodePath;
9042
+ if (isNodeJSComplete(finalNodePath)) return finalNodePath;
8997
9043
  const arch = process.arch === "x64" ? "x64" : process.arch === "arm64" ? "arm64" : "x86";
8998
9044
  const platform = isWindows ? "win" : process.platform === "darwin" ? "osx" : "linux";
8999
9045
  const extension = isWindows ? "zip" : "tar.gz";
@@ -9013,17 +9059,33 @@ async function ensureNodeJS(context, version = DEFAULT_NODE_VERSION) {
9013
9059
  const nodeSubDir = (await readdir(extractTempDir)).find((entry) => entry.startsWith(`node-v${version}`));
9014
9060
  if (!nodeSubDir) throw new Error(`Could not find extracted Node.js directory`);
9015
9061
  const sourceDir = join(extractTempDir, nodeSubDir);
9016
- await mkdir(dirname(nodeDir), { recursive: true });
9017
- await rm(nodeDir, {
9018
- recursive: true,
9019
- force: true
9020
- });
9021
- await cp(sourceDir, nodeDir, { recursive: true });
9022
- await rm(tempDir, {
9023
- recursive: true,
9024
- force: true
9025
- });
9026
- if (!isWindows) await chmod(finalNodePath, 493).catch(() => {});
9062
+ const parentDir = dirname(nodeDir);
9063
+ await mkdir(parentDir, { recursive: true });
9064
+ const tempNodeDir = join(parentDir, `.tmp-node-${version}-${Math.random().toString(36).slice(2)}`);
9065
+ await mkdir(tempNodeDir, { recursive: true });
9066
+ try {
9067
+ await cp(sourceDir, tempNodeDir, { recursive: true });
9068
+ if (!isWindows) await chmod(join(tempNodeDir, "bin/node"), 493).catch(() => {});
9069
+ if (existsSync(nodeDir)) await rm(nodeDir, {
9070
+ recursive: true,
9071
+ force: true
9072
+ }).catch(() => {});
9073
+ try {
9074
+ await rename(tempNodeDir, nodeDir);
9075
+ } catch (err) {
9076
+ if (isNodeJSComplete(finalNodePath)) console.log(`[Fetcher] Node.js directory already exists and is valid.`);
9077
+ else throw err;
9078
+ }
9079
+ } finally {
9080
+ await rm(tempNodeDir, {
9081
+ recursive: true,
9082
+ force: true
9083
+ }).catch(() => {});
9084
+ await rm(tempDir, {
9085
+ recursive: true,
9086
+ force: true
9087
+ }).catch(() => {});
9088
+ }
9027
9089
  return finalNodePath;
9028
9090
  });
9029
9091
  }
@@ -9042,21 +9104,36 @@ async function ensurePNPM(context, version = DEFAULT_PNPM_VERSION) {
9042
9104
  }
9043
9105
  async function installDependencies(packageDir, packageName, options) {
9044
9106
  const nodeModulesPath = join(packageDir, "node_modules");
9045
- if (existsSync(nodeModulesPath)) try {
9046
- if ((await readdir(nodeModulesPath)).length === 0) console.warn(`[Fetcher] ${packageName}: node_modules exists but is empty. Re-installing...`);
9047
- } catch (e) {}
9048
- console.log(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
9107
+ if (isDependenciesInstalledSync(packageDir)) {
9108
+ console.log(`[Fetcher] ${packageName}: Dependencies already installed, skipping.`);
9109
+ return;
9110
+ }
9111
+ const tempDir = `${packageDir}.tmp-deps-${Math.random().toString(36).slice(2)}`;
9112
+ await mkdir(tempDir, { recursive: true });
9049
9113
  try {
9050
- const { all } = await runPnpm(packageDir, {
9114
+ await cp(join(packageDir, "package.json"), join(tempDir, "package.json"));
9115
+ console.log(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
9116
+ const { all } = await runPnpm(tempDir, {
9051
9117
  signal: options.signal,
9052
9118
  context: options.context
9053
9119
  });
9054
9120
  if (all) console.log(`[Fetcher] ${packageName}: Installation trace:\n${all}`);
9121
+ const tempNodeModules = join(tempDir, "node_modules");
9122
+ if (existsSync(nodeModulesPath)) await rm(nodeModulesPath, {
9123
+ recursive: true,
9124
+ force: true
9125
+ }).catch(() => {});
9126
+ await rename(tempNodeModules, nodeModulesPath);
9055
9127
  console.log(`[Fetcher] ${packageName}: Dependencies installed successfully.`);
9056
9128
  } catch (err) {
9057
9129
  console.error(`[Fetcher] ${packageName}: CRITICAL ERROR during dependency installation: ${err.message}`);
9058
9130
  if (err.all) console.error(`[Fetcher] ${packageName}: Error details:\n${err.all}`);
9059
9131
  throw new Error(`Failed to install dependencies for ${packageName}. See logs for details.`);
9132
+ } finally {
9133
+ await rm(tempDir, {
9134
+ recursive: true,
9135
+ force: true
9136
+ }).catch(() => {});
9060
9137
  }
9061
9138
  }
9062
9139
  async function fetchPipelabAsset(packageName, versionOrRange, options) {
@@ -9069,7 +9146,7 @@ async function fetchPipelabAsset(packageName, versionOrRange, options) {
9069
9146
  }
9070
9147
  async function fetchPipelabPlugin(pluginName, versionOrRange, options) {
9071
9148
  const { packageDir, isLocal, entryPoint } = await fetchPackage(pluginName, versionOrRange, {
9072
- installDeps: true,
9149
+ installDeps: false,
9073
9150
  ...options
9074
9151
  });
9075
9152
  let finalEntryPoint = entryPoint;
@@ -9343,9 +9420,9 @@ const DEFAULT_PLUGIN_IDS = [
9343
9420
  ];
9344
9421
  const loadPipelabPlugin = async (id, options) => {
9345
9422
  try {
9346
- const { packageDir, entryPoint } = await fetchPipelabPlugin(`@pipelab/plugin-${id}`, "latest", {
9423
+ const { packageDir, entryPoint } = await fetchPipelabPlugin(`@pipelab/plugin-${id}`, options.context.releaseTag, {
9347
9424
  context: options.context,
9348
- installDeps: true
9425
+ installDeps: false
9349
9426
  });
9350
9427
  console.log(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
9351
9428
  if (!existsSync(entryPoint)) {
@@ -9365,15 +9442,28 @@ const loadPipelabPlugin = async (id, options) => {
9365
9442
  }
9366
9443
  };
9367
9444
  const builtInPlugins = async (options) => {
9368
- console.log("[Plugins] Finalizing default plugins list...");
9445
+ console.log("[Plugins] Starting background plugin loading...");
9369
9446
  sendStartupProgress("Preparing environment...");
9370
9447
  await Promise.all([ensureNodeJS(options.context), ensurePNPM(options.context)]);
9371
- const filtered = (await Promise.allSettled(DEFAULT_PLUGIN_IDS.map(async (id) => {
9372
- sendStartupProgress(`Loading plugin: ${id}`);
9373
- return loadPipelabPlugin(id, options);
9374
- }))).filter((r) => r.status === "fulfilled").map((r) => r.value).filter(Boolean).flat();
9375
- console.log(`[Plugins] Successfully loaded ${filtered.length} default plugins`);
9376
- return filtered;
9448
+ const { usePlugins } = await import("@pipelab/shared");
9449
+ const { registerPlugins } = usePlugins();
9450
+ const { webSocketServer } = await import("./index.mjs");
9451
+ (async () => {
9452
+ for (const id of DEFAULT_PLUGIN_IDS) {
9453
+ sendStartupProgress(`Loading plugin: ${id}`);
9454
+ const plugin = await loadPipelabPlugin(id, options);
9455
+ if (plugin) {
9456
+ registerPlugins([plugin]);
9457
+ webSocketServer.broadcast("plugin:loaded", { plugin });
9458
+ }
9459
+ }
9460
+ console.log("[Plugins] All default plugins loaded.");
9461
+ sendStartupProgress("All plugins loaded.");
9462
+ setTimeout(() => {
9463
+ webSocketServer.broadcast("startup:progress", { type: "ready" });
9464
+ }, 2e3);
9465
+ })();
9466
+ return [];
9377
9467
  };
9378
9468
  //#endregion
9379
9469
  //#region src/utils.ts
@@ -10268,7 +10358,7 @@ const registerAllHandlers = async (options) => {
10268
10358
  registerAuthHandlers(context);
10269
10359
  registerSystemHandlers(options);
10270
10360
  const { registerPlugins } = usePlugins();
10271
- registerPlugins(await builtInPlugins({ context }));
10361
+ builtInPlugins({ context });
10272
10362
  };
10273
10363
  //#endregion
10274
10364
  //#region ../../node_modules/klona/dist/index.mjs
@@ -52607,6 +52697,64 @@ async function runPipelineCommand(file, options, version) {
52607
52697
  }
52608
52698
  }
52609
52699
  //#endregion
52610
- export { BuildHistoryStorage, DEFAULT_NODE_VERSION, DEFAULT_PNPM_VERSION, PipelabContext, WebSocketServer, builtInPlugins, downloadFile, ensure, ensureNodeJS, ensurePNPM, executeGraphWithHistory, extractTarGz, extractZip, fetchPackage, fetchPipelabAsset, fetchPipelabCli, fetchPipelabPlugin, generateTempFolder, getDefaultUserDataPath, getFinalPlugins, getFolderSize, getMigrator, handleActionExecute, handleConditionExecute, isDev, loadPipelabPlugin, projectRoot, registerAgentsHandlers, registerAllHandlers, registerConfigHandlers, registerEngineHandlers, registerFsHandlers, registerHistoryHandlers, registerMigrationHandlers, registerShellHandlers, runPipelineCommand, runPnpm, runWithLiveLogs, sendStartupProgress, sendStartupReady, serveCommand, setupConfigFile, useAPI, usePluginAPI, webSocketServer, zipFolder };
52700
+ //#region src/utils/github.ts
52701
+ /**
52702
+ * Fetches all releases for a specific package from GitHub.
52703
+ * Tags are expected to follow the pattern "{packageName}@{version}"
52704
+ */
52705
+ async function fetchPackageReleases(packageName, options = {}) {
52706
+ const { repo = "CynToolkit/pipelab", allowPrerelease = false } = options;
52707
+ const url = `https://api.github.com/repos/${repo}/releases`;
52708
+ console.log(`[GitHub] Fetching releases for ${packageName} from ${url}...`);
52709
+ try {
52710
+ const response = await fetch(url, { headers: {
52711
+ "User-Agent": "Pipelab-Desktop-Updater",
52712
+ Accept: "application/vnd.github.v3+json"
52713
+ } });
52714
+ if (!response.ok) throw new Error(`GitHub API error: ${response.status} ${response.statusText}`);
52715
+ return (await response.json()).filter((r) => r.tag_name.startsWith(`${packageName}@`)).filter((r) => allowPrerelease || !r.prerelease);
52716
+ } catch (error) {
52717
+ console.error(`[GitHub] Failed to fetch releases for ${packageName}:`, error);
52718
+ return [];
52719
+ }
52720
+ }
52721
+ /**
52722
+ * Fetches the latest release for a specific package.
52723
+ * Supports PIPELAB_OVERRIDE_RELEASE environment variable.
52724
+ */
52725
+ async function fetchLatestPackageRelease(packageName, options = {}) {
52726
+ const releases = await fetchPackageReleases(packageName, options);
52727
+ if (releases.length === 0) return null;
52728
+ const override = process.env.PIPELAB_OVERRIDE_RELEASE;
52729
+ if (override) {
52730
+ const targetTag = override.includes("@") ? override : `${packageName}@${override}`;
52731
+ const release = releases.find((r) => r.tag_name === targetTag);
52732
+ if (release) {
52733
+ console.log(`[GitHub] Using release override from PIPELAB_OVERRIDE_RELEASE: ${release.tag_name}`);
52734
+ return release;
52735
+ }
52736
+ console.warn(`[GitHub] Override release ${override} not found for package ${packageName}`);
52737
+ }
52738
+ const getVersion = (tagName) => tagName.split("@").pop() || "0.0.0";
52739
+ releases.sort((a, b) => {
52740
+ const vA = getVersion(a.tag_name);
52741
+ const vB = getVersion(b.tag_name);
52742
+ if (semver.valid(vA) && semver.valid(vB)) return semver.rcompare(vA, vB);
52743
+ return new Date(b.published_at).getTime() - new Date(a.published_at).getTime();
52744
+ });
52745
+ return releases[0];
52746
+ }
52747
+ /**
52748
+ * Fetches all releases from GitHub and finds the latest one that matches the Pipelab Desktop app tag.
52749
+ * This ensures we don't accidentally pick a package release (e.g. @pipelab/shared) as the "latest".
52750
+ */
52751
+ async function fetchLatestDesktopRelease(options = {}) {
52752
+ const latest = await fetchLatestPackageRelease("@pipelab/app", options);
52753
+ if (latest) console.log(`[GitHub] Found latest desktop release: ${latest.tag_name} (${latest.prerelease ? "pre-release" : "stable"})`);
52754
+ else console.warn(`[GitHub] No desktop releases found`);
52755
+ return latest;
52756
+ }
52757
+ //#endregion
52758
+ export { BuildHistoryStorage, DEFAULT_NODE_VERSION, DEFAULT_PNPM_VERSION, PipelabContext, WebSocketServer, builtInPlugins, downloadFile, ensure, ensureNodeJS, ensurePNPM, executeGraphWithHistory, extractTarGz, extractZip, fetchLatestDesktopRelease, fetchLatestPackageRelease, fetchPackage, fetchPackageReleases, fetchPipelabAsset, fetchPipelabCli, fetchPipelabPlugin, generateTempFolder, getDefaultUserDataPath, getFinalPlugins, getFolderSize, getMigrator, handleActionExecute, handleConditionExecute, isDev, loadPipelabPlugin, projectRoot, registerAgentsHandlers, registerAllHandlers, registerConfigHandlers, registerEngineHandlers, registerFsHandlers, registerHistoryHandlers, registerMigrationHandlers, registerShellHandlers, runPipelineCommand, runPnpm, runWithLiveLogs, sendStartupProgress, sendStartupReady, serveCommand, setupConfigFile, useAPI, usePluginAPI, webSocketServer, zipFolder };
52611
52759
 
52612
52760
  //# sourceMappingURL=index.mjs.map