@ai-ecoverse/slicc-kernel 1.54.9 → 1.56.0

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/node.js CHANGED
@@ -1693,6 +1693,7 @@ var LAST_UID = 6e4;
1693
1693
  var USERS_GROUP = "users";
1694
1694
  var HOME_DIR = /^\/home\/[^/]+$/;
1695
1695
  var SYSTEM_PNPM_HOME = "/usr/local/share/pnpm";
1696
+ var PNPM_CONFIG = "minimumReleaseAge: 1440\n";
1696
1697
  var isId = (text) => text !== void 0 && /^\d+$/.test(text);
1697
1698
  function lines(text) {
1698
1699
  return text.split("\n").filter((line, i, all) => line !== "" || i < all.length - 1);
@@ -1748,6 +1749,7 @@ function userEnv(account, system) {
1748
1749
  USER: account.name,
1749
1750
  LOGNAME: account.name,
1750
1751
  PNPM_HOME: pnpm,
1752
+ NPM_CONFIG_PREFIX: account.uid === 0 ? "/usr/local" : `${account.home}/.local`,
1751
1753
  PATH: `${pnpm}/bin:/usr/local/bin:/usr/bin:/bin`
1752
1754
  };
1753
1755
  }
@@ -1772,6 +1774,18 @@ var UserDb = class {
1772
1774
  group: parseGroup(await this.read(GROUP, DEFAULT_GROUP))
1773
1775
  };
1774
1776
  }
