@codeworksh/aikit 0.6.0-dev.20260613095948 → 0.7.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.
package/cli.d.mts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/cli.mjs CHANGED
@@ -1,241 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { a as protocolForPackage, c as ModelCatalog, l as lazy, n as isAISDKPackage, s as Model, u as Filesystem } from "./registry-DUKrGxt4.mjs";
3
- import { c as openAICodexHeaders, r as OpenAICodexOAuthClient, t as JsonOpenAICodexAuthStorage } from "./codex-C36oU6yH.mjs";
4
- import { resolve } from "node:path";
2
+ import { c as openAICodexHeaders, r as OpenAICodexOAuthClient, t as JsonOpenAICodexAuthStorage } from "./codex-DyQHzQmn.mjs";
3
+ import { t as ModelgenCommand } from "./modelgen-BcsqB44a.mjs";
5
4
  import yargs from "yargs";
6
5
  import { hideBin } from "yargs/helpers";
7
- import { mapValues, pickBy, pipe } from "remeda";
8
6
  //#region package.json
9
- var version = "0.6.0";
10
- //#endregion
11
- //#region src/cli/modelgen.ts
12
- const DEFAULT_PROVIDER_BASE_URLS = {
13
- [Model.KnownProviderEnum.anthropic]: "https://api.anthropic.com/v1",
14
- [Model.KnownProviderEnum.openai]: "https://api.openai.com/v1",
15
- [Model.KnownProviderEnum.openrouter]: "https://openrouter.ai/api/v1",
16
- [Model.KnownProviderEnum.xai]: "https://api.x.ai/v1"
17
- };
18
- function modelsDevURL() {
19
- return process.env.OPENCODE_MODELS_URL || "https://models.dev";
20
- }
21
- function modelsDevPath() {
22
- return process.env.OPENCODE_MODELS_DEV_FILE;
23
- }
24
- const modelsDevData = lazy(async () => {
25
- const path = modelsDevPath();
26
- if (path) {
27
- const result = await Filesystem.readJson(path).catch(() => void 0);
28
- if (result) return result;
29
- }
30
- const json = await fetch(`${modelsDevURL()}/api.json`).then((x) => x.text());
31
- return JSON.parse(json);
32
- });
33
- async function pullModelsDevData() {
34
- return modelsDevData();
35
- }
36
- function toModelValue(providerId, provider, model) {
37
- return applyModification(providerId, provider, model);
38
- }
39
- async function loadBuiltInFromModelsDev() {
40
- return pipe(await pullModelsDevData(), pickBy((provider) => Object.values(provider.models).some((model) => Boolean(model.tool_call) && isAISDKPackage(resolveModelNpm(provider, model)))), mapValues((provider, providerId) => pipe(provider.models, pickBy((model) => Boolean(model.tool_call) && isAISDKPackage(resolveModelNpm(provider, model))), mapValues((model) => toModelValue(providerId, provider, model)), pickBy((model) => model !== void 0))));
41
- }
42
- function resolveModelNpm(provider, model) {
43
- return model.provider?.npm ?? provider.npm ?? "@ai-sdk/openai-compatible";
44
- }
45
- function resolveModelBaseUrl(provider, model) {
46
- const protocol = protocolForPackage(resolveModelNpm(provider, model));
47
- return model.baseUrl ?? model.provider?.api ?? provider.api ?? DEFAULT_PROVIDER_BASE_URLS[protocol] ?? "";
48
- }
49
- function resolveModelAPIMethod(npm) {
50
- const protocol = protocolForPackage(npm);
51
- if (protocol === Model.KnownProviderEnum.openai || protocol === Model.KnownProviderEnum.xai) return Model.APIMethodEnum.responses;
52
- return Model.APIMethodEnum.languageModel;
53
- }
54
- function resolveProviderOptionsKey(protocol) {
55
- if (protocol === Model.KnownProviderEnum.openaiCompatible) return "openai-compatible";
56
- if (protocol === Model.KnownProviderEnum.googleVertex) return "google-vertex";
57
- if (protocol === Model.KnownProviderEnum.googleVertexAnthropic) return "google-vertex-anthropic";
58
- return protocol;
59
- }
60
- const OPENAI_RESPONSES_NONE_REASONING_MODELS = new Set([
61
- "gpt-5.1",
62
- "gpt-5.2",
63
- "gpt-5.3-codex",
64
- "gpt-5.4",
65
- "gpt-5.4-mini",
66
- "gpt-5.4-nano",
67
- "gpt-5.5"
68
- ]);
69
- function supportsOpenAiXhigh(modelId) {
70
- return modelId.includes("gpt-5.2") || modelId.includes("gpt-5.3") || modelId.includes("gpt-5.4") || modelId.includes("gpt-5.5");
71
- }
72
- function mergeThinkingLevelMap(model, map) {
73
- model.thinkingLevelMap = {
74
- ...model.thinkingLevelMap,
75
- ...map
76
- };
77
- }
78
- function applyThinkingLevelMetadata(model) {
79
- if (model.protocol === Model.KnownProviderEnum.openai && model.id.startsWith("gpt-5")) mergeThinkingLevelMap(model, { off: null });
80
- if (model.protocol === Model.KnownProviderEnum.openai && model.provider.id === "openai" && OPENAI_RESPONSES_NONE_REASONING_MODELS.has(model.id)) mergeThinkingLevelMap(model, { off: "none" });
81
- if (supportsOpenAiXhigh(model.id)) mergeThinkingLevelMap(model, { xhigh: "xhigh" });
82
- if (model.id.includes("opus-4-6") || model.id.includes("opus-4.6")) mergeThinkingLevelMap(model, { xhigh: "max" });
83
- if (model.id.includes("opus-4-7") || model.id.includes("opus-4.7")) mergeThinkingLevelMap(model, { xhigh: "xhigh" });
84
- }
85
- const OPENAI_CODEX_PROVIDER_ID = "openai-codex";
86
- const OPENAI_CODEX_NPM = "@codeworksh/ai-sdk-openai-codex";
87
- const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
88
- const OPENAI_CODEX_CONTEXT = 272e3;
89
- const OPENAI_CODEX_SPARK_CONTEXT = 128e3;
90
- const OPENAI_CODEX_MAX_TOKENS = 128e3;
91
- const OPENAI_CODEX_MODELS = [
92
- {
93
- id: "gpt-5.3-codex-spark",
94
- name: "GPT-5.3 Codex Spark",
95
- input: ["text"],
96
- cost: {
97
- input: 1.75,
98
- output: 14,
99
- cacheRead: .175,
100
- cacheWrite: 0
101
- },
102
- contextWindow: OPENAI_CODEX_SPARK_CONTEXT
103
- },
104
- {
105
- id: "gpt-5.4",
106
- name: "GPT-5.4",
107
- input: ["text", "image"],
108
- cost: {
109
- input: 2.5,
110
- output: 15,
111
- cacheRead: .25,
112
- cacheWrite: 0
113
- },
114
- contextWindow: OPENAI_CODEX_CONTEXT
115
- },
116
- {
117
- id: "gpt-5.4-mini",
118
- name: "GPT-5.4 mini",
119
- input: ["text", "image"],
120
- cost: {
121
- input: .75,
122
- output: 4.5,
123
- cacheRead: .075,
124
- cacheWrite: 0
125
- },
126
- contextWindow: OPENAI_CODEX_CONTEXT
127
- },
128
- {
129
- id: "gpt-5.5",
130
- name: "GPT-5.5",
131
- input: ["text", "image"],
132
- cost: {
133
- input: 5,
134
- output: 30,
135
- cacheRead: .5,
136
- cacheWrite: 0
137
- },
138
- contextWindow: OPENAI_CODEX_CONTEXT
139
- }
140
- ];
141
- function openAICodexBuiltInModels() {
142
- const models = {};
143
- for (const seed of OPENAI_CODEX_MODELS) {
144
- const info = {
145
- ...seed,
146
- provider: {
147
- id: OPENAI_CODEX_PROVIDER_ID,
148
- name: "OpenAI Codex (ChatGPT)",
149
- source: "custom",
150
- env: ["OPENAI_CODEX_API_KEY"]
151
- },
152
- baseUrl: OPENAI_CODEX_BASE_URL,
153
- reasoning: true,
154
- thinkingLevelMap: { off: null },
155
- maxTokens: OPENAI_CODEX_MAX_TOKENS,
156
- npm: OPENAI_CODEX_NPM,
157
- api: {
158
- id: seed.id,
159
- url: OPENAI_CODEX_BASE_URL,
160
- method: Model.APIMethodEnum.responses
161
- },
162
- providerOptionsKey: OPENAI_CODEX_PROVIDER_ID,
163
- protocol: Model.KnownProviderEnum.openaiCodex
164
- };
165
- applyThinkingLevelMetadata(info);
166
- models[seed.id] = info;
167
- }
168
- return models;
169
- }
170
- async function generateModels(args = {}) {
171
- const path = resolve(args.path ?? ModelCatalog.path());
172
- const modelsDev = await loadBuiltInFromModelsDev();
173
- const customCodexModels = openAICodexBuiltInModels();
174
- const allModels = {
175
- ...modelsDev,
176
- [OPENAI_CODEX_PROVIDER_ID]: customCodexModels
177
- };
178
- await Filesystem.writeJson(path, allModels);
179
- return path;
180
- }
181
- const ModelgenCommand = {
182
- command: "modelgen [path]",
183
- describe: "generate models.gen.json",
184
- builder: (yargs) => yargs.positional("path", {
185
- type: "string",
186
- describe: "output path (defaults to CODEWORK_MODELS_FILE or ./models.gen.json)"
187
- }),
188
- handler: async (args) => {
189
- const path = await generateModels(args);
190
- console.log(`Generated model catalog at ${path}`);
191
- }
192
- };
193
- function applyModification(providerId, provider, model) {
194
- const npm = resolveModelNpm(provider, model);
195
- if (!isAISDKPackage(npm)) return;
196
- const protocol = protocolForPackage(npm);
197
- const baseUrl = resolveModelBaseUrl(provider, model);
198
- const providerInfo = {
199
- id: providerId,
200
- name: provider.name,
201
- source: "api",
202
- env: provider.env
203
- };
204
- if (provider.key) providerInfo.key = provider.key;
205
- const api = {
206
- id: model.id,
207
- method: resolveModelAPIMethod(npm)
208
- };
209
- if (baseUrl) api.url = baseUrl;
210
- const info = {
211
- id: model.id,
212
- name: model.name,
213
- provider: providerInfo,
214
- baseUrl,
215
- reasoning: Boolean(model.reasoning),
216
- input: Model.normalizeInput(model.modalities.input),
217
- cost: {
218
- input: model.cost?.input ?? 0,
219
- output: model.cost?.output ?? 0,
220
- cacheRead: model.cost?.cache_read ?? 0,
221
- cacheWrite: model.cost?.cache_write ?? 0
222
- },
223
- contextWindow: model.limit?.context ?? 4096,
224
- maxTokens: model.limit?.output ?? 4096,
225
- headers: {
226
- ...provider.headers,
227
- ...model.provider?.headers,
228
- ...model.headers
229
- },
230
- npm,
231
- api,
232
- providerOptionsKey: resolveProviderOptionsKey(protocol),
233
- protocol
234
- };
235
- if (Object.keys(info.headers ?? {}).length === 0) delete info.headers;
236
- applyThinkingLevelMetadata(info);
237
- return info;
238
- }
7
+ var version = "0.7.0";
239
8
  //#endregion
