nanocodex 0.2.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 +111 -13
- package/actions/events.mjs +105 -22
- package/actions/index.mjs +2 -0
- package/actions/session.d.mts +7 -1
- package/actions/session.mjs +10 -0
- package/actions/turn.d.mts +18 -5
- package/actions/turn.mjs +7 -2
- package/browser/Agent.d.mts +14 -6
- package/browser/Agent.mjs +21 -2
- package/browser/host.d.mts +33 -1
- package/browser/host.mjs +53 -11
- package/browser/index.d.mts +4 -0
- package/index.d.mts +4 -0
- package/internal.mjs +233 -24
- package/node/Agent.d.mts +1 -5
- package/node/Agent.mjs +13 -2
- package/node/host.mjs +39 -12
- package/node/index.d.mts +4 -0
- package/package.json +8 -3
- package/pkg-node/nanocodex.d.ts +69 -38
- package/pkg-node/nanocodex.js +203 -88
- package/pkg-node/nanocodex_bg.wasm +0 -0
- package/pkg-node/nanocodex_bg.wasm.d.ts +7 -2
- package/pkg-web/nanocodex.d.ts +76 -40
- package/pkg-web/nanocodex.js +201 -87
- package/pkg-web/nanocodex_bg.wasm +0 -0
- package/pkg-web/nanocodex_bg.wasm.d.ts +7 -2
- package/runtime/code-runtime.mjs +58 -12
- package/types.d.mts +40 -3
- package/wasm.d.mts +4 -0
- package/scripts/check-package.mjs +0 -38
package/node/host.mjs
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { Console } from "node:console";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
+
import { resolve } from "node:path";
|
|
3
4
|
import WebSocket from "ws";
|
|
5
|
+
import packageMetadata from "../package.json" with { type: "json" };
|
|
4
6
|
|
|
5
7
|
import { createCodeRuntime } from "../runtime/code-runtime.mjs";
|
|
6
8
|
|
|
7
9
|
const RESPONSES_WEBSOCKETS_BETA = "responses_websockets=2026-02-06";
|
|
10
|
+
const USER_AGENT = `nanocodex-wasm/${packageMetadata.version}`;
|
|
8
11
|
const DEFAULT_MAX_QUEUED_MESSAGES = 4_096;
|
|
9
12
|
const DEFAULT_MAX_QUEUED_BYTES = 32 * 1024 * 1024;
|
|
10
13
|
const DEFAULT_MAX_FRAME_BYTES = 16 * 1024 * 1024;
|
|
@@ -12,9 +15,13 @@ const DEFAULT_MAX_FRAME_BYTES = 16 * 1024 * 1024;
|
|
|
12
15
|
export function createNodeHost(options = {}) {
|
|
13
16
|
const connections = new Map();
|
|
14
17
|
const code = createCodeRuntime(options.tools, {
|
|
15
|
-
require: createRequire(
|
|
18
|
+
require: createRequire(resolve(options.workspace ?? process.cwd(), ".nanocodex-code-mode.cjs")),
|
|
16
19
|
console: new Console({ stdout: process.stderr, stderr: process.stderr }),
|
|
17
20
|
});
|
|
21
|
+
const toolMode = options.toolMode ?? "code";
|
|
22
|
+
if (toolMode !== "code" && toolMode !== "direct") {
|
|
23
|
+
throw new TypeError("toolMode must be code or direct");
|
|
24
|
+
}
|
|
18
25
|
const onEvent = options.onEvent || (() => {});
|
|
19
26
|
const connectTimeoutMs = options.connectTimeoutMs ?? 30_000;
|
|
20
27
|
const sendTimeoutMs = options.sendTimeoutMs ?? 30_000;
|
|
@@ -23,29 +30,47 @@ export function createNodeHost(options = {}) {
|
|
|
23
30
|
const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;
|
|
24
31
|
let nextHandle = 1;
|
|
25
32
|
|
|
26
|
-
function connect(endpoint, apiKey, sessionId) {
|
|
33
|
+
function connect(endpoint, apiKey, sessionId, metadata = {}) {
|
|
27
34
|
if (options.mpp) return connectMpp(endpoint);
|
|
28
35
|
return new Promise((resolve, reject) => {
|
|
29
36
|
let settled = false;
|
|
30
37
|
let upgradeResponse;
|
|
38
|
+
const headers = {
|
|
39
|
+
Authorization: `Bearer ${apiKey}`,
|
|
40
|
+
"OpenAI-Beta": RESPONSES_WEBSOCKETS_BETA,
|
|
41
|
+
"x-openai-internal-codex-responses-lite": "true",
|
|
42
|
+
"session-id": sessionId,
|
|
43
|
+
"thread-id": sessionId,
|
|
44
|
+
"x-client-request-id": sessionId,
|
|
45
|
+
"x-responsesapi-include-timing-metrics": "true",
|
|
46
|
+
"User-Agent": USER_AGENT,
|
|
47
|
+
};
|
|
48
|
+
if (metadata.accountId) headers["ChatGPT-Account-ID"] = metadata.accountId;
|
|
49
|
+
if (metadata.fedramp) headers["X-OpenAI-Fedramp"] = "true";
|
|
50
|
+
if (metadata.turnState) headers["x-codex-turn-state"] = metadata.turnState;
|
|
31
51
|
const socket = new WebSocket(endpoint, {
|
|
32
52
|
handshakeTimeout: connectTimeoutMs,
|
|
33
53
|
maxPayload: maxFrameBytes,
|
|
34
|
-
headers
|
|
35
|
-
Authorization: `Bearer ${apiKey}`,
|
|
36
|
-
"OpenAI-Beta": RESPONSES_WEBSOCKETS_BETA,
|
|
37
|
-
"x-openai-internal-codex-responses-lite": "true",
|
|
38
|
-
"session-id": sessionId,
|
|
39
|
-
"thread-id": sessionId,
|
|
40
|
-
"x-client-request-id": sessionId,
|
|
41
|
-
"x-responsesapi-include-timing-metrics": "true",
|
|
42
|
-
"User-Agent": "nanocodex-wasm/0.1.0",
|
|
43
|
-
},
|
|
54
|
+
headers,
|
|
44
55
|
});
|
|
45
56
|
const handle = nextHandle++;
|
|
46
57
|
const connection = queueState(socket);
|
|
47
58
|
|
|
48
59
|
socket.on("upgrade", (response) => { upgradeResponse = response; });
|
|
60
|
+
socket.on("unexpected-response", (_request, response) => {
|
|
61
|
+
if (settled) return;
|
|
62
|
+
settled = true;
|
|
63
|
+
const chunks = [];
|
|
64
|
+
response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
65
|
+
response.on("end", () => {
|
|
66
|
+
const error = new Error(`WebSocket handshake was rejected with HTTP ${response.statusCode}`);
|
|
67
|
+
error.status = response.statusCode;
|
|
68
|
+
error.body = chunks.length ? Buffer.concat(chunks).toString("utf8") : "empty response body";
|
|
69
|
+
const retryAfter = Number(header(response.headers, "retry-after"));
|
|
70
|
+
if (Number.isFinite(retryAfter) && retryAfter >= 0) error.retryAfter = retryAfter;
|
|
71
|
+
reject(error);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
49
74
|
socket.on("open", () => {
|
|
50
75
|
settled = true;
|
|
51
76
|
connections.set(handle, connection);
|
|
@@ -216,6 +241,8 @@ export function createNodeHost(options = {}) {
|
|
|
216
241
|
close,
|
|
217
242
|
sleep: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
|
|
218
243
|
executeCode: code.executeCode,
|
|
244
|
+
executeTool: code.executeTool,
|
|
245
|
+
toolMode: () => toolMode,
|
|
219
246
|
toolDefinitions: code.toolDefinitions,
|
|
220
247
|
emitEvent: onEvent,
|
|
221
248
|
reset: code.reset,
|
package/node/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { Actions } from "../index.mjs";
|
|
2
2
|
export type {
|
|
3
3
|
AgentEvent,
|
|
4
|
+
CostStatus,
|
|
5
|
+
EstimatedUsdCost,
|
|
4
6
|
PromptInput,
|
|
5
7
|
PromptItem,
|
|
6
8
|
ReasoningMode,
|
|
@@ -10,5 +12,7 @@ export type {
|
|
|
10
12
|
ToolContext,
|
|
11
13
|
ToolMap,
|
|
12
14
|
Turn,
|
|
15
|
+
TurnResult,
|
|
16
|
+
TurnUsage,
|
|
13
17
|
} from "../types.mjs";
|
|
14
18
|
export * as Agent from "./Agent.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nanocodex",
|
|
3
|
-
"version": "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": [
|
|
@@ -25,10 +29,10 @@
|
|
|
25
29
|
"pkg-node",
|
|
26
30
|
"pkg-web",
|
|
27
31
|
"runtime",
|
|
28
|
-
"scripts/check-package.mjs",
|
|
29
32
|
"internal.mjs",
|
|
30
33
|
"index.d.mts",
|
|
31
34
|
"index.mjs",
|
|
35
|
+
"wasm.d.mts",
|
|
32
36
|
"types.d.mts",
|
|
33
37
|
"README.md"
|
|
34
38
|
],
|
|
@@ -39,7 +43,8 @@
|
|
|
39
43
|
"scripts": {
|
|
40
44
|
"check:package": "node scripts/check-package.mjs",
|
|
41
45
|
"prepack": "npm run check:package",
|
|
42
|
-
"test": "node --test test/*.test.mjs && npm run test:typecheck && npm run check:package",
|
|
46
|
+
"test": "node --test test/*.test.mjs && npm run test:performance && npm run test:typecheck && npm run check:package",
|
|
47
|
+
"test:performance": "node --test test/performance.bench.mjs",
|
|
43
48
|
"test:typecheck": "tsc -p test/tsconfig.json"
|
|
44
49
|
},
|
|
45
50
|
"dependencies": {
|
package/pkg-node/nanocodex.d.ts
CHANGED
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* JavaScript binding over the shared Rust agent lifecycle.
|
|
6
6
|
*/
|
|
7
7
|
export class Nanocodex {
|
|
8
8
|
free(): void;
|
|
9
9
|
[Symbol.dispose](): void;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Compacts retained history immediately without fabricating a user prompt.
|
|
12
|
+
*
|
|
13
|
+
* # Errors
|
|
14
|
+
*
|
|
15
|
+
* Throws when compaction or the agent driver fails.
|
|
16
|
+
*/
|
|
17
|
+
compact(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Forks the latest safe committed model boundary.
|
|
12
20
|
*
|
|
13
21
|
* # Errors
|
|
14
22
|
*
|
|
@@ -16,57 +24,63 @@ export class Nanocodex {
|
|
|
16
24
|
*/
|
|
17
25
|
fork(): Promise<Nanocodex>;
|
|
18
26
|
/**
|
|
19
|
-
*
|
|
27
|
+
* Forks from an exact completed historical turn.
|
|
20
28
|
*
|
|
21
29
|
* # Errors
|
|
22
30
|
*
|
|
23
|
-
* Rejects if the
|
|
24
|
-
* driver stops.
|
|
31
|
+
* Rejects if the result belongs to another agent or the driver stopped.
|
|
25
32
|
*/
|
|
26
|
-
forkFrom(
|
|
33
|
+
forkFrom(result: TurnResult): Promise<Nanocodex>;
|
|
27
34
|
/**
|
|
28
|
-
*
|
|
35
|
+
* Builds an agent from its JavaScript JSON configuration.
|
|
29
36
|
*
|
|
30
37
|
* # Errors
|
|
31
38
|
*
|
|
32
|
-
* Throws when the JSON or
|
|
39
|
+
* Throws when the JSON or agent policy is invalid.
|
|
33
40
|
*/
|
|
34
41
|
constructor(config_json: string);
|
|
35
42
|
/**
|
|
36
|
-
*
|
|
43
|
+
* Accepts a text prompt and returns its independently awaitable turn.
|
|
37
44
|
*
|
|
38
45
|
* # Errors
|
|
39
46
|
*
|
|
40
|
-
* Throws when the prompt is empty
|
|
47
|
+
* Throws when the prompt is empty.
|
|
41
48
|
*/
|
|
42
49
|
prompt(instruction: string): Turn;
|
|
43
50
|
/**
|
|
44
|
-
*
|
|
51
|
+
* Accepts browser-safe multimodal input encoded as JSON.
|
|
45
52
|
*
|
|
46
53
|
* # Errors
|
|
47
54
|
*
|
|
48
|
-
* Throws for malformed
|
|
49
|
-
* stopped driver.
|
|
55
|
+
* Throws for malformed, empty, or local-filesystem input.
|
|
50
56
|
*/
|
|
51
57
|
promptContent(content_json: string): Turn;
|
|
52
58
|
/**
|
|
53
|
-
*
|
|
59
|
+
* Enables or disables priority processing for subsequently accepted turns.
|
|
54
60
|
*
|
|
55
61
|
* # Errors
|
|
56
62
|
*
|
|
57
|
-
* Rejects after the
|
|
63
|
+
* Rejects after the driver stops.
|
|
58
64
|
*/
|
|
59
65
|
setFastMode(enabled: boolean): Promise<void>;
|
|
60
66
|
/**
|
|
61
|
-
*
|
|
67
|
+
* Changes the reasoning effort for subsequently accepted turns.
|
|
62
68
|
*
|
|
63
69
|
* # Errors
|
|
64
70
|
*
|
|
65
|
-
* Rejects an
|
|
71
|
+
* Rejects an invalid effort or a stopped driver.
|
|
66
72
|
*/
|
|
67
73
|
setThinking(thinking: string): Promise<void>;
|
|
68
74
|
/**
|
|
69
|
-
*
|
|
75
|
+
* Gracefully stops the driver and joins every resource owned by this agent.
|
|
76
|
+
*
|
|
77
|
+
* # Errors
|
|
78
|
+
*
|
|
79
|
+
* Rejects when the driver had already stopped or cleanup fails.
|
|
80
|
+
*/
|
|
81
|
+
shutdown(): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Starts a clean sibling with the same private agent policy.
|
|
70
84
|
*
|
|
71
85
|
* # Errors
|
|
72
86
|
*
|
|
@@ -74,60 +88,77 @@ export class Nanocodex {
|
|
|
74
88
|
*/
|
|
75
89
|
spawn(): Promise<Nanocodex>;
|
|
76
90
|
/**
|
|
77
|
-
*
|
|
91
|
+
* Returns the stable `UUIDv7` session identity.
|
|
78
92
|
*/
|
|
79
93
|
readonly sessionId: string;
|
|
80
94
|
}
|
|
81
95
|
|
|
82
96
|
/**
|
|
83
|
-
*
|
|
97
|
+
* JavaScript binding over one shared Rust turn.
|
|
84
98
|
*/
|
|
85
99
|
export class Turn {
|
|
86
100
|
private constructor();
|
|
87
101
|
free(): void;
|
|
88
102
|
[Symbol.dispose](): void;
|
|
89
103
|
/**
|
|
90
|
-
*
|
|
104
|
+
* Cancels this exact active or queued turn.
|
|
91
105
|
*
|
|
92
106
|
* # Errors
|
|
93
107
|
*
|
|
94
|
-
* Rejects if the turn is already terminal or
|
|
108
|
+
* Rejects if the turn is already terminal or its driver stopped.
|
|
95
109
|
*/
|
|
96
110
|
cancel(): Promise<void>;
|
|
97
111
|
/**
|
|
98
|
-
*
|
|
112
|
+
* Waits for the final assistant message.
|
|
99
113
|
*
|
|
100
114
|
* # Errors
|
|
101
115
|
*
|
|
102
|
-
* Rejects when the model run
|
|
103
|
-
* await the same pending turn concurrently.
|
|
116
|
+
* Rejects when the model run or driver fails.
|
|
104
117
|
*/
|
|
105
|
-
result(): Promise<
|
|
118
|
+
result(): Promise<TurnResult>;
|
|
106
119
|
/**
|
|
107
|
-
*
|
|
120
|
+
* Injects text input at the active turn's next safe model boundary.
|
|
108
121
|
*
|
|
109
122
|
* # Errors
|
|
110
123
|
*
|
|
111
|
-
*
|
|
124
|
+
* Rejects if the turn is not active or its driver stopped.
|
|
112
125
|
*/
|
|
113
|
-
|
|
126
|
+
steer(instruction: string): Promise<void>;
|
|
114
127
|
/**
|
|
115
|
-
*
|
|
128
|
+
* Injects browser-safe multimodal input at the active turn's next boundary.
|
|
116
129
|
*
|
|
117
130
|
* # Errors
|
|
118
131
|
*
|
|
119
|
-
* Rejects
|
|
120
|
-
* or a stopped driver.
|
|
132
|
+
* Rejects malformed input or a turn that is no longer active.
|
|
121
133
|
*/
|
|
122
|
-
|
|
134
|
+
steerContent(content_json: string): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* JavaScript binding over one completed Rust turn result.
|
|
139
|
+
*/
|
|
140
|
+
export class TurnResult {
|
|
141
|
+
private constructor();
|
|
142
|
+
free(): void;
|
|
143
|
+
[Symbol.dispose](): void;
|
|
123
144
|
/**
|
|
124
|
-
*
|
|
125
|
-
* turn's next safe model boundary.
|
|
145
|
+
* Serializes this completed boundary's resumable session snapshot.
|
|
126
146
|
*
|
|
127
147
|
* # Errors
|
|
128
148
|
*
|
|
129
|
-
*
|
|
130
|
-
* queued or terminal turn, a full steer queue, or a stopped driver.
|
|
149
|
+
* Throws when serialization fails.
|
|
131
150
|
*/
|
|
132
|
-
|
|
151
|
+
snapshot(): string;
|
|
152
|
+
/**
|
|
153
|
+
* Serializes exact aggregate usage for this completed logical turn.
|
|
154
|
+
*
|
|
155
|
+
* # Errors
|
|
156
|
+
*
|
|
157
|
+
* Throws when serialization fails.
|
|
158
|
+
*/
|
|
159
|
+
usage(): string;
|
|
160
|
+
/**
|
|
161
|
+
* Returns the final assistant message.
|
|
162
|
+
*/
|
|
163
|
+
readonly finalMessage: string;
|
|
133
164
|
}
|