libfx 0.0.1 → 0.0.2
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/fx-core.wasm +0 -0
- package/fx-sdk.js +19 -2
- package/fx-term.wasm +0 -0
- package/libfx.darwin-arm64.node +0 -0
- package/libfx.darwin-x64.node +0 -0
- package/libfx.linux-arm64.node +0 -0
- package/libfx.linux-x64.node +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,6 +73,6 @@ The staging script includes `zig-out/lib/libfx.node` by default for local testin
|
|
|
73
73
|
|
|
74
74
|
The npm `latest` dist-tag is the stable channel. The `dev` dist-tag tracks successful builds from `main` and uses immutable prerelease versions. Publishing runs through `.github/workflows/publish-libfx.yml` with npm trusted publishing and provenance. Configure the npm trusted publisher for the `vercel-labs/fx` repository, workflow filename `publish-libfx.yml`, and GitHub environment `npm`. Because npm requires a package to exist before trusted publishing can be configured, the first `libfx` version must be published once by a maintainer before enabling that relationship.
|
|
75
75
|
|
|
76
|
-
JavaScript hosts
|
|
76
|
+
JavaScript hosts can provide configuration, prompt history, session persistence, device login, URL opening, and a foreground workspace. The optional workspace adapter exposes only `terminal` with `{ action: "exec", command }`; command execution is delegated to the host in a clean, root-fixed environment.
|
|
77
77
|
|
|
78
78
|
WebAssembly builds do not include native processes, OS sandboxing, native MCP, subagents, skills, auto-upgrade, clipboard integration, arbitrary WASI filesystem access, or web search.
|
package/fx-core.wasm
CHANGED
|
Binary file
|
package/fx-sdk.js
CHANGED
|
@@ -4,6 +4,7 @@ const strictDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
|
4
4
|
const workspaceInfoLimit = 4 * 1024;
|
|
5
5
|
const workspaceCommandLimit = 64 * 1024;
|
|
6
6
|
const workspaceOutputLimit = 64 * 1024;
|
|
7
|
+
const streamReadsPerTaskYield = 32;
|
|
7
8
|
|
|
8
9
|
function validWorkspacePath(path) {
|
|
9
10
|
if (typeof path !== "string" || !path.startsWith("/") || path.includes("\0")) return false;
|
|
@@ -205,6 +206,13 @@ function raceWithTimeout(promise, timeoutMs, timeoutValue) {
|
|
|
205
206
|
});
|
|
206
207
|
}
|
|
207
208
|
|
|
209
|
+
function yieldToHostTask() {
|
|
210
|
+
if (typeof globalThis.setImmediate === "function") {
|
|
211
|
+
return new Promise((resolve) => globalThis.setImmediate(resolve));
|
|
212
|
+
}
|
|
213
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
214
|
+
}
|
|
215
|
+
|
|
208
216
|
function createRuntime(options) {
|
|
209
217
|
const stdin = new ByteQueue();
|
|
210
218
|
const streams = new Map();
|
|
@@ -332,6 +340,7 @@ function createRuntime(options) {
|
|
|
332
340
|
options.onTerminalPoll?.();
|
|
333
341
|
if (stdin.chunks.length) return 1;
|
|
334
342
|
if (stdin.closed) return -1;
|
|
343
|
+
if (timeoutMs === 0) return 0;
|
|
335
344
|
return stdin.wait(timeoutMs >= 0 ? timeoutMs : undefined).then(() =>
|
|
336
345
|
stdin.chunks.length ? 1 : (stdin.closed ? -1 : 0));
|
|
337
346
|
}
|
|
@@ -355,6 +364,7 @@ function createRuntime(options) {
|
|
|
355
364
|
pendingRead: null,
|
|
356
365
|
readResult: null,
|
|
357
366
|
readError: null,
|
|
367
|
+
readsSinceTaskYield: 0,
|
|
358
368
|
};
|
|
359
369
|
streams.set(handle, state);
|
|
360
370
|
state.responseSettled = Promise.resolve().then(() => options.fetch(text(urlPtr, urlLen), {
|
|
@@ -389,6 +399,13 @@ function createRuntime(options) {
|
|
|
389
399
|
function streamNext(handle, outPtr, outCap) {
|
|
390
400
|
const state = streams.get(handle);
|
|
391
401
|
if (!state) return -1;
|
|
402
|
+
const yieldAfterReadyResult = (result) => {
|
|
403
|
+
if (result <= 0) return result;
|
|
404
|
+
state.readsSinceTaskYield += 1;
|
|
405
|
+
if (state.readsSinceTaskYield < streamReadsPerTaskYield) return result;
|
|
406
|
+
state.readsSinceTaskYield = 0;
|
|
407
|
+
return yieldToHostTask().then(() => result);
|
|
408
|
+
};
|
|
392
409
|
const copy = (chunk) => {
|
|
393
410
|
const written = chunk.subarray(0, outCap);
|
|
394
411
|
bytes(outPtr, written.length).set(written);
|
|
@@ -406,7 +423,7 @@ function createRuntime(options) {
|
|
|
406
423
|
return copy(value);
|
|
407
424
|
};
|
|
408
425
|
const immediate = consume();
|
|
409
|
-
if (immediate !== null) return immediate;
|
|
426
|
+
if (immediate !== null) return yieldAfterReadyResult(immediate);
|
|
410
427
|
if (!state.reader) return 0;
|
|
411
428
|
if (!state.pendingRead) {
|
|
412
429
|
state.pendingRead = state.reader.read().then((result) => {
|
|
@@ -420,7 +437,7 @@ function createRuntime(options) {
|
|
|
420
437
|
return raceWithTimeout(state.pendingRead.then(() => true), 50, false).then((ready) => {
|
|
421
438
|
if (!ready) return -3;
|
|
422
439
|
const result = consume();
|
|
423
|
-
return result === null ? -3 : result;
|
|
440
|
+
return result === null ? -3 : yieldAfterReadyResult(result);
|
|
424
441
|
});
|
|
425
442
|
}
|
|
426
443
|
|
package/fx-term.wasm
CHANGED
|
Binary file
|
package/libfx.darwin-arm64.node
CHANGED
|
Binary file
|
package/libfx.darwin-x64.node
CHANGED
|
Binary file
|
package/libfx.linux-arm64.node
CHANGED
|
Binary file
|
package/libfx.linux-x64.node
CHANGED
|
Binary file
|