@ai-ecoverse/slicc-kernel 1.13.0 → 1.14.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/README.md +1 -1
- package/dist/kernel-worker.js +40 -5
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node.js +40 -5
- package/dist/node.js.map +2 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -119,7 +119,7 @@ A WASI preview1 or WASIX program (Zig, Rust, Go, wasi-libc or wasix-libc C) has
|
|
|
119
119
|
{ "slicc": { "abi": "wasi", "commands": { "rg": { "wasm": "bin/rg.wasm" }, "rustc": { "script": "bin/rustc" } } } }
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
Entries may also set `argv0`, `args` and `env`, and a package can set `slicc.env` for all of its commands. In `env`, `${package}` is the package directory, `${cwd}` the process's working directory, and `${NAME}` the caller's `NAME` when the program starts (a default naming an unset variable is left out); a relative path that exists in the package (`lib/python3.14`, `./`) becomes that absolute path. The caller's environment wins over these defaults; a `null` value removes the variable for the command, after the caller's environment is applied (a host-networked program can drop the kernel's proxy settings that way), and a command entry can set a variable its package's `slicc.env` removes. The first package to define a name wins. `sh` runs bash as `sh` unless a package provides its own. The installed commands appear as executables in a virtual `/usr/bin` and `/bin`, so `PATH` lookups, `command -v` and `ls /usr/bin` work without writing anything to OPFS. A process can also run a program by the path of its glue when the `.wasm` sits next to it, a wasm module by its own path (as a WASI program), and a script through its `#!` line (including `#!/usr/bin/env name`). Executing any other file fails with `ENOEXEC`, so bash runs it as a shell script, as POSIX shells do. The catalog is re-read
|
|
122
|
+
Entries may also set `argv0`, `args` and `env`, and a package can set `slicc.env` for all of its commands. In `env`, `${package}` is the package directory, `${cwd}` the process's working directory, and `${NAME}` the caller's `NAME` when the program starts (a default naming an unset variable is left out); a relative path that exists in the package (`lib/python3.14`, `./`) becomes that absolute path. The caller's environment wins over these defaults; a `null` value removes the variable for the command, after the caller's environment is applied (a host-networked program can drop the kernel's proxy settings that way), and a command entry can set a variable its package's `slicc.env` removes. The first package to define a name wins. `sh` runs bash as `sh` unless a package provides its own. The installed commands appear as executables in a virtual `/usr/bin` and `/bin`, so `PATH` lookups, `command -v` and `ls /usr/bin` work without writing anything to OPFS. A process can also run a program by the path of its glue when the `.wasm` sits next to it, a wasm module by its own path (as a WASI program), and a script through its `#!` line (including `#!/usr/bin/env name`). Executing any other file fails with `ENOEXEC`, so bash runs it as a shell script, as POSIX shells do. Commands also come from pnpm's global directory. Every process gets `PNPM_HOME=/home/.local/share/pnpm`, unless the embedder sets its own, and has `$PNPM_HOME/bin` on `PATH`. The kernel scans each of pnpm's global install groups (`$PNPM_HOME/global/*/<group>/node_modules`) after `/node_modules`, which wins when both provide a command. The catalog is re-read whenever anything under either changes, so `pnpm add -g @ai-ecoverse/wasi-ripgrep` makes `rg` work in the same shell, and `pnpm remove -g` removes it again.
|
|
123
123
|
|
|
124
124
|
### WASI programs
|
|
125
125
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -3022,9 +3022,28 @@ async function packages(fs, modules) {
|
|
|
3022
3022
|
}
|
|
3023
3023
|
return dirs;
|
|
3024
3024
|
}
|
|
3025
|
+
async function pnpmGlobalRoots(fs, home) {
|
|
3026
|
+
const roots = [];
|
|
3027
|
+
const global = `${home}/global`;
|
|
3028
|
+
for (const version of (await fs.readdir(global).catch(() => [])).sort()) {
|
|
3029
|
+
for (const group of (await fs.readdir(`${global}/${version}`).catch(() => [])).sort()) {
|
|
3030
|
+
const dir = `${global}/${version}/${group}`;
|
|
3031
|
+
const st = await fs.lstat(dir).catch(() => void 0);
|
|
3032
|
+
if (st?.isDirectory && await fs.exists(`${dir}/node_modules`))
|
|
3033
|
+
roots.push(`${dir}/node_modules`);
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
return roots;
|
|
3037
|
+
}
|
|
3038
|
+
async function packagesIn(fs, roots) {
|
|
3039
|
+
const dirs = [];
|
|
3040
|
+
for (const root of typeof roots === "string" ? [roots] : roots)
|
|
3041
|
+
dirs.push(...await packages(fs, root));
|
|
3042
|
+
return dirs;
|
|
3043
|
+
}
|
|
3025
3044
|
async function scanCommands(fs, modules) {
|
|
3026
3045
|
const found = /* @__PURE__ */ new Map();
|
|
3027
|
-
for (const pkg of await
|
|
3046
|
+
for (const pkg of await packagesIn(fs, modules)) {
|
|
3028
3047
|
let manifest;
|
|
3029
3048
|
try {
|
|
3030
3049
|
manifest = JSON.parse(await fs.readFile(`${pkg}/package.json`));
|
|
@@ -3043,7 +3062,7 @@ async function scanCommands(fs, modules) {
|
|
|
3043
3062
|
}
|
|
3044
3063
|
async function scanFilesystems(fs, modules) {
|
|
3045
3064
|
const found = /* @__PURE__ */ new Map();
|
|
3046
|
-
for (const pkg of await
|
|
3065
|
+
for (const pkg of await packagesIn(fs, modules)) {
|
|
3047
3066
|
let manifest;
|
|
3048
3067
|
try {
|
|
3049
3068
|
manifest = JSON.parse(await fs.readFile(`${pkg}/package.json`));
|
|
@@ -6966,6 +6985,7 @@ function foreignImports(bytes) {
|
|
|
6966
6985
|
}
|
|
6967
6986
|
|
|
6968
6987
|
// src/launcher.ts
|
|
6988
|
+
var PNPM_HOME = "/home/.local/share/pnpm";
|
|
6969
6989
|
var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
6970
6990
|
var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
6971
6991
|
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
@@ -7055,6 +7075,7 @@ var Launcher = class {
|
|
|
7055
7075
|
ca;
|
|
7056
7076
|
transport;
|
|
7057
7077
|
watchers = new FsWatchers();
|
|
7078
|
+
pnpmHome;
|
|
7058
7079
|
mounts;
|
|
7059
7080
|
createDriverWorker;
|
|
7060
7081
|
openFiles = /* @__PURE__ */ new Set();
|
|
@@ -7071,6 +7092,7 @@ var Launcher = class {
|
|
|
7071
7092
|
this.base = this.watchers.wrap(this.mounts.wrap(options.fs));
|
|
7072
7093
|
this.createWorker = options.createWorker;
|
|
7073
7094
|
this.createDriverWorker = options.createDriverWorker;
|
|
7095
|
+
this.pnpmHome = options.env?.PNPM_HOME ?? PNPM_HOME;
|
|
7074
7096
|
this.modulesDir = options.modules ?? "/node_modules";
|
|
7075
7097
|
this.env = { ...networkEnv(), ...options.env };
|
|
7076
7098
|
this.ca = kernelCa(options.caStore ?? memoryCaStore());
|
|
@@ -7081,11 +7103,17 @@ var Launcher = class {
|
|
|
7081
7103
|
ca: this.ca
|
|
7082
7104
|
});
|
|
7083
7105
|
this.fs = withCommandDirs(this.base, async () => new Set((await this.commands()).keys()));
|
|
7106
|
+
this.watchers.watch([this.modulesDir, this.pnpmHome], { recursive: true }, () => {
|
|
7107
|
+
this.catalog = void 0;
|
|
7108
|
+
});
|
|
7084
7109
|
}
|
|
7085
7110
|
commands() {
|
|
7086
|
-
this.catalog ??= scanCommands(this.base,
|
|
7111
|
+
this.catalog ??= this.roots().then((roots) => scanCommands(this.base, roots));
|
|
7087
7112
|
return this.catalog;
|
|
7088
7113
|
}
|
|
7114
|
+
async roots() {
|
|
7115
|
+
return [this.modulesDir, ...await pnpmGlobalRoots(this.base, this.pnpmHome)];
|
|
7116
|
+
}
|
|
7089
7117
|
async resolve(file, argv0, cwd) {
|
|
7090
7118
|
const name2 = COMMAND2.exec(file)?.[1] ?? (file.includes("/") ? void 0 : file);
|
|
7091
7119
|
if (name2 !== void 0) {
|
|
@@ -7339,7 +7367,7 @@ var Launcher = class {
|
|
|
7339
7367
|
}
|
|
7340
7368
|
};
|
|
7341
7369
|
}
|
|
7342
|
-
const module = (await scanFilesystems(this.base, this.
|
|
7370
|
+
const module = (await scanFilesystems(this.base, await this.roots())).get(type);
|
|
7343
7371
|
if (!module) throw fsError("ENODEV", `unknown file system type ${type}`);
|
|
7344
7372
|
if (!this.createDriverWorker)
|
|
7345
7373
|
throw fsError("ENODEV", `this kernel cannot start ${type} drivers`);
|
|
@@ -7379,7 +7407,14 @@ var Launcher = class {
|
|
|
7379
7407
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
7380
7408
|
}
|
|
7381
7409
|
environment(cwd, extra) {
|
|
7382
|
-
return {
|
|
7410
|
+
return {
|
|
7411
|
+
PATH: `/usr/bin:/bin:${this.pnpmHome}/bin`,
|
|
7412
|
+
HOME: "/home",
|
|
7413
|
+
PNPM_HOME: this.pnpmHome,
|
|
7414
|
+
...this.env,
|
|
7415
|
+
PWD: cwd,
|
|
7416
|
+
...extra
|
|
7417
|
+
};
|
|
7383
7418
|
}
|
|
7384
7419
|
async starting(argv, dir) {
|
|
7385
7420
|
this.catalog = void 0;
|