@ai-ecoverse/slicc-kernel 1.152.2 → 1.154.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 +28 -3
- package/dist/driver-worker.js +147 -10
- package/dist/driver-worker.js.map +4 -4
- package/dist/index.js +168 -14
- package/dist/index.js.map +4 -4
- package/dist/kernel-worker.js +844 -167
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +147 -10
- package/dist/node-driver-worker.js.map +4 -4
- package/dist/node-process-worker.js +81 -24
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +982 -182
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +81 -24
- package/dist/process-worker.js.map +3 -3
- package/dist/types/client/attach.d.ts +2 -0
- package/dist/types/client/protocol.d.ts +4 -0
- package/dist/types/client/serve-client.d.ts +2 -0
- package/dist/types/embedder-relay.d.ts +58 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/kernel/embedder.d.ts +100 -0
- package/dist/types/kernel/fd-table.d.ts +3 -1
- package/dist/types/kernel/host.d.ts +8 -0
- package/dist/types/kernel/net/tls-client.d.ts +4 -1
- package/dist/types/kernel/net/tls-engine.d.ts +5 -2
- package/dist/types/kernel/net/tls-server.d.ts +2 -0
- package/dist/types/kernel/net/tls-uplink.d.ts +2 -0
- package/dist/types/kernel/process.d.ts +17 -0
- package/dist/types/kernel/socket-syscalls.d.ts +3 -0
- package/dist/types/launcher.d.ts +13 -0
- package/dist/types/node.d.ts +3 -0
- package/dist/types/process/js/js-net.d.ts +3 -0
- package/dist/types/process/kernel-streams.d.ts +2 -1
- package/dist/types/process/wasi/wasi-fds.d.ts +1 -0
- package/dist/types/serve.d.ts +3 -0
- package/package.json +4 -4
|
@@ -46,6 +46,111 @@ function serveCdpPort(port, hook, request, onDone) {
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// src/embedder-relay.ts
|
|
50
|
+
function fresh(bytes) {
|
|
51
|
+
return bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength ? bytes : bytes.slice();
|
|
52
|
+
}
|
|
53
|
+
function errorOf(err) {
|
|
54
|
+
const name = err?.name;
|
|
55
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
56
|
+
return { name: typeof name === "string" ? name : "Error", message };
|
|
57
|
+
}
|
|
58
|
+
function bytesOf(reply) {
|
|
59
|
+
if (reply instanceof ReadableStream) return reply;
|
|
60
|
+
const bytes = typeof reply === "string" ? new TextEncoder().encode(reply) : reply instanceof Uint8Array ? reply : new Uint8Array(0);
|
|
61
|
+
return new ReadableStream({
|
|
62
|
+
start(controller) {
|
|
63
|
+
if (bytes.length > 0) controller.enqueue(bytes);
|
|
64
|
+
controller.close();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function bodyStream(id, state, post) {
|
|
69
|
+
return new ReadableStream(
|
|
70
|
+
{
|
|
71
|
+
pull: async (controller) => {
|
|
72
|
+
if (state.body.length === 0) post({ id, bodyPull: true });
|
|
73
|
+
while (state.body.length === 0 && !state.abort.signal.aborted) {
|
|
74
|
+
await new Promise((resolve) => {
|
|
75
|
+
state.wakeBody = resolve;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const next = state.body.shift();
|
|
79
|
+
if (next) controller.enqueue(next);
|
|
80
|
+
else controller.close();
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{ highWaterMark: 0 }
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
function embedderAnswerer(port, hookFor) {
|
|
87
|
+
const running = /* @__PURE__ */ new Map();
|
|
88
|
+
const post = (message, transfer = []) => port.postMessage({ embedderReply: message }, transfer);
|
|
89
|
+
const fail = (id, err) => {
|
|
90
|
+
running.delete(id);
|
|
91
|
+
post({ id, error: errorOf(err) });
|
|
92
|
+
};
|
|
93
|
+
const start = async (ask) => {
|
|
94
|
+
const state = { abort: new AbortController(), body: [], wakeBody: void 0 };
|
|
95
|
+
running.set(ask.id, state);
|
|
96
|
+
try {
|
|
97
|
+
const hook = hookFor(ask.client);
|
|
98
|
+
if (!hook || !Object.hasOwn(hook.kinds, ask.kind))
|
|
99
|
+
throw Object.assign(new Error(`this page does not answer ${ask.kind}`), {
|
|
100
|
+
name: "NotSupportedError"
|
|
101
|
+
});
|
|
102
|
+
const reply = await hook.handle({
|
|
103
|
+
kind: ask.kind,
|
|
104
|
+
options: ask.options,
|
|
105
|
+
body: bodyStream(ask.id, state, post),
|
|
106
|
+
stamp: ask.stamp,
|
|
107
|
+
signal: state.abort.signal,
|
|
108
|
+
progress: (line) => post({ id: ask.id, progress: String(line) })
|
|
109
|
+
});
|
|
110
|
+
state.reader = bytesOf(reply).getReader();
|
|
111
|
+
post({ id: ask.id, ready: true });
|
|
112
|
+
} catch (err) {
|
|
113
|
+
fail(ask.id, err);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const pull = async (id, state) => {
|
|
117
|
+
try {
|
|
118
|
+
const got = await state.reader.read();
|
|
119
|
+
if (got.done) {
|
|
120
|
+
running.delete(id);
|
|
121
|
+
post({ id, done: true });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const bytes = fresh(got.value);
|
|
125
|
+
post({ id, chunk: bytes }, [bytes.buffer]);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
fail(id, err);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const step = (message) => {
|
|
131
|
+
const state = running.get(message.id);
|
|
132
|
+
if (!state) return;
|
|
133
|
+
if ("body" in message) state.body.push(message.body);
|
|
134
|
+
else if ("bodyEnd" in message) state.body.push(null);
|
|
135
|
+
else if ("pull" in message) void pull(message.id, state);
|
|
136
|
+
else {
|
|
137
|
+
running.delete(message.id);
|
|
138
|
+
state.abort.abort(new DOMException(message.cancel, "AbortError"));
|
|
139
|
+
void state.reader?.cancel(message.cancel).catch(() => void 0);
|
|
140
|
+
}
|
|
141
|
+
state.wakeBody?.();
|
|
142
|
+
};
|
|
143
|
+
return {
|
|
144
|
+
handle(data) {
|
|
145
|
+
const message = data?.embedder;
|
|
146
|
+
if (!message) return false;
|
|
147
|
+
if ("ask" in message) void start(message.ask);
|
|
148
|
+
else step(message);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
49
154
|
// src/facade/port.ts
|
|
50
155
|
function serveFacadePort(port, hook, { name, stamp }, onDone) {
|
|
51
156
|
let conn;
|
|
@@ -96,6 +201,27 @@ function serveFacadePort(port, hook, { name, stamp }, onDone) {
|
|
|
96
201
|
};
|
|
97
202
|
}
|
|
98
203
|
|
|
204
|
+
// src/kernel/pipe.ts
|
|
205
|
+
var PIPE_CAPACITY = 64 * 1024;
|
|
206
|
+
|
|
207
|
+
// src/kernel/embedder.ts
|
|
208
|
+
var EMBEDDER_HEADER_MAX = 64 * 1024;
|
|
209
|
+
var EMBEDDER_WINDOW = 1024 * 1024;
|
|
210
|
+
var EMBEDDER_BUDGET = 256 * 1024 * 1024;
|
|
211
|
+
function kindsOf(hook) {
|
|
212
|
+
if (typeof hook?.handle !== "function" || typeof hook.kinds !== "object" || !hook.kinds)
|
|
213
|
+
throw new TypeError("requests needs kinds and handle");
|
|
214
|
+
return Object.fromEntries(
|
|
215
|
+
Object.entries(hook.kinds).map(([kind, policy]) => [
|
|
216
|
+
kind,
|
|
217
|
+
{
|
|
218
|
+
...policy?.group !== void 0 ? { group: String(policy.group) } : {},
|
|
219
|
+
...policy?.users ? { users: [...policy.users] } : {}
|
|
220
|
+
}
|
|
221
|
+
])
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
99
225
|
// src/kernel/net/ws-queue.ts
|
|
100
226
|
var INBOUND_LIMIT = 16 * 1024 * 1024;
|
|
101
227
|
var MESSAGE_LIMIT = 64 * 1024 * 1024;
|
|
@@ -424,7 +550,7 @@ var KERNEL_SIGINFO = Object.freeze({
|
|
|
424
550
|
});
|
|
425
551
|
|
|
426
552
|
// src/bytes.ts
|
|
427
|
-
function
|
|
553
|
+
function fresh2(bytes, start = 0, end = bytes.length) {
|
|
428
554
|
return new Uint8Array(bytes.subarray(start, end));
|
|
429
555
|
}
|
|
430
556
|
|
|
@@ -481,7 +607,7 @@ function dialStream(port, onClose) {
|
|
|
481
607
|
const writable = new WritableStream({
|
|
482
608
|
write(chunk) {
|
|
483
609
|
if (closed) throw errorWithCode("EPIPE: the connection is closed");
|
|
484
|
-
const copy =
|
|
610
|
+
const copy = fresh2(chunk);
|
|
485
611
|
const acked = new Promise((resolve, reject) => acks.push({ resolve, reject }));
|
|
486
612
|
port.postMessage(copy, [copy.buffer]);
|
|
487
613
|
return acked;
|
|
@@ -668,7 +794,7 @@ async function loopbackFetch(dial, input, options) {
|
|
|
668
794
|
}
|
|
669
795
|
|
|
670
796
|
// src/client/protocol.ts
|
|
671
|
-
var PROTOCOL = [1,
|
|
797
|
+
var PROTOCOL = [1, 13];
|
|
672
798
|
function locksOf(scope = globalThis) {
|
|
673
799
|
const locks = scope.navigator?.locks;
|
|
674
800
|
return typeof locks?.request === "function" ? locks : void 0;
|
|
@@ -696,7 +822,7 @@ var KernelCallError = class extends Error {
|
|
|
696
822
|
}
|
|
697
823
|
};
|
|
698
824
|
var encoder2 = new TextEncoder();
|
|
699
|
-
var
|
|
825
|
+
var bytesOf2 = (data) => typeof data === "string" ? encoder2.encode(data) : data;
|
|
700
826
|
var UNAVAILABLE = {
|
|
701
827
|
manualRedirects: false,
|
|
702
828
|
encodedBodies: false,
|
|
@@ -780,7 +906,9 @@ var Channel = class {
|
|
|
780
906
|
call(call) {
|
|
781
907
|
return this.request(call).done;
|
|
782
908
|
}
|
|
909
|
+
requests;
|
|
783
910
|
receive(data) {
|
|
911
|
+
if (this.requests?.handle(data)) return;
|
|
784
912
|
if (data.traits && data.id === void 0) {
|
|
785
913
|
if (this.remote) this.remote.traits = data.traits;
|
|
786
914
|
for (const listener of [...this.traitsListeners]) listener(data.traits);
|
|
@@ -903,7 +1031,7 @@ async function spawnOn(channel, argv, opts) {
|
|
|
903
1031
|
});
|
|
904
1032
|
const started = Promise.withResolvers();
|
|
905
1033
|
let endedBy;
|
|
906
|
-
const options = { ...rest, ...stdin !== void 0 ? { stdin:
|
|
1034
|
+
const options = { ...rest, ...stdin !== void 0 ? { stdin: bytesOf2(stdin) } : {} };
|
|
907
1035
|
const { done } = channel.request(
|
|
908
1036
|
{ op: "spawn", argv, options },
|
|
909
1037
|
{
|
|
@@ -986,7 +1114,7 @@ async function terminalOn(channel, argv, opts) {
|
|
|
986
1114
|
listener = next;
|
|
987
1115
|
if (next) for (const bytes of backlog.splice(0)) next(bytes);
|
|
988
1116
|
},
|
|
989
|
-
write: (data) => send({ action: "write", bytes:
|
|
1117
|
+
write: (data) => send({ action: "write", bytes: bytesOf2(data) }),
|
|
990
1118
|
resize: (cols, rows) => send({ action: "resize", cols, rows }),
|
|
991
1119
|
signal: (name) => send({ action: "signal", signal: name }),
|
|
992
1120
|
close: () => send({ action: "close" })
|
|
@@ -1048,8 +1176,10 @@ function since(channel, minor, what, run) {
|
|
|
1048
1176
|
}
|
|
1049
1177
|
return run();
|
|
1050
1178
|
}
|
|
1051
|
-
async function greet(channel, lock, timeoutMs) {
|
|
1052
|
-
channel.post({
|
|
1179
|
+
async function greet(channel, lock, timeoutMs, requests) {
|
|
1180
|
+
channel.post({
|
|
1181
|
+
hello: { protocol: PROTOCOL, ...lock ? { lock } : {}, ...requests ? { requests } : {} }
|
|
1182
|
+
});
|
|
1053
1183
|
const timer = setTimeout(
|
|
1054
1184
|
() => channel.end(
|
|
1055
1185
|
new KernelGoneError(`no slicc-kernel answered on this port within ${timeoutMs} ms`)
|
|
@@ -1074,7 +1204,14 @@ async function attachKernel(port, options = {}) {
|
|
|
1074
1204
|
const locks = options.locks === null ? void 0 : options.locks ?? locksOf();
|
|
1075
1205
|
const own = await holdLock(locks);
|
|
1076
1206
|
const channel = new Channel(port, own.release);
|
|
1077
|
-
const
|
|
1207
|
+
const requests = options.requests;
|
|
1208
|
+
if (requests) channel.requests = embedderAnswerer(port, () => requests);
|
|
1209
|
+
const hello = await greet(
|
|
1210
|
+
channel,
|
|
1211
|
+
own.name,
|
|
1212
|
+
options.timeoutMs ?? 1e4,
|
|
1213
|
+
requests ? kindsOf(requests) : void 0
|
|
1214
|
+
);
|
|
1078
1215
|
channel.protocol = hello.protocol;
|
|
1079
1216
|
if (hello.lock && locks) void locks.request(hello.lock, () => channel.end(new KernelGoneError()));
|
|
1080
1217
|
const transport = new RemoteTransport(
|
|
@@ -1237,7 +1374,7 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
1237
1374
|
(result) => {
|
|
1238
1375
|
if (result instanceof Uint8Array) {
|
|
1239
1376
|
const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;
|
|
1240
|
-
const bytes = options.owned && whole ? result :
|
|
1377
|
+
const bytes = options.owned && whole ? result : fresh2(result);
|
|
1241
1378
|
reply({ id: data.id, result: bytes }, [bytes.buffer]);
|
|
1242
1379
|
} else reply({ id: data.id, result: result ?? null });
|
|
1243
1380
|
},
|