240
9
  //#region src/cli/oauth.ts
241
10
  async function promptLine(message) {
@@ -289,7 +58,7 @@ function printCredentials(credentials, options) {
289
58
  }
290
59
  }
291
60
  async function runOpenAICodexAuth(args) {
292
- const storage = new JsonOpenAICodexAuthStorage({ path: args.authFile });
61
+ const storage = new JsonOpenAICodexAuthStorage({ ...args.authFile !== void 0 && { path: args.authFile } });
293
62
  const client = new OpenAICodexOAuthClient({ storage });
294
63
  if (args.logout) {
295
64
  await client.logout();
@@ -318,7 +87,8 @@ async function runOpenAICodexAuth(args) {
318
87
  return;
319
88
  }
320
89
  const credentials = await client.login({
321
- originator: args.originator,
90
+ ...args.originator !== void 0 && { originator: args.originator },
91
+ ...args.manual && { onManualCodeInput: async () => promptLine("Paste the redirect URL or authorization code, or wait for browser callback:") },
322
92
  onAuth: (info) => {
323
93
  console.log(info.instructions ?? "Complete OpenAI Codex authentication in your browser.");
324
94
  console.log(info.url);
@@ -326,8 +96,7 @@ async function runOpenAICodexAuth(args) {
326
96
  console.warn(`Failed to open browser: ${error instanceof Error ? error.message : String(error)}`);
327
97
  });
328
98
  },
329
- onPrompt: async (prompt) => promptLine(prompt.message),
330
- onManualCodeInput: args.manual ? async () => promptLine("Paste the redirect URL or authorization code, or wait for browser callback:") : void 0
99
+ onPrompt: async (prompt) => promptLine(prompt.message)
331
100
  });
332
101
  console.log(`Saved OpenAI Codex credentials to ${storage.path}`);
333
102
  printCredentials(credentials, args);
package/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":["pkg.version"],"sources":["../../package.json","../../src/cli/modelgen.ts","../../src/cli/oauth.ts","../../src/cli.ts"],"sourcesContent":["","import { Filesystem, lazy } from \"@codeworksh/utils\";\nimport { resolve } from \"node:path\";\nimport { mapValues, pickBy, pipe } from \"remeda\";\nimport type { CommandModule } from \"yargs\";\nimport { DEFAULT_AI_SDK_FALLBACK, isAISDKPackage, protocolForPackage } from \"../llm/registry\";\nimport { ModelCatalog } from \"../model/catalog\";\nimport { Model } from \"../model/model\";\n\nconst DEFAULT_PROVIDER_BASE_URLS: Partial<Record<Model.KnownProviderEnum, string>> = {\n\t[Model.KnownProviderEnum.anthropic]: \"https://api.anthropic.com/v1\",\n\t[Model.KnownProviderEnum.openai]: \"https://api.openai.com/v1\",\n\t[Model.KnownProviderEnum.openrouter]: \"https://openrouter.ai/api/v1\",\n\t[Model.KnownProviderEnum.xai]: \"https://api.x.ai/v1\",\n};\n\ninterface ModelsDevModel {\n\tid: string;\n\tname: string;\n\tfamily: string;\n\tattachment: boolean;\n\treasoning?: boolean;\n\ttool_call?: boolean;\n\ttemperature?: boolean;\n\tknowledge?: string | boolean;\n\trelease_date: string;\n\tlast_updated: string;\n\tmodalities: {\n\t\tinput?: string[];\n\t\toutput: string[];\n\t};\n\topen_weights: boolean;\n\tbaseUrl?: string;\n\theaders?: Record<string, string>;\n\tcost?: {\n\t\tinput?: number;\n\t\toutput?: number;\n\t\tcache_read?: number;\n\t\tcache_write?: number;\n\t};\n\tlimit?: {\n\t\tcontext?: number;\n\t\toutput?: number;\n\t};\n\tstructured_output?: boolean;\n\tprovider?: {\n\t\tnpm?: string;\n\t\tapi?: string;\n\t\theaders?: Record<string, string>;\n\t};\n}\n\ninterface ModelsDevProvider {\n\tid: string;\n\tenv: string[];\n\tnpm?: string;\n\tapi?: string;\n\tname: string;\n\tdoc?: string; // reference documentation link\n\tkey?: string; // runtime placeholder for api/oauth key\n\theaders?: Record<string, string>; // custom overrides at provider level\n\tmodels: Record<string, ModelsDevModel>;\n}\n\nexport type BuiltInModels = Partial<Record<string, Record<string, Model.Info>>>;\n\n// Doesn't represent the full spec from models.dev.\n// Represents the provider entries on a best-effort basis.\ntype ModelsDevCatalog = Record<string, ModelsDevProvider>;\ntype LazyModelsDevCatalog = ReturnType<typeof lazy<Promise<ModelsDevCatalog>>>;\n\nfunction modelsDevURL(): string {\n\treturn process.env.OPENCODE_MODELS_URL || \"https://models.dev\";\n}\n\nfunction modelsDevPath(): string | undefined {\n\treturn process.env.OPENCODE_MODELS_DEV_FILE;\n}\n\nconst modelsDevData: LazyModelsDevCatalog = lazy(async () => {\n\tconst path = modelsDevPath();\n\tif (path) {\n\t\tconst result = await Filesystem.readJson<ModelsDevCatalog>(path).catch(() => undefined);\n\t\tif (result) return result;\n\t}\n\n\tconst json = await fetch(`${modelsDevURL()}/api.json`).then((x) => x.text());\n\treturn JSON.parse(json) as ModelsDevCatalog;\n});\n\nasync function pullModelsDevData(): Promise<ModelsDevCatalog> {\n\treturn modelsDevData();\n}\n\nfunction toModelValue(providerId: string, provider: ModelsDevProvider, model: ModelsDevModel): Model.Info | undefined {\n\treturn applyModification(providerId, provider, model);\n}\n\nasync function loadBuiltInFromModelsDev() {\n\tconst catalog = await pullModelsDevData();\n\treturn pipe(\n\t\tcatalog,\n\t\tpickBy((provider) =>\n\t\t\tObject.values(provider.models).some(\n\t\t\t\t// If `resolveModelNpm` fallbacks to `@ai-sdk/openai-compatible`\n\t\t\t\t// isAISDKPakage will be truthy, modify resolveModelNpm for custom logic if needed.\n\t\t\t\t// Keep `isAISDKPackage` as readonly for supported implemenatations key check\n\t\t\t\t(model) => Boolean(model.tool_call) && isAISDKPackage(resolveModelNpm(provider, model)),\n\t\t\t),\n\t\t),\n\t\tmapValues((provider, providerId) =>\n\t\t\tpipe(\n\t\t\t\tprovider.models,\n\t\t\t\tpickBy((model) => Boolean(model.tool_call) && isAISDKPackage(resolveModelNpm(provider, model))),\n\t\t\t\tmapValues((model) => toModelValue(providerId, provider, model)),\n\t\t\t\tpickBy((model): model is Model.Info => model !== undefined),\n\t\t\t),\n\t\t),\n\t) as BuiltInModels;\n}\n\ntype ThinkingLevelMap = NonNullable<Model.Info[\"thinkingLevelMap\"]>;\n\nfunction resolveModelNpm(provider: ModelsDevProvider, model: ModelsDevModel): string {\n\treturn model.provider?.npm ?? provider.npm ?? DEFAULT_AI_SDK_FALLBACK;\n}\n\nfunction resolveModelBaseUrl(provider: ModelsDevProvider, model: ModelsDevModel): string {\n\tconst npm = resolveModelNpm(provider, model);\n\tconst protocol = protocolForPackage(npm);\n\treturn model.baseUrl ?? model.provider?.api ?? provider.api ?? DEFAULT_PROVIDER_BASE_URLS[protocol] ?? \"\";\n}\n\nfunction resolveModelAPIMethod(npm: string): Model.APIMethodEnum {\n\tconst protocol = protocolForPackage(npm);\n\t// `By default, xai(modelId) uses the Chat API.\n\t// To use the Responses API with server-side agentic tools, explicitly use xai.responses(modelId).`\n\t// References: https://ai-sdk.dev/providers/ai-sdk-providers/xai\n\tif (protocol === Model.KnownProviderEnum.openai || protocol === Model.KnownProviderEnum.xai) {\n\t\treturn Model.APIMethodEnum.responses;\n\t}\n\treturn Model.APIMethodEnum.languageModel;\n}\n\nfunction resolveProviderOptionsKey(protocol: Model.KnownProviderEnum): string {\n\tif (protocol === Model.KnownProviderEnum.openaiCompatible) return \"openai-compatible\";\n\tif (protocol === Model.KnownProviderEnum.googleVertex) return \"google-vertex\";\n\tif (protocol === Model.KnownProviderEnum.googleVertexAnthropic) return \"google-vertex-anthropic\";\n\treturn protocol;\n}\n\n//\n// adhoc helpers variations\nconst OPENAI_RESPONSES_NONE_REASONING_MODELS = new Set([\n\t\"gpt-5.1\",\n\t\"gpt-5.2\",\n\t\"gpt-5.3-codex\",\n\t\"gpt-5.4\",\n\t\"gpt-5.4-mini\",\n\t\"gpt-5.4-nano\",\n\t\"gpt-5.5\",\n]);\n\nfunction supportsOpenAiXhigh(modelId: string): boolean {\n\treturn (\n\t\tmodelId.includes(\"gpt-5.2\") ||\n\t\tmodelId.includes(\"gpt-5.3\") ||\n\t\tmodelId.includes(\"gpt-5.4\") ||\n\t\tmodelId.includes(\"gpt-5.5\")\n\t);\n}\n\nfunction mergeThinkingLevelMap(model: Model.Info, map: ThinkingLevelMap): void {\n\tmodel.thinkingLevelMap = { ...model.thinkingLevelMap, ...map };\n}\n\nfunction applyThinkingLevelMetadata(model: Model.Info): void {\n\tif (model.protocol === Model.KnownProviderEnum.openai && model.id.startsWith(\"gpt-5\")) {\n\t\tmergeThinkingLevelMap(model, { off: null });\n\t}\n\tif (\n\t\tmodel.protocol === Model.KnownProviderEnum.openai &&\n\t\tmodel.provider.id === \"openai\" &&\n\t\tOPENAI_RESPONSES_NONE_REASONING_MODELS.has(model.id)\n\t) {\n\t\tmergeThinkingLevelMap(model, { off: \"none\" });\n\t}\n\tif (supportsOpenAiXhigh(model.id)) {\n\t\tmergeThinkingLevelMap(model, { xhigh: \"xhigh\" });\n\t}\n\tif (model.id.includes(\"opus-4-6\") || model.id.includes(\"opus-4.6\")) {\n\t\tmergeThinkingLevelMap(model, { xhigh: \"max\" });\n\t}\n\tif (model.id.includes(\"opus-4-7\") || model.id.includes(\"opus-4.7\")) {\n\t\tmergeThinkingLevelMap(model, { xhigh: \"xhigh\" });\n\t}\n}\n\n//\n// OpenAI Codex (ChatGPT OAuth) models.\n// NOTE: These are not fetched from models.dev; we keep a small, explicit list to avoid aliases.\n// Context window is based on observed server limits (400s above ~272k), not marketing numbers.\nconst OPENAI_CODEX_PROVIDER_ID = \"openai-codex\";\nconst OPENAI_CODEX_NPM = \"@codeworksh/ai-sdk-openai-codex\";\nconst OPENAI_CODEX_BASE_URL = \"https://chatgpt.com/backend-api\";\nconst OPENAI_CODEX_CONTEXT = 272_000;\nconst OPENAI_CODEX_SPARK_CONTEXT = 128_000;\nconst OPENAI_CODEX_MAX_TOKENS = 128_000;\n\ntype OpenAICodexModelSeed = Pick<Model.Info, \"id\" | \"name\" | \"input\" | \"cost\" | \"contextWindow\">;\n\nconst OPENAI_CODEX_MODELS: OpenAICodexModelSeed[] = [\n\t{\n\t\tid: \"gpt-5.3-codex-spark\",\n\t\tname: \"GPT-5.3 Codex Spark\",\n\t\tinput: [\"text\"],\n\t\tcost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },\n\t\tcontextWindow: OPENAI_CODEX_SPARK_CONTEXT,\n\t},\n\t{\n\t\tid: \"gpt-5.4\",\n\t\tname: \"GPT-5.4\",\n\t\tinput: [\"text\", \"image\"],\n\t\tcost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 },\n\t\tcontextWindow: OPENAI_CODEX_CONTEXT,\n\t},\n\t{\n\t\tid: \"gpt-5.4-mini\",\n\t\tname: \"GPT-5.4 mini\",\n\t\tinput: [\"text\", \"image\"],\n\t\tcost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },\n\t\tcontextWindow: OPENAI_CODEX_CONTEXT,\n\t},\n\t{\n\t\tid: \"gpt-5.5\",\n\t\tname: \"GPT-5.5\",\n\t\tinput: [\"text\", \"image\"],\n\t\tcost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },\n\t\tcontextWindow: OPENAI_CODEX_CONTEXT,\n\t},\n];\n\nexport function openAICodexBuiltInModels(): Record<string, Model.Info> {\n\tconst models: Record<string, Model.Info> = {};\n\tfor (const seed of OPENAI_CODEX_MODELS) {\n\t\tconst info: Model.Info = {\n\t\t\t...seed,\n\t\t\tprovider: {\n\t\t\t\tid: OPENAI_CODEX_PROVIDER_ID,\n\t\t\t\tname: \"OpenAI Codex (ChatGPT)\",\n\t\t\t\tsource: \"custom\",\n\t\t\t\tenv: [\"OPENAI_CODEX_API_KEY\"],\n\t\t\t},\n\t\t\tbaseUrl: OPENAI_CODEX_BASE_URL,\n\t\t\treasoning: true,\n\t\t\t// Codex models always reason; the off level cannot be requested.\n\t\t\tthinkingLevelMap: { off: null },\n\t\t\tmaxTokens: OPENAI_CODEX_MAX_TOKENS,\n\t\t\tnpm: OPENAI_CODEX_NPM,\n\t\t\tapi: {\n\t\t\t\tid: seed.id,\n\t\t\t\turl: OPENAI_CODEX_BASE_URL,\n\t\t\t\tmethod: Model.APIMethodEnum.responses,\n\t\t\t},\n\t\t\tproviderOptionsKey: OPENAI_CODEX_PROVIDER_ID,\n\t\t\tprotocol: Model.KnownProviderEnum.openaiCodex,\n\t\t};\n\t\tapplyThinkingLevelMetadata(info);\n\t\tmodels[seed.id] = info;\n\t}\n\treturn models;\n}\n\nexport async function generateModels(args: { path?: string } = {}): Promise<string> {\n\tconst path = resolve(args.path ?? ModelCatalog.path());\n\tconst modelsDev = await loadBuiltInFromModelsDev();\n\tconst customCodexModels = openAICodexBuiltInModels();\n\n\tconst allModels = { ...modelsDev, [OPENAI_CODEX_PROVIDER_ID]: customCodexModels };\n\tawait Filesystem.writeJson(path, allModels);\n\treturn path;\n}\n\n//\n// CLI entry\nexport const ModelgenCommand: CommandModule<object, { path?: string }> = {\n\tcommand: \"modelgen [path]\",\n\tdescribe: \"generate models.gen.json\",\n\tbuilder: (yargs) =>\n\t\tyargs.positional(\"path\", {\n\t\t\ttype: \"string\",\n\t\t\tdescribe: \"output path (defaults to CODEWORK_MODELS_FILE or ./models.gen.json)\",\n\t\t}),\n\thandler: async (args) => {\n\t\tconst path = await generateModels(args);\n\t\tconsole.log(`Generated model catalog at ${path}`);\n\t},\n};\n\nexport function applyModification(\n\tproviderId: string,\n\tprovider: ModelsDevProvider,\n\tmodel: ModelsDevModel,\n): Model.Info | undefined {\n\tconst npm = resolveModelNpm(provider, model);\n\tif (!isAISDKPackage(npm)) return;\n\n\tconst protocol = protocolForPackage(npm);\n\tconst baseUrl = resolveModelBaseUrl(provider, model);\n\tconst providerInfo: Model.ProviderInfo = {\n\t\tid: providerId,\n\t\tname: provider.name,\n\t\tsource: \"api\",\n\t\tenv: provider.env,\n\t};\n\tif (provider.key) providerInfo.key = provider.key;\n\tconst api: Model.APIMetadata = {\n\t\tid: model.id,\n\t\tmethod: resolveModelAPIMethod(npm),\n\t};\n\tif (baseUrl) api.url = baseUrl;\n\n\tconst info: Model.Info = {\n\t\tid: model.id,\n\t\tname: model.name,\n\t\tprovider: providerInfo,\n\t\tbaseUrl,\n\t\treasoning: Boolean(model.reasoning),\n\t\tinput: Model.normalizeInput(model.modalities.input),\n\t\tcost: {\n\t\t\tinput: model.cost?.input ?? 0,\n\t\t\toutput: model.cost?.output ?? 0,\n\t\t\tcacheRead: model.cost?.cache_read ?? 0,\n\t\t\tcacheWrite: model.cost?.cache_write ?? 0,\n\t\t},\n\t\tcontextWindow: model.limit?.context ?? 4096,\n\t\tmaxTokens: model.limit?.output ?? 4096,\n\t\theaders: {\n\t\t\t...provider.headers,\n\t\t\t...model.provider?.headers,\n\t\t\t...model.headers,\n\t\t},\n\t\tnpm,\n\t\tapi,\n\t\tproviderOptionsKey: resolveProviderOptionsKey(protocol),\n\t\tprotocol,\n\t};\n\tif (Object.keys(info.headers ?? {}).length === 0) delete info.headers;\n\tapplyThinkingLevelMetadata(info);\n\treturn info;\n}\n","import type { CommandModule } from \"yargs\";\nimport {\n\tJsonOpenAICodexAuthStorage,\n\tOpenAICodexOAuthClient,\n\ttype OpenAICodexOAuthCredentials,\n\topenAICodexHeaders,\n} from \"../oauth/openai/codex\";\n\ntype AuthArgs = {\n\topenaiCodex?: boolean;\n\tauthFile?: string;\n\tbrowser?: boolean;\n\tmanual?: boolean;\n\tstatus?: boolean;\n\trefresh?: boolean;\n\tlogout?: boolean;\n\tjson?: boolean;\n\tprintHeaders?: boolean;\n\toriginator?: string;\n};\n\nasync function promptLine(message: string): Promise<string> {\n\tconst readline = await import(\"node:readline/promises\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t});\n\n\ttry {\n\t\treturn await rl.question(`${message} `);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function openBrowser(url: string): Promise<void> {\n\tconst { spawn } = await import(\"node:child_process\");\n\tconst command =\n\t\tprocess.platform === \"darwin\"\n\t\t\t? { file: \"open\", args: [url] }\n\t\t\t: process.platform === \"win32\"\n\t\t\t\t? { file: \"cmd\", args: [\"/c\", \"start\", \"\", url] }\n\t\t\t\t: { file: \"xdg-open\", args: [url] };\n\n\tconst child = spawn(command.file, command.args, {\n\t\tdetached: true,\n\t\tstdio: \"ignore\",\n\t});\n\tchild.unref();\n}\n\nfunction printCredentials(\n\tcredentials: OpenAICodexOAuthCredentials,\n\toptions: { json?: boolean; printHeaders?: boolean },\n) {\n\tif (options.json) {\n\t\tconsole.log(\n\t\t\tJSON.stringify(\n\t\t\t\t{\n\t\t\t\t\taccountId: credentials.accountId,\n\t\t\t\t\texpires: credentials.expires,\n\t\t\t\t\texpiresAt: new Date(credentials.expires).toISOString(),\n\t\t\t\t\theaders: options.printHeaders ? openAICodexHeaders(credentials) : undefined,\n\t\t\t\t},\n\t\t\t\tnull,\n\t\t\t\t2,\n\t\t\t),\n\t\t);\n\t\treturn;\n\t}\n\n\tconsole.log(`Account: ${credentials.accountId}`);\n\tconsole.log(`Expires: ${new Date(credentials.expires).toLocaleString()}`);\n\tif (options.printHeaders) {\n\t\tconsole.log(\"Headers:\");\n\t\tfor (const [name, value] of Object.entries(openAICodexHeaders(credentials))) {\n\t\t\tconsole.log(`${name}: ${value}`);\n\t\t}\n\t}\n}\n\nasync function runOpenAICodexAuth(args: AuthArgs): Promise<void> {\n\tconst storage = new JsonOpenAICodexAuthStorage({ path: args.authFile });\n\tconst client = new OpenAICodexOAuthClient({ storage });\n\n\tif (args.logout) {\n\t\tawait client.logout();\n\t\tconsole.log(`Cleared OpenAI Codex credentials from ${storage.path}`);\n\t\treturn;\n\t}\n\n\tif (args.status) {\n\t\tconst credentials = await storage.get();\n\t\tif (!credentials) {\n\t\t\tconsole.log(`No OpenAI Codex credentials found at ${storage.path}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tprintCredentials(credentials, args);\n\t\treturn;\n\t}\n\n\tif (args.refresh) {\n\t\tconst credentials = await client.getCredentials();\n\t\tif (!credentials) {\n\t\t\tconsole.log(`No OpenAI Codex credentials found at ${storage.path}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tconsole.log(`Refreshed OpenAI Codex credentials in ${storage.path}`);\n\t\tprintCredentials(credentials, args);\n\t\treturn;\n\t}\n\n\tconst credentials = await client.login({\n\t\toriginator: args.originator,\n\t\tonAuth: (info) => {\n\t\t\tconsole.log(info.instructions ?? \"Complete OpenAI Codex authentication in your browser.\");\n\t\t\tconsole.log(info.url);\n\t\t\tif (args.browser !== false) {\n\t\t\t\tvoid openBrowser(info.url).catch((error) => {\n\t\t\t\t\tconsole.warn(`Failed to open browser: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tonPrompt: async (prompt) => promptLine(prompt.message),\n\t\tonManualCodeInput: args.manual\n\t\t\t? async () => promptLine(\"Paste the redirect URL or authorization code, or wait for browser callback:\")\n\t\t\t: undefined,\n\t});\n\n\tconsole.log(`Saved OpenAI Codex credentials to ${storage.path}`);\n\tprintCredentials(credentials, args);\n}\n\nexport const OAuthCommand: CommandModule<object, AuthArgs> = {\n\tcommand: \"auth\",\n\tdescribe: \"manage OAuth credentials\",\n\tbuilder: (yargs) =>\n\t\tyargs\n\t\t\t.option(\"openai-codex\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"use OpenAI Codex OAuth\",\n\t\t\t})\n\t\t\t.option(\"auth-file\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescribe: \"path to auth.json (defaults to CODEWORK_CREDENTIALS or ~/.codework/aikit/auth.json)\",\n\t\t\t})\n\t\t\t.option(\"browser\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefault: true,\n\t\t\t\tdescribe: \"open the authorization URL in the default browser\",\n\t\t\t})\n\t\t\t.option(\"manual\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefault: false,\n\t\t\t\tdescribe: \"also prompt for a pasted redirect URL or authorization code\",\n\t\t\t})\n\t\t\t.option(\"originator\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdefault: \"codework\",\n\t\t\t\tdescribe: \"OAuth originator value\",\n\t\t\t})\n\t\t\t.option(\"status\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"show stored credential status without refreshing\",\n\t\t\t})\n\t\t\t.option(\"refresh\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"refresh stored credentials if expired\",\n\t\t\t})\n\t\t\t.option(\"logout\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"clear stored credentials\",\n\t\t\t})\n\t\t\t.option(\"json\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"print machine-readable output\",\n\t\t\t})\n\t\t\t.option(\"print-headers\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"print request headers for Codex API calls\",\n\t\t\t})\n\t\t\t.check((args) => {\n\t\t\t\tif (!args.openaiCodex) throw new Error(\"Choose an auth provider, for example: auth --openai-codex\");\n\t\t\t\tconst actions = [args.status, args.refresh, args.logout].filter(Boolean).length;\n\t\t\t\tif (actions > 1) throw new Error(\"Choose only one of --status, --refresh, or --logout\");\n\t\t\t\treturn true;\n\t\t\t}),\n\thandler: async (args) => {\n\t\tawait runOpenAICodexAuth(args);\n\t},\n};\n","#!/usr/bin/env node\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { ModelgenCommand } from \"./cli/modelgen\";\nimport { OAuthCommand } from \"./cli/oauth\";\n\nconst cli = yargs(hideBin(process.argv))\n\t.scriptName(\"aikit\")\n\t.wrap(100)\n\t.help(\"help\", \"show help\")\n\t.alias(\"help\", \"h\")\n\t.version(\"version\", \"show version number\", pkg.version)\n\t.alias(\"version\", \"v\")\n\t.command(ModelgenCommand)\n\t.command(OAuthCommand)\n\t.demandCommand(1, \"Choose a command\")\n\t.strict()\n\t.fail((message, error) => {\n\t\tif (error) throw error;\n\t\tif (message) throw new Error(message);\n\t});\n\ntry {\n\tawait cli.parse();\n} catch (error) {\n\tprocess.exitCode = 1;\n\tconsole.error(error instanceof Error ? error.message : String(error));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":["pkg.version"],"sources":["../../package.json","../../src/cli/oauth.ts","../../src/cli.ts"],"sourcesContent":["","import type { CommandModule } from \"yargs\";\nimport {\n\tJsonOpenAICodexAuthStorage,\n\tOpenAICodexOAuthClient,\n\ttype OpenAICodexOAuthCredentials,\n\topenAICodexHeaders,\n} from \"../oauth/openai/codex.ts\";\n\n// `?: T | undefined` rather than plain `?: T`: yargs hands these through as explicit `undefined`,\n// which a bare optional property no longer accepts under `exactOptionalPropertyTypes`.\ntype AuthArgs = {\n\topenaiCodex?: boolean | undefined;\n\tauthFile?: string | undefined;\n\tbrowser?: boolean | undefined;\n\tmanual?: boolean | undefined;\n\tstatus?: boolean | undefined;\n\trefresh?: boolean | undefined;\n\tlogout?: boolean | undefined;\n\tjson?: boolean | undefined;\n\tprintHeaders?: boolean | undefined;\n\toriginator?: string | undefined;\n};\n\nasync function promptLine(message: string): Promise<string> {\n\tconst readline = await import(\"node:readline/promises\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t});\n\n\ttry {\n\t\treturn await rl.question(`${message} `);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function openBrowser(url: string): Promise<void> {\n\tconst { spawn } = await import(\"node:child_process\");\n\tconst command =\n\t\tprocess.platform === \"darwin\"\n\t\t\t? { file: \"open\", args: [url] }\n\t\t\t: process.platform === \"win32\"\n\t\t\t\t? { file: \"cmd\", args: [\"/c\", \"start\", \"\", url] }\n\t\t\t\t: { file: \"xdg-open\", args: [url] };\n\n\tconst child = spawn(command.file, command.args, {\n\t\tdetached: true,\n\t\tstdio: \"ignore\",\n\t});\n\tchild.unref();\n}\n\nfunction printCredentials(\n\tcredentials: OpenAICodexOAuthCredentials,\n\toptions: { json?: boolean | undefined; printHeaders?: boolean | undefined },\n) {\n\tif (options.json) {\n\t\tconsole.log(\n\t\t\tJSON.stringify(\n\t\t\t\t{\n\t\t\t\t\taccountId: credentials.accountId,\n\t\t\t\t\texpires: credentials.expires,\n\t\t\t\t\texpiresAt: new Date(credentials.expires).toISOString(),\n\t\t\t\t\theaders: options.printHeaders ? openAICodexHeaders(credentials) : undefined,\n\t\t\t\t},\n\t\t\t\tnull,\n\t\t\t\t2,\n\t\t\t),\n\t\t);\n\t\treturn;\n\t}\n\n\tconsole.log(`Account: ${credentials.accountId}`);\n\tconsole.log(`Expires: ${new Date(credentials.expires).toLocaleString()}`);\n\tif (options.printHeaders) {\n\t\tconsole.log(\"Headers:\");\n\t\tfor (const [name, value] of Object.entries(openAICodexHeaders(credentials))) {\n\t\t\tconsole.log(`${name}: ${value}`);\n\t\t}\n\t}\n}\n\nasync function runOpenAICodexAuth(args: AuthArgs): Promise<void> {\n\tconst storage = new JsonOpenAICodexAuthStorage({\n\t\t...(args.authFile !== undefined && { path: args.authFile }),\n\t});\n\tconst client = new OpenAICodexOAuthClient({ storage });\n\n\tif (args.logout) {\n\t\tawait client.logout();\n\t\tconsole.log(`Cleared OpenAI Codex credentials from ${storage.path}`);\n\t\treturn;\n\t}\n\n\tif (args.status) {\n\t\tconst credentials = await storage.get();\n\t\tif (!credentials) {\n\t\t\tconsole.log(`No OpenAI Codex credentials found at ${storage.path}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tprintCredentials(credentials, args);\n\t\treturn;\n\t}\n\n\tif (args.refresh) {\n\t\tconst credentials = await client.getCredentials();\n\t\tif (!credentials) {\n\t\t\tconsole.log(`No OpenAI Codex credentials found at ${storage.path}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tconsole.log(`Refreshed OpenAI Codex credentials in ${storage.path}`);\n\t\tprintCredentials(credentials, args);\n\t\treturn;\n\t}\n\n\tconst credentials = await client.login({\n\t\t...(args.originator !== undefined && { originator: args.originator }),\n\t\t...(args.manual && {\n\t\t\tonManualCodeInput: async () =>\n\t\t\t\tpromptLine(\"Paste the redirect URL or authorization code, or wait for browser callback:\"),\n\t\t}),\n\t\tonAuth: (info) => {\n\t\t\tconsole.log(info.instructions ?? \"Complete OpenAI Codex authentication in your browser.\");\n\t\t\tconsole.log(info.url);\n\t\t\tif (args.browser !== false) {\n\t\t\t\tvoid openBrowser(info.url).catch((error) => {\n\t\t\t\t\tconsole.warn(`Failed to open browser: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tonPrompt: async (prompt) => promptLine(prompt.message),\n\t});\n\n\tconsole.log(`Saved OpenAI Codex credentials to ${storage.path}`);\n\tprintCredentials(credentials, args);\n}\n\nexport const OAuthCommand: CommandModule<object, AuthArgs> = {\n\tcommand: \"auth\",\n\tdescribe: \"manage OAuth credentials\",\n\tbuilder: (yargs) =>\n\t\tyargs\n\t\t\t.option(\"openai-codex\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"use OpenAI Codex OAuth\",\n\t\t\t})\n\t\t\t.option(\"auth-file\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescribe: \"path to auth.json (defaults to CODEWORK_CREDENTIALS or ~/.codework/aikit/auth.json)\",\n\t\t\t})\n\t\t\t.option(\"browser\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefault: true,\n\t\t\t\tdescribe: \"open the authorization URL in the default browser\",\n\t\t\t})\n\t\t\t.option(\"manual\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefault: false,\n\t\t\t\tdescribe: \"also prompt for a pasted redirect URL or authorization code\",\n\t\t\t})\n\t\t\t.option(\"originator\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdefault: \"codework\",\n\t\t\t\tdescribe: \"OAuth originator value\",\n\t\t\t})\n\t\t\t.option(\"status\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"show stored credential status without refreshing\",\n\t\t\t})\n\t\t\t.option(\"refresh\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"refresh stored credentials if expired\",\n\t\t\t})\n\t\t\t.option(\"logout\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"clear stored credentials\",\n\t\t\t})\n\t\t\t.option(\"json\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"print machine-readable output\",\n\t\t\t})\n\t\t\t.option(\"print-headers\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: \"print request headers for Codex API calls\",\n\t\t\t})\n\t\t\t.check((args) => {\n\t\t\t\tif (!args.openaiCodex) throw new Error(\"Choose an auth provider, for example: auth --openai-codex\");\n\t\t\t\tconst actions = [args.status, args.refresh, args.logout].filter(Boolean).length;\n\t\t\t\tif (actions > 1) throw new Error(\"Choose only one of --status, --refresh, or --logout\");\n\t\t\t\treturn true;\n\t\t\t}),\n\thandler: async (args) => {\n\t\tawait runOpenAICodexAuth(args);\n\t},\n};\n","#!/usr/bin/env node\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { ModelgenCommand } from \"./cli/modelgen.ts\";\nimport { OAuthCommand } from \"./cli/oauth.ts\";\n\nconst cli = yargs(hideBin(process.argv))\n\t.scriptName(\"aikit\")\n\t.wrap(100)\n\t.help(\"help\", \"show help\")\n\t.alias(\"help\", \"h\")\n\t.version(\"version\", \"show version number\", pkg.version)\n\t.alias(\"version\", \"v\")\n\t.command(ModelgenCommand)\n\t.command(OAuthCommand)\n\t.demandCommand(1, \"Choose a command\")\n\t.strict()\n\t.fail((message, error) => {\n\t\tif (error) throw error;\n\t\tif (message) throw new Error(message);\n\t});\n\ntry {\n\tawait cli.parse();\n} catch (error) {\n\tprocess.exitCode = 1;\n\tconsole.error(error instanceof Error ? error.message : String(error));\n}\n"],"mappings":"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"}
@@ -28,7 +28,7 @@ const DEFAULT_SCOPE = "openid profile email offline_access";
28
28
  const DEFAULT_ORIGINATOR = "codework";
