@ai-sdk/harness-codex 0.0.0 → 1.0.0-canary.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.
@@ -0,0 +1,100 @@
1
+ export type CodexAuthOptions = {
2
+ readonly openaiCompatible?: {
3
+ readonly apiKey?: string;
4
+ readonly baseUrl?: string;
5
+ readonly modelProviderName?: string;
6
+ readonly queryParamsJson?: string;
7
+ };
8
+ readonly openai?: {
9
+ readonly apiKey?: string;
10
+ readonly baseUrl?: string;
11
+ readonly organization?: string;
12
+ readonly project?: string;
13
+ };
14
+ readonly gateway?: {
15
+ readonly apiKey?: string;
16
+ readonly baseUrl?: string;
17
+ };
18
+ };
19
+
20
+ /**
21
+ * Resolve the environment-variable blob the codex bridge needs. Precedence:
22
+ *
23
+ * 1. Explicit `auth.openaiCompatible` — pin to a custom OpenAI-compatible endpoint.
24
+ * 2. Explicit `auth.openai` — pin to direct OpenAI auth.
25
+ * 3. Explicit `auth.gateway` — pin to Vercel AI Gateway.
26
+ * 4. Auto-detect from the host process env: gateway first
27
+ * (`AI_GATEWAY_API_KEY`), then `CODEX_API_KEY` / `OPENAI_API_KEY`.
28
+ */
29
+ export function resolveCodexEnv(
30
+ auth: CodexAuthOptions | undefined,
31
+ processEnv: Record<string, string | undefined> = process.env,
32
+ ): Record<string, string> {
33
+ if (auth?.openaiCompatible) {
34
+ return pickOpenAICompatible(auth.openaiCompatible, processEnv);
35
+ }
36
+ if (auth?.openai) {
37
+ return pickOpenAI({ explicit: auth.openai, processEnv });
38
+ }
39
+ if (auth?.gateway) {
40
+ return pickGateway(auth.gateway, processEnv);
41
+ }
42
+ if (processEnv.AI_GATEWAY_API_KEY) {
43
+ return pickGateway({}, processEnv);
44
+ }
45
+ return pickOpenAI({ processEnv });
46
+ }
47
+
48
+ function pickOpenAICompatible(
49
+ explicit: NonNullable<CodexAuthOptions['openaiCompatible']>,
50
+ processEnv: Record<string, string | undefined>,
51
+ ): Record<string, string> {
52
+ const env: Record<string, string> = {};
53
+ const apiKey =
54
+ explicit.apiKey ?? processEnv.OPENAI_API_KEY ?? processEnv.CODEX_API_KEY;
55
+ if (apiKey) env.CODEX_API_KEY = apiKey;
56
+ if (explicit.baseUrl) env.OPENAI_BASE_URL = explicit.baseUrl;
57
+ if (explicit.modelProviderName)
58
+ env.CODEX_MODEL_PROVIDER_NAME = explicit.modelProviderName;
59
+ if (explicit.queryParamsJson)
60
+ env.OPENAI_QUERY_PARAMS_JSON = explicit.queryParamsJson;
61
+ return env;
62
+ }
63
+
64
+ function pickOpenAI({
65
+ explicit,
66
+ processEnv,
67
+ }: {
68
+ explicit?: NonNullable<CodexAuthOptions['openai']>;
69
+ processEnv: Record<string, string | undefined>;
70
+ }): Record<string, string> {
71
+ const env: Record<string, string> = {};
72
+ const apiKey =
73
+ explicit?.apiKey ?? processEnv.OPENAI_API_KEY ?? processEnv.CODEX_API_KEY;
74
+ if (apiKey) env.CODEX_API_KEY = apiKey;
75
+ const baseUrl = explicit?.baseUrl ?? processEnv.OPENAI_BASE_URL;
76
+ if (baseUrl) env.OPENAI_BASE_URL = baseUrl;
77
+ const organization = explicit?.organization ?? processEnv.OPENAI_ORGANIZATION;
78
+ if (organization) env.OPENAI_ORGANIZATION = organization;
79
+ const project = explicit?.project ?? processEnv.OPENAI_PROJECT;
80
+ if (project) env.OPENAI_PROJECT = project;
81
+ return env;
82
+ }
83
+
84
+ function pickGateway(
85
+ explicit: NonNullable<CodexAuthOptions['gateway']>,
86
+ processEnv: Record<string, string | undefined>,
87
+ ): Record<string, string> {
88
+ const apiKey = explicit.apiKey ?? processEnv.AI_GATEWAY_API_KEY;
89
+ const baseUrl =
90
+ explicit.baseUrl ??
91
+ processEnv.AI_GATEWAY_BASE_URL ??
92
+ 'https://ai-gateway.vercel.sh/v1';
93
+ const env: Record<string, string> = {};
94
+ if (apiKey) {
95
+ env.AI_GATEWAY_API_KEY = apiKey;
96
+ env.CODEX_API_KEY = apiKey;
97
+ }
98
+ env.AI_GATEWAY_BASE_URL = baseUrl;
99
+ return env;
100
+ }
@@ -0,0 +1,48 @@
1
+ import {
2
+ harnessV1BridgeInboundCommandSchemas,
3
+ harnessV1BridgeOutboundMessageSchema,
4
+ harnessV1BridgeReadySchema,
5
+ harnessV1BridgeStartBaseSchema,
6
+ } from '@ai-sdk/harness';
7
+ import { z } from 'zod/v4';
8
+
9
+ /*
10
+ * Codex's bridge wire protocol. The outbound events (including `file-change`
11
+ * and the `bridge-thread` resume coordinate), transport frames, shared inbound
12
+ * commands, and `bridge-ready` line all come from the shared `@ai-sdk/harness`
13
+ * protocol — the only Codex-specific piece is the `start` payload.
14
+ */
15
+
16
+ export const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;
17
+ export type OutboundMessage = z.infer<typeof outboundMessageSchema>;
18
+
19
+ export const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
20
+ instructions: z.string().optional(),
21
+ reasoningEffort: z.enum(['low', 'medium', 'high']).optional(),
22
+ webSearch: z.boolean().optional(),
23
+ skills: z
24
+ .array(
25
+ z.object({
26
+ name: z.string(),
27
+ description: z.string(),
28
+ content: z.string(),
29
+ }),
30
+ )
31
+ .optional(),
32
+ // Resume signal. When supplied, the bridge calls
33
+ // `codex.resumeThread(resumeThreadId, …)` instead of starting a fresh thread.
34
+ // The host sources the id from lifecycle state `data` cached from a prior
35
+ // `agent.detach`.
36
+ resumeThreadId: z.string().optional(),
37
+ });
38
+
39
+ export type StartMessage = z.infer<typeof startMessageSchema>;
40
+
41
+ export const inboundMessageSchema = z.discriminatedUnion('type', [
42
+ startMessageSchema,
43
+ ...harnessV1BridgeInboundCommandSchemas,
44
+ ]);
45
+ export type InboundMessage = z.infer<typeof inboundMessageSchema>;
46
+
47
+ export const bridgeReadySchema = harnessV1BridgeReadySchema;
48
+ export type BridgeReady = z.infer<typeof bridgeReadySchema>;