@ai-ecoverse/slicc-kernel 1.154.1 → 1.154.3

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
@@ -1141,7 +1141,7 @@ cat <&3 > text.txt
1141
1141
  printf '{"kind":"open.url","url":"%s"}\n' "$url" | cat > /dev/embedder
1142
1142
  ```
1143
1143
 
1144
- - **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. The request goes to the page when its header line ends.
1144
+ - **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.
1145
1145
  - **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.
1146
1146
  - **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.
1147
1147
  - **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.
@@ -75,7 +75,8 @@ function bodyStream(id, state, post) {
75
75
  const next = state.body.shift();
76
76
  if (next) controller.enqueue(next);
77
77
  else controller.close();
78
- }
78
+ },
79
+ cancel: () => post({ id, bodyCancel: true })
79
80
  },
80
81
  { highWaterMark: 0 }
81
82
  );
@@ -96,14 +97,16 @@ function embedderAnswerer(port, hookFor) {
96
97
  throw Object.assign(new Error(`this page does not answer ${ask.kind}`), {
97
98
  name: "NotSupportedError"
98
99
  });
100
+ const body = bodyStream(ask.id, state, post);
99
101
  const reply = await hook.handle({
100
102
  kind: ask.kind,
101
103
  options: ask.options,
102
- body: bodyStream(ask.id, state, post),
104
+ body,
103
105
  stamp: ask.stamp,
104
106
  signal: state.abort.signal,
105
107
  progress: (line) => post({ id: ask.id, progress: String(line) })
106
108
  });
109
+ if (!(reply instanceof ReadableStream)) post({ id: ask.id, bodyCancel: true });
107
110
  state.reader = bytesOf(reply).getReader();
108
111
  post({ id: ask.id, ready: true });
109
112
  } catch (err) {