29
29
  const DEFAULT_PROVIDER_ID = "openai-codex";
30
30
  const JWT_CLAIM_PATH = "https://api.openai.com/auth";
31
- const REFRESH_SKEW_MS = 60 * 1e3;
31
+ const REFRESH_SKEW_MS = 6e4;
32
32
  function readEnv(name) {
33
33
  if (typeof process === "undefined") return void 0;
34
34
  return process.env[name];
@@ -78,12 +78,12 @@ function getCrypto() {
78
78
  return globalThis.crypto;
79
79
  }
80
80
  function createState() {
81
- const bytes = new Uint8Array(16);
81
+ const bytes = /* @__PURE__ */ new Uint8Array(16);
82
82
  getCrypto().getRandomValues(bytes);
83
83
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
84
84
  }
85
85
  async function generatePKCE() {
86
- const bytes = new Uint8Array(32);
86
+ const bytes = /* @__PURE__ */ new Uint8Array(32);
87
87
  getCrypto().getRandomValues(bytes);
88
88
  const verifier = base64UrlEncode(bytes);
89
89
  const data = new TextEncoder().encode(verifier);
@@ -93,29 +93,26 @@ async function generatePKCE() {
93
93
  challenge: base64UrlEncode(new Uint8Array(hash))
94
94
  };
95
95
  }
96
+ function authorizationInput(code, state) {
97
+ return {
98
+ ...code != null && { code },
99
+ ...state != null && { state }
100
+ };
101
+ }
96
102
  function parseOpenAICodexAuthorizationInput(input) {
97
103
  const value = input.trim();
98
104
  if (!value) return {};
99
105
  try {
100
106
  const url = new URL(value);
101
- return {
102
- code: url.searchParams.get("code") ?? void 0,
103
- state: url.searchParams.get("state") ?? void 0
104
- };
107
+ return authorizationInput(url.searchParams.get("code"), url.searchParams.get("state"));
105
108
  } catch {}
106
109
  if (value.includes("#")) {
107
110
  const [code, state] = value.split("#", 2);
108
- return {
109
- code,
110
- state
111
- };
111
+ return authorizationInput(code, state);
112
112
  }
113
113
  if (value.includes("code=")) {
114
114
  const params = new URLSearchParams(value);
115
- return {
116
- code: params.get("code") ?? void 0,
117
- state: params.get("state") ?? void 0
118
- };
115
+ return authorizationInput(params.get("code"), params.get("state"));
119
116
  }
120
117
  return { code: value };
121
118
  }
@@ -274,7 +271,7 @@ function oauthErrorHtml(message, details) {
274
271
  title: "Authentication failed",
275
272
  heading: "Authentication failed",
276
273
  message,
277
- details
274
+ ...details !== void 0 && { details }
278
275
  });
