@ai-sdk/harness-codex 1.0.94 → 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.
@@ -9,55 +9,55 @@ importers:
9
9
  .:
10
10
  dependencies:
11
11
  '@openai/codex-sdk':
12
- specifier: 0.144.5
13
- version: 0.144.5
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.144.5':
21
- resolution: {integrity: sha512-90wHPEGyk74On6gwQPNtw+wzuDJ2zYpiVADDxw43S1cWn3QbBh/21zFS2xlAWWCrdY0gE90yXfmmrzwdUDlBGw==}
20
+ '@openai/codex-sdk@0.149.1':
21
+ resolution: {integrity: sha512-R00Rz5327LefZggAxl28r7vFQq1vxa91OxtjZJOsQfAM/MyH8InW5qwwRu6pzUmRGp1E29XrOzm7u1TeV5Yz2A==}
22
22
  engines: {node: '>=18'}
23
23
 
24
- '@openai/codex@0.144.5':
25
- resolution: {integrity: sha512-jjB+K+OMv572mKhS+2QuLxWXDJNdpwbPenf+V+8bdq7wg4Scqt3cn6WEekD8wPqDVZqck0HSX17K9rD9kbDJQA==}
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.144.5-darwin-arm64':
30
- resolution: {integrity: sha512-zcT6NfBCqLFt+BReNSETTZW6v6PdbH0dzNtm9j7l7mDGqwPbKZDGJdnpkBao2389I0ZacyIKgSZoI0vez1d4Dw==}
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.144.5-darwin-x64':
36
- resolution: {integrity: sha512-//Mo0m1MwaoT6psu5xsmofXpKx4/0irIkeq10xJvk59+886EG355ibjA+ZmlRcKhE3bLjsKD7p81nTbAdRL/bw==}
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.144.5-linux-arm64':
42
- resolution: {integrity: sha512-zAHggxVwR2TBxKmybXY7ZMiB0G8DMonY2YPdwNNjwXcf+LOIqNGgswwNCDMbP/HEe6r8j+R9ZX/yYoo8f+n/RQ==}
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.144.5-linux-x64':
48
- resolution: {integrity: sha512-FalLJlBQGFdK8Gc3kj9sa/ekNdgkHhUawLaKkvy5CtB18JaP2YxtTP/Pe1pD2iBiq8mMUliRnafpF6AdBdQMbg==}
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.144.5-win32-arm64':
54
- resolution: {integrity: sha512-0Pj7iqjEOEvPQPO3kFfCy9vGX4BTu76ChFFZHr2eNNIfVc3FOENAv/X98u4L+iIUtDOK9DbqmfUudW3DPapshg==}
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.144.5-win32-x64':
60
- resolution: {integrity: sha512-DnsSTlnnzleTxvLwIGnBitKInscxn2I7qASqosS8Fv+qysBygd+ZiBn/SQsRCgQ28PAlsNzmd3Gf3ZTecolAmg==}
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.144.5':
79
+ '@openai/codex-sdk@0.149.1':
80
80
  dependencies:
81
- '@openai/codex': 0.144.5
81
+ '@openai/codex': 0.149.1
82
82
 
83
- '@openai/codex@0.144.5':
83
+ '@openai/codex@0.149.1':
84
84
  optionalDependencies:
85
- '@openai/codex-darwin-arm64': '@openai/codex@0.144.5-darwin-arm64'
86
- '@openai/codex-darwin-x64': '@openai/codex@0.144.5-darwin-x64'
87
- '@openai/codex-linux-arm64': '@openai/codex@0.144.5-linux-arm64'
88
- '@openai/codex-linux-x64': '@openai/codex@0.144.5-linux-x64'
89
- '@openai/codex-win32-arm64': '@openai/codex@0.144.5-win32-arm64'
90
- '@openai/codex-win32-x64': '@openai/codex@0.144.5-win32-x64'
91
-
92
- '@openai/codex@0.144.5-darwin-arm64':
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.144.5-darwin-x64':
95
+ '@openai/codex@0.149.1-darwin-x64':
96
96
  optional: true
97
97
 
98
- '@openai/codex@0.144.5-linux-arm64':
98
+ '@openai/codex@0.149.1-linux-arm64':
99
99
  optional: true
100
100
 
101
- '@openai/codex@0.144.5-linux-x64':
101
+ '@openai/codex@0.149.1-linux-x64':
102
102
  optional: true
103
103
 
104
- '@openai/codex@0.144.5-win32-arm64':
104
+ '@openai/codex@0.149.1-win32-arm64':
105
105
  optional: true
106
106
 
107
- '@openai/codex@0.144.5-win32-x64':
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
@@ -25,6 +25,8 @@ type CodexHarnessSettings = {
25
25
  /**
26
26
  * OpenAI model id the underlying `codex` CLI should use. Leaving this unset
27
27
  * pins the adapter default (`DEFAULT_CODEX_MODEL`).
28
+ *
29
+ * @deprecated Use `model` on `HarnessAgent` instead.
28
30
  */
29
31
  readonly model?: string;
30
32
  /**
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,
@@ -183,7 +183,8 @@ var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
183
183
  // `codex.resumeThread(resumeThreadId, …)` instead of starting a fresh thread.
184
184
  // The host sources the id from lifecycle state `data` cached from a prior
185
185
  // `agent.detach`.
186
- resumeThreadId: z.string().optional()
186
+ resumeThreadId: z.string().optional(),
187
+ restartThread: z.boolean().optional()
187
188
  });
188
189
  var inboundMessageSchema = z.discriminatedUnion("type", [
189
190
  startMessageSchema,
@@ -194,7 +195,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
194
195
  var CLI_SHIM_FILENAME = "harness-tool.mjs";
195
196
 
196
197
  // src/version.ts
197
- var VERSION = true ? "1.0.94" : "0.0.0-test";
198
+ var VERSION = true ? "1.0.95" : "0.0.0-test";
198
199
 
199
200
  // src/codex-harness.ts
200
201
  var DEFAULT_CODEX_MODEL = "gpt-5.5";
@@ -221,6 +222,7 @@ var codexBridgeCoordsSchema = z2.object({
221
222
  });
222
223
  var codexResumeStateSchema = z2.object({
223
224
  threadId: z2.string().optional(),
225
+ turnConfigurationFingerprint: z2.string().optional(),
224
226
  bridge: codexBridgeCoordsSchema.optional(),
225
227
  sandboxCredentialEnvironment: z2.record(z2.string(), z2.string()).optional()
226
228
  });
@@ -233,6 +235,7 @@ function createCodex(settings = {}) {
233
235
  lifecycleStateSchema: codexResumeStateSchema,
234
236
  getBootstrap: getCodexBootstrap,
235
237
  doStart: async (startOpts) => {
238
+ const model = startOpts.model ?? settings.model ?? DEFAULT_CODEX_MODEL;
236
239
  if (startOpts.builtinToolFiltering != null) {
237
240
  throw new HarnessCapabilityUnsupportedError({
238
241
  message: "Harness 'codex' does not support built-in tool filtering controls.",
@@ -269,6 +272,7 @@ function createCodex(settings = {}) {
269
272
  const resumeData = isResume && typeof lifecycleState?.data === "object" ? lifecycleState.data : void 0;
270
273
  const resumeThreadId = resumeData?.threadId;
271
274
  const resumeThreadIdString = typeof resumeThreadId === "string" && resumeThreadId.length > 0 ? resumeThreadId : void 0;
275
+ const turnConfigurationFingerprint = typeof resumeData?.turnConfigurationFingerprint === "string" ? resumeData.turnConfigurationFingerprint : void 0;
272
276
  const coords = resumeData?.bridge;
273
277
  const authenticationMode = resolveCodexAuthenticationMode(settings.auth);
274
278
  const resolvedAuthEnvironment = resolveCodexEnv(settings.auth);
@@ -307,6 +311,10 @@ function createCodex(settings = {}) {
307
311
  CODEX_BOOTSTRAP_DIR
308
312
  );
309
313
  const workDir = startOpts.sessionWorkDir;
314
+ const sandboxHomeDir = await resolveSandboxHomeDir({
315
+ sandbox: toolSafeSandboxSession,
316
+ abortSignal: startOpts.abortSignal
317
+ });
310
318
  const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;
311
319
  const bridgeStateDir = `${sessionDataDir}/bridge`;
312
320
  const cliShimDir = `${sessionDataDir}/codex`;
@@ -348,7 +356,7 @@ function createCodex(settings = {}) {
348
356
  cliShimPath,
349
357
  // The live bridge was spawned by another process; no process handle.
350
358
  proc: void 0,
351
- model: settings.model ?? DEFAULT_CODEX_MODEL,
359
+ model,
352
360
  reasoningEffort: settings.reasoningEffort,
353
361
  webSearch: settings.webSearch,
354
362
  codexConfig: settings.codexConfig,
@@ -362,7 +370,10 @@ function createCodex(settings = {}) {
362
370
  sandboxId,
363
371
  sandboxCredentialEnvironment,
364
372
  debug: startOpts.observability?.debug,
365
- permissionMode: startOpts.permissionMode
373
+ permissionMode: startOpts.permissionMode,
374
+ sandbox: toolSafeSandboxSession,
375
+ sandboxHomeDir,
376
+ turnConfigurationFingerprint
366
377
  });
367
378
  } catch {
368
379
  }
@@ -389,20 +400,11 @@ function createCodex(settings = {}) {
389
400
  credentialEnvironmentVariables: CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,
390
401
  credentialForwarding: settings.credentialForwarding
391
402
  });
392
- const codexSkillSetup = startOpts.skills && startOpts.skills.length > 0 ? await writeCodexSkills({
393
- sandbox: toolSafeSandboxSession,
394
- skills: startOpts.skills,
395
- abortSignal: startOpts.abortSignal
396
- }) : void 0;
397
403
  const env = {
398
404
  ...forwardedAuthEnvironment,
399
405
  AI_SDK_HARNESS_CLIENT_APP: CODEX_CLIENT_APP,
400
406
  BRIDGE_CHANNEL_TOKEN: token,
401
407
  BRIDGE_WS_PORT: String(port),
402
- ...codexSkillSetup ? {
403
- HOME: codexSkillSetup.homeDir,
404
- CODEX_HOME: codexSkillSetup.codexHomeDir
405
- } : {},
406
408
  ...respawnStrategy === "replay" ? { BRIDGE_REPLAY_FROM_DISK: "1" } : {}
407
409
  };
408
410
  if (respawnStrategy === void 0) {
@@ -476,7 +478,7 @@ function createCodex(settings = {}) {
476
478
  channel,
477
479
  cliShimPath,
478
480
  proc,
479
- model: settings.model ?? DEFAULT_CODEX_MODEL,
481
+ model,
480
482
  reasoningEffort: settings.reasoningEffort,
481
483
  webSearch: settings.webSearch,
482
484
  codexConfig: settings.codexConfig,
@@ -490,7 +492,10 @@ function createCodex(settings = {}) {
490
492
  sandboxId,
491
493
  sandboxCredentialEnvironment,
492
494
  debug: startOpts.observability?.debug,
493
- permissionMode: startOpts.permissionMode
495
+ permissionMode: startOpts.permissionMode,
496
+ sandbox: toolSafeSandboxSession,
497
+ sandboxHomeDir,
498
+ turnConfigurationFingerprint
494
499
  });
495
500
  }
496
501
  };
@@ -543,17 +548,12 @@ async function resolveBridgeEndpoint({
543
548
  }
544
549
  async function writeCodexSkills({
545
550
  sandbox,
551
+ sandboxHomeDir,
546
552
  skills,
547
553
  abortSignal
548
554
  }) {
549
- const homeDir = await resolveSandboxHomeDir({ sandbox, abortSignal });
550
- const codexHomeDir = path.posix.join(homeDir, ".codex");
551
- await sandbox.run({
552
- command: `mkdir -p ${shellQuote(codexHomeDir)}`,
553
- abortSignal
554
- });
555
- const rootDir = path.posix.join(homeDir, ".agents", "skills");
556
- await writeHarnessSkills({
555
+ const rootDir = path.posix.join(sandboxHomeDir, ".agents", "skills");
556
+ return writeHarnessSkills({
557
557
  sandbox,
558
558
  rootDir,
559
559
  skills,
@@ -561,10 +561,6 @@ async function writeCodexSkills({
561
561
  invalidSkillNameMessage: ({ name }) => `Invalid Codex skill name: ${name}`,
562
562
  invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid Codex skill file path for ${skillName}: ${filePath}`
563
563
  });
564
- return {
565
- homeDir,
566
- codexHomeDir
567
- };
568
564
  }
569
565
  function openWebSocket({
570
566
  url,
@@ -613,16 +609,44 @@ function createSession({
613
609
  sandboxId,
614
610
  sandboxCredentialEnvironment,
615
611
  debug,
616
- permissionMode
612
+ permissionMode,
613
+ sandbox,
614
+ sandboxHomeDir,
615
+ turnConfigurationFingerprint
617
616
  }) {
618
617
  let stopped = false;
619
618
  let stopPromise;
620
619
  let pendingResumeThreadId = seedResumeThreadOnFirstPrompt ? resumeThreadId : void 0;
621
620
  let initialPromptGuidanceApplied = isResume;
622
621
  let latestThreadId = resumeThreadId;
622
+ let latestTurnConfigurationFingerprint = turnConfigurationFingerprint;
623
623
  channel.on("bridge-thread", (msg) => {
624
624
  latestThreadId = msg.threadId;
625
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
+ };
626
650
  const wireTurn = (turnOpts) => {
627
651
  let pendingResolve;
628
652
  let pendingReject;
@@ -757,15 +781,21 @@ function createSession({
757
781
  harnessId: "codex"
758
782
  });
759
783
  }
760
- const turn = wireTurn({
761
- emit: promptOpts.emit,
762
- abortSignal: promptOpts.abortSignal
763
- });
764
784
  const tools = (promptOpts.tools ?? []).map((t) => ({
765
785
  name: t.name,
766
786
  description: t.description,
767
787
  inputSchema: t.inputSchema
768
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
+ });
769
799
  let promptText = extractUserText(promptOpts.prompt);
770
800
  if (!initialPromptGuidanceApplied) {
771
801
  promptText = frameInitialPromptGuidance({
@@ -790,6 +820,7 @@ function createSession({
790
820
  ...mcpServers == null ? {} : { mcpServers },
791
821
  ...permissionMode ? { permissionMode } : {},
792
822
  ...pendingResumeThreadId ? { resumeThreadId: pendingResumeThreadId } : {},
823
+ ...restartThread ? { restartThread: true } : {},
793
824
  ...debug ? { debug } : {}
794
825
  };
795
826
  pendingResumeThreadId = void 0;
@@ -803,6 +834,17 @@ function createSession({
803
834
  harnessId: "codex"
804
835
  });
805
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
+ });
806
848
  const turn = wireTurn({
807
849
  emit: continueOpts.emit,
808
850
  abortSignal: continueOpts.abortSignal
@@ -821,11 +863,7 @@ function createSession({
821
863
  * empty text block trips the Anthropic API's `cache_control` rule).
822
864
  */
823
865
  prompt: "Continue.",
824
- tools: (continueOpts.tools ?? []).map((t) => ({
825
- name: t.name,
826
- description: t.description,
827
- inputSchema: t.inputSchema
828
- })),
866
+ tools,
829
867
  ...continueOpts.responseFormat == null ? {} : { responseFormat: continueOpts.responseFormat },
830
868
  ...continueOpts.instructions ? { instructions: continueOpts.instructions } : {},
831
869
  model,
@@ -835,6 +873,7 @@ function createSession({
835
873
  ...mcpServers == null ? {} : { mcpServers },
836
874
  ...permissionMode ? { permissionMode } : {},
837
875
  ...threadId ? { resumeThreadId: threadId } : {},
876
+ ...restartThread ? { restartThread: true } : {},
838
877
  ...debug ? { debug } : {}
839
878
  })
840
879
  );
@@ -861,6 +900,9 @@ function createSession({
861
900
  specificationVersion: "harness-v1",
862
901
  data: {
863
902
  ...latestThreadId ? { threadId: latestThreadId } : {},
903
+ ...latestTurnConfigurationFingerprint ? {
904
+ turnConfigurationFingerprint: latestTurnConfigurationFingerprint
905
+ } : {},
864
906
  ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
865
907
  bridge: {
866
908
  port: bridgePort,
@@ -962,6 +1004,9 @@ function createSession({
962
1004
  specificationVersion: "harness-v1",
963
1005
  data: {
964
1006
  ...lifecycleData,
1007
+ ...latestTurnConfigurationFingerprint ? {
1008
+ turnConfigurationFingerprint: latestTurnConfigurationFingerprint
1009
+ } : {},
965
1010
  ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment }
966
1011
  }
967
1012
  };
@@ -981,6 +1026,9 @@ function createSession({
981
1026
  specificationVersion: "harness-v1",
982
1027
  data: {
983
1028
  ...latestThreadId ? { threadId: latestThreadId } : {},
1029
+ ...latestTurnConfigurationFingerprint ? {
1030
+ turnConfigurationFingerprint: latestTurnConfigurationFingerprint
1031
+ } : {},
984
1032
  ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
985
1033
  bridge: {
986
1034
  port: bridgePort,
@@ -994,6 +1042,12 @@ function createSession({
994
1042
  }
995
1043
  };
996
1044
  }
1045
+ function fingerprintCodexTurnConfiguration({
1046
+ instructions,
1047
+ tools
1048
+ }) {
1049
+ return createHash("sha256").update(JSON.stringify({ instructions: instructions ?? null, tools })).digest("hex");
1050
+ }
997
1051
  function frameInitialPromptGuidance({
998
1052
  toolUsageBlock,
999
1053
  userText