@ai-ecoverse/slicc-kernel 1.160.0 → 1.160.1

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 CHANGED
@@ -1156,6 +1156,7 @@ printf '{"kind":"open.url","url":"%s"}\n' "$url" | cat > /dev/embedder
1156
1156
 
1157
1157
  - **The request:** the first line is a JSON object with a `kind` (`a.b-c`: lower-case words with dots, at most 64 bytes) and options (every other key), at most 64 KiB. Everything written after it is the body, streamed to the page as it is written: a write waits while 1 MiB of it is unread by the page. A bad header fails that `write()` with `EINVAL`, and the description stays failed. A page that answers with bytes, a string or nothing, or cancels the body, before it has read all of it gets no more: the rest the program writes is dropped ([#1536](https://github.com/ai-ecoverse/slicc-kernel/issues/1536)), so a writer never waits on a body nobody reads. A page that answers with a stream keeps the body until that stream ends, so it must read or cancel the body: until it does, a writer past the 1 MiB window waits. The request goes to the page when its header line ends.
1158
1158
  - **The reply:** reads return the page's reply in order, pulled as the program reads, and its end is end-of-file. Opened `O_RDWR`, the first `read()` ends the body. Opened `O_WRONLY` (nobody reads), the last close ends the body and waits for the page to finish, so `close()` returns its error (an Emscripten program's standard output follows `/dev/clipboard`'s exit rule, so `printf … | cat > /dev/embedder` fails with `cat: write error: …`). There is no timeout: a reply may wait for a prompt or a model download; run `timeout` for one.
1159
+ - **Who waits:** the process that does the last close waits for the reply, and only a signal to that process interrupts it. So put the open inside the command that `timeout` bounds: `timeout 12 sh -c 'cat request > /dev/embedder'`. In `timeout 12 cat request > /dev/embedder` the redirection is `timeout`'s own. `cat` writes the header and exits at once, so the timer never fires, and then `timeout` waits in its own last close, on its way out (coreutils closes its standard output), until the page answers.
1159
1160
  - **Cancel:** a signal during a blocked read, write or `O_WRONLY` close fails it with `EINTR`, and the page's `signal` aborts with reason `interrupted`. Closing the description before the end of the reply aborts it with reason `closed`, and that is no error: it is how `hear` stops recording. A process that ends during a request aborts it too.
1160
1161
  - **Errors:** the hook's error gives the errno: `NotAllowedError` or `AbortError` (a dismissed prompt, a refused permission) `EACCES`; `NotSupportedError` `ENOTSUP`; `NotFoundError` `ENOENT`; anything else `EIO`. An Emscripten or WASI program first gets `<argv0>: /dev/embedder: <first line of the message>` on standard error, as for `/dev/clipboard`; a JS program has it in the error. `request.progress(line)` from the page writes `<argv0>: <line>` to standard error the same way, at most 4 lines a second.
1161
1162
  - **Who answers:** the hook of the client the process's session was started through, inherited by its children, forks and `exec`s: `createKernel({ requests })` (and `createNodeKernel`) for the page's own `run` and `openTerminal`, the hook a port was made with (`connect({ requests })`), or the hook its attached client brought (`connect({ requests: 'attach' })`, then `attachKernel(port, { requests })`). Nothing falls back to another client's hook, so a request from another tab's terminal never opens in this one. With no hook, or a kind the hook doesn't list, the request is `ENOTSUP` before the page sees it. A program has no way to register, replace or see a hook.
@@ -8236,7 +8236,7 @@ function satisfies(version, range2) {
8236
8236
  }
8237
8237
 
8238
8238
  // src/version.ts
8239
- var KERNEL_VERSION = true ? "1.160.0" : "0.0.0-dev";
8239
+ var KERNEL_VERSION = true ? "1.160.1" : "0.0.0-dev";
8240
8240
  var OS_RELEASE = "6.0.0-slicc";
8241
8241
  function procVersion() {
8242
8242
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -14932,7 +14932,8 @@ async function dispatchSyncFs(req) {
14932
14932
  const entry = resolveSyncFsToken(req.token);
14933
14933
  if (!entry) return { ok: false, errno: "EACCES", message: "sync-fs: unknown or revoked token" };
14934
14934
  if (req.identity && req.op === "create") return created2(entry, req);
14935
- if (!req.identity || !IDENTITY_OPS.has(req.op)) return dispatchOne(entry, req);
14935
+ if (!req.identity || !IDENTITY_OPS.has(req.op))
14936
+ return devsOf(entry, req, await dispatchOne(entry, req));
14936
14937
  const { fs, cwd } = entry;
14937
14938
  const path = fs.resolvePath(cwd, req.path);
14938
14939
  const identified = async (held) => {
@@ -14950,6 +14951,30 @@ async function dispatchSyncFs(req) {
14950
14951
  return toErrno(err);
14951
14952
  }
14952
14953
  }
14954
+ var DEV_PROBES = /* @__PURE__ */ new Set(["stat", "lstat", "read", "exists"]);
14955
+ async function devsOf(entry, req, result) {
14956
+ if (req.devs !== true || !DEV_PROBES.has(req.op)) return result;
14957
+ const absent2 = result.ok ? result.kind === "json" && result.json === false : result.errno === "ENOENT";
14958
+ if (!absent2) return result;
14959
+ const dev = await devTarget(entry, req, entry.fs.resolvePath(entry.cwd, req.path));
14960
+ if (dev === void 0) return result;
14961
+ return result.ok ? json2({ dev }) : { ...result, dev };
14962
+ }
14963
+ async function devTarget(entry, req, path) {
14964
+ const look = async (op, at) => {
14965
+ const r = await dispatchPath(entry, { token: req.token, op, path: at });
14966
+ if (!r.ok) throw new Error(r.errno);
14967
+ return r.json;
14968
+ };
14969
+ const resolved2 = await physicalPathAsync(
14970
+ {
14971
+ lstat: async (p) => await look("lstat", p),
14972
+ readlink: async (p) => String(await look("readlink", p))
14973
+ },
14974
+ path
14975
+ );
14976
+ return resolved2 !== path && (resolved2 === "/dev" || resolved2.startsWith("/dev/")) ? resolved2 : void 0;
14977
+ }
14953
14978
  async function created2(entry, req) {
14954
14979
  const result = await dispatchOne(entry, req);
14955
14980
  if (!result.ok) return result;
@@ -15136,7 +15161,8 @@ function encodeSabResult(result) {
15136
15161
  JSON.stringify({
15137
15162
  errno: result.errno,
15138
15163
  message: result.message,
15139
- ...result.direct ? { direct: true } : {}
15164
+ ...result.direct ? { direct: true } : {},
15165
+ ...result.dev !== void 0 ? { dev: result.dev } : {}
15140
15166
  })
15141
15167
  )
15142
15168
  };