@codeworksh/aikit 0.3.1 → 0.4.1-dev.20260530133305

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/README.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # @codeworksh/aikit
2
2
 
3
- Toolkit for building AI agents and streaming LLM workflows.
3
+ @codeworksh/aikit is a **TypeScript SDK** for building AI agents and agentic harnesses. It provides a unified API for working with multiple LLM providers, built on top of the Vercel AI SDK, with full support for tool calling (function calling) required for agentic workflows.
4
+
5
+ It gives you the basic primitives for streaming LLM responses without the extra bloat, letting you handle the orchestration yourself.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Supported Providers](#supported-providers)
11
+ - [Quick Start](#quick-start)
12
+ - [Tools](#tools)
13
+ - [Providers and Models](#providers-and-models)
14
+ - [CLI Tools](#cli-tools)
15
+ - [Model Generation](#model-generation)
16
+ - [OAuth Providers](#oauth-providers)
17
+ - [Contribute](#contribute)
4
18
 
5
19
  ## Installation
6
20
 
@@ -10,196 +24,146 @@ npm install @codeworksh/aikit
10
24
 
11
25
  Node `>=24.14.1` is required.
12
26
 
13
- ## What You Get
14
-
15
- - `llm(...)` to resolve a model from the built-in registry
16
- - `stream(...)` and `stream.complete(...)` for provider-normalized LLM streaming
17
- - `Agent.create(...)` for a stateful agent instance
18
- - `agent.loop(...)` and `agent.loopContinue(...)` for lower-level turn orchestration
19
- - `Message` helpers for typed messages and generated `messageId` values
27
+ ## Supported Providers
20
28
 
21
- ## Root API
29
+ Built on top of the Vercel AI SDK, `@codeworksh/aikit` supports a wide array of providers natively:
22
30
 
23
- ```ts
24
- import { Agent, Message, agent, llm, stream } from "@codeworksh/aikit";
25
- ```
31
+ - **Anthropic** (`@ai-sdk/anthropic`)
32
+ - **OpenAI** (`@ai-sdk/openai`)
33
+ - **Google** (`@ai-sdk/google`)
34
+ - **Google Vertex AI** (`@ai-sdk/google-vertex`)
35
+ - **xAI** (`@ai-sdk/xai`)
36
+ - **OpenRouter** (`@openrouter/ai-sdk-provider`)
37
+ - **OpenAI Compatible APIs** (`@ai-sdk/openai-compatible`)
26
38
 
27
39
  ## Quick Start
28
40
 
29
41
  ```ts
30
- import { Agent } from "@codeworksh/aikit";
31
-
32
- const agent = await Agent.create({
33
- provider: "anthropic",
34
- model: "claude-haiku-4-5-20251001",
35
- getApiKey: async () => process.env.ANTHROPIC_API_KEY,
36
- });
37
-
38
- agent.setSystemPrompt("Be concise.");
39
-
40
- await agent.prompt([{ type: "text", text: "Reply with exactly: hello" }]);
41
-
42
- const lastMessage = agent.state.messages.at(-1);
43
- console.log(lastMessage?.messageId);
44
- console.log(lastMessage?.role);
45
- ```
46
-
47
- ## Stream Events
48
-
49
- Use `stream(...)` when you want token and part-level events.
50
-
51
- ```ts
52
- import { Message, llm, stream } from "@codeworksh/aikit";
42
+ import { llm, stream, Message } from "@codeworksh/aikit";
53
43
 
44
+ // Resolve a model from the built-in registry
54
45
  const model = await llm("anthropic", "claude-haiku-4-5-20251001");
55
46
  if (!model) throw new Error("Model not found");
56
47
 
57
- const s = stream(
58
- model,
59
- {
60
- messages: [
61
- Message.createUserMessage({
62
- role: "user",
63
- time: { created: Date.now() },
64
- parts: [{ type: "text", text: "Count from 1 to 3" }],
65
- }),
66
- ],
67
- },
68
- { apiKey: process.env.ANTHROPIC_API_KEY },
69
- );
48
+ // Setup conversation context
49
+ const context: Message.Context = {
50
+ systemPrompt: "You are a helpful coding assistant.",
51
+ messages: [
52
+ Message.createUserMessage({
53
+ role: "user",
54
+ time: { created: Date.now() },
55
+ parts: [{ type: "text", text: "Write a simple loop in TypeScript." }],
56
+ }),
57
+ ],
58
+ };
59
+
60
+ // Option 1: Stream events
61
+ const s = stream(model, context, { apiKey: process.env.ANTHROPIC_API_KEY });
70
62
 
71
63
  for await (const event of s) {
72
- if (event.type === "text.delta") {
73
- process.stdout.write(event.delta);
74
- }
64
+ if (event.type === "text.delta") {
65
+ process.stdout.write(event.delta);
66
+ }
75
67
  }
76
68
 
77
69
  const finalMessage = await s.result();
78
- console.log(finalMessage.messageId);
70
+ console.log(`\nMessage ID: ${finalMessage.messageId}`);
71
+
72
+ // Option 2: Get complete response without streaming
73
+ const message = await stream.complete(model, context, { apiKey: process.env.ANTHROPIC_API_KEY });
74
+ console.log(message.parts);
79
75
  ```
80
76
 
81
- ## Agent Instance
77
+ ## Tools
82
78
 
83
- `Agent.create(...)` is the simplest way to work with a stateful agent.
79
+ Tools enable LLMs to interact with external systems. `@codeworksh/aikit` provides native support for function calling and schema validation using TypeBox.
84
80
 
85
81
  ```ts
86
- import { Agent } from "@codeworksh/aikit";
87
-
88
- const agent = await Agent.create({
89
- provider: "anthropic",
90
- model: "claude-haiku-4-5-20251001",
91
- getApiKey: async () => process.env.ANTHROPIC_API_KEY,
92
- });
82
+ import { Type, llm, stream, Message, validateToolArguments } from "@codeworksh/aikit";
83
+
84
+ const calculatorTool = {
85
+ name: "calculator",
86
+ description: "Evaluate arithmetic expressions",
87
+ parameters: Type.Object({
88
+ expression: Type.String(),
89
+ }),
90
+ };
91
+
92
+ const context: Message.Context = {
93
+ messages: [
94
+ Message.createUserMessage({
95
+ role: "user",
96
+ time: { created: Date.now() },
97
+ parts: [{ type: "text", text: "What is 25 * 18?" }],
98
+ }),
99
+ ],
100
+ tools: [calculatorTool],
101
+ };
102
+
103
+ const response = await stream.complete(model, context, { apiKey: process.env.ANTHROPIC_API_KEY });
104
+
105
+ // Check for tool calls in the response
106
+ for (const part of response.parts) {
107
+ if (part.type === "toolCall") {
108
+ console.log(`Executing tool: ${part.name}`);
109
+
110
+ // Validates arguments against TypeBox schema automatically
111
+ const args = validateToolArguments(calculatorTool.parameters, part.arguments);
112
+ // Execute your tool logic here...
113
+ }
114
+ }
115
+ ```
93
116
 
94
- agent.setSystemPrompt("Be concise.");
117
+ ## Providers and Models
95
118
 
96
- agent.subscribe((event) => {
97
- if (event.type === "message.end") {
98
- console.log(event.message.role, event.message.messageId);
99
- }
100
- });
119
+ `@codeworksh/aikit` uses a registry to fetch model specifications and metadata.
101
120
 
102
- await agent.prompt([{ type: "text", text: "Say hello in one line." }]);
121
+ ```ts
122
+ import { llm } from "@codeworksh/aikit";
103
123
 
104
- console.log(agent.state.messages);
105
- ```
124
+ // Get all available providers
125
+ const providers = await llm.providers();
126
+ console.log(providers);
106
127
 
107
- ## With Tools
128
+ // Get all models for a specific provider
129
+ const anthropicModels = await llm.models("anthropic");
108
130
 
109
- ```ts
110
- import { Type } from "@sinclair/typebox";
111
- import { Agent } from "@codeworksh/aikit";
112
-
113
- const calculatorTool = Agent.defineTool({
114
- name: "calculator",
115
- label: "Calculator",
116
- description: "Evaluate arithmetic expressions",
117
- parameters: Type.Object({
118
- expression: Type.String(),
119
- }),
120
- async execute(_callID, params) {
121
- return {
122
- status: "completed",
123
- result: {
124
- content: [{ type: "text", text: `result for ${params.expression}` }],
125
- isError: false,
126
- },
127
- };
128
- },
129
- });
130
-
131
- const instance = await Agent.create({
132
- provider: "anthropic",
133
- model: "claude-haiku-4-5-20251001",
134
- getApiKey: async () => process.env.ANTHROPIC_API_KEY,
135
- initialState: {
136
- tools: [calculatorTool],
137
- },
138
- });
139
-
140
- await instance.prompt([{ type: "text", text: "Use the calculator tool for 25 * 18." }]);
131
+ // Get a specific model directly
132
+ const gpt4 = await llm.model("openai", "gpt-4o");
141
133
  ```
142
134
 
143
- ## Lower-Level Loop
135
+ ## CLI Tools
144
136
 
145
- Use `agent.loop(...)` when you want loop execution without creating a stateful instance.
137
+ `@codeworksh/aikit` ships with a CLI tool for managing local metadata and authentication.
146
138
 
147
- ```ts
148
- import { Message, agent, llm } from "@codeworksh/aikit";
139
+ You can invoke it using `npx aikit` or `pnpm aikit`.
149
140
 
150
- const model = await llm("anthropic", "claude-haiku-4-5-20251001");
151
- if (!model) throw new Error("Model not found");
141
+ ### Model Generation
142
+
143
+ Generate a `models.gen.json` file fetching the latest metadata about providers and their available models from `models.dev`.
152
144
 
153
- const run = agent.loop(
154
- {
155
- model,
156
- apiKey: process.env.ANTHROPIC_API_KEY,
157
- convertToLlm: async (messages) => messages,
158
- },
159
- {
160
- systemPrompt: "Be concise.",
161
- messages: [],
162
- tools: [],
163
- },
164
- [
165
- Message.createUserMessage({
166
- role: "user",
167
- time: { created: Date.now() },
168
- parts: [{ type: "text", text: "Reply with exactly: ok" }],
169
- }),
170
- ],
171
- );
172
-
173
- const messages = await run.result();
174
- console.log(messages.at(-1)?.role);
145
+ ```bash
146
+ pnpm aikit modelgen [path]
175
147
  ```
176
148
 
177
- ## Message IDs
149
+ ### OAuth Providers
178
150
 
179
- Every user and assistant message has a `messageId`.
151
+ Manage OAuth credentials for providers that require it, such as OpenAI Codex.
180
152
 
181
- Use the helpers when constructing messages yourself:
153
+ ```bash
154
+ # Start an OAuth login flow in your browser
155
+ pnpm aikit auth --openai-codex
182
156
 
183
- ```ts
184
- import { Message } from "@codeworksh/aikit";
157
+ # Check the status of your stored credentials
158
+ pnpm aikit auth --openai-codex --status
185
159
 
186
- const userMessage = Message.createUserMessage({
187
- role: "user",
188
- time: { created: Date.now() },
189
- parts: [{ type: "text", text: "hello" }],
190
- });
160
+ # Refresh your current credentials
161
+ pnpm aikit auth --openai-codex --refresh
191
162
 
192
- console.log(userMessage.messageId);
163
+ # Clear stored credentials
164
+ pnpm aikit auth --openai-codex --logout
193
165
  ```
194
166
 
195
- This is useful for persistence layers like SQLite, event reconciliation, and updating stored messages by identity instead of array position.
196
-
197
- ## Lower-Level APIs
198
-
199
- - `stream(...)`: raw provider-normalized stream
200
- - `stream.complete(...)`: final assistant message without manual iteration
201
- - `Agent.create(...)`: stateful agent instance
202
- - `agent.loop(...)`: lower-level agent loop
203
- - `agent.loopContinue(...)`: continue from an existing context
167
+ ## Contribute
204
168
 
205
- API docs can be added later. For now, the tests under `packages/aikit/test/` are the best reference for concrete usage.
169
+ `@codeworksh/aikit` is open to community contribution. Please ensure you submit an issue before submitting a pull request. The project prefers open community discussion before accepting new features.
package/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/cli.mjs ADDED
@@ -0,0 +1,308 @@
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-CYfzJ6lk.mjs";
3
+ import { c as openAICodexHeaders, n as OpenAICodexOAuthClient, t as JsonOpenAICodexAuthStorage } from "./codex-DfYk740t.mjs";
4
+ import { resolve } from "node:path";
5
+ import yargs from "yargs";
6
+ import { hideBin } from "yargs/helpers";
7
+ import { mapValues, pickBy, pipe } from "remeda";
8
+ //#region package.json
9
+ var version = "0.4.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.CODEWORK_MODELS_DEV;
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
+ async function generateModels(args = {}) {
86
+ const path = resolve(args.path ?? ModelCatalog.path());
87
+ const models = await loadBuiltInFromModelsDev();
88
+ await Filesystem.writeJson(path, models);
89
+ return path;
90
+ }
91
+ const ModelgenCommand = {
92
+ command: "modelgen [path]",
93
+ describe: "generate models.gen.json",
94
+ builder: (yargs) => yargs.positional("path", {
95
+ type: "string",
96
+ describe: "output path (defaults to CODEWORK_MODELGEN_PATH or ./models.gen.json)"
97
+ }),
98
+ handler: async (args) => {
99
+ const path = await generateModels(args);
100
+ console.log(`Generated model catalog at ${path}`);
101
+ }
102
+ };
103
+ function applyModification(providerId, provider, model) {
104
+ const npm = resolveModelNpm(provider, model);
105
+ if (!isAISDKPackage(npm)) return;
106
+ const protocol = protocolForPackage(npm);
107
+ const baseUrl = resolveModelBaseUrl(provider, model);
108
+ const providerInfo = {
109
+ id: providerId,
110
+ name: provider.name,
111
+ source: "api",
112
+ env: provider.env
113
+ };
114
+ if (provider.key) providerInfo.key = provider.key;
115
+ const api = {
116
+ id: model.id,
117
+ method: resolveModelAPIMethod(npm)
118
+ };
119
+ if (baseUrl) api.url = baseUrl;
120
+ const info = {
121
+ id: model.id,
122
+ name: model.name,
123
+ provider: providerInfo,
124
+ baseUrl,
125
+ reasoning: Boolean(model.reasoning),
126
+ input: Model.normalizeInput(model.modalities.input),
127
+ cost: {
128
+ input: model.cost?.input ?? 0,
129
+ output: model.cost?.output ?? 0,
130
+ cacheRead: model.cost?.cache_read ?? 0,
131
+ cacheWrite: model.cost?.cache_write ?? 0
132
+ },
133
+ contextWindow: model.limit?.context ?? 4096,
134
+ maxTokens: model.limit?.output ?? 4096,
135
+ headers: {
136
+ ...provider.headers,
137
+ ...model.provider?.headers,
138
+ ...model.headers
139
+ },
140
+ npm,
141
+ api,
142
+ providerOptionsKey: resolveProviderOptionsKey(protocol),
143
+ protocol
144
+ };
145
+ if (Object.keys(info.headers ?? {}).length === 0) delete info.headers;
146
+ applyThinkingLevelMetadata(info);
147
+ return info;
148
+ }
149
+ //#endregion
150
+ //#region src/cli/oauth.ts
151
+ async function promptLine(message) {
152
+ const rl = (await import("node:readline/promises")).createInterface({
153
+ input: process.stdin,
154
+ output: process.stdout
155
+ });
156
+ try {
157
+ return await rl.question(`${message} `);
158
+ } finally {
159
+ rl.close();
160
+ }
161
+ }
162
+ async function openBrowser(url) {
163
+ const { spawn } = await import("node:child_process");
164
+ const command = process.platform === "darwin" ? {
165
+ file: "open",
166
+ args: [url]
167
+ } : process.platform === "win32" ? {
168
+ file: "cmd",
169
+ args: [
170
+ "/c",
171
+ "start",
172
+ "",
173
+ url
174
+ ]
175
+ } : {
176
+ file: "xdg-open",
177
+ args: [url]
178
+ };
179
+ spawn(command.file, command.args, {
180
+ detached: true,
181
+ stdio: "ignore"
182
+ }).unref();
183
+ }
184
+ function printCredentials(credentials, options) {
185
+ if (options.json) {
186
+ console.log(JSON.stringify({
187
+ accountId: credentials.accountId,
188
+ expires: credentials.expires,
189
+ expiresAt: new Date(credentials.expires).toISOString(),
190
+ headers: options.printHeaders ? openAICodexHeaders(credentials) : void 0
191
+ }, null, 2));
192
+ return;
193
+ }
194
+ console.log(`Account: ${credentials.accountId}`);
195
+ console.log(`Expires: ${new Date(credentials.expires).toLocaleString()}`);
196
+ if (options.printHeaders) {
197
+ console.log("Headers:");
198
+ for (const [name, value] of Object.entries(openAICodexHeaders(credentials))) console.log(`${name}: ${value}`);
199
+ }
200
+ }
201
+ async function runOpenAICodexAuth(args) {
202
+ const storage = new JsonOpenAICodexAuthStorage({ path: args.authFile });
203
+ const client = new OpenAICodexOAuthClient({ storage });
204
+ if (args.logout) {
205
+ await client.logout();
206
+ console.log(`Cleared OpenAI Codex credentials from ${storage.path}`);
207
+ return;
208
+ }
209
+ if (args.status) {
210
+ const credentials = await storage.get();
211
+ if (!credentials) {
212
+ console.log(`No OpenAI Codex credentials found at ${storage.path}`);
213
+ process.exitCode = 1;
214
+ return;
215
+ }
216
+ printCredentials(credentials, args);
217
+ return;
218
+ }
219
+ if (args.refresh) {
220
+ const credentials = await client.getCredentials();
221
+ if (!credentials) {
222
+ console.log(`No OpenAI Codex credentials found at ${storage.path}`);
223
+ process.exitCode = 1;
224
+ return;
225
+ }
226
+ console.log(`Refreshed OpenAI Codex credentials in ${storage.path}`);
227
+ printCredentials(credentials, args);
228
+ return;
229
+ }
230
+ const credentials = await client.login({
231
+ originator: args.originator,
232
+ onAuth: (info) => {
233
+ console.log(info.instructions ?? "Complete OpenAI Codex authentication in your browser.");
234
+ console.log(info.url);
235
+ if (args.browser !== false) openBrowser(info.url).catch((error) => {
236
+ console.warn(`Failed to open browser: ${error instanceof Error ? error.message : String(error)}`);
237
+ });
238
+ },
239
+ onPrompt: async (prompt) => promptLine(prompt.message),
240
+ onManualCodeInput: args.manual ? async () => promptLine("Paste the redirect URL or authorization code, or wait for browser callback:") : void 0
241
+ });
242
+ console.log(`Saved OpenAI Codex credentials to ${storage.path}`);
243
+ printCredentials(credentials, args);
244
+ }
245
+ //#endregion
246
+ //#region src/cli.ts
247
+ const cli = yargs(hideBin(process.argv)).scriptName("aikit").wrap(100).help("help", "show help").alias("help", "h").version("version", "show version number", version).alias("version", "v").command(ModelgenCommand).command({
248
+ command: "auth",
249
+ describe: "manage OAuth credentials",
250
+ builder: (yargs) => yargs.option("openai-codex", {
251
+ type: "boolean",
252
+ describe: "use OpenAI Codex OAuth"
253
+ }).option("auth-file", {
254
+ type: "string",
255
+ describe: "path to auth.json (defaults to CODEWORK_CREDENTIALS or ~/.codework/aikit/auth.json)"
256
+ }).option("browser", {
257
+ type: "boolean",
258
+ default: true,
259
+ describe: "open the authorization URL in the default browser"
260
+ }).option("manual", {
261
+ type: "boolean",
262
+ default: false,
263
+ describe: "also prompt for a pasted redirect URL or authorization code"
264
+ }).option("originator", {
265
+ type: "string",
266
+ default: "codework",
267
+ describe: "OAuth originator value"
268
+ }).option("status", {
269
+ type: "boolean",
270
+ describe: "show stored credential status without refreshing"
271
+ }).option("refresh", {
272
+ type: "boolean",
273
+ describe: "refresh stored credentials if expired"
274
+ }).option("logout", {
275
+ type: "boolean",
276
+ describe: "clear stored credentials"
277
+ }).option("json", {
278
+ type: "boolean",
279
+ describe: "print machine-readable output"
280
+ }).option("print-headers", {
281
+ type: "boolean",
282
+ describe: "print request headers for Codex API calls"
283
+ }).check((args) => {
284
+ if (!args.openaiCodex) throw new Error("Choose an auth provider, for example: auth --openai-codex");
285
+ if ([
286
+ args.status,
287
+ args.refresh,
288
+ args.logout
289
+ ].filter(Boolean).length > 1) throw new Error("Choose only one of --status, --refresh, or --logout");
290
+ return true;
291
+ }),
292
+ handler: async (args) => {
293
+ await runOpenAICodexAuth(args);
294
+ }
295
+ }).demandCommand(1, "Choose a command").strict().fail((message, error) => {
296
+ if (error) throw error;
297
+ if (message) throw new Error(message);
298
+ });
299
+ try {
300
+ await cli.parse();
301
+ } catch (error) {
302
+ process.exitCode = 1;
303
+ console.error(error instanceof Error ? error.message : String(error));
304
+ }
305
+ //#endregion
306
+ export {};
307
+
308
+ //# sourceMappingURL=cli.mjs.map