libfx 0.0.11 → 0.0.13

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/node.js CHANGED
@@ -13,13 +13,14 @@ import {
13
13
  encodeXtermKeyEvent,
14
14
  fxSdkApiVersion,
15
15
  listModels,
16
+ normalizeAgentOptions,
16
17
  supportsJspi,
17
18
  xtermAdapter,
18
19
  } from "./fx-sdk.js";
19
20
 
20
21
  export { encodeXtermKeyEvent, fxSdkApiVersion, listModels, supportsJspi, xtermAdapter };
21
22
  export const libfxApiVersion = 2;
22
- const nativeCoreApiVersion = 3;
23
+ const nativeCoreApiVersion = 4;
23
24
 
24
25
  const fetchOperationStale = 0;
25
26
  const fetchOperationApplied = 1;
@@ -345,7 +346,12 @@ export async function getBackendInfo(value = {}) {
345
346
  }
346
347
 
347
348
  function createNativeCoreRuntime(addon, options) {
348
- const { apiKey, model, effort, fast, gatewayChatUrl } = options;
349
+ const { apiKey, model, effort, fast, ultrafast, gatewayChatUrl } = options;
350
+ if (ultrafast !== undefined && addon.supportsUltrafast !== true) {
351
+ const error = new Error("native addon does not support the ultrafast option");
352
+ error.code = "LIBFX_NATIVE_CAPABILITY_UNAVAILABLE";
353
+ throw error;
354
+ }
349
355
  const core = addon.createCore({
350
356
  apiKey,
351
357
  home: options.home ?? homedir(),
@@ -353,6 +359,7 @@ function createNativeCoreRuntime(addon, options) {
353
359
  ...(model === undefined ? {} : { model }),
354
360
  ...(effort === undefined ? {} : { effort }),
355
361
  ...(fast === undefined ? {} : { fast }),
362
+ ...(ultrafast === undefined ? {} : { ultrafast }),
356
363
  ...(gatewayChatUrl === undefined ? {} : { gatewayChatUrl }),
357
364
  });
358
365
  let readyFd;
@@ -390,7 +397,7 @@ function createNativeCoreRuntime(addon, options) {
390
397
  readySocket.destroy();
391
398
  void readyClosed.then(() => exitedResolve(code));
392
399
  };
393
- const pumpFetch = async (request) => {
400
+ const pumpFetch = async (request, body) => {
394
401
  const controller = new AbortController();
395
402
  const state = { handle: request.handle, controller };
396
403
  fetchState = state;
@@ -398,7 +405,7 @@ function createNativeCoreRuntime(addon, options) {
398
405
  const response = await (options.fetch ?? globalThis.fetch)(request.url, {
399
406
  method: request.method,
400
407
  headers: new Headers(JSON.parse(request.headers).map(({ name, value }) => [name, value])),
401
- body: request.body?.length ? Buffer.from(request.body, "base64") : undefined,
408
+ body: body.length ? body : undefined,
402
409
  signal: controller.signal,
403
410
  });
404
411
  const started = addon.startCoreFetchResponse(core, state.handle, response.status);
@@ -447,8 +454,9 @@ function createNativeCoreRuntime(addon, options) {
447
454
  fetchState.controller.abort();
448
455
  }
449
456
  } else {
457
+ // The core hands over JSON metadata and the raw request body separately.
450
458
  const fetchRequest = addon.takeCoreFetch(core);
451
- if (fetchRequest) void pumpFetch(JSON.parse(fetchRequest.toString("utf8")));
459
+ if (fetchRequest) void pumpFetch(JSON.parse(fetchRequest.request.toString("utf8")), fetchRequest.body);
452
460
  }
453
461
  if (addon.coreExitCode(core) !== 0) {
454
462
  finish(1, new Error("native output delivery failed"));
@@ -493,6 +501,12 @@ function createNativeCoreRuntime(addon, options) {
493
501
  exited,
494
502
  get error() { return outputError; },
495
503
  write(data) { addon.writeCore(core, Buffer.from(data)); },
504
+ // The addon copies attachment bytes before returning.
505
+ writeAttachment(id, bytes) {
506
+ addon.writeCoreAttachment(core, id, Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength));
507
+ },
508
+ takeAttachment(id) { return addon.takeCoreAttachment(core, id); },
509
+ discardAttachments() { addon.discardCoreAttachments(core); },
496
510
  closeStdin() { addon.closeCore(core); },
497
511
  abortHostEffects,
498
512
  abort(error) {
@@ -513,10 +527,11 @@ function createNativeAgent(addon, options) {
513
527
  }
514
528
 
515
529
  async function createWithFallback(surface, nativeMethod, wasmFactory, defaultWasm, options) {
516
- const { nativeAddon, backend = "auto", ...runtimeOptions } = options ?? {};
530
+ const { nativeAddon, backend = "auto", ...unvalidatedOptions } = options ?? {};
517
531
  if (!new Set(["auto", "native", "wasm"]).has(backend)) {
518
532
  throw new TypeError('backend must be "auto", "native", or "wasm"');
519
533
  }
534
+ const runtimeOptions = surface === "agent" ? normalizeAgentOptions(unvalidatedOptions) : unvalidatedOptions;
520
535
 
521
536
  let nativeError;
522
537
  let nativeAttempted = false;
@@ -530,7 +545,8 @@ async function createWithFallback(surface, nativeMethod, wasmFactory, defaultWas
530
545
  return await native.backend[nativeMethod](runtimeOptions);
531
546
  } catch (error) {
532
547
  nativeError = error;
533
- if (backend === "native") throw error;
548
+ if (backend === "native" || error?.code === "LIBFX_MODEL_UNSUPPORTED_FAST" ||
549
+ error?.code === "LIBFX_MODEL_UNSUPPORTED_EFFORT") throw error;
534
550
  }
535
551
  }
536
552
  if (backend === "native") {
@@ -549,9 +565,6 @@ async function createWithFallback(surface, nativeMethod, wasmFactory, defaultWas
549
565
  }
550
566
 
551
567
  export async function createFxAgent(options = {}) {
552
- if (options != null && Object.hasOwn(Object(options), "env")) {
553
- throw new TypeError("createFxAgent() does not accept env; pass apiKey and model directly");
554
- }
555
568
  return createWithFallback(
556
569
  "agent",
557
570
  "createCore",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libfx",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Embed fx agents and terminals in JavaScript hosts",
5
5
  "type": "module",
6
6
  "repository": {