agent-web-os 0.1.3 → 0.1.5

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.d.cts CHANGED
@@ -130,14 +130,6 @@ declare class AlmostNodeSession {
130
130
  * package directory directly.
131
131
  */
132
132
  private resolveBarePkgEntryCache;
133
- /**
134
- * Packages whose imports are handled by the browser import map.
135
- * These are NOT rewritten to /node_modules/... paths.
136
- * Now empty: react/react-dom are served from node_modules via our
137
- * CJS→ESM shim, which supports the actual installed version rather
138
- * than the outdated esm.sh CDN pinned in almostnode's import map.
139
- */
140
- private importMapPackages;
141
133
  private parseCachedPackageJson;
142
134
  private transformTextWithCache;
143
135
  private resolveBarePkgEntry;
@@ -168,7 +160,10 @@ declare class AlmostNodeSession {
168
160
  rewriteBareImports(code: string, root: string, virtualPrefix?: string): string;
169
161
  private serveExistingVirtualStaticFile;
170
162
  private stopViteServer;
163
+ private resolveBinFromPackageJson;
171
164
  private resolveNpmBinPath;
165
+ private resolveGlobalBinPath;
166
+ private registerGlobalBinCommands;
172
167
  private resolveAndRegisterBinCommands;
173
168
  private trackOperation;
174
169
  private flushPendingOperations;
package/dist/index.d.ts CHANGED
@@ -130,14 +130,6 @@ declare class AlmostNodeSession {
130
130
  * package directory directly.
131
131
  */
132
132
  private resolveBarePkgEntryCache;
133
- /**
134
- * Packages whose imports are handled by the browser import map.
135
- * These are NOT rewritten to /node_modules/... paths.
136
- * Now empty: react/react-dom are served from node_modules via our
137
- * CJS→ESM shim, which supports the actual installed version rather
138
- * than the outdated esm.sh CDN pinned in almostnode's import map.
139
- */
140
- private importMapPackages;
141
133
  private parseCachedPackageJson;
142
134
  private transformTextWithCache;
143
135
  private resolveBarePkgEntry;
@@ -168,7 +160,10 @@ declare class AlmostNodeSession {
168
160
  rewriteBareImports(code: string, root: string, virtualPrefix?: string): string;
169
161
  private serveExistingVirtualStaticFile;
170
162
  private stopViteServer;
163
+ private resolveBinFromPackageJson;
171
164
  private resolveNpmBinPath;
165
+ private resolveGlobalBinPath;
166
+ private registerGlobalBinCommands;
172
167
  private resolveAndRegisterBinCommands;
173
168
  private trackOperation;
174
169
  private flushPendingOperations;
package/dist/index.js CHANGED
@@ -36543,19 +36543,6 @@ function assertObservableInMemoryFs(value) {
36543
36543
  }
36544
36544
  return value;
36545
36545
  }
36546
- function formatChangeEventForLog(event) {
36547
- const previousPathSuffix = event.previousPath ? ` (from ${event.previousPath})` : "";
36548
- return `[ObservableInMemoryFs] ${event.event} ${event.entryType} ${event.path}${previousPathSuffix}`;
36549
- }
36550
- function normalizeEntryType(stat) {
36551
- if (stat.isDirectory) {
36552
- return "directory";
36553
- }
36554
- if (stat.isSymbolicLink) {
36555
- return "symlink";
36556
- }
36557
- return "file";
36558
- }
36559
36546
  async function readPathState(fs, path2) {
36560
36547
  const exists = await fs.exists(path2);
36561
36548
  if (!exists) {
@@ -36568,35 +36555,19 @@ async function readPathState(fs, path2) {
36568
36555
  };
36569
36556
  }
36570
36557
  const stat = await fs.lstat(path2);
36558
+ const entryType = stat.isDirectory ? "directory" : stat.isSymbolicLink ? "symlink" : "file";
36571
36559
  return {
36572
36560
  exists: true,
36573
- entryType: normalizeEntryType(stat)
36561
+ entryType
36574
36562
  };
36575
36563
  }
36576
36564
  function mapAddEvent(entryType) {
36577
36565
  return entryType === "directory" ? "addDir" : "add";
36578
36566
  }
36579
- function mapUnlinkEvent(entryType) {
36580
- return entryType === "directory" ? "unlinkDir" : "unlink";
36581
- }
36582
36567
  function normalizeFsPathForLogScope(fsPath) {
36583
36568
  const normalized = posixPath.normalize(fsPath);
36584
36569
  return normalized === "." ? "/" : normalized;
36585
36570
  }
36586
- function createWorkspacePathFilter(workspaceRoot) {
36587
- const normalizedWorkspaceRoot = normalizeFsPathForLogScope(workspaceRoot);
36588
- return (fsPath) => {
36589
- const normalizedPath = normalizeFsPathForLogScope(fsPath);
36590
- if (normalizedPath !== normalizedWorkspaceRoot && !normalizedPath.startsWith(`${normalizedWorkspaceRoot}/`)) {
36591
- return false;
36592
- }
36593
- const relativePath = posixPath.relative(normalizedWorkspaceRoot, normalizedPath);
36594
- if (!relativePath || relativePath === ".") {
36595
- return true;
36596
- }
36597
- return relativePath.split("/").every((segment) => segment.length > 0 && !segment.startsWith("."));
36598
- };
36599
- }
36600
36571
  var ObservableInMemoryFs = class extends Ir {
36601
36572
  listeners;
36602
36573
  lazyPaths = /* @__PURE__ */ new Set();
@@ -36608,7 +36579,18 @@ var ObservableInMemoryFs = class extends Ir {
36608
36579
  constructor(options2) {
36609
36580
  super();
36610
36581
  this.consoleLogChanges = options2?.consoleLogChanges ?? false;
36611
- this.isLoggableWorkspacePath = createWorkspacePathFilter(options2?.workspaceRoot ?? "/");
36582
+ const normalizedWorkspaceRoot = normalizeFsPathForLogScope(options2?.workspaceRoot ?? "/");
36583
+ this.isLoggableWorkspacePath = (fsPath) => {
36584
+ const normalizedPath = normalizeFsPathForLogScope(fsPath);
36585
+ if (normalizedPath !== normalizedWorkspaceRoot && !normalizedPath.startsWith(`${normalizedWorkspaceRoot}/`)) {
36586
+ return false;
36587
+ }
36588
+ const relativePath = posixPath.relative(normalizedWorkspaceRoot, normalizedPath);
36589
+ if (!relativePath || relativePath === ".") {
36590
+ return true;
36591
+ }
36592
+ return relativePath.split("/").every((segment) => segment.length > 0 && !segment.startsWith("."));
36593
+ };
36612
36594
  }
36613
36595
  isPathLazy(filePath) {
36614
36596
  return this.lazyPaths.has(normalizeFsPathForLogScope(filePath));
@@ -36680,7 +36662,7 @@ var ObservableInMemoryFs = class extends Ir {
36680
36662
  emit(event, options2) {
36681
36663
  const shouldConsoleLog = options2?.shouldConsoleLog ?? this.shouldConsoleLogChangeEvent(event);
36682
36664
  if (this.consoleLogChanges && shouldConsoleLog && !this.areConsoleLogsSuppressed()) {
36683
- console.log(formatChangeEventForLog(event));
36665
+ console.log(`[ObservableInMemoryFs] ${event.event} ${event.entryType} ${event.path}${event.previousPath ? ` (from ${event.previousPath})` : ""}`);
36684
36666
  }
36685
36667
  if (!this.listeners) {
36686
36668
  return;
@@ -36757,7 +36739,7 @@ var ObservableInMemoryFs = class extends Ir {
36757
36739
  return;
36758
36740
  }
36759
36741
  this.emit({
36760
- event: mapUnlinkEvent(previous.entryType),
36742
+ event: previous.entryType === "directory" ? "unlinkDir" : "unlink",
36761
36743
  path: path2,
36762
36744
  entryType: previous.entryType
36763
36745
  }, options2);
@@ -54487,6 +54469,7 @@ var ALMOSTNODE_INTERNAL_ROOT = "/.almostnode";
54487
54469
  var ALMOSTNODE_NODE_VERSION = "v20.0.0";
54488
54470
  var ALMOSTNODE_NPM_VERSION = "9.6.4";
54489
54471
  var NODE_EXEC_PATH = "/usr/local/bin/node";
54472
+ var GLOBAL_NODE_MODULES_ROOT = "/usr/local/lib/node_modules";
54490
54473
  var DEFAULT_PATH = "/usr/local/bin:/usr/bin:/bin:/node_modules/.bin";
54491
54474
  var NPM_USAGE = [
54492
54475
  "Usage: npm <command>",
@@ -54771,6 +54754,66 @@ var AlmostNodeSession = class {
54771
54754
  constructor(fs) {
54772
54755
  this.fs = fs;
54773
54756
  this._vfs.mkdirSync(ALMOSTNODE_INTERNAL_ROOT, { recursive: true });
54757
+ this._vfs.mkdirSync("/node_modules/constants", { recursive: true });
54758
+ this._vfs.writeFileSync("/node_modules/constants/package.json", JSON.stringify({
54759
+ name: "constants",
54760
+ version: "0.0.1",
54761
+ main: "index.js"
54762
+ }));
54763
+ this._vfs.writeFileSync("/node_modules/constants/index.js", [
54764
+ "// Node.js `constants` shim (os.constants + fs.constants)",
54765
+ "var os = require('os');",
54766
+ "var constants = {};",
54767
+ "if (os.constants) {",
54768
+ " if (os.constants.signals) Object.assign(constants, os.constants.signals);",
54769
+ " if (os.constants.errno) Object.assign(constants, os.constants.errno);",
54770
+ " if (os.constants.priority) Object.assign(constants, os.constants.priority);",
54771
+ "}",
54772
+ "// Common fs.constants used by npm packages",
54773
+ "constants.O_RDONLY = 0;",
54774
+ "constants.O_WRONLY = 1;",
54775
+ "constants.O_RDWR = 2;",
54776
+ "constants.O_CREAT = 64;",
54777
+ "constants.O_EXCL = 128;",
54778
+ "constants.O_TRUNC = 512;",
54779
+ "constants.O_APPEND = 1024;",
54780
+ "constants.O_DIRECTORY = 65536;",
54781
+ "constants.O_NOFOLLOW = 131072;",
54782
+ "constants.O_SYNC = 1052672;",
54783
+ "constants.O_SYMLINK = 2097152;",
54784
+ "constants.O_NONBLOCK = 2048;",
54785
+ "constants.S_IFMT = 61440;",
54786
+ "constants.S_IFREG = 32768;",
54787
+ "constants.S_IFDIR = 16384;",
54788
+ "constants.S_IFCHR = 8192;",
54789
+ "constants.S_IFBLK = 24576;",
54790
+ "constants.S_IFIFO = 4096;",
54791
+ "constants.S_IFLNK = 40960;",
54792
+ "constants.S_IFSOCK = 49152;",
54793
+ "constants.S_IRWXU = 448;",
54794
+ "constants.S_IRUSR = 256;",
54795
+ "constants.S_IWUSR = 128;",
54796
+ "constants.S_IXUSR = 64;",
54797
+ "constants.S_IRWXG = 56;",
54798
+ "constants.S_IRGRP = 32;",
54799
+ "constants.S_IWGRP = 16;",
54800
+ "constants.S_IXGRP = 8;",
54801
+ "constants.S_IRWXO = 7;",
54802
+ "constants.S_IROTH = 4;",
54803
+ "constants.S_IWOTH = 2;",
54804
+ "constants.S_IXOTH = 1;",
54805
+ "constants.F_OK = 0;",
54806
+ "constants.R_OK = 4;",
54807
+ "constants.W_OK = 2;",
54808
+ "constants.X_OK = 1;",
54809
+ "constants.COPYFILE_EXCL = 1;",
54810
+ "constants.COPYFILE_FICLONE = 2;",
54811
+ "constants.COPYFILE_FICLONE_FORCE = 4;",
54812
+ "constants.UV_FS_COPYFILE_EXCL = 1;",
54813
+ "constants.UV_FS_COPYFILE_FICLONE = 2;",
54814
+ "constants.UV_FS_COPYFILE_FICLONE_FORCE = 4;",
54815
+ "module.exports = constants;"
54816
+ ].join("\n"));
54774
54817
  this.disposeObservableSubscription = this.fs.subscribe((event) => {
54775
54818
  void this.trackOperation((async () => {
54776
54819
  if (!this.initialized || this.suppressObservableMirrorCount > 0) {
@@ -54843,14 +54886,6 @@ var AlmostNodeSession = class {
54843
54886
  * package directory directly.
54844
54887
  */
54845
54888
  resolveBarePkgEntryCache = /* @__PURE__ */ new Map();
54846
- /**
54847
- * Packages whose imports are handled by the browser import map.
54848
- * These are NOT rewritten to /node_modules/... paths.
54849
- * Now empty: react/react-dom are served from node_modules via our
54850
- * CJS→ESM shim, which supports the actual installed version rather
54851
- * than the outdated esm.sh CDN pinned in almostnode's import map.
54852
- */
54853
- importMapPackages = /* @__PURE__ */ new Set();
54854
54889
  parseCachedPackageJson(packageJsonPath, raw) {
54855
54890
  const cached = this.parsedPackageJsonCache.get(packageJsonPath);
54856
54891
  if (cached && cached.raw === raw) {
@@ -54899,7 +54934,6 @@ var AlmostNodeSession = class {
54899
54934
  subPath = specifier.slice(slashIdx + 1);
54900
54935
  }
54901
54936
  }
54902
- if (this.importMapPackages.has(pkgName)) return null;
54903
54937
  const nodeModulesPath = `${root2}/node_modules/${pkgName}`;
54904
54938
  const pkgJsonPath = `${nodeModulesPath}/package.json`;
54905
54939
  let pkgJson = null;
@@ -55119,6 +55153,19 @@ var AlmostNodeSession = class {
55119
55153
  this.vitePreviewUrl = null;
55120
55154
  this.vitePreviewListener?.(null);
55121
55155
  }
55156
+ resolveBinFromPackageJson(binName, packageName, pkgJson, pkgDir) {
55157
+ if (typeof pkgJson.bin === "string") {
55158
+ const inferredBinName = typeof pkgJson.name === "string" ? pkgJson.name.split("/").pop() ?? pkgJson.name : packageName.split("/").pop() ?? packageName;
55159
+ if (binName === inferredBinName) {
55160
+ return normalizePath(posixPath.join(pkgDir, pkgJson.bin));
55161
+ }
55162
+ }
55163
+ if (typeof pkgJson.bin === "object" && pkgJson.bin !== null && binName in pkgJson.bin) {
55164
+ const namedBins = pkgJson.bin;
55165
+ return normalizePath(posixPath.join(pkgDir, namedBins[binName]));
55166
+ }
55167
+ return null;
55168
+ }
55122
55169
  async resolveNpmBinPath(binName, cwd) {
55123
55170
  const candidatePackageNames = [binName];
55124
55171
  const packageJsonResult = await this.readPackageJson(cwd);
@@ -55141,21 +55188,94 @@ var AlmostNodeSession = class {
55141
55188
  continue;
55142
55189
  }
55143
55190
  const pkgDir = normalizePath(posixPath.join(cwd, "node_modules", packageName));
55144
- if (typeof pkgJson.bin === "string") {
55145
- const inferredBinName = typeof pkgJson.name === "string" ? pkgJson.name.split("/").pop() ?? pkgJson.name : packageName.split("/").pop() ?? packageName;
55146
- if (binName === inferredBinName) {
55147
- return normalizePath(posixPath.join(pkgDir, pkgJson.bin));
55191
+ const result = this.resolveBinFromPackageJson(binName, packageName, pkgJson, pkgDir);
55192
+ if (result) return result;
55193
+ } catch {
55194
+ }
55195
+ }
55196
+ const globalResult = await this.resolveGlobalBinPath(binName);
55197
+ if (globalResult) return globalResult;
55198
+ return null;
55199
+ }
55200
+ async resolveGlobalBinPath(binName) {
55201
+ try {
55202
+ const globalModulesDir = GLOBAL_NODE_MODULES_ROOT;
55203
+ if (!this._vfs.existsSync(globalModulesDir)) return null;
55204
+ const globalPackages = this._vfs.readdirSync(globalModulesDir);
55205
+ for (const entry of globalPackages) {
55206
+ const packageName = entry;
55207
+ const pkgJsonPath = normalizePath(posixPath.join(globalModulesDir, packageName, "package.json"));
55208
+ if (!this._vfs.existsSync(pkgJsonPath)) {
55209
+ if (entry.startsWith("@")) {
55210
+ try {
55211
+ const scopeDir = normalizePath(posixPath.join(globalModulesDir, entry));
55212
+ const scopedPackages = this._vfs.readdirSync(scopeDir);
55213
+ for (const scopedPkg of scopedPackages) {
55214
+ const scopedName = `${entry}/${scopedPkg}`;
55215
+ const scopedPkgJsonPath = normalizePath(posixPath.join(globalModulesDir, scopedName, "package.json"));
55216
+ if (!this._vfs.existsSync(scopedPkgJsonPath)) continue;
55217
+ const raw = this._vfs.readFileSync(scopedPkgJsonPath, "utf8");
55218
+ const pkgJson = this.parseCachedPackageJson(scopedPkgJsonPath, raw);
55219
+ if (!pkgJson) continue;
55220
+ const pkgDir = normalizePath(posixPath.join(globalModulesDir, scopedName));
55221
+ const result = this.resolveBinFromPackageJson(binName, scopedName, pkgJson, pkgDir);
55222
+ if (result) return result;
55223
+ }
55224
+ } catch {
55225
+ }
55148
55226
  }
55227
+ continue;
55149
55228
  }
55150
- if (typeof pkgJson.bin === "object" && pkgJson.bin !== null && binName in pkgJson.bin) {
55151
- const namedBins = pkgJson.bin;
55152
- return normalizePath(posixPath.join(pkgDir, namedBins[binName]));
55229
+ try {
55230
+ const raw = this._vfs.readFileSync(pkgJsonPath, "utf8");
55231
+ const pkgJson = this.parseCachedPackageJson(pkgJsonPath, raw);
55232
+ if (!pkgJson) continue;
55233
+ const pkgDir = normalizePath(posixPath.join(globalModulesDir, packageName));
55234
+ const result = this.resolveBinFromPackageJson(binName, packageName, pkgJson, pkgDir);
55235
+ if (result) return result;
55236
+ } catch {
55153
55237
  }
55154
- } catch {
55155
55238
  }
55239
+ } catch {
55156
55240
  }
55157
55241
  return null;
55158
55242
  }
55243
+ async registerGlobalBinCommands(packageName) {
55244
+ if (!this.binCommandRegistrar) return;
55245
+ const pkgJsonPath = normalizePath(posixPath.join(GLOBAL_NODE_MODULES_ROOT, packageName, "package.json"));
55246
+ if (!this._vfs.existsSync(pkgJsonPath)) return;
55247
+ try {
55248
+ const raw = this._vfs.readFileSync(pkgJsonPath, "utf8");
55249
+ const pkgJson = this.parseCachedPackageJson(pkgJsonPath, raw);
55250
+ if (!pkgJson) return;
55251
+ let binNames;
55252
+ if (typeof pkgJson.bin === "string") {
55253
+ const name = typeof pkgJson.name === "string" ? pkgJson.name.split("/").pop() ?? "" : "";
55254
+ binNames = name ? [name] : [];
55255
+ } else if (typeof pkgJson.bin === "object" && pkgJson.bin !== null) {
55256
+ binNames = Object.keys(pkgJson.bin);
55257
+ } else {
55258
+ binNames = [];
55259
+ }
55260
+ for (const binName of binNames) {
55261
+ if (this.registeredBinCommands.has(binName)) continue;
55262
+ this.registeredBinCommands.add(binName);
55263
+ this.binCommandRegistrar(binName, async (args, ctx) => {
55264
+ const resolvedPath2 = await this.resolveGlobalBinPath(binName) ?? await this.resolveNpmBinPath(binName, normalizePath(ctx.cwd));
55265
+ if (!resolvedPath2) {
55266
+ return {
55267
+ stdout: "",
55268
+ stderr: `bash: ${binName}: command not found
55269
+ `,
55270
+ exitCode: 127
55271
+ };
55272
+ }
55273
+ return this.executeNode([resolvedPath2, ...args], ctx);
55274
+ });
55275
+ }
55276
+ } catch {
55277
+ }
55278
+ }
55159
55279
  async resolveAndRegisterBinCommands(command, cwd) {
55160
55280
  if (!this.binCommandRegistrar) {
55161
55281
  return;
@@ -55524,6 +55644,7 @@ var AlmostNodeSession = class {
55524
55644
  PATH: Array.from(/* @__PURE__ */ new Set([
55525
55645
  normalizePath(posixPath.join(cwd, "node_modules/.bin")),
55526
55646
  "/node_modules/.bin",
55647
+ `${GLOBAL_NODE_MODULES_ROOT}/.bin`,
55527
55648
  ...(baseEnv.PATH?.trim() || DEFAULT_PATH).split(":").filter(Boolean)
55528
55649
  ])).join(":")
55529
55650
  };
@@ -55598,26 +55719,30 @@ var AlmostNodeSession = class {
55598
55719
  case "install":
55599
55720
  case "i":
55600
55721
  case "add": {
55722
+ const isGlobal = args.includes("-g") || args.includes("--global");
55601
55723
  const packageSpecs = args.slice(1).filter((arg) => !arg.startsWith("-"));
55602
55724
  let stdout = "";
55603
55725
  try {
55604
- const packageJsonResult = await this.readPackageJson(cwd);
55605
- if ("error" in packageJsonResult) {
55606
- result = packageJsonResult.error;
55607
- break;
55608
- }
55609
- await ensureEsbuildWasm();
55610
- const packageManager = new PackageManager(this.vfs, { cwd });
55611
- if (packageSpecs.length === 0) {
55612
- const installResult = await packageManager.installFromPackageJson({
55613
- onProgress: (message) => {
55614
- stdout += `${message}
55615
- `;
55616
- }
55617
- });
55618
- stdout += `added ${installResult.added.length} packages
55619
- `;
55620
- } else {
55726
+ if (isGlobal) {
55727
+ if (packageSpecs.length === 0) {
55728
+ result = { stdout: "", stderr: "npm ERR! npm install -g requires a package name\n", exitCode: 1 };
55729
+ break;
55730
+ }
55731
+ await ensureEsbuildWasm();
55732
+ this._vfs.mkdirSync(GLOBAL_NODE_MODULES_ROOT, { recursive: true });
55733
+ await ensureObservableDirectory(this.fs, GLOBAL_NODE_MODULES_ROOT);
55734
+ const globalPkgJsonPath = normalizePath(posixPath.join(GLOBAL_NODE_MODULES_ROOT, "..", "package.json"));
55735
+ if (!this._vfs.existsSync(globalPkgJsonPath)) {
55736
+ const minimalPkg = JSON.stringify({ name: "global", version: "0.0.0", private: true }, null, 2);
55737
+ this._vfs.mkdirSync(posixPath.dirname(globalPkgJsonPath), { recursive: true });
55738
+ this._vfs.writeFileSync(globalPkgJsonPath, minimalPkg);
55739
+ await this.withSuppressedObservableMirroring(async () => {
55740
+ await ensureObservableDirectory(this.fs, posixPath.dirname(globalPkgJsonPath));
55741
+ await this.fs.writeFile(globalPkgJsonPath, minimalPkg);
55742
+ });
55743
+ }
55744
+ const globalCwd = normalizePath(posixPath.join(GLOBAL_NODE_MODULES_ROOT, ".."));
55745
+ const packageManager = new PackageManager(this.vfs, { cwd: globalCwd });
55621
55746
  for (const packageSpec of packageSpecs) {
55622
55747
  const installResult = await packageManager.install(packageSpec, {
55623
55748
  save: true,
@@ -55628,9 +55753,48 @@ var AlmostNodeSession = class {
55628
55753
  });
55629
55754
  stdout += `added ${installResult.added.length} packages
55630
55755
  `;
55756
+ const installedPkgName = packageSpec.replace(/@[^/]*$/, "") || packageSpec;
55757
+ await this.registerGlobalBinCommands(installedPkgName);
55758
+ for (const added of installResult.added) {
55759
+ const addedName = typeof added === "string" ? String(added).replace(/@[^/]*$/, "") : added?.name;
55760
+ if (addedName && addedName !== installedPkgName) {
55761
+ await this.registerGlobalBinCommands(addedName);
55762
+ }
55763
+ }
55764
+ }
55765
+ result = { stdout, stderr: "", exitCode: 0 };
55766
+ } else {
55767
+ const packageJsonResult = await this.readPackageJson(cwd);
55768
+ if ("error" in packageJsonResult) {
55769
+ result = packageJsonResult.error;
55770
+ break;
55771
+ }
55772
+ await ensureEsbuildWasm();
55773
+ const packageManager = new PackageManager(this.vfs, { cwd });
55774
+ if (packageSpecs.length === 0) {
55775
+ const installResult = await packageManager.installFromPackageJson({
55776
+ onProgress: (message) => {
55777
+ stdout += `${message}
55778
+ `;
55779
+ }
55780
+ });
55781
+ stdout += `added ${installResult.added.length} packages
55782
+ `;
55783
+ } else {
55784
+ for (const packageSpec of packageSpecs) {
55785
+ const installResult = await packageManager.install(packageSpec, {
55786
+ save: true,
55787
+ onProgress: (message) => {
55788
+ stdout += `${message}
55789
+ `;
55790
+ }
55791
+ });
55792
+ stdout += `added ${installResult.added.length} packages
55793
+ `;
55794
+ }
55631
55795
  }
55796
+ result = { stdout, stderr: "", exitCode: 0 };
55632
55797
  }
55633
- result = { stdout, stderr: "", exitCode: 0 };
55634
55798
  } catch (error) {
55635
55799
  result = {
55636
55800
  stdout,