libfx 0.0.8-dev.820.g1d9d3b63d6ea → 0.0.8
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 +13 -2
- package/fx-core.wasm +0 -0
- package/fx-sdk.js +18 -4
- 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/node.cjs +61 -20
- package/node.js +45 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -256,6 +256,11 @@ creates a separate WebAssembly instance for every Agent. Agent memory, history,
|
|
|
256
256
|
tools, cancellation, and shutdown remain isolated. Workers and separate
|
|
257
257
|
processes maintain their own module caches, as do the ESM and CommonJS entries.
|
|
258
258
|
|
|
259
|
+
Node factories and `getBackendInfo()` also accept a `wasm` Promise resolving
|
|
260
|
+
to an HTTP(S) URL string, a `Response`, Wasm bytes, or a compiled
|
|
261
|
+
`WebAssembly.Module`. Asset resolver failures propagate from factories and
|
|
262
|
+
appear as `LIBFX_WASM_LOAD_FAILED` in diagnostics.
|
|
263
|
+
|
|
259
264
|
Node.js 20+ is supported. Browser WebAssembly requires a JSPI-capable browser.
|
|
260
265
|
The Linux x64 and arm64 native addons require glibc 2.34 or newer. Native
|
|
261
266
|
agents do not require JSPI or experimental Node flags.
|
|
@@ -268,8 +273,14 @@ JIT tier-up.
|
|
|
268
273
|
|
|
269
274
|
Create agents in a server route using the Node.js runtime. Import `libfx`
|
|
270
275
|
normally; the package includes its native assets and exposes both ESM and
|
|
271
|
-
CommonJS Node entrypoints.
|
|
272
|
-
|
|
276
|
+
CommonJS Node entrypoints. Native agents support Next.js 15 with webpack and
|
|
277
|
+
Next.js 16 with webpack or Turbopack, without `serverExternalPackages` or manual
|
|
278
|
+
native-file inclusion. Webpack's emitted assets are resolved relative to the
|
|
279
|
+
server bundle, including standalone builds with a custom `distDir` or `assetPrefix`.
|
|
280
|
+
|
|
281
|
+
This native setup does not require JSPI. Explicit WebAssembly use still needs
|
|
282
|
+
JSPI and available Wasm assets; Next.js's standalone tracer excludes `.wasm`
|
|
283
|
+
files, so a standalone Wasm host must supply those assets separately.
|
|
273
284
|
|
|
274
285
|
```js
|
|
275
286
|
import { createFxAgent } from "libfx";
|
package/fx-core.wasm
CHANGED
|
Binary file
|
package/fx-sdk.js
CHANGED
|
@@ -996,7 +996,10 @@ async function instantiate(options) {
|
|
|
996
996
|
runtime.setInstance(null);
|
|
997
997
|
if (options.args?.[0] === "acp" && !String(error).includes("proc_exit")) runtime.abort(error);
|
|
998
998
|
else {
|
|
999
|
-
if (!String(error).includes("proc_exit"))
|
|
999
|
+
if (!String(error).includes("proc_exit")) {
|
|
1000
|
+
runtime.abortHostEffects();
|
|
1001
|
+
console.error(error);
|
|
1002
|
+
}
|
|
1000
1003
|
runtime.markExited(runtime.aborted ? 130 : 1);
|
|
1001
1004
|
}
|
|
1002
1005
|
},
|
|
@@ -1040,13 +1043,13 @@ export async function createFxTerminal(options) {
|
|
|
1040
1043
|
if (interruptKey && data.includes(interruptKey)) runtime.abortHostEffects();
|
|
1041
1044
|
runtime.write(data);
|
|
1042
1045
|
};
|
|
1043
|
-
const unsubscribeData = options.terminal.onData(forwardData);
|
|
1044
|
-
const unsubscribeKeyData = options.terminal.onKeyData?.(forwardData) ?? (() => {});
|
|
1045
1046
|
const signalResize = () => {
|
|
1046
1047
|
emit("terminal.resize", { cols: options.terminal.cols, rows: options.terminal.rows });
|
|
1047
1048
|
runtime.wake();
|
|
1048
1049
|
};
|
|
1049
|
-
|
|
1050
|
+
let unsubscribeData;
|
|
1051
|
+
let unsubscribeKeyData;
|
|
1052
|
+
let unsubscribeResize;
|
|
1050
1053
|
let subscriptionsReleased = false;
|
|
1051
1054
|
const releaseSubscriptions = () => {
|
|
1052
1055
|
if (subscriptionsReleased) return;
|
|
@@ -1059,6 +1062,17 @@ export async function createFxTerminal(options) {
|
|
|
1059
1062
|
releaseSubscriptions();
|
|
1060
1063
|
emit("runtime.exit", { surface: "terminal", code });
|
|
1061
1064
|
});
|
|
1065
|
+
try {
|
|
1066
|
+
unsubscribeData = options.terminal.onData(forwardData);
|
|
1067
|
+
unsubscribeKeyData = options.terminal.onKeyData?.(forwardData);
|
|
1068
|
+
unsubscribeResize = options.terminal.onResize(signalResize);
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
// The rejected factory never transfers this promise to a caller.
|
|
1071
|
+
interactive.catch(() => {});
|
|
1072
|
+
releaseSubscriptions();
|
|
1073
|
+
runtime.abort();
|
|
1074
|
+
throw error;
|
|
1075
|
+
}
|
|
1062
1076
|
return {
|
|
1063
1077
|
interactive,
|
|
1064
1078
|
exited: runtime.exited,
|
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
|
package/node.cjs
CHANGED
|
@@ -1329,8 +1329,10 @@ async function instantiate(options) {
|
|
|
1329
1329
|
if (options.args?.[0] === "acp" && !String(error).includes("proc_exit"))
|
|
1330
1330
|
runtime.abort(error);
|
|
1331
1331
|
else {
|
|
1332
|
-
if (!String(error).includes("proc_exit"))
|
|
1332
|
+
if (!String(error).includes("proc_exit")) {
|
|
1333
|
+
runtime.abortHostEffects();
|
|
1333
1334
|
console.error(error);
|
|
1335
|
+
}
|
|
1334
1336
|
runtime.markExited(runtime.aborted ? 130 : 1);
|
|
1335
1337
|
}
|
|
1336
1338
|
});
|
|
@@ -1378,13 +1380,13 @@ async function createFxTerminal(options) {
|
|
|
1378
1380
|
runtime.abortHostEffects();
|
|
1379
1381
|
runtime.write(data);
|
|
1380
1382
|
};
|
|
1381
|
-
const unsubscribeData = options.terminal.onData(forwardData);
|
|
1382
|
-
const unsubscribeKeyData = options.terminal.onKeyData?.(forwardData) ?? (() => {});
|
|
1383
1383
|
const signalResize = () => {
|
|
1384
1384
|
emit("terminal.resize", { cols: options.terminal.cols, rows: options.terminal.rows });
|
|
1385
1385
|
runtime.wake();
|
|
1386
1386
|
};
|
|
1387
|
-
|
|
1387
|
+
let unsubscribeData;
|
|
1388
|
+
let unsubscribeKeyData;
|
|
1389
|
+
let unsubscribeResize;
|
|
1388
1390
|
let subscriptionsReleased = false;
|
|
1389
1391
|
const releaseSubscriptions = () => {
|
|
1390
1392
|
if (subscriptionsReleased)
|
|
@@ -1410,6 +1412,16 @@ async function createFxTerminal(options) {
|
|
|
1410
1412
|
releaseSubscriptions();
|
|
1411
1413
|
emit("runtime.exit", { surface: "terminal", code });
|
|
1412
1414
|
});
|
|
1415
|
+
try {
|
|
1416
|
+
unsubscribeData = options.terminal.onData(forwardData);
|
|
1417
|
+
unsubscribeKeyData = options.terminal.onKeyData?.(forwardData);
|
|
1418
|
+
unsubscribeResize = options.terminal.onResize(signalResize);
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
interactive.catch(() => {});
|
|
1421
|
+
releaseSubscriptions();
|
|
1422
|
+
runtime.abort();
|
|
1423
|
+
throw error;
|
|
1424
|
+
}
|
|
1413
1425
|
return {
|
|
1414
1426
|
interactive,
|
|
1415
1427
|
exited: runtime.exited,
|
|
@@ -2050,6 +2062,12 @@ var backendReasonCodes = {
|
|
|
2050
2062
|
jspiUnavailable: "LIBFX_JSPI_UNAVAILABLE",
|
|
2051
2063
|
wasmLoad: "LIBFX_WASM_LOAD_FAILED"
|
|
2052
2064
|
};
|
|
2065
|
+
function bundledAssetUrl(asset) {
|
|
2066
|
+
if (asset.protocol !== "" || typeof asset.href !== "string" || typeof __webpack_base_uri__ === "undefined" || typeof __webpack_public_path__ !== "string" || !asset.href.startsWith(__webpack_public_path__)) {
|
|
2067
|
+
throw new TypeError("Bundled asset URL has no filesystem mapping");
|
|
2068
|
+
}
|
|
2069
|
+
return new URL(asset.href.slice(__webpack_public_path__.length), __webpack_base_uri__);
|
|
2070
|
+
}
|
|
2053
2071
|
function jspiFallbackError(surface, nativeError) {
|
|
2054
2072
|
const nativeDetail = nativeError ? ` Native loading failed: ${nativeError.message}.` : " No compatible native addon was found.";
|
|
2055
2073
|
const error = new Error(`libfx could not start the ${surface} backend.${nativeDetail} ` + "The WebAssembly fallback requires JavaScript Promise Integration (JSPI). " + "Run Node with --experimental-wasm-jspi or install a libfx package containing a compatible native addon.");
|
|
@@ -2061,6 +2079,8 @@ async function loadNativeCandidate(candidate) {
|
|
|
2061
2079
|
if (candidate == null)
|
|
2062
2080
|
return null;
|
|
2063
2081
|
if (candidate instanceof URL) {
|
|
2082
|
+
if (candidate.protocol === "")
|
|
2083
|
+
candidate = bundledAssetUrl(candidate);
|
|
2064
2084
|
if (candidate.protocol === "file:" && candidate.pathname.endsWith(".node")) {
|
|
2065
2085
|
return Reflect.apply(nodeRequire, undefined, [import_node_url.fileURLToPath(candidate)]);
|
|
2066
2086
|
}
|
|
@@ -2080,16 +2100,32 @@ async function loadNativeCandidate(candidate) {
|
|
|
2080
2100
|
}
|
|
2081
2101
|
function defaultNativeCandidate() {
|
|
2082
2102
|
if (process.platform === "linux" && process.arch === "x64") {
|
|
2083
|
-
|
|
2103
|
+
const asset = new URL("./libfx.linux-x64.node", __libfxModuleUrl);
|
|
2104
|
+
if (asset.protocol === "")
|
|
2105
|
+
return import_node_url.fileURLToPath(bundledAssetUrl(asset));
|
|
2106
|
+
const path = import_node_url.fileURLToPath(asset);
|
|
2107
|
+
return path;
|
|
2084
2108
|
}
|
|
2085
2109
|
if (process.platform === "linux" && process.arch === "arm64") {
|
|
2086
|
-
|
|
2110
|
+
const asset = new URL("./libfx.linux-arm64.node", __libfxModuleUrl);
|
|
2111
|
+
if (asset.protocol === "")
|
|
2112
|
+
return import_node_url.fileURLToPath(bundledAssetUrl(asset));
|
|
2113
|
+
const path = import_node_url.fileURLToPath(asset);
|
|
2114
|
+
return path;
|
|
2087
2115
|
}
|
|
2088
2116
|
if (process.platform === "darwin" && process.arch === "x64") {
|
|
2089
|
-
|
|
2117
|
+
const asset = new URL("./libfx.darwin-x64.node", __libfxModuleUrl);
|
|
2118
|
+
if (asset.protocol === "")
|
|
2119
|
+
return import_node_url.fileURLToPath(bundledAssetUrl(asset));
|
|
2120
|
+
const path = import_node_url.fileURLToPath(asset);
|
|
2121
|
+
return path;
|
|
2090
2122
|
}
|
|
2091
2123
|
if (process.platform === "darwin" && process.arch === "arm64") {
|
|
2092
|
-
|
|
2124
|
+
const asset = new URL("./libfx.darwin-arm64.node", __libfxModuleUrl);
|
|
2125
|
+
if (asset.protocol === "")
|
|
2126
|
+
return import_node_url.fileURLToPath(bundledAssetUrl(asset));
|
|
2127
|
+
const path = import_node_url.fileURLToPath(asset);
|
|
2128
|
+
return path;
|
|
2093
2129
|
}
|
|
2094
2130
|
return null;
|
|
2095
2131
|
}
|
|
@@ -2111,8 +2147,11 @@ function missingArtifact(error) {
|
|
|
2111
2147
|
return error?.code === "ENOENT" || error?.code === "MODULE_NOT_FOUND" || error?.code === "ERR_MODULE_NOT_FOUND";
|
|
2112
2148
|
}
|
|
2113
2149
|
function nativeCandidateFilePath(candidate) {
|
|
2114
|
-
if (candidate instanceof URL)
|
|
2150
|
+
if (candidate instanceof URL) {
|
|
2151
|
+
if (candidate.protocol === "")
|
|
2152
|
+
candidate = bundledAssetUrl(candidate);
|
|
2115
2153
|
return candidate.protocol === "file:" ? import_node_url.fileURLToPath(candidate) : null;
|
|
2154
|
+
}
|
|
2116
2155
|
if (typeof candidate !== "string")
|
|
2117
2156
|
return null;
|
|
2118
2157
|
if (candidate.startsWith("file:"))
|
|
@@ -2152,7 +2191,7 @@ async function discoverNativeBackend() {
|
|
|
2152
2191
|
return { backend: null, error: null, failure: "unsupported" };
|
|
2153
2192
|
}
|
|
2154
2193
|
try {
|
|
2155
|
-
await import_promises.access(
|
|
2194
|
+
await import_promises.access(candidate);
|
|
2156
2195
|
} catch (error) {
|
|
2157
2196
|
if (missingArtifact(error)) {
|
|
2158
2197
|
return { backend: null, error: null, probeError: error, failure: "missing" };
|
|
@@ -2194,8 +2233,12 @@ function wasmInput(input) {
|
|
|
2194
2233
|
return pending;
|
|
2195
2234
|
}
|
|
2196
2235
|
function wasmFilePath(input) {
|
|
2197
|
-
if (input instanceof URL
|
|
2198
|
-
|
|
2236
|
+
if (input instanceof URL) {
|
|
2237
|
+
if (input.protocol === "")
|
|
2238
|
+
input = bundledAssetUrl(input);
|
|
2239
|
+
if (input.protocol === "file:")
|
|
2240
|
+
return import_node_url.fileURLToPath(input);
|
|
2241
|
+
}
|
|
2199
2242
|
if (typeof input === "string" && !URL.canParse(input))
|
|
2200
2243
|
return import_node_path.resolve(input);
|
|
2201
2244
|
return null;
|
|
@@ -2231,28 +2274,26 @@ function validateBackendInfoOptions(value) {
|
|
|
2231
2274
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2232
2275
|
throw new TypeError("getBackendInfo() options must be an object");
|
|
2233
2276
|
}
|
|
2234
|
-
const
|
|
2277
|
+
const { nativeAddon, backend = "auto", surface = "agent", ...options } = value;
|
|
2235
2278
|
for (const key of Object.keys(options)) {
|
|
2236
|
-
if (
|
|
2279
|
+
if (key !== "wasm") {
|
|
2237
2280
|
throw new TypeError(`getBackendInfo() does not accept ${key}`);
|
|
2238
2281
|
}
|
|
2239
2282
|
}
|
|
2240
|
-
const surface = options.surface ?? "agent";
|
|
2241
2283
|
if (!new Set(["agent", "terminal"]).has(surface)) {
|
|
2242
2284
|
throw new TypeError('surface must be "agent" or "terminal"');
|
|
2243
2285
|
}
|
|
2244
|
-
const backend = options.backend ?? "auto";
|
|
2245
2286
|
if (!new Set(["auto", "native", "wasm"]).has(backend)) {
|
|
2246
2287
|
throw new TypeError('backend must be "auto", "native", or "wasm"');
|
|
2247
2288
|
}
|
|
2248
|
-
if (
|
|
2289
|
+
if (nativeAddon !== undefined && nativeAddon !== false && typeof nativeAddon !== "string" && !(nativeAddon instanceof URL) && (typeof nativeAddon !== "object" || nativeAddon === null)) {
|
|
2249
2290
|
throw new TypeError("nativeAddon must be a module, path, URL, false, or undefined");
|
|
2250
2291
|
}
|
|
2251
2292
|
const validWasm = options.wasm === undefined || typeof options.wasm === "string" || options.wasm instanceof URL || options.wasm instanceof Promise || options.wasm instanceof WebAssembly.Module || options.wasm instanceof Response || options.wasm instanceof ArrayBuffer || ArrayBuffer.isView(options.wasm);
|
|
2252
2293
|
if (Object.hasOwn(options, "wasm") && !validWasm) {
|
|
2253
2294
|
throw new TypeError("wasm must be a URL, Response, ArrayBuffer, typed array, or WebAssembly.Module");
|
|
2254
2295
|
}
|
|
2255
|
-
return { ...options, surface, backend };
|
|
2296
|
+
return { ...options, surface, backend, nativeAddon };
|
|
2256
2297
|
}
|
|
2257
2298
|
async function getBackendInfo(value = {}) {
|
|
2258
2299
|
const { surface, backend, nativeAddon, wasm } = validateBackendInfoOptions(value);
|
|
@@ -2280,7 +2321,7 @@ async function getBackendInfo(value = {}) {
|
|
|
2280
2321
|
const defaultWasm = surface === "agent" ? defaultCoreWasm : defaultTermWasm;
|
|
2281
2322
|
const wasmSource = wasm ?? defaultWasm;
|
|
2282
2323
|
try {
|
|
2283
|
-
await loadModule(wasmInput(wasmSource));
|
|
2324
|
+
await loadModule(await wasmInput(wasmSource));
|
|
2284
2325
|
attempts.push({ backend: "wasm-jspi", available: true, reason: null });
|
|
2285
2326
|
return { surface, backend: "wasm-jspi", attempts };
|
|
2286
2327
|
} catch (error) {
|
|
@@ -2529,7 +2570,7 @@ async function createWithFallback(surface, nativeMethod, wasmFactory, defaultWas
|
|
|
2529
2570
|
throw jspiFallbackError(surface, nativeError);
|
|
2530
2571
|
}
|
|
2531
2572
|
const wasmSource = runtimeOptions.wasm ?? defaultWasm;
|
|
2532
|
-
return wasmFactory({ ...runtimeOptions, wasm: wasmInput(wasmSource) });
|
|
2573
|
+
return wasmFactory({ ...runtimeOptions, wasm: await wasmInput(wasmSource) });
|
|
2533
2574
|
}
|
|
2534
2575
|
async function createFxAgent2(options = {}) {
|
|
2535
2576
|
if (options != null && Object.hasOwn(Object(options), "env")) {
|
package/node.js
CHANGED
|
@@ -42,6 +42,16 @@ const backendReasonCodes = {
|
|
|
42
42
|
wasmLoad: "LIBFX_WASM_LOAD_FAILED",
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
function bundledAssetUrl(asset) {
|
|
46
|
+
if (asset.protocol !== "" || typeof asset.href !== "string" ||
|
|
47
|
+
typeof __webpack_base_uri__ === "undefined" || typeof __webpack_public_path__ !== "string" ||
|
|
48
|
+
!asset.href.startsWith(__webpack_public_path__)) {
|
|
49
|
+
throw new TypeError("Bundled asset URL has no filesystem mapping");
|
|
50
|
+
}
|
|
51
|
+
// Webpack's relative URL is a public asset address, not a Node URL instance.
|
|
52
|
+
return new URL(asset.href.slice(__webpack_public_path__.length), __webpack_base_uri__);
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
function jspiFallbackError(surface, nativeError) {
|
|
46
56
|
const nativeDetail = nativeError ? ` Native loading failed: ${nativeError.message}.` : " No compatible native addon was found.";
|
|
47
57
|
const error = new Error(
|
|
@@ -57,6 +67,7 @@ function jspiFallbackError(surface, nativeError) {
|
|
|
57
67
|
async function loadNativeCandidate(candidate) {
|
|
58
68
|
if (candidate == null) return null;
|
|
59
69
|
if (candidate instanceof URL) {
|
|
70
|
+
if (candidate.protocol === "") candidate = bundledAssetUrl(candidate);
|
|
60
71
|
if (candidate.protocol === "file:" && candidate.pathname.endsWith(".node")) {
|
|
61
72
|
// Bundlers trace the asset URL; Node must load the native file at runtime.
|
|
62
73
|
return Reflect.apply(nodeRequire, undefined, [fileURLToPath(candidate)]);
|
|
@@ -76,17 +87,30 @@ async function loadNativeCandidate(candidate) {
|
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
function defaultNativeCandidate() {
|
|
90
|
+
// Local path bindings let deployment tracers retain these assets in the generated CommonJS entry.
|
|
79
91
|
if (process.platform === "linux" && process.arch === "x64") {
|
|
80
|
-
|
|
92
|
+
const asset = new URL("./libfx.linux-x64.node", import.meta.url);
|
|
93
|
+
if (asset.protocol === "") return fileURLToPath(bundledAssetUrl(asset));
|
|
94
|
+
const path = fileURLToPath(asset);
|
|
95
|
+
return path;
|
|
81
96
|
}
|
|
82
97
|
if (process.platform === "linux" && process.arch === "arm64") {
|
|
83
|
-
|
|
98
|
+
const asset = new URL("./libfx.linux-arm64.node", import.meta.url);
|
|
99
|
+
if (asset.protocol === "") return fileURLToPath(bundledAssetUrl(asset));
|
|
100
|
+
const path = fileURLToPath(asset);
|
|
101
|
+
return path;
|
|
84
102
|
}
|
|
85
103
|
if (process.platform === "darwin" && process.arch === "x64") {
|
|
86
|
-
|
|
104
|
+
const asset = new URL("./libfx.darwin-x64.node", import.meta.url);
|
|
105
|
+
if (asset.protocol === "") return fileURLToPath(bundledAssetUrl(asset));
|
|
106
|
+
const path = fileURLToPath(asset);
|
|
107
|
+
return path;
|
|
87
108
|
}
|
|
88
109
|
if (process.platform === "darwin" && process.arch === "arm64") {
|
|
89
|
-
|
|
110
|
+
const asset = new URL("./libfx.darwin-arm64.node", import.meta.url);
|
|
111
|
+
if (asset.protocol === "") return fileURLToPath(bundledAssetUrl(asset));
|
|
112
|
+
const path = fileURLToPath(asset);
|
|
113
|
+
return path;
|
|
90
114
|
}
|
|
91
115
|
return null;
|
|
92
116
|
}
|
|
@@ -110,7 +134,10 @@ function missingArtifact(error) {
|
|
|
110
134
|
}
|
|
111
135
|
|
|
112
136
|
function nativeCandidateFilePath(candidate) {
|
|
113
|
-
if (candidate instanceof URL)
|
|
137
|
+
if (candidate instanceof URL) {
|
|
138
|
+
if (candidate.protocol === "") candidate = bundledAssetUrl(candidate);
|
|
139
|
+
return candidate.protocol === "file:" ? fileURLToPath(candidate) : null;
|
|
140
|
+
}
|
|
114
141
|
if (typeof candidate !== "string") return null;
|
|
115
142
|
if (candidate.startsWith("file:")) return fileURLToPath(new URL(candidate));
|
|
116
143
|
return URL.canParse(candidate) ? null : resolve(candidate);
|
|
@@ -151,7 +178,7 @@ async function discoverNativeBackend() {
|
|
|
151
178
|
return { backend: null, error: null, failure: "unsupported" };
|
|
152
179
|
}
|
|
153
180
|
try {
|
|
154
|
-
await access(
|
|
181
|
+
await access(candidate);
|
|
155
182
|
} catch (error) {
|
|
156
183
|
if (missingArtifact(error)) {
|
|
157
184
|
return { backend: null, error: null, probeError: error, failure: "missing" };
|
|
@@ -191,7 +218,10 @@ function wasmInput(input) {
|
|
|
191
218
|
}
|
|
192
219
|
|
|
193
220
|
function wasmFilePath(input) {
|
|
194
|
-
if (input instanceof URL
|
|
221
|
+
if (input instanceof URL) {
|
|
222
|
+
if (input.protocol === "") input = bundledAssetUrl(input);
|
|
223
|
+
if (input.protocol === "file:") return fileURLToPath(input);
|
|
224
|
+
}
|
|
195
225
|
if (typeof input === "string" && !URL.canParse(input)) return resolve(input);
|
|
196
226
|
return null;
|
|
197
227
|
}
|
|
@@ -240,23 +270,21 @@ function validateBackendInfoOptions(value) {
|
|
|
240
270
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
241
271
|
throw new TypeError("getBackendInfo() options must be an object");
|
|
242
272
|
}
|
|
243
|
-
const
|
|
273
|
+
const { nativeAddon, backend = "auto", surface = "agent", ...options } = value;
|
|
244
274
|
for (const key of Object.keys(options)) {
|
|
245
|
-
if (
|
|
275
|
+
if (key !== "wasm") {
|
|
246
276
|
throw new TypeError(`getBackendInfo() does not accept ${key}`);
|
|
247
277
|
}
|
|
248
278
|
}
|
|
249
|
-
const surface = options.surface ?? "agent";
|
|
250
279
|
if (!new Set(["agent", "terminal"]).has(surface)) {
|
|
251
280
|
throw new TypeError('surface must be "agent" or "terminal"');
|
|
252
281
|
}
|
|
253
|
-
const backend = options.backend ?? "auto";
|
|
254
282
|
if (!new Set(["auto", "native", "wasm"]).has(backend)) {
|
|
255
283
|
throw new TypeError('backend must be "auto", "native", or "wasm"');
|
|
256
284
|
}
|
|
257
|
-
if (
|
|
258
|
-
typeof
|
|
259
|
-
(typeof
|
|
285
|
+
if (nativeAddon !== undefined && nativeAddon !== false &&
|
|
286
|
+
typeof nativeAddon !== "string" && !(nativeAddon instanceof URL) &&
|
|
287
|
+
(typeof nativeAddon !== "object" || nativeAddon === null)) {
|
|
260
288
|
throw new TypeError("nativeAddon must be a module, path, URL, false, or undefined");
|
|
261
289
|
}
|
|
262
290
|
const validWasm = options.wasm === undefined || typeof options.wasm === "string" || options.wasm instanceof URL ||
|
|
@@ -265,7 +293,7 @@ function validateBackendInfoOptions(value) {
|
|
|
265
293
|
if (Object.hasOwn(options, "wasm") && !validWasm) {
|
|
266
294
|
throw new TypeError("wasm must be a URL, Response, ArrayBuffer, typed array, or WebAssembly.Module");
|
|
267
295
|
}
|
|
268
|
-
return { ...options, surface, backend };
|
|
296
|
+
return { ...options, surface, backend, nativeAddon };
|
|
269
297
|
}
|
|
270
298
|
|
|
271
299
|
export async function getBackendInfo(value = {}) {
|
|
@@ -299,7 +327,7 @@ export async function getBackendInfo(value = {}) {
|
|
|
299
327
|
const defaultWasm = surface === "agent" ? defaultCoreWasm : defaultTermWasm;
|
|
300
328
|
const wasmSource = wasm ?? defaultWasm;
|
|
301
329
|
try {
|
|
302
|
-
await loadModule(wasmInput(wasmSource));
|
|
330
|
+
await loadModule(await wasmInput(wasmSource));
|
|
303
331
|
attempts.push({ backend: "wasm-jspi", available: true, reason: null });
|
|
304
332
|
return { surface, backend: "wasm-jspi", attempts };
|
|
305
333
|
} catch (error) {
|
|
@@ -514,7 +542,7 @@ async function createWithFallback(surface, nativeMethod, wasmFactory, defaultWas
|
|
|
514
542
|
throw jspiFallbackError(surface, nativeError);
|
|
515
543
|
}
|
|
516
544
|
const wasmSource = runtimeOptions.wasm ?? defaultWasm;
|
|
517
|
-
return wasmFactory({ ...runtimeOptions, wasm: wasmInput(wasmSource) });
|
|
545
|
+
return wasmFactory({ ...runtimeOptions, wasm: await wasmInput(wasmSource) });
|
|
518
546
|
}
|
|
519
547
|
|
|
520
548
|
export async function createFxAgent(options = {}) {
|