279
276
  }
280
277
  async function startLocalOAuthServer(state) {
@@ -321,10 +318,17 @@ async function startLocalOAuthServer(state) {
321
318
  res.end(oauthErrorHtml("Internal error while processing OAuth callback.", error instanceof Error ? error.message : String(error)));
322
319
  }
323
320
  });
321
+ const close = async () => {
322
+ if (!server.listening) return;
323
+ await new Promise((resolve) => {
324
+ server.close(() => resolve());
325
+ server.closeAllConnections();
326
+ });
327
+ };
324
328
  return new Promise((resolve) => {
325
329
  server.listen(1455, readEnv(CODEWORK_OAUTH_CALLBACK_HOST) || "127.0.0.1", () => {
326
330
  resolve({
327
- close: () => server.close(),
331
+ close,
328
332
  cancelWait: () => {
329
333
  settleWait?.(null);
330
334
  },
@@ -333,11 +337,7 @@ async function startLocalOAuthServer(state) {
333
337
  }).on("error", () => {
334
338
  settleWait?.(null);
335
339
  resolve({
336
- close: () => {
337
- try {
338
- server.close();
339
- } catch {}
340
- },
340
+ close,
341
341
  cancelWait: () => {},
342
342
  waitForCode: async () => null
343
343
  });
@@ -401,7 +401,7 @@ async function loginOpenAICodex(options) {
401
401
  accountId
402
402
  };
403
403
  } finally {
404
- server.close();
404
+ await server.close();
405
405
  }
406
406
  }
407
407
  async function refreshOpenAICodexToken(refreshToken) {
@@ -525,4 +525,4 @@ async function getOpenAICodexApiKey(options = {}) {
525
525
  //#endregion
526
526
  export { exchangeOpenAICodexAuthorizationCode as a, openAICodexHeaders as c, createOpenAICodexAuthorizationFlow as i, parseOpenAICodexAuthorizationInput as l, OPENAI_CODEX_API_KEY_ENV as n, getOpenAICodexAccountId as o, OpenAICodexOAuthClient as r, getOpenAICodexApiKey as s, JsonOpenAICodexAuthStorage as t, refreshOpenAICodexToken as u };
527
527
 
528
- //# sourceMappingURL=codex-C36oU6yH.mjs.map
528
+ //# sourceMappingURL=codex-DyQHzQmn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-DyQHzQmn.mjs","names":[],"sources":["../../src/oauth/openai/codex.ts"],"sourcesContent":["/**\n * OpenAI Codex OAuth.\n *\n * Public interface, by use case:\n *\n * 1. Server OAuth integration (storage-free, bring your own routes):\n * `createOpenAICodexAuthorizationFlow`, `exchangeOpenAICodexAuthorizationCode`,\n * `parseOpenAICodexAuthorizationInput`, `refreshOpenAICodexToken`, `getOpenAICodexAccountId`.\n * 2. CLI / interactive login (localhost callback server, persisted credentials):\n * `OpenAICodexOAuthClient`, `JsonOpenAICodexAuthStorage`, `OpenAICodexAuthStorage`.\n * 3. Application credential access (get key, auto-refresh, request headers):\n * `getOpenAICodexApiKey`, `OpenAICodexOAuthClient.getCredentials/getApiKey/getHeaders`,\n * `openAICodexHeaders`, `OPENAI_CODEX_API_KEY_ENV`.\n *\n * Everything else in this module is an implementation detail and intentionally\n * not exported.\n */\n\nimport dedent from \"dedent\";\n\nconst CODEWORK_OAUTH_CALLBACK_HOST = \"CODEWORK_OAUTH_CALLBACK_HOST\";\nconst CODEWORK_CREDENTIALS = \"CODEWORK_CREDENTIALS\";\nconst CODEWORK_HOME_DIR = \"CODEWORK_HOME_DIR\";\n\nconst CLIENT_ID = \"app_EMoamEEZ73f0CkXaXp7hrann\";\nconst AUTHORIZE_URL = \"https://auth.openai.com/oauth/authorize\";\nconst TOKEN_URL = \"https://auth.openai.com/oauth/token\";\nconst DEFAULT_REDIRECT_URI = \"http://localhost:1455/auth/callback\";\nconst DEFAULT_SCOPE = \"openid profile email offline_access\";\nconst DEFAULT_ORIGINATOR = \"codework\";\nconst DEFAULT_PROVIDER_ID = \"openai-codex\";\nconst JWT_CLAIM_PATH = \"https://api.openai.com/auth\";\nconst REFRESH_SKEW_MS = 60 * 1000;\n\nexport type OpenAICodexOAuthCredentials = {\n\taccess: string;\n\trefresh: string;\n\texpires: number;\n\taccountId: string;\n};\n\nexport type OpenAICodexTokenSuccess = {\n\ttype: \"success\";\n\taccess: string;\n\trefresh: string;\n\texpires: number;\n};\n\nexport type OpenAICodexTokenFailure = {\n\ttype: \"failed\";\n\tmessage: string;\n\tstatus?: number;\n};\n\nexport type OpenAICodexTokenResult = OpenAICodexTokenSuccess | OpenAICodexTokenFailure;\n\nexport type OpenAICodexAuthorizationFlow = {\n\turl: string;\n\tverifier: string;\n\tstate: string;\n\tredirectUri: string;\n};\n\nexport type OpenAICodexAuthorizationOptions = {\n\toriginator?: string;\n\tredirectUri?: string;\n\tscope?: string;\n};\n\nexport type OpenAICodexLoginPrompt = {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n};\n\nexport type OpenAICodexLoginOptions = OpenAICodexAuthorizationOptions & {\n\tonAuth: (info: { url: string; instructions?: string }) => void;\n\tonPrompt: (prompt: OpenAICodexLoginPrompt) => Promise<string>;\n\tonProgress?: (message: string) => void;\n\tonManualCodeInput?: () => Promise<string>;\n};\n\nexport interface OpenAICodexAuthStorage {\n\tget(): Promise<OpenAICodexOAuthCredentials | undefined>;\n\tset(credentials: OpenAICodexOAuthCredentials): Promise<void>;\n\tclear(): Promise<void>;\n}\n\nexport type JsonOpenAICodexAuthStorageOptions = {\n\tpath?: string;\n\tproviderId?: string;\n};\n\ntype JwtPayload = {\n\t[JWT_CLAIM_PATH]?: {\n\t\tchatgpt_account_id?: string;\n\t};\n\t[key: string]: unknown;\n};\n\ntype OAuthServerInfo = {\n\tclose: () => Promise<void>;\n\tcancelWait: () => void;\n\twaitForCode: () => Promise<{ code: string } | null>;\n};\n\ntype AuthFile = Record<string, unknown>;\n\nfunction readEnv(name: string): string | undefined {\n\tif (typeof process === \"undefined\") return undefined;\n\treturn process.env[name];\n}\n\nfunction joinPath(...parts: string[]): string {\n\treturn parts.filter(Boolean).join(\"/\").replaceAll(/\\/+/g, \"/\");\n}\n\nfunction expandHome(path: string): string {\n\tif (path === \"~\") return homeDirectory();\n\tif (path.startsWith(\"~/\")) return joinPath(homeDirectory(), path.slice(2));\n\treturn path;\n}\n\nfunction homeDirectory(): string {\n\tconst home = readEnv(\"HOME\") ?? readEnv(\"USERPROFILE\");\n\tif (!home) {\n\t\tthrow new Error(\"Unable to resolve home directory for OpenAI Codex auth storage\");\n\t}\n\treturn home;\n}\n\nfunction codeworkHomeDirectory(): string {\n\tconst override = readEnv(CODEWORK_HOME_DIR);\n\tif (override) return expandHome(override);\n\treturn joinPath(homeDirectory(), \".codework\");\n}\n\n// Internal: the resolved location is exposed as `JsonOpenAICodexAuthStorage#path`.\nfunction defaultOpenAICodexAuthFilePath(): string {\n\tconst authFile = readEnv(CODEWORK_CREDENTIALS);\n\tif (authFile) return expandHome(authFile);\n\n\treturn joinPath(codeworkHomeDirectory(), \"aikit\", \"auth.json\");\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isOpenAICodexCredentials(value: unknown): value is OpenAICodexOAuthCredentials {\n\tif (!isObject(value)) return false;\n\treturn (\n\t\ttypeof value.access === \"string\" &&\n\t\ttypeof value.refresh === \"string\" &&\n\t\ttypeof value.expires === \"number\" &&\n\t\ttypeof value.accountId === \"string\"\n\t);\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (const byte of bytes) {\n\t\tbinary += String.fromCharCode(byte);\n\t}\n\treturn btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\n\nfunction base64UrlDecode(value: string): string {\n\tconst base64 = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\");\n\tconst padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, \"=\");\n\treturn atob(padded);\n}\n\ntype WebCrypto = typeof globalThis.crypto;\n\nfunction getCrypto(): WebCrypto {\n\tif (!globalThis.crypto?.getRandomValues || !globalThis.crypto.subtle) {\n\t\tthrow new Error(\"OpenAI Codex OAuth requires Web Crypto support\");\n\t}\n\treturn globalThis.crypto;\n}\n\nfunction createState(): string {\n\tconst bytes = new Uint8Array(16);\n\tgetCrypto().getRandomValues(bytes);\n\treturn Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nasync function generatePKCE(): Promise<{\n\tverifier: string;\n\tchallenge: string;\n}> {\n\tconst bytes = new Uint8Array(32);\n\tgetCrypto().getRandomValues(bytes);\n\tconst verifier = base64UrlEncode(bytes);\n\n\tconst data = new TextEncoder().encode(verifier);\n\tconst hash = await getCrypto().subtle.digest(\"SHA-256\", data);\n\tconst challenge = base64UrlEncode(new Uint8Array(hash));\n\n\treturn { verifier, challenge };\n}\n\nfunction authorizationInput(code: string | null | undefined, state: string | null | undefined) {\n\treturn {\n\t\t...(code != null && { code }),\n\t\t...(state != null && { state }),\n\t};\n}\n\nexport function parseOpenAICodexAuthorizationInput(input: string): {\n\tcode?: string;\n\tstate?: string;\n} {\n\tconst value = input.trim();\n\tif (!value) return {};\n\n\ttry {\n\t\tconst url = new URL(value);\n\t\treturn authorizationInput(url.searchParams.get(\"code\"), url.searchParams.get(\"state\"));\n\t} catch {\n\t\t// Not a URL.\n\t}\n\n\tif (value.includes(\"#\")) {\n\t\tconst [code, state] = value.split(\"#\", 2);\n\t\treturn authorizationInput(code, state);\n\t}\n\n\tif (value.includes(\"code=\")) {\n\t\tconst params = new URLSearchParams(value);\n\t\treturn authorizationInput(params.get(\"code\"), params.get(\"state\"));\n\t}\n\n\treturn { code: value };\n}\n\nfunction decodeJwt(token: string): JwtPayload | null {\n\ttry {\n\t\tconst parts = token.split(\".\");\n\t\tif (parts.length !== 3) return null;\n\t\treturn JSON.parse(base64UrlDecode(parts[1] ?? \"\")) as JwtPayload;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function getOpenAICodexAccountId(accessToken: string): string | null {\n\tconst payload = decodeJwt(accessToken);\n\tconst auth = payload?.[JWT_CLAIM_PATH];\n\tconst accountId = auth?.chatgpt_account_id;\n\treturn typeof accountId === \"string\" && accountId.length > 0 ? accountId : null;\n}\n\nexport async function createOpenAICodexAuthorizationFlow(\n\toptions: OpenAICodexAuthorizationOptions = {},\n): Promise<OpenAICodexAuthorizationFlow> {\n\tconst redirectUri = options.redirectUri ?? DEFAULT_REDIRECT_URI;\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst state = createState();\n\n\tconst url = new URL(AUTHORIZE_URL);\n\turl.searchParams.set(\"response_type\", \"code\");\n\turl.searchParams.set(\"client_id\", CLIENT_ID);\n\turl.searchParams.set(\"redirect_uri\", redirectUri);\n\turl.searchParams.set(\"scope\", options.scope ?? DEFAULT_SCOPE);\n\turl.searchParams.set(\"code_challenge\", challenge);\n\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\turl.searchParams.set(\"state\", state);\n\turl.searchParams.set(\"id_token_add_organizations\", \"true\");\n\turl.searchParams.set(\"codex_cli_simplified_flow\", \"true\");\n\turl.searchParams.set(\"originator\", options.originator ?? DEFAULT_ORIGINATOR);\n\n\treturn { verifier, state, redirectUri, url: url.toString() };\n}\n\nexport async function exchangeOpenAICodexAuthorizationCode(\n\tcode: string,\n\tverifier: string,\n\tredirectUri: string = DEFAULT_REDIRECT_URI,\n): Promise<OpenAICodexTokenResult> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode,\n\t\t\tcode_verifier: verifier,\n\t\t\tredirect_uri: redirectUri,\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text().catch(() => \"\");\n\t\treturn {\n\t\t\ttype: \"failed\",\n\t\t\tstatus: response.status,\n\t\t\tmessage: `OpenAI Codex token exchange failed (${response.status}): ${text || response.statusText}`,\n\t\t};\n\t}\n\n\tconst json = (await response.json()) as {\n\t\taccess_token?: string;\n\t\trefresh_token?: string;\n\t\texpires_in?: number;\n\t};\n\n\tif (!json.access_token || !json.refresh_token || typeof json.expires_in !== \"number\") {\n\t\treturn {\n\t\t\ttype: \"failed\",\n\t\t\tmessage: `OpenAI Codex token exchange response missing fields: ${JSON.stringify(json)}`,\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: \"success\",\n\t\taccess: json.access_token,\n\t\trefresh: json.refresh_token,\n\t\texpires: Date.now() + json.expires_in * 1000,\n\t};\n}\n\nasync function refreshAccessToken(refreshToken: string): Promise<OpenAICodexTokenResult> {\n\ttry {\n\t\tconst response = await fetch(TOKEN_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\trefresh_token: refreshToken,\n\t\t\t\tclient_id: CLIENT_ID,\n\t\t\t}),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst text = await response.text().catch(() => \"\");\n\t\t\treturn {\n\t\t\t\ttype: \"failed\",\n\t\t\t\tstatus: response.status,\n\t\t\t\tmessage: `OpenAI Codex token refresh failed (${response.status}): ${text || response.statusText}`,\n\t\t\t};\n\t\t}\n\n\t\tconst json = (await response.json()) as {\n\t\t\taccess_token?: string;\n\t\t\trefresh_token?: string;\n\t\t\texpires_in?: number;\n\t\t};\n\n\t\tif (!json.access_token || !json.refresh_token || typeof json.expires_in !== \"number\") {\n\t\t\treturn {\n\t\t\t\ttype: \"failed\",\n\t\t\t\tmessage: `OpenAI Codex token refresh response missing fields: ${JSON.stringify(json)}`,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\ttype: \"success\",\n\t\t\taccess: json.access_token,\n\t\t\trefresh: json.refresh_token,\n\t\t\texpires: Date.now() + json.expires_in * 1000,\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\ttype: \"failed\",\n\t\t\tmessage: `OpenAI Codex token refresh error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t};\n\t}\n}\n\nfunction oauthPage(options: { title: string; heading: string; message: string; details?: string }): string {\n\tconst escapeHtml = (value: string) =>\n\t\tvalue\n\t\t\t.replaceAll(\"&\", \"&amp;\")\n\t\t\t.replaceAll(\"<\", \"&lt;\")\n\t\t\t.replaceAll(\">\", \"&gt;\")\n\t\t\t.replaceAll('\"', \"&quot;\")\n\t\t\t.replaceAll(\"'\", \"&#39;\");\n\tconst details = options.details ? escapeHtml(options.details) : undefined;\n\n\treturn dedent`\n\t<!doctype html>\n\t<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t\t<title>${escapeHtml(options.title)}</title>\n\t\t<style>\n\t\t\thtml { color-scheme: dark; }\n\t\t\tbody {\n\t\t\tmargin: 0;\n\t\t\tmin-height: 100vh;\n\t\t\tdisplay: grid;\n\t\t\tplace-items: center;\n\t\t\tpadding: 24px;\n\t\t\tbackground: #09090b;\n\t\t\tcolor: #fafafa;\n\t\t\tfont-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n\t\t\ttext-align: center;\n\t\t\t}\n\t\t\tmain { width: 100%; max-width: 560px; }\n\t\t\th1 { margin: 0 0 10px; font-size: 28px; line-height: 1.15; font-weight: 650; }\n\t\t\tp { margin: 0; line-height: 1.7; color: #a1a1aa; font-size: 15px; }\n\t\t\t.details { margin-top: 16px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; color: #a1a1aa; white-space: pre-wrap; word-break: break-word; }\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<main>\n\t\t\t<h1>${escapeHtml(options.heading)}</h1>\n\t\t\t<p>${escapeHtml(options.message)}</p>\n\t\t\t${details ? `<div class=\"details\">${details}</div>` : \"\"}\n\t\t</main>\n\t</body>\n\t</html>\n\t`;\n}\n\nfunction oauthSuccessHtml(message: string): string {\n\treturn oauthPage({\n\t\ttitle: \"Authentication successful\",\n\t\theading: \"Authentication successful\",\n\t\tmessage,\n\t});\n}\n\nfunction oauthErrorHtml(message: string, details?: string): string {\n\treturn oauthPage({\n\t\ttitle: \"Authentication failed\",\n\t\theading: \"Authentication failed\",\n\t\tmessage,\n\t\t...(details !== undefined && { details }),\n\t});\n}\n\nasync function startLocalOAuthServer(state: string): Promise<OAuthServerInfo> {\n\tconst http = await import(\"node:http\").catch(() => undefined);\n\tif (!http) {\n\t\tthrow new Error(\"OpenAI Codex OAuth callback server is only available in Node.js environments\");\n\t}\n\n\tlet settleWait: ((value: { code: string } | null) => void) | undefined;\n\tconst waitForCodePromise = new Promise<{ code: string } | null>((resolve) => {\n\t\tlet settled = false;\n\t\tsettleWait = (value) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tresolve(value);\n\t\t};\n\t});\n\n\tconst server = http.createServer((req, res) => {\n\t\ttry {\n\t\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\t\tif (url.pathname !== \"/auth/callback\") {\n\t\t\t\tres.statusCode = 404;\n\t\t\t\tres.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n\t\t\t\tres.end(oauthErrorHtml(\"Callback route not found.\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (url.searchParams.get(\"state\") !== state) {\n\t\t\t\tres.statusCode = 400;\n\t\t\t\tres.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n\t\t\t\tres.end(oauthErrorHtml(\"State mismatch.\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst code = url.searchParams.get(\"code\");\n\t\t\tif (!code) {\n\t\t\t\tres.statusCode = 400;\n\t\t\t\tres.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n\t\t\t\tres.end(oauthErrorHtml(\"Missing authorization code.\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tres.statusCode = 200;\n\t\t\tres.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n\t\t\tres.end(oauthSuccessHtml(\"OpenAI authentication completed. You can close this window.\"));\n\t\t\tsettleWait?.({ code });\n\t\t} catch (error) {\n\t\t\tres.statusCode = 500;\n\t\t\tres.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n\t\t\tres.end(\n\t\t\t\toauthErrorHtml(\n\t\t\t\t\t\"Internal error while processing OAuth callback.\",\n\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t});\n\tconst close = async (): Promise<void> => {\n\t\tif (!server.listening) return;\n\t\tawait new Promise<void>((resolve) => {\n\t\t\tserver.close(() => resolve());\n\t\t\tserver.closeAllConnections();\n\t\t});\n\t};\n\n\treturn new Promise((resolve) => {\n\t\tserver\n\t\t\t.listen(1455, readEnv(CODEWORK_OAUTH_CALLBACK_HOST) || \"127.0.0.1\", () => {\n\t\t\t\tresolve({\n\t\t\t\t\tclose,\n\t\t\t\t\tcancelWait: () => {\n\t\t\t\t\t\tsettleWait?.(null);\n\t\t\t\t\t},\n\t\t\t\t\twaitForCode: () => waitForCodePromise,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.on(\"error\", () => {\n\t\t\t\tsettleWait?.(null);\n\t\t\t\tresolve({\n\t\t\t\t\tclose,\n\t\t\t\t\tcancelWait: () => {},\n\t\t\t\t\twaitForCode: async () => null,\n\t\t\t\t});\n\t\t\t});\n\t});\n}\n\n// Internal: the public login entry point is `OpenAICodexOAuthClient#login`,\n// which persists the credentials. Server integrations should use the\n// storage-free authorization helpers instead of this localhost-callback flow.\nasync function loginOpenAICodex(options: OpenAICodexLoginOptions): Promise<OpenAICodexOAuthCredentials> {\n\tconst flow = await createOpenAICodexAuthorizationFlow(options);\n\tconst server = await startLocalOAuthServer(flow.state);\n\n\toptions.onAuth({\n\t\turl: flow.url,\n\t\tinstructions: \"Complete the browser login to finish OpenAI Codex authentication.\",\n\t});\n\n\tlet code: string | undefined;\n\ttry {\n\t\tif (options.onManualCodeInput) {\n\t\t\tlet manualCode: string | undefined;\n\t\t\tlet manualError: Error | undefined;\n\t\t\tconst manualPromise = options\n\t\t\t\t.onManualCodeInput()\n\t\t\t\t.then((input) => {\n\t\t\t\t\tmanualCode = input;\n\t\t\t\t\tif (input.trim()) server.cancelWait();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tmanualError = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\tserver.cancelWait();\n\t\t\t\t});\n\n\t\t\tconst result = await server.waitForCode();\n\t\t\tif (manualError) throw manualError;\n\n\t\t\tif (result?.code) {\n\t\t\t\tcode = result.code;\n\t\t\t} else if (manualCode) {\n\t\t\t\tconst parsed = parseOpenAICodexAuthorizationInput(manualCode);\n\t\t\t\tif (parsed.state && parsed.state !== flow.state) throw new Error(\"State mismatch\");\n\t\t\t\tcode = parsed.code;\n\t\t\t}\n\n\t\t\tif (!code) {\n\t\t\t\tawait manualPromise;\n\t\t\t\tif (manualError) throw manualError;\n\t\t\t\tif (manualCode) {\n\t\t\t\t\tconst parsed = parseOpenAICodexAuthorizationInput(manualCode);\n\t\t\t\t\tif (parsed.state && parsed.state !== flow.state) throw new Error(\"State mismatch\");\n\t\t\t\t\tcode = parsed.code;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst result = await server.waitForCode();\n\t\t\tif (result?.code) code = result.code;\n\t\t}\n\n\t\tif (!code) {\n\t\t\tconst input = await options.onPrompt({\n\t\t\t\tmessage: \"Paste the authorization code or full redirect URL:\",\n\t\t\t});\n\t\t\tconst parsed = parseOpenAICodexAuthorizationInput(input);\n\t\t\tif (parsed.state && parsed.state !== flow.state) throw new Error(\"State mismatch\");\n\t\t\tcode = parsed.code;\n\t\t}\n\n\t\tif (!code) throw new Error(\"Missing authorization code\");\n\n\t\tconst tokenResult = await exchangeOpenAICodexAuthorizationCode(code, flow.verifier, flow.redirectUri);\n\t\tif (tokenResult.type !== \"success\") throw new Error(tokenResult.message);\n\n\t\tconst accountId = getOpenAICodexAccountId(tokenResult.access);\n\t\tif (!accountId) throw new Error(\"Failed to extract accountId from token\");\n\n\t\treturn {\n\t\t\taccess: tokenResult.access,\n\t\t\trefresh: tokenResult.refresh,\n\t\t\texpires: tokenResult.expires,\n\t\t\taccountId,\n\t\t};\n\t} finally {\n\t\tawait server.close();\n\t}\n}\n\nexport async function refreshOpenAICodexToken(refreshToken: string): Promise<OpenAICodexOAuthCredentials> {\n\tconst result = await refreshAccessToken(refreshToken);\n\tif (result.type !== \"success\") {\n\t\tthrow new Error(result.message);\n\t}\n\n\tconst accountId = getOpenAICodexAccountId(result.access);\n\tif (!accountId) {\n\t\tthrow new Error(\"Failed to extract accountId from token\");\n\t}\n\n\treturn {\n\t\taccess: result.access,\n\t\trefresh: result.refresh,\n\t\texpires: result.expires,\n\t\taccountId,\n\t};\n}\n\nexport function openAICodexHeaders(credentials: OpenAICodexOAuthCredentials): Record<string, string> {\n\treturn {\n\t\tAuthorization: `Bearer ${credentials.access}`,\n\t\t\"chatgpt-account-id\": credentials.accountId,\n\t\t\"OpenAI-Beta\": \"responses=experimental\",\n\t};\n}\n\nexport class JsonOpenAICodexAuthStorage implements OpenAICodexAuthStorage {\n\treadonly path: string;\n\treadonly providerId: string;\n\n\tconstructor(options: JsonOpenAICodexAuthStorageOptions = {}) {\n\t\tthis.path = options.path ? expandHome(options.path) : defaultOpenAICodexAuthFilePath();\n\t\tthis.providerId = options.providerId ?? DEFAULT_PROVIDER_ID;\n\t}\n\n\tasync get(): Promise<OpenAICodexOAuthCredentials | undefined> {\n\t\tconst file = await this.readFile();\n\t\tif (!file) return undefined;\n\n\t\tif (isOpenAICodexCredentials(file)) return file;\n\n\t\tconst direct = file[this.providerId];\n\t\tif (isOpenAICodexCredentials(direct)) return direct;\n\n\t\tconst providers = file.providers;\n\t\tif (isObject(providers) && isOpenAICodexCredentials(providers[this.providerId])) {\n\t\t\treturn providers[this.providerId] as OpenAICodexOAuthCredentials;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tasync set(credentials: OpenAICodexOAuthCredentials): Promise<void> {\n\t\tconst current = await this.readFile();\n\t\tconst next = isObject(current) && !isOpenAICodexCredentials(current) ? current : {};\n\t\tnext[this.providerId] = credentials;\n\t\tawait this.writeFile(next);\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tconst current = await this.readFile();\n\t\tif (!current) return;\n\n\t\tif (isOpenAICodexCredentials(current)) {\n\t\t\tawait this.writeFile({});\n\t\t\treturn;\n\t\t}\n\n\t\tdelete current[this.providerId];\n\t\tconst providers = current.providers;\n\t\tif (isObject(providers)) delete providers[this.providerId];\n\t\tawait this.writeFile(current);\n\t}\n\n\tprivate async readFile(): Promise<AuthFile | undefined> {\n\t\tconst fs = await import(\"node:fs/promises\");\n\t\ttry {\n\t\t\tconst text = await fs.readFile(this.path, \"utf8\");\n\t\t\tconst parsed = JSON.parse(text) as unknown;\n\t\t\treturn isObject(parsed) ? parsed : undefined;\n\t\t} catch (error) {\n\t\t\tif (isObject(error) && error.code === \"ENOENT\") return undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async writeFile(value: AuthFile): Promise<void> {\n\t\tconst fs = await import(\"node:fs/promises\");\n\t\tconst path = await import(\"node:path\");\n\t\tawait fs.mkdir(path.dirname(this.path), { recursive: true });\n\t\tconst tempPath = `${this.path}.${process.pid}.${Date.now()}.tmp`;\n\t\tawait fs.writeFile(tempPath, `${JSON.stringify(value, null, \"\\t\")}\\n`, \"utf8\");\n\t\tawait fs.rename(tempPath, this.path);\n\t}\n}\n\nexport type OpenAICodexOAuthClientOptions = {\n\tstorage?: OpenAICodexAuthStorage;\n\trefreshSkewMs?: number;\n};\n\nexport class OpenAICodexOAuthClient {\n\treadonly storage: OpenAICodexAuthStorage;\n\treadonly refreshSkewMs: number;\n\n\tconstructor(options: OpenAICodexOAuthClientOptions = {}) {\n\t\tthis.storage = options.storage ?? new JsonOpenAICodexAuthStorage();\n\t\tthis.refreshSkewMs = options.refreshSkewMs ?? REFRESH_SKEW_MS;\n\t}\n\n\tasync login(options: OpenAICodexLoginOptions): Promise<OpenAICodexOAuthCredentials> {\n\t\tconst credentials = await loginOpenAICodex(options);\n\t\tawait this.storage.set(credentials);\n\t\treturn credentials;\n\t}\n\n\tasync getCredentials(): Promise<OpenAICodexOAuthCredentials | undefined> {\n\t\tconst credentials = await this.storage.get();\n\t\tif (!credentials) return undefined;\n\n\t\tif (credentials.expires > Date.now() + this.refreshSkewMs) {\n\t\t\treturn credentials;\n\t\t}\n\n\t\tconst refreshed = await refreshOpenAICodexToken(credentials.refresh);\n\t\tawait this.storage.set(refreshed);\n\t\treturn refreshed;\n\t}\n\n\tasync getApiKey(): Promise<string | undefined> {\n\t\treturn (await this.getCredentials())?.access;\n\t}\n\n\tasync getHeaders(): Promise<Record<string, string> | undefined> {\n\t\tconst credentials = await this.getCredentials();\n\t\treturn credentials ? openAICodexHeaders(credentials) : undefined;\n\t}\n\n\tasync logout(): Promise<void> {\n\t\tawait this.storage.clear();\n\t}\n}\n\nexport const OPENAI_CODEX_API_KEY_ENV = \"OPENAI_CODEX_API_KEY\";\n\n/**\n * Resolve the OpenAI Codex API key the same way other provider API keys are\n * resolved: prefer the OPENAI_CODEX_API_KEY environment variable, then fall\n * back to stored OAuth credentials (refreshing them when close to expiry).\n *\n * The result can be passed directly as `apiKey` to the runtime options or to\n * `createOpenAICodex`. Returns undefined when no key is available.\n */\nexport async function getOpenAICodexApiKey(options: OpenAICodexOAuthClientOptions = {}): Promise<string | undefined> {\n\tconst envKey = readEnv(OPENAI_CODEX_API_KEY_ENV);\n\tif (envKey) return envKey;\n\n\treturn new OpenAICodexOAuthClient(options).getApiKey();\n}\n"],"mappings":"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"}