1777
+ async provision(row) {
1778
+ const pnpm = `${row.home}/.local/share/pnpm`;
1779
+ if (!await this.fs.exists(pnpm)) {
1780
+ await this.fs.mkdir(pnpm, { recursive: true });
1781
+ await this.fs.chmod(pnpm, row.name.startsWith("scoop-") ? 488 : 448);
1782
+ }
1783
+ const config = `${row.home}/.config/pnpm/config.yaml`;
1784
+ if (!await this.fs.exists(config)) {
1785
+ await this.fs.mkdir(`${row.home}/.config/pnpm`, { recursive: true });
1786
+ await this.fs.writeFile(config, PNPM_CONFIG);
1787
+ }
1788
+ }
1775
1789
  async commit(passwd, group, then) {
1776
1790
  const before = [await this.read(PASSWD, DEFAULT_PASSWD), await this.read(GROUP, DEFAULT_GROUP)];
1777
1791
  try {
@@ -1845,6 +1859,7 @@ var UserDb = class {
1845
1859
  const groups = parsed(group);
1846
1860
  const found = users.find((r) => r.name === name2);
1847
1861
  if (found) {
1862
+ if (found.uid >= FIRST_UID && found.uid <= LAST_UID) await this.provision(found);
1848
1863
  remember();
1849
1864
  return this.account(found, groups);
1850
1865
  }
@@ -1863,6 +1878,7 @@ var UserDb = class {
1863
1878
  const fresh = !await this.fs.exists(home);
1864
1879
  await this.fs.mkdir(home, { recursive: true });
1865
1880
  try {
1881
+ await this.provision(row);
1866
1882
  await this.fs.mkdir("/etc", { recursive: true });
1867
1883
  await this.commit(formatPasswd(passwd), formatGroup(group));
1868
1884
  } catch (err) {
@@ -2749,7 +2765,7 @@ var OpfsFs = class {
2749
2765
  const parent = await this.locate(parentOf2(path), true);
2750
2766
  if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
2751
2767
  await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
2752
- this.touch(parent.path);
2768
+ this.touch(parent.path, `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`);
2753
2769
  }
2754
2770
  async rm(path, options = {}) {
2755
2771
  let found;
@@ -4156,17 +4172,22 @@ async function followLinks(fs, path) {
4156
4172
  }
4157
4173
  return current;
4158
4174
  }
4159
- function withCommandDirs(fs, names) {
4175
+ function withCommandDirs(fs, names, userDir = async () => void 0) {
4160
4176
  async function children2(path) {
4161
4177
  if (path === "/") return ["bin", "usr"];
4162
4178
  if (path === "/usr") return ["bin"];
4163
4179
  if (path === "/bin" || path === "/usr/bin") return [...await names()];
4164
- return void 0;
4180
+ const own = await userDir(path);
4181
+ return own?.size ? [...own] : void 0;
4165
4182
  }
4166
4183
  async function virtual(path) {
4167
4184
  if (path === "/usr" || path === "/bin" || path === "/usr/bin") return synthetic(true, path);
4168
4185
  const name2 = COMMAND.exec(path)?.[1];
4169
- return name2 !== void 0 && (await names()).has(name2) ? synthetic(false, path) : void 0;
4186
+ if (name2 !== void 0) return (await names()).has(name2) ? synthetic(false, path) : void 0;
4187
+ if ((await userDir(path))?.size) return synthetic(true, path);
4188
+ const slash = path.lastIndexOf("/");
4189
+ const own = await userDir(path.slice(0, slash));
4190
+ return own?.has(path.slice(slash + 1)) ? synthetic(false, path) : void 0;
4170
4191
  }
4171
4192
  async function linked(path) {
4172
4193
  return await virtual(path) ?? virtual(await followLinks(fs, path));
@@ -12777,8 +12798,11 @@ var Launcher = class {
12777
12798
  createWorker;
12778
12799
  modulesDir;
12779
12800
  env;
12780
- catalog;
12781
- binfmts;
12801
+ catalogs = /* @__PURE__ */ new Map();
12802
+ ownCatalogs = /* @__PURE__ */ new Map();
12803
+ binfmts = /* @__PURE__ */ new Map();
12804
+ scopes;
12805
+ unwatchScopes = () => void 0;
12782
12806
  warned = /* @__PURE__ */ new Set();
12783
12807
  compiled = /* @__PURE__ */ new Map();
12784
12808
  processes = /* @__PURE__ */ new Map();
@@ -12858,7 +12882,11 @@ var Launcher = class {
12858
12882
  ca: this.ca
12859
12883
  });
12860
12884
  enableCdp(this.net, this.cdp);
12861
- const fs = withCommandDirs(this.base, async () => new Set((await this.commands()).keys()));
12885
+ const fs = withCommandDirs(
12886
+ this.base,
12887
+ async () => new Set((await this.commands()).keys()),
12888
+ (dir) => this.userCommandDir(dir)
12889
+ );
12862
12890
  this.nodes = new VfsNodes(fs, (path) => this.released(path));
12863
12891
  this.nodes.keepsOnDisk = true;
12864
12892
  this.openFiles.add(this.nodes);
@@ -12876,35 +12904,99 @@ var Launcher = class {
12876
12904
  this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
12877
12905
  this.users = new UserDb(this.fs);
12878
12906
  void this.unlinked.sweep("/");
12879
- this.watchers.watch([this.modulesDir, this.pnpmHome], { recursive: true }, () => {
12880
- this.catalog = void 0;
12881
- this.binfmts = void 0;
12907
+ this.watchers.watch(
12908
+ [this.modulesDir, this.pnpmHome],
12909
+ { recursive: true },
12910
+ () => this.resetCatalogs()
12911
+ );
12912
+ this.watchers.watch([PASSWD], { recursive: false }, () => {
12913
+ this.scopes = void 0;
12914
+ this.resetCatalogs();
12882
12915
  });
12883
12916
  }
12884
12917
  setRoutes(table) {
12885
12918
  this.routes.set(table);
12886
12919
  }
12887
- commands() {
12888
- this.catalog ??= this.roots().then((roots) => scanCommands(this.base, roots));
12889
- return this.catalog;
12920
+ commands(scope = "") {
12921
+ let found = this.catalogs.get(scope);
12922
+ if (!found) {
12923
+ found = this.roots(scope).then((roots) => scanCommands(this.base, roots));
12924
+ this.catalogs.set(scope, found);
12925
+ }
12926
+ return found;
12890
12927
  }
12891
- interpreters() {
12892
- this.binfmts ??= this.roots().then(
12893
- (roots) => scanBinfmts(this.base, roots, (message3) => {
12894
- if (this.warned.has(message3)) return;
12895
- this.warned.add(message3);
12896
- console.warn(message3);
12897
- })
12898
- );
12899
- return this.binfmts;
12928
+ ownCommands(scope) {
12929
+ let found = this.ownCatalogs.get(scope);
12930
+ if (!found) {
12931
+ found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.base, roots)).then((commands) => new Set(commands.keys()));
12932
+ this.ownCatalogs.set(scope, found);
12933
+ }
12934
+ return found;
12935
+ }
12936
+ interpreters(scope = "") {
12937
+ let found = this.binfmts.get(scope);
12938
+ if (!found) {
12939
+ found = this.roots(scope).then(
12940
+ (roots) => scanBinfmts(this.base, roots, (message3) => {
12941
+ if (this.warned.has(message3)) return;
12942
+ this.warned.add(message3);
12943
+ console.warn(message3);
12944
+ })
12945
+ );
12946
+ this.binfmts.set(scope, found);
12947
+ }
12948
+ return found;
12900
12949
  }
12901
- async roots() {
12902
- return [this.modulesDir, ...await pnpmGlobalRoots(this.base, this.pnpmHome)];
12950
+ async roots(scope = "") {
12951
+ const system = [this.modulesDir, ...await pnpmGlobalRoots(this.base, this.pnpmHome)];
12952
+ return scope ? [...await pnpmGlobalRoots(this.base, scope), ...system] : system;
12953
+ }
12954
+ resetCatalogs() {
12955
+ this.catalogs.clear();
12956
+ this.ownCatalogs.clear();
12957
+ this.binfmts.clear();
12958
+ }
12959
+ userScopes() {
12960
+ this.scopes ??= this.users.list().then(
12961
+ (accounts) => {
12962
+ const users = accounts.filter((account) => account.uid !== 0);
12963
+ const homes = users.map((account) => pnpmHomeOf(account, this.pnpmHome));
12964
+ this.unwatchScopes();
12965
+ this.unwatchScopes = this.watchers.watch(
12966
+ homes,
12967
+ { recursive: true },
12968
+ () => this.resetCatalogs()
12969
+ );
12970
+ return {
12971
+ byUid: new Map(users.map((account, i) => [account.uid, homes[i]])),
12972
+ byBin: new Map(homes.map((home) => [`${home}/bin`, home]))
12973
+ };
12974
+ },
12975
+ () => ({ byUid: /* @__PURE__ */ new Map(), byBin: /* @__PURE__ */ new Map() })
12976
+ );
12977
+ return this.scopes;
12978
+ }
12979
+ async userCommandDir(dir) {
12980
+ const scope = (await this.userScopes()).byBin.get(dir);
12981
+ return scope === void 0 ? void 0 : this.ownCommands(scope);
12982
+ }
12983
+ async scopeOf(uid) {
12984
+ return (await this.userScopes()).byUid.get(uid) ?? "";
12985
+ }
12986
+ async commandAt(file, scope) {
12987
+ const system = COMMAND2.exec(file)?.[1];
12988
+ if (system !== void 0) return (await this.commands()).get(system);
12989
+ if (!file.includes("/")) return (await this.commands(scope)).get(file);
12990
+ const slash = file.lastIndexOf("/");
12991
+ const owner = (await this.userScopes()).byBin.get(file.slice(0, slash));
12992
+ if (owner === void 0 || !(await this.ownCommands(owner)).has(file.slice(slash + 1))) {
12993
+ return void 0;
12994
+ }
12995
+ return (await this.commands(owner)).get(file.slice(slash + 1));
12903
12996
  }
12904
- async resolve(file, argv0, cwd) {
12905
- const name2 = COMMAND2.exec(file)?.[1] ?? (file.includes("/") ? void 0 : file);
12906
- if (name2 !== void 0) {
12907
- const command = (await this.commands()).get(name2);
12997
+ async resolve(file, argv0, cwd, scope = "") {
12998
+ if (!file.includes("/") || COMMAND2.test(file)) {
12999
+ const command = await this.commandAt(file, scope);
12908
13000
  return command && !command.script ? targetOf(command) : void 0;
12909
13001
  }
12910
13002
  const path = this.fs.resolvePath(cwd, file);
@@ -12915,6 +13007,8 @@ var Launcher = class {
12915
13007
  const byPath = !COMMAND2.test(path) && (await this.commands()).get(linked)?.argv0Path === true;
12916
13008
  return target && byPath ? { ...target, argv0: path } : target;
12917
13009
  }
13010
+ const own = await this.commandAt(glue, scope);
13011
+ if (own) return own.script ? void 0 : targetOf(own);
12918
13012
  const head = await this.head(glue);
12919
13013
  if (!head) return void 0;
12920
13014
  if (isWasm(head)) {
@@ -12937,45 +13031,45 @@ var Launcher = class {
12937
13031
  return void 0;
12938
13032
  }
12939
13033
  }
12940
- async scriptCommand(file) {
12941
- const name2 = COMMAND2.exec(file)?.[1] ?? (file.includes("/") ? void 0 : file);
12942
- if (name2 === void 0) return void 0;
12943
- const command = (await this.commands()).get(name2);
13034
+ async scriptCommand(file, cwd, scope) {
13035
+ const direct = !file.includes("/") || COMMAND2.test(file);
13036
+ const at = direct ? file : await followLinks(this.base, this.fs.resolvePath(cwd, file));
13037
+ const command = await this.commandAt(at, scope);
12944
13038
  return command?.script ? command : void 0;
12945
13039
  }
12946
- async interpreted(file, argv, cwd, depth = 0) {
12947
- const command = await this.scriptCommand(file);
13040
+ async interpreted(file, argv, cwd, scope, depth = 0) {
13041
+ const command = await this.scriptCommand(file, cwd, scope);
12948
13042
  const script = command?.script ?? this.fs.resolvePath(cwd, file);
12949
13043
  const head = await this.head(script);
12950
13044
  if (!head) return void 0;
12951
- const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(), script);
13045
+ const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(scope), script);
12952
13046
  const words = shebang(head) ?? (binfmt ? [binfmt] : void 0);
12953
13047
  if (!words) return void 0;
12954
13048
  if (baseName(words[0]) === "env") words.shift();
12955
13049
  const [interp, ...rest2] = words;
12956
13050
  const arg = rest2.join(" ");
12957
13051
  const passed = [...arg ? [arg] : [], command ? script : file, ...argv.slice(1)];
12958
- const found = interp ? await this.resolve(interp, interp, cwd) : void 0;
13052
+ const found = interp ? await this.resolve(interp, interp, cwd, scope) : void 0;
12959
13053
  if (!found) {
12960
- if (!interp || depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp)) {
13054
+ if (!interp || depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp, cwd, scope)) {
12961
13055
  return void 0;
12962
13056
  }
12963
- const inner = await this.interpreted(interp, [interp, ...passed], cwd, depth + 1);
13057
+ const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
12964
13058
  return inner && { ...inner, target: withScriptEnv(inner.target, command) };
12965
13059
  }
12966
13060
  const target = withScriptEnv(found, command);
12967
13061
  return { target, args: [...target.prefix ?? [], ...passed] };
12968
13062
  }
12969
- async plan(file, argv, cwd) {
12970
- const direct = await this.resolve(file, argv[0] ?? file, cwd);
13063
+ async plan(file, argv, cwd, scope) {
13064
+ const direct = await this.resolve(file, argv[0] ?? file, cwd, scope);
12971
13065
  if (direct) return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)] };
12972
- return this.interpreted(file, argv, cwd);
13066
+ return this.interpreted(file, argv, cwd, scope);
12973
13067
  }
12974
- async unrunnable(file, cwd) {
13068
+ async unrunnable(file, cwd, scope) {
12975
13069
  const path = this.fs.resolvePath(cwd, file);
12976
13070
  const head = await this.base.readFileBuffer(path).catch(() => null);
12977
13071
  if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
12978
- return binfmtOf(await this.interpreters(), path) ? "ENOENT" : "ENOEXEC";
13072
+ return binfmtOf(await this.interpreters(scope), path) ? "ENOENT" : "ENOEXEC";
12979
13073
  }
12980
13074
  module(path) {
12981
13075
  return this.base.stat(path).then((st) => {
@@ -13185,10 +13279,11 @@ var Launcher = class {
13185
13279
  }
13186
13280
  spawner(ppid, report) {
13187
13281
  return async (req, fds) => {
13188
- const planned = await this.plan(req.file, req.argv, req.cwd);
13282
+ const scope = await this.scopeOf(this.credOf(ppid).euid);
13283
+ const planned = await this.plan(req.file, req.argv, req.cwd, scope);
13189
13284
  if (!planned) {
13190
13285
  await fds.closeAll();
13191
- throw new SpawnError(await this.unrunnable(req.file, req.cwd));
13286
+ throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
13192
13287
  }
13193
13288
  const exec = req.exec ? { exec: true } : {};
13194
13289
  const deciding = req.exec ? void 0 : this.undecided(ppid);
@@ -13490,18 +13585,18 @@ var Launcher = class {
13490
13585
  ...account.umask !== void 0 ? { umask: account.umask } : {}
13491
13586
  };
13492
13587
  }
13493
- async starting(argv, dir) {
13494
- this.catalog = void 0;
13495
- this.binfmts = void 0;
13588
+ async starting(argv, dir, account) {
13589
+ this.resetCatalogs();
13590
+ const scope = account.uid === 0 ? "" : pnpmHomeOf(account, this.pnpmHome);
13496
13591
  const start2 = dir ?? "/";
13497
13592
  const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
13498
13593
  const [file = ""] = argv;
13499
13594
  await this.base.mkdir(cwd, { recursive: true });
13500
- return { cwd, file, planned: await this.plan(file, argv, cwd) };
13595
+ return { cwd, file, planned: await this.plan(file, argv, cwd, scope) };
13501
13596
  }
13502
13597
  async openTerminal(argv, options) {
13503
13598
  const account = await this.account(options.user);
13504
- const { cwd, file, planned } = await this.starting(argv, options.cwd);
13599
+ const { cwd, file, planned } = await this.starting(argv, options.cwd, account);
13505
13600
  if (!planned) throw new Error(`${file}: command not found`);
13506
13601
  let leader = 0;
13507
13602
  const tty = new KernelTty(
@@ -13544,7 +13639,7 @@ var Launcher = class {
13544
13639
  }
13545
13640
  async run(argv, options = {}) {
13546
13641
  const account = await this.account(options.user);
13547
- const { cwd, file, planned } = await this.starting(argv, options.cwd);
13642
+ const { cwd, file, planned } = await this.starting(argv, options.cwd, account);
13548
13643
  const env = this.environment(cwd, options.env, account);
13549
13644
  const out = [];
13550
13645
  const err = [];