@ai-sdk/harness-codex 1.0.73 → 1.0.75
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/CHANGELOG.md +22 -0
- package/README.md +10 -1
- package/dist/bridge/index.mjs +17 -21
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +153 -56
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/bridge/index.ts +5 -0
- package/src/codex-auth.ts +52 -2
- package/src/codex-bootstrap.ts +60 -0
- package/src/codex-bridge-protocol.ts +1 -0
- package/src/codex-harness.ts +123 -75
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @ai-sdk/harness-codex
|
|
2
2
|
|
|
3
|
+
## 1.0.75
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 62a9c2a: feat(harness): add support for structured output to `HarnessAgent` via `output` property
|
|
8
|
+
- Updated dependencies [62a9c2a]
|
|
9
|
+
- Updated dependencies [d25cae2]
|
|
10
|
+
- @ai-sdk/harness@1.0.73
|
|
11
|
+
|
|
12
|
+
## 1.0.74
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 69bb613: feat(harness): support request transformations in network sandbox abstraction and use it to apply credential brokering when available
|
|
17
|
+
- 52bc889: feat(harness): add `getPortEndpoint()` as more comprehensive replacement to `getPortUrl()` (now deprecated) in `HarnessV1NetworkSandboxSession`
|
|
18
|
+
- c89c2ec: feat(harness-codex): allow passing arbitrary `config.toml` values to the harness via `codexConfig`
|
|
19
|
+
- 4cd4989: chore(harness): decouple bridge based harness bootstrap recipe logic from dynamic params and enforce unique harnesses in `prepareSandboxForHarness()` helper
|
|
20
|
+
- Updated dependencies [69bb613]
|
|
21
|
+
- Updated dependencies [52bc889]
|
|
22
|
+
- Updated dependencies [4cd4989]
|
|
23
|
+
- @ai-sdk/harness@1.0.72
|
|
24
|
+
|
|
3
25
|
## 1.0.73
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -20,7 +20,11 @@ import { tool } from 'ai';
|
|
|
20
20
|
import { z } from 'zod/v4';
|
|
21
21
|
|
|
22
22
|
const agent = new HarnessAgent({
|
|
23
|
-
harness: createCodex(
|
|
23
|
+
harness: createCodex({
|
|
24
|
+
codexConfig: {
|
|
25
|
+
model_verbosity: 'low',
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
24
28
|
id: 'demo',
|
|
25
29
|
sandbox: createVercelSandbox({
|
|
26
30
|
runtime: 'node24',
|
|
@@ -39,6 +43,11 @@ const agent = new HarnessAgent({
|
|
|
39
43
|
});
|
|
40
44
|
```
|
|
41
45
|
|
|
46
|
+
`codexConfig` accepts additional native Codex configuration. Values pass
|
|
47
|
+
through as provided, so use the snake_case keys from Codex's `config.toml`
|
|
48
|
+
reference. The adapter's managed values take precedence over conflicting
|
|
49
|
+
entries.
|
|
50
|
+
|
|
42
51
|
> Codex does not auto-discover a skills directory the way the `claude` CLI
|
|
43
52
|
> does, so when you supply `skills: [...]` on the factory the adapter
|
|
44
53
|
> injects every skill inline into the user prompt on each turn. Use fewer,
|
package/dist/bridge/index.mjs
CHANGED
|
@@ -53,7 +53,6 @@ async function runBridge(options) {
|
|
|
53
53
|
let currentBoundPort = 0;
|
|
54
54
|
let currentTurnState = "init";
|
|
55
55
|
let activeSocket;
|
|
56
|
-
let activeSocketReadyForLiveEvents = false;
|
|
57
56
|
let isFirstTurn = true;
|
|
58
57
|
let turnAbort;
|
|
59
58
|
let currentUserMessages;
|
|
@@ -137,14 +136,6 @@ async function runBridge(options) {
|
|
|
137
136
|
} catch {
|
|
138
137
|
}
|
|
139
138
|
};
|
|
140
|
-
const sendControl = (msg) => {
|
|
141
|
-
if (activeSocket?.readyState === WS_OPEN) {
|
|
142
|
-
try {
|
|
143
|
-
activeSocket.send(JSON.stringify(msg));
|
|
144
|
-
} catch {
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
139
|
const emit = (event) => {
|
|
149
140
|
const seq = ++seqCounter;
|
|
150
141
|
const line = JSON.stringify({ ...event, seq });
|
|
@@ -152,7 +143,7 @@ async function runBridge(options) {
|
|
|
152
143
|
diskBuffer += `${line}
|
|
153
144
|
`;
|
|
154
145
|
scheduleEventFlush();
|
|
155
|
-
if (
|
|
146
|
+
if (activeSocket?.readyState === WS_OPEN) {
|
|
156
147
|
try {
|
|
157
148
|
activeSocket.send(line);
|
|
158
149
|
} catch {
|
|
@@ -255,8 +246,7 @@ async function runBridge(options) {
|
|
|
255
246
|
const handleInbound = async (msg, ws) => {
|
|
256
247
|
switch (msg.type) {
|
|
257
248
|
case "start": {
|
|
258
|
-
|
|
259
|
-
activeSocketReadyForLiveEvents = true;
|
|
249
|
+
activeSocket = ws;
|
|
260
250
|
const firstTurn = isFirstTurn;
|
|
261
251
|
isFirstTurn = false;
|
|
262
252
|
eventLog = [];
|
|
@@ -336,9 +326,8 @@ async function runBridge(options) {
|
|
|
336
326
|
turnAbort?.abort();
|
|
337
327
|
return;
|
|
338
328
|
case "resume":
|
|
339
|
-
|
|
329
|
+
activeSocket = ws;
|
|
340
330
|
replay(ws, msg.lastSeenEventId);
|
|
341
|
-
activeSocketReadyForLiveEvents = true;
|
|
342
331
|
return;
|
|
343
332
|
case "destroy":
|
|
344
333
|
currentTurnState = "done";
|
|
@@ -350,7 +339,7 @@ async function runBridge(options) {
|
|
|
350
339
|
currentTurnState = "done";
|
|
351
340
|
void writeBridgeMeta("done");
|
|
352
341
|
const data = await onStop?.() ?? {};
|
|
353
|
-
sendControl({ type: "bridge-stop", data });
|
|
342
|
+
sendControl(ws, { type: "bridge-stop", data });
|
|
354
343
|
drainThenExit(ws, 1e3, "stop");
|
|
355
344
|
return;
|
|
356
345
|
}
|
|
@@ -403,9 +392,7 @@ async function runBridge(options) {
|
|
|
403
392
|
ws.close(1008, "unauthorized");
|
|
404
393
|
return;
|
|
405
394
|
}
|
|
406
|
-
|
|
407
|
-
activeSocketReadyForLiveEvents = false;
|
|
408
|
-
sendControl({
|
|
395
|
+
sendControl(ws, {
|
|
409
396
|
type: "bridge-hello",
|
|
410
397
|
state: currentTurnState,
|
|
411
398
|
lastSeq: seqCounter
|
|
@@ -416,7 +403,7 @@ async function runBridge(options) {
|
|
|
416
403
|
const text = typeof raw === "string" ? raw : Buffer.from(raw).toString("utf8");
|
|
417
404
|
parsed = JSON.parse(text);
|
|
418
405
|
} catch (err) {
|
|
419
|
-
sendControl({
|
|
406
|
+
sendControl(ws, {
|
|
420
407
|
type: "error",
|
|
421
408
|
error: `protocol parse error: ${err.message}`
|
|
422
409
|
});
|
|
@@ -427,7 +414,6 @@ async function runBridge(options) {
|
|
|
427
414
|
ws.on("close", () => {
|
|
428
415
|
if (activeSocket === ws) {
|
|
429
416
|
activeSocket = void 0;
|
|
430
|
-
activeSocketReadyForLiveEvents = false;
|
|
431
417
|
}
|
|
432
418
|
});
|
|
433
419
|
ws.on("error", () => {
|
|
@@ -454,6 +440,14 @@ async function runBridge(options) {
|
|
|
454
440
|
})
|
|
455
441
|
};
|
|
456
442
|
}
|
|
443
|
+
function sendControl(socket, message) {
|
|
444
|
+
if (socket?.readyState === WS_OPEN) {
|
|
445
|
+
try {
|
|
446
|
+
socket.send(JSON.stringify(message));
|
|
447
|
+
} catch {
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
457
451
|
function serialiseError(err) {
|
|
458
452
|
if (err instanceof Error) {
|
|
459
453
|
return { name: err.name, message: err.message, stack: err.stack };
|
|
@@ -1159,6 +1153,7 @@ async function runTurn(start, turn) {
|
|
|
1159
1153
|
);
|
|
1160
1154
|
}
|
|
1161
1155
|
const codexConfig = {
|
|
1156
|
+
...start.codexConfig,
|
|
1162
1157
|
developer_instructions: [
|
|
1163
1158
|
start.instructions,
|
|
1164
1159
|
"Only respond with your `final` message once you have fully addressed the user request."
|
|
@@ -1234,7 +1229,8 @@ async function runTurn(start, turn) {
|
|
|
1234
1229
|
});
|
|
1235
1230
|
try {
|
|
1236
1231
|
const { events } = await thread.runStreamed(userMessage, {
|
|
1237
|
-
signal: turn.abortSignal
|
|
1232
|
+
signal: turn.abortSignal,
|
|
1233
|
+
...start.responseFormat?.type === "json" && start.responseFormat.schema != null ? { outputSchema: start.responseFormat.schema } : {}
|
|
1238
1234
|
});
|
|
1239
1235
|
for await (const event of events) {
|
|
1240
1236
|
if (turn.abortSignal.aborted) break;
|