@ai-sdk/harness-codex 1.0.66 → 1.0.68

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.
@@ -75,6 +75,11 @@ const CODEX_CLIENT_APP = `ai-sdk/harness-codex/${VERSION}`;
75
75
 
76
76
  export type CodexHarnessSettings = {
77
77
  readonly auth?: CodexAuthOptions;
78
+ /**
79
+ * MCP server definitions keyed by server name. Each definition uses the
80
+ * underlying runtime's native MCP server configuration format.
81
+ */
82
+ readonly mcpServers?: Record<string, unknown>;
78
83
  /**
79
84
  * OpenAI model id the underlying `codex` CLI should use. Leaving this unset
80
85
  * pins the adapter default (`DEFAULT_CODEX_MODEL`).
@@ -98,6 +103,11 @@ export type CodexHarnessSettings = {
98
103
  readonly port?: number;
99
104
  /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */
100
105
  readonly startupTimeoutMs?: number;
106
+ /**
107
+ * Creates the authentication token used by the sandbox bridge. Defaults to
108
+ * a random 32-byte hexadecimal token.
109
+ */
110
+ readonly mintBridgeToken?: (sandboxId: string) => string;
101
111
  };
102
112
 
103
113
  /*
@@ -298,6 +308,7 @@ export function createCodex(
298
308
  model: settings.model ?? DEFAULT_CODEX_MODEL,
299
309
  reasoningEffort: settings.reasoningEffort,
300
310
  webSearch: settings.webSearch,
311
+ mcpServers: settings.mcpServers,
301
312
  resumeThreadId: resumeThreadIdString,
302
313
  isResume: true,
303
314
  seedResumeThreadOnFirstPrompt: false,
@@ -337,7 +348,10 @@ export function createCodex(
337
348
  }
338
349
 
339
350
  const port = resolveBridgePort(sandboxSession, settings.port);
340
- const token = randomBytes(32).toString('hex');
351
+ const token =
352
+ settings.mintBridgeToken == null
353
+ ? randomBytes(32).toString('hex')
354
+ : settings.mintBridgeToken(sandboxId);
341
355
  const codexSkillSetup =
342
356
  startOpts.skills && startOpts.skills.length > 0
343
357
  ? await writeCodexSkills({
@@ -445,6 +459,7 @@ export function createCodex(
445
459
  model: settings.model ?? DEFAULT_CODEX_MODEL,
446
460
  reasoningEffort: settings.reasoningEffort,
447
461
  webSearch: settings.webSearch,
462
+ mcpServers: settings.mcpServers,
448
463
  resumeThreadId: resumeThreadIdString,
449
464
  isResume: respawnStrategy !== undefined,
450
465
  seedResumeThreadOnFirstPrompt: respawnStrategy !== undefined,
@@ -548,6 +563,7 @@ function createSession({
548
563
  model,
549
564
  reasoningEffort,
550
565
  webSearch,
566
+ mcpServers,
551
567
  resumeThreadId,
552
568
  isResume,
553
569
  seedResumeThreadOnFirstPrompt,
@@ -566,6 +582,7 @@ function createSession({
566
582
  model: string | undefined;
567
583
  reasoningEffort: 'low' | 'medium' | 'high' | undefined;
568
584
  webSearch: boolean | undefined;
585
+ mcpServers: Record<string, unknown> | undefined;
569
586
  resumeThreadId: string | undefined;
570
587
  isResume: boolean;
571
588
  seedResumeThreadOnFirstPrompt: boolean;
@@ -588,12 +605,12 @@ function createSession({
588
605
  ? resumeThreadId
589
606
  : undefined;
590
607
  /*
591
- * Initial prompt guidance is prepended to the first user message of a fresh
592
- * session only. A resumed session (attach/replay/rerun) already carried it
593
- * in its original first message (preserved in the persisted thread), so it
608
+ * Host-tool relay guidance is prepended to the first user message of a fresh
609
+ * session only. A resumed session (attach/replay/rerun) already carried it in
610
+ * its original first message (preserved in the persisted thread), so it
594
611
  * starts "applied".
595
612
  */
