nanocodex 0.3.0 → 0.4.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 CHANGED
@@ -9,6 +9,7 @@ import { Actions, Agent } from "nanocodex/node";
9
9
 
10
10
  const agent = await Agent.create({
11
11
  apiKey: process.env.OPENAI_API_KEY,
12
+ model: "gpt-5.6-luna",
12
13
  instructions: "You are a Rust coding agent. Preserve unrelated work and run relevant tests.",
13
14
  reasoningMode: "pro",
14
15
  thinking: "high",
@@ -242,12 +243,50 @@ const agent = await Agent.create({
242
243
  });
243
244
  ```
244
245
 
246
+ Server-side Worker runtimes can await a `fetch()`-based WebSocket upgrade. The
247
+ third callback argument is a discriminated authorization request plus connection
248
+ metadata. With `apiKey`, `authorization` is `"bearer"` and `bearerToken` is
249
+ present. With `hostAuth: true`, it is `"host_managed"`; the host must resolve
250
+ credentials without exposing them to WASM. Do not retain or log bearer tokens.
251
+ Return the socket alone or a descriptor containing response metadata:
252
+
253
+ ```js
254
+ import { Agent } from "nanocodex/browser";
255
+ import module from "nanocodex/wasm";
256
+
257
+ const agent = await Agent.create({
258
+ apiKey,
259
+ module,
260
+ async createWebSocket(endpoint, sessionId, request) {
261
+ if (request.authorization !== "bearer") {
262
+ throw new Error("this host requires Nanocodex bearer authorization");
263
+ }
264
+ const response = await fetch(endpoint.replace("wss:", "https:"), {
265
+ headers: {
266
+ Authorization: `Bearer ${request.bearerToken}`,
267
+ Upgrade: "websocket",
268
+ "session-id": sessionId,
269
+ },
270
+ });
271
+ if (!response.webSocket) throw new Error(`upgrade failed: ${response.status}`);
272
+ response.webSocket.accept();
273
+ return { socket: response.webSocket, status: response.status };
274
+ },
275
+ });
276
+ ```
277
+
278
+ `hostAuth` is useful when the embedding runtime owns rotating credentials. The
279
+ callback can acquire a fresh token, attempt the upgrade, and refresh-and-retry
280
+ on 401. Bound and reject upgrade work in the callback: until it returns a
281
+ socket, there is no connection handle for Nanocodex to close. `apiKey`,
282
+ `hostAuth`, and `mpp` are mutually exclusive.
283
+
245
284
  After publication, a browser can load the same entrypoint without a package
246
285
  manager or build step:
247
286
 
248
287
  ```html
249
288
  <script type="module">
250
- import { Agent } from "https://cdn.jsdelivr.net/npm/nanocodex@0.3.0/browser/index.mjs";
289
+ import { Agent } from "https://cdn.jsdelivr.net/npm/nanocodex@0.4.0/browser/index.mjs";
251
290
  const agent = await Agent.create({ websocketUrl: "/api/responses" });
252
291
  const turn = agent.turn.prompt({ input: "Hello." });
253
292
  try {
@@ -4,6 +4,10 @@ import type {
4
4
  MppSession,
5
5
  ToolMap,
6
6
  } from "../types.mjs";
7
+ import type {
8
+ BrowserWebSocketConnection,
9
+ BrowserWebSocketRequest,
10
+ } from "./host.mjs";
7
11
 
8
12
  export type Agent = DefaultAgent;
9
13
 
@@ -11,14 +15,21 @@ export type Agent = DefaultAgent;
11
15
  export function create(options?: create.Options): Promise<create.ReturnType>;
12
16
  export declare namespace create {
13
17
  type Options = AgentOptions & (
14
- | { apiKey?: string | undefined; mpp?: never }
15
- | { apiKey?: never; mpp: MppSession }
18
+ | { apiKey?: string | undefined; hostAuth?: never; mpp?: never }
19
+ | { apiKey?: never; hostAuth?: true; mpp?: never }
20
+ | { apiKey?: never; hostAuth?: never; mpp: MppSession }
16
21
  ) & {
17
22
  WebSocketImpl?: typeof WebSocket | undefined;
18
23
  apiBaseUrl?: string | undefined;
19
- createWebSocket?(endpoint: string, sessionId: string): WebSocket;
24
+ createWebSocket?(
25
+ endpoint: string,
26
+ sessionId: string,
27
+ request: BrowserWebSocketRequest,
28
+ ): WebSocket | BrowserWebSocketConnection | Promise<WebSocket | BrowserWebSocketConnection>;
20
29
  module?: unknown;
21
30
  tools?: ToolMap | undefined;
31
+ /** Direct dispatch is CSP-safe; Code Mode requires dynamic JavaScript evaluation. */
32
+ toolMode?: "code" | "direct" | undefined;
22
33
  websocketUrl?: string | undefined;
23
34
  };
24
35
  type ReturnType = Agent;
package/browser/Agent.mjs CHANGED
@@ -17,10 +17,12 @@ let initialized;
17
17
  export function create(options = {}) {
18
18
  const {
19
19
  apiKey,
20
+ hostAuth,
20
21
  mpp,
21
22
  websocketUrl,
22
23
  apiBaseUrl,
23
24
  module,
25
+ model,
24
26
  thinking,
25
27
  reasoningMode,
26
28
  fastMode,
@@ -31,17 +33,23 @@ export function create(options = {}) {
31
33
  WebSocketImpl,
32
34
  createWebSocket,
33
35
  tools,
36
+ toolMode,
34
37
  } = options;
35
38
  if (mpp !== undefined && apiKey !== undefined) {
36
39
  throw new TypeError("apiKey and mpp are mutually exclusive");
37
40
  }
41
+ if (hostAuth && (apiKey !== undefined || mpp !== undefined)) {
42
+ throw new TypeError("hostAuth is mutually exclusive with apiKey and mpp");
43
+ }
38
44
  const events = createEventChannel();
39
45
  const host = createBrowserHost({
40
46
  WebSocketImpl,
41
47
  createWebSocket,
48
+ hostAuth: hostAuth === true || (apiKey === undefined && mpp === undefined),
42
49
  mpp,
43
50
  onEvent: events.emit,
44
51
  tools,
52
+ toolMode,
45
53
  });
46
54
  activateHost(host);
47
55
  const runtime = defineRuntime({
@@ -68,6 +76,7 @@ export function create(options = {}) {
68
76
  decorate: (agent) => agent.extend(agentActions()),
69
77
  });
70
78
  return createAgentClient(runtime, {
79
+ model,
71
80
  thinking,
72
81
  reasoningMode,
73
82
  fastMode,
@@ -9,9 +9,41 @@ export type BrowserTool = {
9
9
 
10
10
  export type BrowserToolMap = Record<string, BrowserTool>;
11
11
 
12
+ type BrowserWebSocketMetadata = {
13
+ accountId?: string | undefined;
14
+ fedramp?: boolean | undefined;
15
+ turnState?: string | undefined;
16
+ };
17
+
18
+ export type BrowserWebSocketRequest = BrowserWebSocketMetadata & (
19
+ | {
20
+ authorization: "bearer";
21
+ /** Resolved credential for this handshake. Do not retain or log it. */
22
+ bearerToken: string;
23
+ }
24
+ | {
25
+ authorization: "host_managed";
26
+ bearerToken?: never;
27
+ }
28
+ );
29
+
30
+ export type BrowserWebSocketConnection = {
31
+ socket: WebSocket;
32
+ status?: number | undefined;
33
+ requestId?: string | undefined;
34
+ serverModel?: string | undefined;
35
+ reasoningIncluded?: boolean | undefined;
36
+ turnState?: string | undefined;
37
+ };
38
+
12
39
  export function createBrowserHost(options?: {
13
40
  WebSocketImpl?: typeof WebSocket;
14
- createWebSocket?: (endpoint: string, sessionId: string) => WebSocket;
41
+ hostAuth?: boolean;
42
+ createWebSocket?: (
43
+ endpoint: string,
44
+ sessionId: string,
45
+ request: BrowserWebSocketRequest,
46
+ ) => WebSocket | BrowserWebSocketConnection | Promise<WebSocket | BrowserWebSocketConnection>;
15
47
  onEvent?: (eventJson: string) => void;
16
48
  tools?: BrowserToolMap;
17
49
  maxQueuedMessages?: number;
package/browser/host.mjs CHANGED
@@ -14,6 +14,10 @@ export function createBrowserHost(options = {}) {
14
14
  }
15
15
  const connections = new Map();
16
16
  const code = createCodeRuntime(options.tools);
17
+ const toolMode = options.toolMode ?? "code";
18
+ if (toolMode !== "code" && toolMode !== "direct") {
19
+ throw new TypeError("toolMode must be code or direct");
20
+ }
17
21
  const onEvent = options.onEvent || (() => {});
18
22
  const maxQueuedMessages = options.maxQueuedMessages ?? DEFAULT_MAX_QUEUED_MESSAGES;
19
23
  const maxQueuedBytes = options.maxQueuedBytes ?? DEFAULT_MAX_QUEUED_BYTES;
@@ -21,12 +25,19 @@ export function createBrowserHost(options = {}) {
21
25
  const encoder = new TextEncoder();
22
26
  let nextHandle = 1;
23
27
 
24
- function connect(endpoint, _apiKey, sessionId, metadata = {}) {
28
+ async function connect(endpoint, apiKey, sessionId, metadata = {}) {
25
29
  if (options.mpp) return connectMpp(endpoint);
30
+ const authorization = options.hostAuth
31
+ ? { authorization: "host_managed" }
32
+ : { authorization: "bearer", bearerToken: apiKey };
33
+ const request = { ...metadata };
34
+ delete request.authorization;
35
+ delete request.bearerToken;
36
+ Object.assign(request, authorization);
37
+ const opened = await createWebSocket(endpoint, sessionId, request);
38
+ const { socket, ...handshake } = normalizeWebSocketConnection(opened);
26
39
  return new Promise((resolve, reject) => {
27
40
  let settled = false;
28
- const handle = nextHandle++;
29
- const socket = createWebSocket(endpoint, sessionId, metadata);
30
41
  const connection = {
31
42
  socket,
32
43
  queue: [],
@@ -35,11 +46,21 @@ export function createBrowserHost(options = {}) {
35
46
  intentionallyClosed: false,
36
47
  overflowed: false,
37
48
  };
38
- socket.addEventListener("open", () => {
49
+ const resolveOpen = () => {
50
+ if (settled) return;
39
51
  settled = true;
52
+ const handle = nextHandle++;
40
53
  connections.set(handle, connection);
41
- resolve(JSON.stringify({ handle, status: 101, reasoning_included: false }));
42
- }, { once: true });
54
+ resolve(JSON.stringify({
55
+ handle,
56
+ status: handshake.status ?? 101,
57
+ request_id: handshake.requestId,
58
+ server_model: handshake.serverModel,
59
+ reasoning_included: handshake.reasoningIncluded ?? false,
60
+ turn_state: handshake.turnState,
61
+ }));
62
+ };
63
+ socket.addEventListener("open", resolveOpen, { once: true });
43
64
  socket.addEventListener("message", (event) => {
44
65
  enqueue(connection, typeof event.data === "string"
45
66
  ? { kind: "text", text: event.data }
@@ -61,6 +82,11 @@ export function createBrowserHost(options = {}) {
61
82
  enqueue(connection, { kind: "error", detail: "WebSocket connection failed" });
62
83
  }
63
84
  });
85
+ if (socket.readyState === WEBSOCKET_OPEN) resolveOpen();
86
+ else if (socket.readyState > WEBSOCKET_OPEN) {
87
+ settled = true;
88
+ reject(new Error("WebSocket closed during connection"));
89
+ }
64
90
  });
65
91
  }
66
92
 
@@ -198,8 +224,20 @@ export function createBrowserHost(options = {}) {
198
224
  close,
199
225
  sleep: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
200
226
  executeCode: code.executeCode,
227
+ executeTool: code.executeTool,
228
+ toolMode: () => toolMode,
201
229
  toolDefinitions: code.toolDefinitions,
202
230
  emitEvent: onEvent,
203
231
  reset: code.reset,
204
232
  });
205
233
  }
234
+
235
+ function normalizeWebSocketConnection(opened) {
236
+ if (opened?.socket && typeof opened.socket.addEventListener === "function") {
237
+ return opened;
238
+ }
239
+ if (!opened || typeof opened.addEventListener !== "function") {
240
+ throw new TypeError("createWebSocket must return a WebSocket or a connection descriptor");
241
+ }
242
+ return { socket: opened };
243
+ }
package/internal.mjs CHANGED
@@ -141,6 +141,7 @@ export function toWasmConfig(options = {}) {
141
141
  throw new TypeError("apiKey must be a non-empty string");
142
142
  }
143
143
  const config = { api_key: apiKey };
144
+ copy(config, "model", options.model);
144
145
  copy(config, "thinking", options.thinking);
145
146
  copy(config, "reasoning_mode", options.reasoningMode);
146
147
  copy(config, "fast_mode", options.fastMode);
@@ -235,6 +236,13 @@ const hostBridge = Object.freeze({
235
236
  executeCode(source, sessionId, callId) {
236
237
  return requiredSessionHost(sessionId).executeCode(source, sessionId, callId);
237
238
  },
239
+ executeTool(name, input, sessionId, callId) {
240
+ return requiredSessionHost(sessionId).executeTool(name, input, sessionId, callId);
241
+ },
242
+ toolMode(sessionId) {
243
+ // The WASM constructor asks before its session is adopted.
244
+ return (hostSessions.get(sessionId) ?? requiredActiveHost()).toolMode();
245
+ },
238
246
  toolDefinitions(sessionId) {
239
247
  // ModelRun builds its stable tool prefix inside the WASM constructor,
240
248
  // immediately before the returned session can be adopted. Runtime
package/node/Agent.d.mts CHANGED
@@ -14,6 +14,7 @@ export declare namespace create {
14
14
  apiBaseUrl?: string | undefined;
15
15
  module?: unknown;
16
16
  tools?: ToolMap | undefined;
17
+ toolMode?: "code" | "direct" | undefined;
17
18
  websocketUrl?: string | undefined;
18
19
  };
19
20
  type ReturnType = Agent;
package/node/Agent.mjs CHANGED
@@ -18,6 +18,7 @@ let NodeNanocodex;
18
18
 
19
19
  export function create(options = {}) {
20
20
  const {
21
+ model,
21
22
  thinking,
22
23
  reasoningMode,
23
24
  fastMode,
@@ -31,6 +32,7 @@ export function create(options = {}) {
31
32
  apiBaseUrl,
32
33
  module,
33
34
  tools,
35
+ toolMode,
34
36
  } = options;
35
37
  const events = createEventChannel();
36
38
  if (mpp !== undefined && apiKey !== undefined) {
@@ -40,6 +42,7 @@ export function create(options = {}) {
40
42
  mpp,
41
43
  onEvent: events.emit,
42
44
  tools,
45
+ toolMode,
43
46
  workspace: workspace ?? resume?.workspace,
44
47
  });
45
48
  activateHost(host);
@@ -68,6 +71,7 @@ export function create(options = {}) {
68
71
  decorate: (agent) => agent.extend(agentActions()),
69
72
  });
70
73
  return createAgentClient(runtime, {
74
+ model,
71
75
  thinking,
72
76
  reasoningMode,
73
77
  fastMode,
package/node/host.mjs CHANGED
@@ -18,6 +18,10 @@ export function createNodeHost(options = {}) {
18
18
  require: createRequire(resolve(options.workspace ?? process.cwd(), ".nanocodex-code-mode.cjs")),
19
19
  console: new Console({ stdout: process.stderr, stderr: process.stderr }),
20
20
  });
21
+ const toolMode = options.toolMode ?? "code";
22
+ if (toolMode !== "code" && toolMode !== "direct") {
23
+ throw new TypeError("toolMode must be code or direct");
24
+ }
21
25
  const onEvent = options.onEvent || (() => {});
22
26
  const connectTimeoutMs = options.connectTimeoutMs ?? 30_000;
23
27
  const sendTimeoutMs = options.sendTimeoutMs ?? 30_000;
@@ -237,6 +241,8 @@ export function createNodeHost(options = {}) {
237
241
  close,
238
242
  sleep: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
239
243
  executeCode: code.executeCode,
244
+ executeTool: code.executeTool,
245
+ toolMode: () => toolMode,
240
246
  toolDefinitions: code.toolDefinitions,
241
247
  emitEvent: onEvent,
242
248
  reset: code.reset,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nanocodex",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Viem-style Node and browser bindings for the Nanocodex WASM agent",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -16,6 +16,10 @@
16
16
  "./browser": {
17
17
  "types": "./browser/index.d.mts",
18
18
  "import": "./browser/index.mjs"
19
+ },
20
+ "./wasm": {
21
+ "types": "./wasm.d.mts",
22
+ "import": "./pkg-web/nanocodex_bg.wasm"
19
23
  }
20
24
  },
21
25
  "files": [
@@ -28,6 +32,7 @@
28
32
  "internal.mjs",
29
33
  "index.d.mts",
30
34
  "index.mjs",
35
+ "wasm.d.mts",
31
36
  "types.d.mts",
32
37
  "README.md"
33
38
  ],
@@ -390,20 +390,24 @@ function __wbg_get_imports() {
390
390
  const ret = arg0.call(arg1, arg2);
391
391
  return ret;
392
392
  }, arguments); },
393
- __wbg_close_84b985b15720666a: function(arg0) {
393
+ __wbg_close_01cad5fe38e81c86: function(arg0) {
394
394
  globalThis.nanocodexHost.close(arg0 >>> 0);
395
395
  },
396
- __wbg_connect_fdf81494b56b3a0a: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) {
396
+ __wbg_connect_5611ecc28eb874ce: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) {
397
397
  const ret = globalThis.nanocodexHost.connect(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5), arg6 !== 0, getStringFromWasm0(arg7, arg8), arg9 === 0 ? undefined : getStringFromWasm0(arg9, arg10));
398
398
  return ret;
399
399
  }, arguments); },
400
- __wbg_emitEvent_52491cc5b9c996ad: function(arg0, arg1) {
400
+ __wbg_emitEvent_3feefd1f718bb4db: function(arg0, arg1) {
401
401
  globalThis.nanocodexHost.emitEvent(getStringFromWasm0(arg0, arg1));
402
402
  },
403
- __wbg_executeCode_616baf56d3c8480c: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) {
403
+ __wbg_executeCode_8137943d0e1986eb: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) {
404
404
  const ret = globalThis.nanocodexHost.executeCode(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), getStringFromWasm0(arg4, arg5));
405
405
  return ret;
406
406
  }, arguments); },
407
+ __wbg_executeTool_e4208b9be8ad5132: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
408
+ const ret = globalThis.nanocodexHost.executeTool(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), getStringFromWasm0(arg4, arg5), getStringFromWasm0(arg6, arg7));
409
+ return ret;
410
+ }, arguments); },
407
411
  __wbg_getRandomValues_ceb34d8ffce7e87f: function() { return handleError(function (arg0, arg1) {
408
412
  globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
409
413
  }, arguments); },
@@ -465,7 +469,7 @@ function __wbg_get_imports() {
465
469
  state0.a = 0;
466
470
  }
467
471
  },
468
- __wbg_next_4acad3c8f1e88dfb: function() { return handleError(function (arg0, arg1) {
472
+ __wbg_next_ad2796bd351c174b: function() { return handleError(function (arg0, arg1) {
469
473
  const ret = globalThis.nanocodexHost.next(arg0 >>> 0, arg1 >>> 0);
470
474
  return ret;
471
475
  }, arguments); },
@@ -496,11 +500,11 @@ function __wbg_get_imports() {
496
500
  const ret = arg0.resolvedOptions();
497
501
  return ret;
498
502
  },
499
- __wbg_send_bdd41ab8e18f6042: function() { return handleError(function (arg0, arg1, arg2) {
503
+ __wbg_send_864d9417bda59954: function() { return handleError(function (arg0, arg1, arg2) {
500
504
  const ret = globalThis.nanocodexHost.send(arg0 >>> 0, getStringFromWasm0(arg1, arg2));
501
505
  return ret;
502
506
  }, arguments); },
503
- __wbg_sleep_c32f4fdaac627991: function() { return handleError(function (arg0, arg1, arg2) {
507
+ __wbg_sleep_926d4c81d29ad90a: function() { return handleError(function (arg0, arg1, arg2) {
504
508
  const ret = globalThis.nanocodexHost.sleep(getStringFromWasm0(arg0, arg1), arg2 >>> 0);
505
509
  return ret;
506
510
  }, arguments); },
@@ -528,19 +532,26 @@ function __wbg_get_imports() {
528
532
  const ret = arg0.then(arg1);
529
533
  return ret;
530
534
  },
531
- __wbg_toolDefinitions_4f496f9fbb096753: function() { return handleError(function (arg0, arg1, arg2) {
535
+ __wbg_toolDefinitions_fc0bd1da5e037164: function() { return handleError(function (arg0, arg1, arg2) {
532
536
  const ret = globalThis.nanocodexHost.toolDefinitions(getStringFromWasm0(arg1, arg2));
533
537
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
534
538
  const len1 = WASM_VECTOR_LEN;
535
539
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
536
540
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
537
541
  }, arguments); },
542
+ __wbg_toolMode_4ce2699746be96ac: function(arg0, arg1, arg2) {
543
+ const ret = globalThis.nanocodexHost.toolMode(getStringFromWasm0(arg1, arg2));
544
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
545
+ const len1 = WASM_VECTOR_LEN;
546
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
547
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
548
+ },
538
549
  __wbg_turnresult_new: function(arg0) {
539
550
  const ret = TurnResult.__wrap(arg0);
540
551
  return ret;
541
552
  },
542
553
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
543
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 446, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
554
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 455, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
544
555
  const ret = makeMutClosure(arg0, arg1, wasm_bindgen_6c97e59ea7837008___convert__closures_____invoke___wasm_bindgen_6c97e59ea7837008___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_6c97e59ea7837008___JsError___true_);
545
556
  return ret;
546
557
  },
Binary file
@@ -387,20 +387,24 @@ function __wbg_get_imports() {
387
387
  const ret = arg0.call(arg1, arg2);
388
388
  return ret;
389
389
  }, arguments); },
390
- __wbg_close_84b985b15720666a: function(arg0) {
390
+ __wbg_close_01cad5fe38e81c86: function(arg0) {
391
391
  globalThis.nanocodexHost.close(arg0 >>> 0);
392
392
  },
393
- __wbg_connect_fdf81494b56b3a0a: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) {
393
+ __wbg_connect_5611ecc28eb874ce: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) {
394
394
  const ret = globalThis.nanocodexHost.connect(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5), arg6 !== 0, getStringFromWasm0(arg7, arg8), arg9 === 0 ? undefined : getStringFromWasm0(arg9, arg10));
395
395
  return ret;
396
396
  }, arguments); },
397
- __wbg_emitEvent_52491cc5b9c996ad: function(arg0, arg1) {
397
+ __wbg_emitEvent_3feefd1f718bb4db: function(arg0, arg1) {
398
398
  globalThis.nanocodexHost.emitEvent(getStringFromWasm0(arg0, arg1));
399
399
  },
400
- __wbg_executeCode_616baf56d3c8480c: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) {
400
+ __wbg_executeCode_8137943d0e1986eb: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) {
401
401
  const ret = globalThis.nanocodexHost.executeCode(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), getStringFromWasm0(arg4, arg5));
402
402
  return ret;
403
403
  }, arguments); },
404
+ __wbg_executeTool_e4208b9be8ad5132: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
405
+ const ret = globalThis.nanocodexHost.executeTool(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), getStringFromWasm0(arg4, arg5), getStringFromWasm0(arg6, arg7));
406
+ return ret;
407
+ }, arguments); },
404
408
  __wbg_getRandomValues_ceb34d8ffce7e87f: function() { return handleError(function (arg0, arg1) {
405
409
  globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
406
410
  }, arguments); },
@@ -462,7 +466,7 @@ function __wbg_get_imports() {
462
466
  state0.a = 0;
463
467
  }
464
468
  },
465
- __wbg_next_4acad3c8f1e88dfb: function() { return handleError(function (arg0, arg1) {
469
+ __wbg_next_ad2796bd351c174b: function() { return handleError(function (arg0, arg1) {
466
470
  const ret = globalThis.nanocodexHost.next(arg0 >>> 0, arg1 >>> 0);
467
471
  return ret;
468
472
  }, arguments); },
@@ -493,11 +497,11 @@ function __wbg_get_imports() {
493
497
  const ret = arg0.resolvedOptions();
494
498
  return ret;
495
499
  },
496
- __wbg_send_bdd41ab8e18f6042: function() { return handleError(function (arg0, arg1, arg2) {
500
+ __wbg_send_864d9417bda59954: function() { return handleError(function (arg0, arg1, arg2) {
497
501
  const ret = globalThis.nanocodexHost.send(arg0 >>> 0, getStringFromWasm0(arg1, arg2));
498
502
  return ret;
499
503
  }, arguments); },
500
- __wbg_sleep_c32f4fdaac627991: function() { return handleError(function (arg0, arg1, arg2) {
504
+ __wbg_sleep_926d4c81d29ad90a: function() { return handleError(function (arg0, arg1, arg2) {
501
505
  const ret = globalThis.nanocodexHost.sleep(getStringFromWasm0(arg0, arg1), arg2 >>> 0);
502
506
  return ret;
503
507
  }, arguments); },
@@ -525,19 +529,26 @@ function __wbg_get_imports() {
525
529
  const ret = arg0.then(arg1);
526
530
  return ret;
527
531
  },
528
- __wbg_toolDefinitions_4f496f9fbb096753: function() { return handleError(function (arg0, arg1, arg2) {
532
+ __wbg_toolDefinitions_fc0bd1da5e037164: function() { return handleError(function (arg0, arg1, arg2) {
529
533
  const ret = globalThis.nanocodexHost.toolDefinitions(getStringFromWasm0(arg1, arg2));
530
534
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
531
535
  const len1 = WASM_VECTOR_LEN;
532
536
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
533
537
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
534
538
  }, arguments); },
539
+ __wbg_toolMode_4ce2699746be96ac: function(arg0, arg1, arg2) {
540
+ const ret = globalThis.nanocodexHost.toolMode(getStringFromWasm0(arg1, arg2));
541
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
542
+ const len1 = WASM_VECTOR_LEN;
543
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
544
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
545
+ },
535
546
  __wbg_turnresult_new: function(arg0) {
536
547
  const ret = TurnResult.__wrap(arg0);
537
548
  return ret;
538
549
  },
539
550
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
540
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 446, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
551
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 455, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
541
552
  const ret = makeMutClosure(arg0, arg1, wasm_bindgen_6c97e59ea7837008___convert__closures_____invoke___wasm_bindgen_6c97e59ea7837008___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_6c97e59ea7837008___JsError___true_);
542
553
  return ret;
543
554
  },
Binary file
@@ -23,6 +23,24 @@ export function createCodeRuntime(toolConfiguration = {}, extras = {}) {
23
23
  Object.freeze(configuredTools);
24
24
  Object.freeze(definitions);
25
25
  const encodedDefinitions = JSON.stringify(definitions);
26
+ const toolByName = new Map(configuredTools.map((tool) => [tool.name, tool]));
27
+
28
+ async function executeTool(name, encodedInput, sessionId = "default", callId = "tool") {
29
+ const tool = toolByName.get(name);
30
+ if (!tool) return encodeToolOutput(`unknown application tool: ${name}`, false, null);
31
+ let input;
32
+ try {
33
+ input = JSON.parse(encodedInput);
34
+ } catch (error) {
35
+ return encodeToolOutput(`invalid tool input: ${errorMessage(error)}`, false, null);
36
+ }
37
+ try {
38
+ const result = await tool.handler(input, { sessionId, parentCallId: "", callId });
39
+ return encodeToolOutput(outputBody(result), true, clone(result) ?? null);
40
+ } catch (error) {
41
+ return encodeToolOutput(errorMessage(error), false, null);
42
+ }
43
+ }
26
44
 
27
45
  async function executeCode(source, sessionId = "default", parentCallId = "exec") {
28
46
  const startedAt = performance.now();
@@ -151,6 +169,7 @@ export function createCodeRuntime(toolConfiguration = {}, extras = {}) {
151
169
 
152
170
  return Object.freeze({
153
171
  executeCode,
172
+ executeTool,
154
173
  toolDefinitions: () => encodedDefinitions,
155
174
  reset() {
156
175
  stores.clear();
@@ -158,6 +177,16 @@ export function createCodeRuntime(toolConfiguration = {}, extras = {}) {
158
177
  });
159
178
  }
160
179
 
180
+ function encodeToolOutput(output, success, codeModeValue) {
181
+ return JSON.stringify({
182
+ output,
183
+ success,
184
+ code_mode_value: codeModeValue,
185
+ metadata: null,
186
+ process_trace: null,
187
+ });
188
+ }
189
+
161
190
  function outputBody(value) {
162
191
  if (Array.isArray(value) && value.every((item) => item?.type === "input_text" || item?.type === "input_image")) {
163
192
  return clone(value);
package/types.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type Thinking = "none" | "low" | "medium" | "high" | "xhigh" | "max";
2
2
  export type ReasoningMode = "standard" | "pro";
3
+ export type Model = "gpt-5.6-sol" | "gpt-5.6-terra" | "gpt-5.6-luna";
3
4
 
4
5
  export type PromptItem =
5
6
  | { type: "text"; text: string }
@@ -18,6 +19,7 @@ export type AgentEvent = {
18
19
 
19
20
  export type AgentOptions = {
20
21
  instructions?: string | undefined;
22
+ model?: Model | undefined;
21
23
  reasoningMode?: ReasoningMode | undefined;
22
24
  fastMode?: boolean | undefined;
23
25
  sessionId?: string | undefined;
package/wasm.d.mts ADDED
@@ -0,0 +1,4 @@
1
+ /** Precompiled web WASM module for runtimes that import binary modules. */
2
+ declare const module: WebAssembly.Module;
3
+
4
+ export default module;