@ai-sdk/harness-codex 1.0.93 → 1.0.95
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 +23 -0
- package/dist/bridge/index.mjs +32 -6
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/bridge/package.json +1 -1
- package/dist/bridge/pnpm-lock.yaml +34 -34
- package/dist/index.d.ts +6 -27
- package/dist/index.js +112 -102
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/bridge/index.ts +3 -1
- package/src/bridge/package.json +1 -1
- package/src/bridge/pnpm-lock.yaml +34 -34
- package/src/codex-auth.ts +28 -107
- package/src/codex-bridge-protocol.ts +1 -0
- package/src/codex-harness.ts +139 -48
- package/src/index.ts +1 -1
package/dist/bridge/package.json
CHANGED
|
@@ -9,55 +9,55 @@ importers:
|
|
|
9
9
|
.:
|
|
10
10
|
dependencies:
|
|
11
11
|
'@openai/codex-sdk':
|
|
12
|
-
specifier: 0.
|
|
13
|
-
version: 0.
|
|
12
|
+
specifier: 0.149.1
|
|
13
|
+
version: 0.149.1
|
|
14
14
|
ws:
|
|
15
15
|
specifier: 8.21.0
|
|
16
16
|
version: 8.21.0
|
|
17
17
|
|
|
18
18
|
packages:
|
|
19
19
|
|
|
20
|
-
'@openai/codex-sdk@0.
|
|
21
|
-
resolution: {integrity: sha512-
|
|
20
|
+
'@openai/codex-sdk@0.149.1':
|
|
21
|
+
resolution: {integrity: sha512-R00Rz5327LefZggAxl28r7vFQq1vxa91OxtjZJOsQfAM/MyH8InW5qwwRu6pzUmRGp1E29XrOzm7u1TeV5Yz2A==}
|
|
22
22
|
engines: {node: '>=18'}
|
|
23
23
|
|
|
24
|
-
'@openai/codex@0.
|
|
25
|
-
resolution: {integrity: sha512-
|
|
24
|
+
'@openai/codex@0.149.1':
|
|
25
|
+
resolution: {integrity: sha512-6q5pbcpFbJbqOpkubSDBwXmktQ55aD8eUzGzBF1zASob2DjwhBKDSNGtdZKalfrNJUdTDTPDMmzCXEXs5tMBYA==}
|
|
26
26
|
engines: {node: '>=16'}
|
|
27
27
|
hasBin: true
|
|
28
28
|
|
|
29
|
-
'@openai/codex@0.
|
|
30
|
-
resolution: {integrity: sha512-
|
|
29
|
+
'@openai/codex@0.149.1-darwin-arm64':
|
|
30
|
+
resolution: {integrity: sha512-6X84kTCbnTgPIJ2EdcPsrvwS0Wxsqpa+bCswGmRf4BjhcQ5nPMnBC6yCAaCMj+vrbXQHj+L6sa9FaR4QkmA1qw==}
|
|
31
31
|
engines: {node: '>=16'}
|
|
32
32
|
cpu: [arm64]
|
|
33
33
|
os: [darwin]
|
|
34
34
|
|
|
35
|
-
'@openai/codex@0.
|
|
36
|
-
resolution: {integrity: sha512
|
|
35
|
+
'@openai/codex@0.149.1-darwin-x64':
|
|
36
|
+
resolution: {integrity: sha512-MfLBQLfcElJL9tvj6y45qVHHMGSXCPnQOixuD3/Zq0g1BW/eFizkrGLdn48cFpc+l8cK+gt5nYG5pQYwVs6g4A==}
|
|
37
37
|
engines: {node: '>=16'}
|
|
38
38
|
cpu: [x64]
|
|
39
39
|
os: [darwin]
|
|
40
40
|
|
|
41
|
-
'@openai/codex@0.
|
|
42
|
-
resolution: {integrity: sha512-
|
|
41
|
+
'@openai/codex@0.149.1-linux-arm64':
|
|
42
|
+
resolution: {integrity: sha512-OqxUfZ1TVvHd18zHPKK/8ZRlpk8Vy11mg5CMHaLxNWldTbwVImDKtSLWT+m8m4NM5Sz4PbjtZMrVT/RfpBW/mQ==}
|
|
43
43
|
engines: {node: '>=16'}
|
|
44
44
|
cpu: [arm64]
|
|
45
45
|
os: [linux]
|
|
46
46
|
|
|
47
|
-
'@openai/codex@0.
|
|
48
|
-
resolution: {integrity: sha512-
|
|
47
|
+
'@openai/codex@0.149.1-linux-x64':
|
|
48
|
+
resolution: {integrity: sha512-Of5fGYgr7tAMsyj6vhXb4/RM/UoA3Zq8BLegUBDC09UNy1XTLGYP/2XD+UX8z3qh0NDwxYdCjFIWdDNijKZggQ==}
|
|
49
49
|
engines: {node: '>=16'}
|
|
50
50
|
cpu: [x64]
|
|
51
51
|
os: [linux]
|
|
52
52
|
|
|
53
|
-
'@openai/codex@0.
|
|
54
|
-
resolution: {integrity: sha512-
|
|
53
|
+
'@openai/codex@0.149.1-win32-arm64':
|
|
54
|
+
resolution: {integrity: sha512-5K0DmOKGK9Bos627p8sK8ATHjovPK0sDyT6h9Cb+4v+5CW5SGw1HLgjGxoLfJ8g3cg6mtg/pRCXXo2L/j71UVA==}
|
|
55
55
|
engines: {node: '>=16'}
|
|
56
56
|
cpu: [arm64]
|
|
57
57
|
os: [win32]
|
|
58
58
|
|
|
59
|
-
'@openai/codex@0.
|
|
60
|
-
resolution: {integrity: sha512-
|
|
59
|
+
'@openai/codex@0.149.1-win32-x64':
|
|
60
|
+
resolution: {integrity: sha512-G3QXGAg7nyyhqOeooAMUekBCeHd8a1QByhKcVAFyzNBaI06t6Ft7nsF+1SzFS0spuIdU4YyMi5YD26ukADBQUQ==}
|
|
61
61
|
engines: {node: '>=16'}
|
|
62
62
|
cpu: [x64]
|
|
63
63
|
os: [win32]
|
|
@@ -76,35 +76,35 @@ packages:
|
|
|
76
76
|
|
|
77
77
|
snapshots:
|
|
78
78
|
|
|
79
|
-
'@openai/codex-sdk@0.
|
|
79
|
+
'@openai/codex-sdk@0.149.1':
|
|
80
80
|
dependencies:
|
|
81
|
-
'@openai/codex': 0.
|
|
81
|
+
'@openai/codex': 0.149.1
|
|
82
82
|
|
|
83
|
-
'@openai/codex@0.
|
|
83
|
+
'@openai/codex@0.149.1':
|
|
84
84
|
optionalDependencies:
|
|
85
|
-
'@openai/codex-darwin-arm64': '@openai/codex@0.
|
|
86
|
-
'@openai/codex-darwin-x64': '@openai/codex@0.
|
|
87
|
-
'@openai/codex-linux-arm64': '@openai/codex@0.
|
|
88
|
-
'@openai/codex-linux-x64': '@openai/codex@0.
|
|
89
|
-
'@openai/codex-win32-arm64': '@openai/codex@0.
|
|
90
|
-
'@openai/codex-win32-x64': '@openai/codex@0.
|
|
91
|
-
|
|
92
|
-
'@openai/codex@0.
|
|
85
|
+
'@openai/codex-darwin-arm64': '@openai/codex@0.149.1-darwin-arm64'
|
|
86
|
+
'@openai/codex-darwin-x64': '@openai/codex@0.149.1-darwin-x64'
|
|
87
|
+
'@openai/codex-linux-arm64': '@openai/codex@0.149.1-linux-arm64'
|
|
88
|
+
'@openai/codex-linux-x64': '@openai/codex@0.149.1-linux-x64'
|
|
89
|
+
'@openai/codex-win32-arm64': '@openai/codex@0.149.1-win32-arm64'
|
|
90
|
+
'@openai/codex-win32-x64': '@openai/codex@0.149.1-win32-x64'
|
|
91
|
+
|
|
92
|
+
'@openai/codex@0.149.1-darwin-arm64':
|
|
93
93
|
optional: true
|
|
94
94
|
|
|
95
|
-
'@openai/codex@0.
|
|
95
|
+
'@openai/codex@0.149.1-darwin-x64':
|
|
96
96
|
optional: true
|
|
97
97
|
|
|
98
|
-
'@openai/codex@0.
|
|
98
|
+
'@openai/codex@0.149.1-linux-arm64':
|
|
99
99
|
optional: true
|
|
100
100
|
|
|
101
|
-
'@openai/codex@0.
|
|
101
|
+
'@openai/codex@0.149.1-linux-x64':
|
|
102
102
|
optional: true
|
|
103
103
|
|
|
104
|
-
'@openai/codex@0.
|
|
104
|
+
'@openai/codex@0.149.1-win32-arm64':
|
|
105
105
|
optional: true
|
|
106
106
|
|
|
107
|
-
'@openai/codex@0.
|
|
107
|
+
'@openai/codex@0.149.1-win32-x64':
|
|
108
108
|
optional: true
|
|
109
109
|
|
|
110
110
|
ws@8.21.0: {}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,33 +1,10 @@
|
|
|
1
1
|
import * as _ai_sdk_harness from '@ai-sdk/harness';
|
|
2
|
-
import { HarnessV1CredentialForwarding, HarnessV1PortEndpoint, HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
2
|
+
import { HarnessV1Authentication, HarnessV1CredentialForwarding, HarnessV1PortEndpoint, HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
3
3
|
|
|
4
|
-
type
|
|
5
|
-
type CodexAuthenticationMode = CodexResolvedAuthenticationMode | 'auto';
|
|
6
|
-
/**
|
|
7
|
-
* @deprecated Passing an object to auth options is deprecated. Use a `CodexAuthenticationMode` string value ("auto" | "direct" | "ai-gateway") instead, and pass credentials via environment variables.
|
|
8
|
-
*/
|
|
9
|
-
type LegacyCodexAuthOptions = {
|
|
10
|
-
readonly openaiCompatible?: {
|
|
11
|
-
readonly apiKey?: string;
|
|
12
|
-
readonly baseUrl?: string;
|
|
13
|
-
readonly modelProviderName?: string;
|
|
14
|
-
readonly queryParamsJson?: string;
|
|
15
|
-
};
|
|
16
|
-
readonly openai?: {
|
|
17
|
-
readonly apiKey?: string;
|
|
18
|
-
readonly baseUrl?: string;
|
|
19
|
-
readonly organization?: string;
|
|
20
|
-
readonly project?: string;
|
|
21
|
-
};
|
|
22
|
-
readonly gateway?: {
|
|
23
|
-
readonly apiKey?: string;
|
|
24
|
-
readonly baseUrl?: string;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
type CodexAuthOptions = CodexAuthenticationMode | LegacyCodexAuthOptions;
|
|
4
|
+
type CodexAuthenticationMode = HarnessV1Authentication;
|
|
28
5
|
|
|
29
6
|
type CodexHarnessSettings = {
|
|
30
|
-
readonly auth?:
|
|
7
|
+
readonly auth?: CodexAuthenticationMode;
|
|
31
8
|
/**
|
|
32
9
|
* Customizes each credential value before it is forwarded into a sandbox
|
|
33
10
|
* process. This does not restrict which credentials the harness adapter can
|
|
@@ -48,6 +25,8 @@ type CodexHarnessSettings = {
|
|
|
48
25
|
/**
|
|
49
26
|
* OpenAI model id the underlying `codex` CLI should use. Leaving this unset
|
|
50
27
|
* pins the adapter default (`DEFAULT_CODEX_MODEL`).
|
|
28
|
+
*
|
|
29
|
+
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
51
30
|
*/
|
|
52
31
|
readonly model?: string;
|
|
53
32
|
/**
|
|
@@ -105,4 +84,4 @@ declare const codex: _ai_sdk_harness.HarnessV1<{
|
|
|
105
84
|
}, unknown>;
|
|
106
85
|
}>;
|
|
107
86
|
|
|
108
|
-
export { type
|
|
87
|
+
export { type CodexAuthenticationMode, type CodexHarnessSettings, VERSION, codex, createCodex };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/codex-harness.ts
|
|
2
|
-
import { randomBytes } from "crypto";
|
|
2
|
+
import { createHash, randomBytes } from "crypto";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import {
|
|
5
5
|
commonTool,
|
|
@@ -76,7 +76,8 @@ async function readBridgeAsset(name) {
|
|
|
76
76
|
// src/codex-auth.ts
|
|
77
77
|
import {
|
|
78
78
|
createCredentialRequestTransformation,
|
|
79
|
-
getAiGatewayAuthFromEnv
|
|
79
|
+
getAiGatewayAuthFromEnv,
|
|
80
|
+
isHarnessAuthenticationEnvironment
|
|
80
81
|
} from "@ai-sdk/harness/utils";
|
|
81
82
|
var DEFAULT_AI_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh/v1";
|
|
82
83
|
var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
@@ -105,95 +106,50 @@ function createCodexRequestTransformations({
|
|
|
105
106
|
];
|
|
106
107
|
}
|
|
107
108
|
function resolveCodexEnv(auth, processEnv = process.env) {
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (normalizedAuth?.openai) {
|
|
113
|
-
return pickOpenAI({ explicit: normalizedAuth.openai, processEnv });
|
|
109
|
+
const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);
|
|
110
|
+
const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;
|
|
111
|
+
if (auth === "direct") {
|
|
112
|
+
return pickOpenAI({ processEnv: authenticationEnvironment });
|
|
114
113
|
}
|
|
115
114
|
const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({
|
|
116
|
-
env:
|
|
115
|
+
env: authenticationEnvironment
|
|
117
116
|
});
|
|
118
|
-
if (
|
|
119
|
-
return pickGateway({
|
|
120
|
-
explicit: normalizedAuth.gateway,
|
|
121
|
-
gatewayAuthFromEnv
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
if (gatewayAuthFromEnv.apiKey) {
|
|
125
|
-
return pickGateway({
|
|
126
|
-
explicit: {},
|
|
127
|
-
gatewayAuthFromEnv
|
|
128
|
-
});
|
|
117
|
+
if (auth === "ai-gateway" || gatewayAuthFromEnv.apiKey) {
|
|
118
|
+
return pickGateway({ gatewayAuthFromEnv });
|
|
129
119
|
}
|
|
130
|
-
return pickOpenAI({ processEnv });
|
|
120
|
+
return pickOpenAI({ processEnv: authenticationEnvironment });
|
|
131
121
|
}
|
|
132
122
|
function resolveCodexAuthenticationMode(auth, processEnv = process.env) {
|
|
133
|
-
if (
|
|
134
|
-
return "direct";
|
|
123
|
+
if (isHarnessAuthenticationEnvironment(auth)) {
|
|
124
|
+
return getAiGatewayAuthFromEnv({ env: auth }).apiKey ? "ai-gateway" : "direct";
|
|
135
125
|
}
|
|
136
|
-
if (auth === "direct"
|
|
126
|
+
if (auth === "direct") {
|
|
137
127
|
return "direct";
|
|
138
128
|
}
|
|
139
|
-
if (auth === "ai-gateway"
|
|
129
|
+
if (auth === "ai-gateway") {
|
|
140
130
|
return "ai-gateway";
|
|
141
131
|
}
|
|
142
132
|
return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey ? "ai-gateway" : "direct";
|
|
143
133
|
}
|
|
144
|
-
function normalizeCodexAuthToLegacyAuth(auth) {
|
|
145
|
-
if (auth == null || auth === "auto") {
|
|
146
|
-
return void 0;
|
|
147
|
-
}
|
|
148
|
-
if (typeof auth === "string") {
|
|
149
|
-
switch (auth) {
|
|
150
|
-
case "direct":
|
|
151
|
-
return { openai: {} };
|
|
152
|
-
case "ai-gateway":
|
|
153
|
-
return { gateway: {} };
|
|
154
|
-
default:
|
|
155
|
-
return void 0;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
console.warn(
|
|
159
|
-
'[codex] Passing an object to auth options is deprecated. Use a string mode ("auto" | "direct" | "ai-gateway") instead, and pass credentials via environment variables.'
|
|
160
|
-
);
|
|
161
|
-
return auth;
|
|
162
|
-
}
|
|
163
|
-
function pickOpenAICompatible(explicit, processEnv) {
|
|
164
|
-
const env = {};
|
|
165
|
-
const apiKey = explicit.apiKey ?? processEnv.OPENAI_API_KEY ?? processEnv.CODEX_API_KEY;
|
|
166
|
-
if (apiKey) env.CODEX_API_KEY = apiKey;
|
|
167
|
-
if (explicit.baseUrl) env.OPENAI_BASE_URL = explicit.baseUrl;
|
|
168
|
-
if (explicit.modelProviderName)
|
|
169
|
-
env.CODEX_MODEL_PROVIDER_NAME = explicit.modelProviderName;
|
|
170
|
-
if (explicit.queryParamsJson)
|
|
171
|
-
env.OPENAI_QUERY_PARAMS_JSON = explicit.queryParamsJson;
|
|
172
|
-
return env;
|
|
173
|
-
}
|
|
174
134
|
function pickOpenAI({
|
|
175
|
-
explicit,
|
|
176
135
|
processEnv
|
|
177
136
|
}) {
|
|
178
137
|
const env = {};
|
|
179
|
-
const apiKey =
|
|
138
|
+
const apiKey = processEnv.OPENAI_API_KEY ?? processEnv.CODEX_API_KEY;
|
|
180
139
|
if (apiKey) env.CODEX_API_KEY = apiKey;
|
|
181
|
-
const baseUrl =
|
|
140
|
+
const baseUrl = processEnv.OPENAI_BASE_URL;
|
|
182
141
|
if (baseUrl) env.OPENAI_BASE_URL = baseUrl;
|
|
183
|
-
const organization =
|
|
142
|
+
const organization = processEnv.OPENAI_ORGANIZATION;
|
|
184
143
|
if (organization) env.OPENAI_ORGANIZATION = organization;
|
|
185
|
-
const project =
|
|
144
|
+
const project = processEnv.OPENAI_PROJECT;
|
|
186
145
|
if (project) env.OPENAI_PROJECT = project;
|
|
187
146
|
return env;
|
|
188
147
|
}
|
|
189
148
|
function pickGateway({
|
|
190
|
-
explicit,
|
|
191
149
|
gatewayAuthFromEnv
|
|
192
150
|
}) {
|
|
193
|
-
const apiKey =
|
|
194
|
-
const baseUrl = toCodexGatewayBaseUrl(
|
|
195
|
-
explicit.baseUrl ?? gatewayAuthFromEnv.baseUrl
|
|
196
|
-
);
|
|
151
|
+
const apiKey = gatewayAuthFromEnv.apiKey;
|
|
152
|
+
const baseUrl = toCodexGatewayBaseUrl(gatewayAuthFromEnv.baseUrl);
|
|
197
153
|
const env = {};
|
|
198
154
|
if (apiKey) {
|
|
199
155
|
env.AI_GATEWAY_API_KEY = apiKey;
|
|
@@ -227,7 +183,8 @@ var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
|
|
|
227
183
|
// `codex.resumeThread(resumeThreadId, …)` instead of starting a fresh thread.
|
|
228
184
|
// The host sources the id from lifecycle state `data` cached from a prior
|
|
229
185
|
// `agent.detach`.
|
|
230
|
-
resumeThreadId: z.string().optional()
|
|
186
|
+
resumeThreadId: z.string().optional(),
|
|
187
|
+
restartThread: z.boolean().optional()
|
|
231
188
|
});
|
|
232
189
|
var inboundMessageSchema = z.discriminatedUnion("type", [
|
|
233
190
|
startMessageSchema,
|
|
@@ -238,7 +195,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
238
195
|
var CLI_SHIM_FILENAME = "harness-tool.mjs";
|
|
239
196
|
|
|
240
197
|
// src/version.ts
|
|
241
|
-
var VERSION = true ? "1.0.
|
|
198
|
+
var VERSION = true ? "1.0.95" : "0.0.0-test";
|
|
242
199
|
|
|
243
200
|
// src/codex-harness.ts
|
|
244
201
|
var DEFAULT_CODEX_MODEL = "gpt-5.5";
|
|
@@ -265,6 +222,7 @@ var codexBridgeCoordsSchema = z2.object({
|
|
|
265
222
|
});
|
|
266
223
|
var codexResumeStateSchema = z2.object({
|
|
267
224
|
threadId: z2.string().optional(),
|
|
225
|
+
turnConfigurationFingerprint: z2.string().optional(),
|
|
268
226
|
bridge: codexBridgeCoordsSchema.optional(),
|
|
269
227
|
sandboxCredentialEnvironment: z2.record(z2.string(), z2.string()).optional()
|
|
270
228
|
});
|
|
@@ -277,6 +235,7 @@ function createCodex(settings = {}) {
|
|
|
277
235
|
lifecycleStateSchema: codexResumeStateSchema,
|
|
278
236
|
getBootstrap: getCodexBootstrap,
|
|
279
237
|
doStart: async (startOpts) => {
|
|
238
|
+
const model = startOpts.model ?? settings.model ?? DEFAULT_CODEX_MODEL;
|
|
280
239
|
if (startOpts.builtinToolFiltering != null) {
|
|
281
240
|
throw new HarnessCapabilityUnsupportedError({
|
|
282
241
|
message: "Harness 'codex' does not support built-in tool filtering controls.",
|
|
@@ -313,6 +272,7 @@ function createCodex(settings = {}) {
|
|
|
313
272
|
const resumeData = isResume && typeof lifecycleState?.data === "object" ? lifecycleState.data : void 0;
|
|
314
273
|
const resumeThreadId = resumeData?.threadId;
|
|
315
274
|
const resumeThreadIdString = typeof resumeThreadId === "string" && resumeThreadId.length > 0 ? resumeThreadId : void 0;
|
|
275
|
+
const turnConfigurationFingerprint = typeof resumeData?.turnConfigurationFingerprint === "string" ? resumeData.turnConfigurationFingerprint : void 0;
|
|
316
276
|
const coords = resumeData?.bridge;
|
|
317
277
|
const authenticationMode = resolveCodexAuthenticationMode(settings.auth);
|
|
318
278
|
const resolvedAuthEnvironment = resolveCodexEnv(settings.auth);
|
|
@@ -351,6 +311,10 @@ function createCodex(settings = {}) {
|
|
|
351
311
|
CODEX_BOOTSTRAP_DIR
|
|
352
312
|
);
|
|
353
313
|
const workDir = startOpts.sessionWorkDir;
|
|
314
|
+
const sandboxHomeDir = await resolveSandboxHomeDir({
|
|
315
|
+
sandbox: toolSafeSandboxSession,
|
|
316
|
+
abortSignal: startOpts.abortSignal
|
|
317
|
+
});
|
|
354
318
|
const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;
|
|
355
319
|
const bridgeStateDir = `${sessionDataDir}/bridge`;
|
|
356
320
|
const cliShimDir = `${sessionDataDir}/codex`;
|
|
@@ -392,7 +356,7 @@ function createCodex(settings = {}) {
|
|
|
392
356
|
cliShimPath,
|
|
393
357
|
// The live bridge was spawned by another process; no process handle.
|
|
394
358
|
proc: void 0,
|
|
395
|
-
model
|
|
359
|
+
model,
|
|
396
360
|
reasoningEffort: settings.reasoningEffort,
|
|
397
361
|
webSearch: settings.webSearch,
|
|
398
362
|
codexConfig: settings.codexConfig,
|
|
@@ -406,7 +370,10 @@ function createCodex(settings = {}) {
|
|
|
406
370
|
sandboxId,
|
|
407
371
|
sandboxCredentialEnvironment,
|
|
408
372
|
debug: startOpts.observability?.debug,
|
|
409
|
-
permissionMode: startOpts.permissionMode
|
|
373
|
+
permissionMode: startOpts.permissionMode,
|
|
374
|
+
sandbox: toolSafeSandboxSession,
|
|
375
|
+
sandboxHomeDir,
|
|
376
|
+
turnConfigurationFingerprint
|
|
410
377
|
});
|
|
411
378
|
} catch {
|
|
412
379
|
}
|
|
@@ -433,20 +400,11 @@ function createCodex(settings = {}) {
|
|
|
433
400
|
credentialEnvironmentVariables: CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,
|
|
434
401
|
credentialForwarding: settings.credentialForwarding
|
|
435
402
|
});
|
|
436
|
-
const codexSkillSetup = startOpts.skills && startOpts.skills.length > 0 ? await writeCodexSkills({
|
|
437
|
-
sandbox: toolSafeSandboxSession,
|
|
438
|
-
skills: startOpts.skills,
|
|
439
|
-
abortSignal: startOpts.abortSignal
|
|
440
|
-
}) : void 0;
|
|
441
403
|
const env = {
|
|
442
404
|
...forwardedAuthEnvironment,
|
|
443
405
|
AI_SDK_HARNESS_CLIENT_APP: CODEX_CLIENT_APP,
|
|
444
406
|
BRIDGE_CHANNEL_TOKEN: token,
|
|
445
407
|
BRIDGE_WS_PORT: String(port),
|
|
446
|
-
...codexSkillSetup ? {
|
|
447
|
-
HOME: codexSkillSetup.homeDir,
|
|
448
|
-
CODEX_HOME: codexSkillSetup.codexHomeDir
|
|
449
|
-
} : {},
|
|
450
408
|
...respawnStrategy === "replay" ? { BRIDGE_REPLAY_FROM_DISK: "1" } : {}
|
|
451
409
|
};
|
|
452
410
|
if (respawnStrategy === void 0) {
|
|
@@ -520,7 +478,7 @@ function createCodex(settings = {}) {
|
|
|
520
478
|
channel,
|
|
521
479
|
cliShimPath,
|
|
522
480
|
proc,
|
|
523
|
-
model
|
|
481
|
+
model,
|
|
524
482
|
reasoningEffort: settings.reasoningEffort,
|
|
525
483
|
webSearch: settings.webSearch,
|
|
526
484
|
codexConfig: settings.codexConfig,
|
|
@@ -534,7 +492,10 @@ function createCodex(settings = {}) {
|
|
|
534
492
|
sandboxId,
|
|
535
493
|
sandboxCredentialEnvironment,
|
|
536
494
|
debug: startOpts.observability?.debug,
|
|
537
|
-
permissionMode: startOpts.permissionMode
|
|
495
|
+
permissionMode: startOpts.permissionMode,
|
|
496
|
+
sandbox: toolSafeSandboxSession,
|
|
497
|
+
sandboxHomeDir,
|
|
498
|
+
turnConfigurationFingerprint
|
|
538
499
|
});
|
|
539
500
|
}
|
|
540
501
|
};
|
|
@@ -587,17 +548,12 @@ async function resolveBridgeEndpoint({
|
|
|
587
548
|
}
|
|
588
549
|
async function writeCodexSkills({
|
|
589
550
|
sandbox,
|
|
551
|
+
sandboxHomeDir,
|
|
590
552
|
skills,
|
|
591
553
|
abortSignal
|
|
592
554
|
}) {
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
await sandbox.run({
|
|
596
|
-
command: `mkdir -p ${shellQuote(codexHomeDir)}`,
|
|
597
|
-
abortSignal
|
|
598
|
-
});
|
|
599
|
-
const rootDir = path.posix.join(homeDir, ".agents", "skills");
|
|
600
|
-
await writeHarnessSkills({
|
|
555
|
+
const rootDir = path.posix.join(sandboxHomeDir, ".agents", "skills");
|
|
556
|
+
return writeHarnessSkills({
|
|
601
557
|
sandbox,
|
|
602
558
|
rootDir,
|
|
603
559
|
skills,
|
|
@@ -605,10 +561,6 @@ async function writeCodexSkills({
|
|
|
605
561
|
invalidSkillNameMessage: ({ name }) => `Invalid Codex skill name: ${name}`,
|
|
606
562
|
invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid Codex skill file path for ${skillName}: ${filePath}`
|
|
607
563
|
});
|
|
608
|
-
return {
|
|
609
|
-
homeDir,
|
|
610
|
-
codexHomeDir
|
|
611
|
-
};
|
|
612
564
|
}
|
|
613
565
|
function openWebSocket({
|
|
614
566
|
url,
|
|
@@ -657,16 +609,44 @@ function createSession({
|
|
|
657
609
|
sandboxId,
|
|
658
610
|
sandboxCredentialEnvironment,
|
|
659
611
|
debug,
|
|
660
|
-
permissionMode
|
|
612
|
+
permissionMode,
|
|
613
|
+
sandbox,
|
|
614
|
+
sandboxHomeDir,
|
|
615
|
+
turnConfigurationFingerprint
|
|
661
616
|
}) {
|
|
662
617
|
let stopped = false;
|
|
663
618
|
let stopPromise;
|
|
664
619
|
let pendingResumeThreadId = seedResumeThreadOnFirstPrompt ? resumeThreadId : void 0;
|
|
665
620
|
let initialPromptGuidanceApplied = isResume;
|
|
666
621
|
let latestThreadId = resumeThreadId;
|
|
622
|
+
let latestTurnConfigurationFingerprint = turnConfigurationFingerprint;
|
|
667
623
|
channel.on("bridge-thread", (msg) => {
|
|
668
624
|
latestThreadId = msg.threadId;
|
|
669
625
|
});
|
|
626
|
+
const synchronizeTurnConfiguration = async ({
|
|
627
|
+
skills,
|
|
628
|
+
instructions,
|
|
629
|
+
tools,
|
|
630
|
+
abortSignal
|
|
631
|
+
}) => {
|
|
632
|
+
const skillsResult = await writeCodexSkills({
|
|
633
|
+
sandbox,
|
|
634
|
+
sandboxHomeDir,
|
|
635
|
+
skills,
|
|
636
|
+
abortSignal
|
|
637
|
+
});
|
|
638
|
+
const nextFingerprint = fingerprintCodexTurnConfiguration({
|
|
639
|
+
instructions,
|
|
640
|
+
tools
|
|
641
|
+
});
|
|
642
|
+
const restartThread = latestThreadId != null && (skillsResult.changed || latestTurnConfigurationFingerprint != null && latestTurnConfigurationFingerprint !== nextFingerprint);
|
|
643
|
+
latestTurnConfigurationFingerprint = nextFingerprint;
|
|
644
|
+
if (restartThread) {
|
|
645
|
+
initialPromptGuidanceApplied = false;
|
|
646
|
+
pendingResumeThreadId = void 0;
|
|
647
|
+
}
|
|
648
|
+
return { restartThread };
|
|
649
|
+
};
|
|
670
650
|
const wireTurn = (turnOpts) => {
|
|
671
651
|
let pendingResolve;
|
|
672
652
|
let pendingReject;
|
|
@@ -801,15 +781,21 @@ function createSession({
|
|
|
801
781
|
harnessId: "codex"
|
|
802
782
|
});
|
|
803
783
|
}
|
|
804
|
-
const turn = wireTurn({
|
|
805
|
-
emit: promptOpts.emit,
|
|
806
|
-
abortSignal: promptOpts.abortSignal
|
|
807
|
-
});
|
|
808
784
|
const tools = (promptOpts.tools ?? []).map((t) => ({
|
|
809
785
|
name: t.name,
|
|
810
786
|
description: t.description,
|
|
811
787
|
inputSchema: t.inputSchema
|
|
812
788
|
}));
|
|
789
|
+
const { restartThread } = await synchronizeTurnConfiguration({
|
|
790
|
+
skills: promptOpts.skills,
|
|
791
|
+
instructions: promptOpts.instructions,
|
|
792
|
+
tools,
|
|
793
|
+
abortSignal: promptOpts.abortSignal
|
|
794
|
+
});
|
|
795
|
+
const turn = wireTurn({
|
|
796
|
+
emit: promptOpts.emit,
|
|
797
|
+
abortSignal: promptOpts.abortSignal
|
|
798
|
+
});
|
|
813
799
|
let promptText = extractUserText(promptOpts.prompt);
|
|
814
800
|
if (!initialPromptGuidanceApplied) {
|
|
815
801
|
promptText = frameInitialPromptGuidance({
|
|
@@ -834,6 +820,7 @@ function createSession({
|
|
|
834
820
|
...mcpServers == null ? {} : { mcpServers },
|
|
835
821
|
...permissionMode ? { permissionMode } : {},
|
|
836
822
|
...pendingResumeThreadId ? { resumeThreadId: pendingResumeThreadId } : {},
|
|
823
|
+
...restartThread ? { restartThread: true } : {},
|
|
837
824
|
...debug ? { debug } : {}
|
|
838
825
|
};
|
|
839
826
|
pendingResumeThreadId = void 0;
|
|
@@ -847,6 +834,17 @@ function createSession({
|
|
|
847
834
|
harnessId: "codex"
|
|
848
835
|
});
|
|
849
836
|
}
|
|
837
|
+
const tools = (continueOpts.tools ?? []).map((t) => ({
|
|
838
|
+
name: t.name,
|
|
839
|
+
description: t.description,
|
|
840
|
+
inputSchema: t.inputSchema
|
|
841
|
+
}));
|
|
842
|
+
const { restartThread } = await synchronizeTurnConfiguration({
|
|
843
|
+
skills: continueOpts.skills,
|
|
844
|
+
instructions: continueOpts.instructions,
|
|
845
|
+
tools,
|
|
846
|
+
abortSignal: continueOpts.abortSignal
|
|
847
|
+
});
|
|
850
848
|
const turn = wireTurn({
|
|
851
849
|
emit: continueOpts.emit,
|
|
852
850
|
abortSignal: continueOpts.abortSignal
|
|
@@ -865,11 +863,7 @@ function createSession({
|
|
|
865
863
|
* empty text block trips the Anthropic API's `cache_control` rule).
|
|
866
864
|
*/
|
|
867
865
|
prompt: "Continue.",
|
|
868
|
-
tools
|
|
869
|
-
name: t.name,
|
|
870
|
-
description: t.description,
|
|
871
|
-
inputSchema: t.inputSchema
|
|
872
|
-
})),
|
|
866
|
+
tools,
|
|
873
867
|
...continueOpts.responseFormat == null ? {} : { responseFormat: continueOpts.responseFormat },
|
|
874
868
|
...continueOpts.instructions ? { instructions: continueOpts.instructions } : {},
|
|
875
869
|
model,
|
|
@@ -879,6 +873,7 @@ function createSession({
|
|
|
879
873
|
...mcpServers == null ? {} : { mcpServers },
|
|
880
874
|
...permissionMode ? { permissionMode } : {},
|
|
881
875
|
...threadId ? { resumeThreadId: threadId } : {},
|
|
876
|
+
...restartThread ? { restartThread: true } : {},
|
|
882
877
|
...debug ? { debug } : {}
|
|
883
878
|
})
|
|
884
879
|
);
|
|
@@ -905,6 +900,9 @@ function createSession({
|
|
|
905
900
|
specificationVersion: "harness-v1",
|
|
906
901
|
data: {
|
|
907
902
|
...latestThreadId ? { threadId: latestThreadId } : {},
|
|
903
|
+
...latestTurnConfigurationFingerprint ? {
|
|
904
|
+
turnConfigurationFingerprint: latestTurnConfigurationFingerprint
|
|
905
|
+
} : {},
|
|
908
906
|
...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
|
|
909
907
|
bridge: {
|
|
910
908
|
port: bridgePort,
|
|
@@ -1006,6 +1004,9 @@ function createSession({
|
|
|
1006
1004
|
specificationVersion: "harness-v1",
|
|
1007
1005
|
data: {
|
|
1008
1006
|
...lifecycleData,
|
|
1007
|
+
...latestTurnConfigurationFingerprint ? {
|
|
1008
|
+
turnConfigurationFingerprint: latestTurnConfigurationFingerprint
|
|
1009
|
+
} : {},
|
|
1009
1010
|
...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment }
|
|
1010
1011
|
}
|
|
1011
1012
|
};
|
|
@@ -1025,6 +1026,9 @@ function createSession({
|
|
|
1025
1026
|
specificationVersion: "harness-v1",
|
|
1026
1027
|
data: {
|
|
1027
1028
|
...latestThreadId ? { threadId: latestThreadId } : {},
|
|
1029
|
+
...latestTurnConfigurationFingerprint ? {
|
|
1030
|
+
turnConfigurationFingerprint: latestTurnConfigurationFingerprint
|
|
1031
|
+
} : {},
|
|
1028
1032
|
...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
|
|
1029
1033
|
bridge: {
|
|
1030
1034
|
port: bridgePort,
|
|
@@ -1038,6 +1042,12 @@ function createSession({
|
|
|
1038
1042
|
}
|
|
1039
1043
|
};
|
|
1040
1044
|
}
|
|
1045
|
+
function fingerprintCodexTurnConfiguration({
|
|
1046
|
+
instructions,
|
|
1047
|
+
tools
|
|
1048
|
+
}) {
|
|
1049
|
+
return createHash("sha256").update(JSON.stringify({ instructions: instructions ?? null, tools })).digest("hex");
|
|
1050
|
+
}
|
|
1041
1051
|
function frameInitialPromptGuidance({
|
|
1042
1052
|
toolUsageBlock,
|
|
1043
1053
|
userText
|