596
- let instructionsApplied = isResume;
613
+ let initialPromptGuidanceApplied = isResume;
597
614
 
598
615
  /*
599
616
  * Latest codex thread id, cached from the bridge's `bridge-thread`
@@ -778,12 +795,8 @@ function createSession({
778
795
  inputSchema: t.inputSchema,
779
796
  }));
780
797
  let promptText = extractUserText(promptOpts.prompt);
781
- if (!instructionsApplied) {
782
- const instructions =
783
- (promptOpts.instructions ? promptOpts.instructions + '\n\n' : '') +
784
- 'Only respond with your `final` message once you have fully addressed the user request.';
798
+ if (!initialPromptGuidanceApplied) {
785
799
  promptText = frameInitialPromptGuidance({
786
- instructions,
787
800
  toolUsageBlock:
788
801
  tools.length > 0
789
802
  ? composeToolUsageInstructions({
@@ -794,15 +807,19 @@ function createSession({
794
807
  userText: promptText,
795
808
  });
796
809
  }
797
- instructionsApplied = true;
810
+ initialPromptGuidanceApplied = true;
798
811
 
799
812
  const startMessage = {
800
813
  type: 'start' as const,
801
814
  prompt: promptText,
802
815
  tools,
816
+ ...(promptOpts.instructions
817
+ ? { instructions: promptOpts.instructions }
818
+ : {}),
803
819
  model,
804
820
  reasoningEffort,
805
821
  webSearch,
822
+ ...(mcpServers == null ? {} : { mcpServers }),
806
823
  ...(permissionMode ? { permissionMode } : {}),
807
824
  ...(pendingResumeThreadId
808
825
  ? { resumeThreadId: pendingResumeThreadId }
@@ -851,9 +868,13 @@ function createSession({
851
868
  description: t.description,
852
869
  inputSchema: t.inputSchema,
853
870
  })),
871
+ ...(continueOpts.instructions
872
+ ? { instructions: continueOpts.instructions }
873
+ : {}),
854
874
  model,
855
875
  reasoningEffort,
856
876
  webSearch,
877
+ ...(mcpServers == null ? {} : { mcpServers }),
857
878
  ...(permissionMode ? { permissionMode } : {}),
858
879
  ...(threadId ? { resumeThreadId: threadId } : {}),
859
880
  ...(debug ? { debug } : {}),
@@ -1043,28 +1064,18 @@ function createSession({
1043
1064
  }
1044
1065
 
1045
1066
  /*
1046
- * Frame session instructions, host-tool relay guidance, and the user's text so
1047
- * Codex treats the prepended blocks as operating guidance rather than user
1048
- * prose. Applied only to the first user message of a fresh session.
1067
+ * Frame host-tool relay guidance and the user's text so Codex treats the
1068
+ * prepended block as operating guidance rather than user prose. Applied only
1069
+ * to the first user message of a fresh session.
1049
1070
  */
1050
1071
  function frameInitialPromptGuidance({
1051
- instructions,
1052
1072
  toolUsageBlock,
1053
1073
  userText,
1054
1074
  }: {
1055
- instructions: string | undefined;
1056
1075
  toolUsageBlock: string | undefined;
1057
1076
  userText: string;
1058
1077
  }): string {
1059
1078
  const blocks: string[] = [];
1060
- if (instructions) {
1061
- blocks.push(
1062
- '<session-instructions>\n' +
1063
- 'The block below is operating guidance from the system, not a message from the user — follow it, but do not mention it or attribute it to the user.\n\n' +
1064
- `${instructions}\n` +
1065
- '</session-instructions>',
1066
- );
1067
- }
1068
1079
  if (toolUsageBlock) blocks.push(toolUsageBlock);
1069
1080
  if (blocks.length === 0) return userText;
1070
1081
  return `${blocks.join('\n\n')}\n\n<user-message>\n${userText}\n</user-message>`;