@agentionai/agents 1.12.0 → 1.14.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.
@@ -42,7 +42,7 @@ type OpenRouterAgentConfig = Omit<BaseAgentConfig, "vendor" | "model"> & OpenRou
42
42
  };
43
43
  type AgentConfig = ClaudeAgentConfig | OpenAIAgentConfig | GeminiAgentConfig | MistralAgentConfig | OllamaAgentConfig | LlamaCppAgentConfig | OpenRouterAgentConfig;
44
44
  export declare class Agent {
45
- static create(config: AgentConfig, history?: History): ClaudeAgent | GeminiAgent | MistralAgent | OllamaAgent | LlamaCppAgent | OpenRouterAgent | OpenAiAgent<(string & {}) | "gpt-5-pro" | "gpt-5.2-pro" | "gpt-5.4-pro" | "gpt-5.5-pro" | "o1" | "o1-pro" | "o3" | "o3-mini" | "o4-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gpt-5.1" | "gpt-5.2" | "gpt-5.4" | "gpt-5.4-mini" | "gpt-5.4-nano" | "gpt-5.5" | "gpt-5.6" | "gpt-5.6-sol" | "gpt-5.6-terra" | "gpt-5.6-luna" | "gpt-4.1" | "gpt-4.1-mini" | "gpt-4.1-nano" | "gpt-4o" | "gpt-4o-mini" | "gpt-4o-2024-11-20" | "gpt-4o-2024-08-06" | "gpt-4o-2024-05-13" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo-1106" | "o1-preview" | "o1-mini">;
45
+ static create(config: AgentConfig, history?: History): ClaudeAgent | GeminiAgent | MistralAgent | OllamaAgent | LlamaCppAgent | OpenRouterAgent | OpenAiAgent<(string & {}) | "gpt-5-pro" | "gpt-5.2-pro" | "gpt-5.4-pro" | "gpt-5.5-pro" | "o1" | "o1-pro" | "o3" | "o3-mini" | "o4-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gpt-5.1" | "gpt-5.2" | "gpt-5.4" | "gpt-5.4-mini" | "gpt-5.4-nano" | "gpt-5.5" | "gpt-5.6" | "gpt-5.6-sol" | "gpt-5.6-terra" | "gpt-5.6-luna" | "gpt-4.1" | "gpt-4.1-mini" | "gpt-4.1-nano" | "gpt-4o" | "gpt-4o-mini" | "gpt-4o-2024-11-20" | "gpt-4o-2024-08-06" | "gpt-4o-2024-05-13" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo-1106" | "o1-preview" | "o1-mini", import("openai/resources/models").Model>;
46
46
  }
47
47
  export {};
48
48
  //# sourceMappingURL=Agent.d.ts.map
@@ -137,6 +137,40 @@ export interface OpenAISpecificConfig {
137
137
  * see `lib/tools/BuiltInTool.ts`.
138
138
  */
139
139
  builtInTools?: BuiltInTool[];
140
+ /**
141
+ * Cache-routing key sent as `prompt_cache_key`. Requests sharing a key are
142
+ * steered to the same prompt cache, raising the hit rate for a long
143
+ * conversation or a fleet of agents sharing a system prompt and tool belt.
144
+ */
145
+ promptCacheKey?: string;
146
+ /**
147
+ * How long cached prefixes stay warm — `"24h"` opts into extended retention.
148
+ * Ignored by the ChatGPT/Codex backend, which manages its own cache.
149
+ */
150
+ promptCacheRetention?: "in-memory" | "24h";
151
+ /**
152
+ * Override the API base URL. Defaults to `api.openai.com/v1`; `CodexAgent`
153
+ * defaults it to `https://chatgpt.com/backend-api/codex`, and setting it
154
+ * there points at a Codex proxy instead.
155
+ */
156
+ baseURL?: string;
157
+ /**
158
+ * `CodexAgent` only: ChatGPT workspace to bill, sent as the
159
+ * `chatgpt-account-id` header.
160
+ */
161
+ accountId?: string;
162
+ /**
163
+ * `CodexAgent` only: client identifier sent as the `originator` header.
164
+ * OpenAI varies the model catalog by originator.
165
+ *
166
+ * @default "codex_cli_rs"
167
+ */
168
+ originator?: string;
169
+ /**
170
+ * `client_version` sent to the Codex models endpoint, which requires one and
171
+ * hides models newer than the version claimed.
172
+ */
173
+ clientVersion?: string;
140
174
  }
141
175
  /**
142
176
  * Vendor-specific configuration for Mistral
@@ -17,6 +17,12 @@ export declare class AgentEvent {
17
17
  * to history. The listener receives the `PartialTurn` that was salvaged.
18
18
  */
19
19
  static PARTIAL_TURN: string;
20
+ /**
21
+ * The provider reported how much of the account's allowance is left. Emitted
22
+ * by `CodexAgent`, whose backend returns rate-limit and credit headers on
23
+ * every response; the listener receives a `CodexUsageLimits`.
24
+ */
25
+ static USAGE_LIMITS: string;
20
26
  private defaultPrevented;
21
27
  constructor(target: BaseAgent<any>);
22
28
  preventDefault(): void;
@@ -30,4 +30,10 @@ AgentEvent.REASONING_CHUNK = "reasoning_chunk";
30
30
  * to history. The listener receives the `PartialTurn` that was salvaged.
31
31
  */
32
32
  AgentEvent.PARTIAL_TURN = "partial_turn";
33
+ /**
34
+ * The provider reported how much of the account's allowance is left. Emitted
35
+ * by `CodexAgent`, whose backend returns rate-limit and credit headers on
36
+ * every response; the listener receives a `CodexUsageLimits`.
37
+ */
38
+ AgentEvent.USAGE_LIMITS = "usage_limits";
33
39
  //# sourceMappingURL=AgentEvent.js.map
@@ -41,6 +41,24 @@ export type TokenUsage = {
41
41
  * for instance, folds thinking tokens into `output_tokens`.
42
42
  */
43
43
  reasoning_tokens?: number;
44
+ /**
45
+ * Prompt tokens the provider served from its own cache instead of processing
46
+ * afresh — a subset of `input_tokens`, not an addition to them, and normally
47
+ * billed at a discount.
48
+ *
49
+ * `0` is a real answer ("nothing hit the cache"); `undefined` means the
50
+ * provider said nothing about caching at all.
51
+ */
52
+ cache_read_tokens?: number;
53
+ /**
54
+ * Prompt tokens this call wrote *into* the provider's cache, where the
55
+ * provider reports writes separately from reads. Also a subset of
56
+ * `input_tokens` on the OpenAI-shaped providers.
57
+ *
58
+ * Rarer than `cache_read_tokens` — of the providers wired here only the
59
+ * ChatGPT/Codex backend reports it, and the platform Responses API does not.
60
+ */
61
+ cache_write_tokens?: number;
44
62
  /**
45
63
  * USD billed for this usage, straight from the provider's own accounting —
46
64
  * not derived from a local price table. Undefined where the provider
@@ -253,6 +253,8 @@ class BaseAgent extends events_1.default {
253
253
  output_tokens: previous.output_tokens + timed.output_tokens,
254
254
  total_tokens: previous.total_tokens + timed.total_tokens,
255
255
  reasoning_tokens: sumOptional(previous.reasoning_tokens, timed.reasoning_tokens),
256
+ cache_read_tokens: sumOptional(previous.cache_read_tokens, timed.cache_read_tokens),
257
+ cache_write_tokens: sumOptional(previous.cache_write_tokens, timed.cache_write_tokens),
256
258
  cost_usd: sumOptional(previous.cost_usd, timed.cost_usd),
257
259
  timeToFirstTokenMs: sumOptional(previous.timeToFirstTokenMs, timed.timeToFirstTokenMs),
258
260
  generationMs: sumOptional(previous.generationMs, timed.generationMs),
@@ -0,0 +1,169 @@
1
+ import { History } from "../../history/History";
2
+ import { ModelInfo } from "../BaseAgent";
3
+ import { ResponseInputItem } from "openai/resources/responses/responses";
4
+ import { OpenAIModel } from "../model-types";
5
+ import { AgentConfig as OpenAiAgentConfig, OpenAiAgent } from "./OpenAiAgent";
6
+ import { CodexCredentials, CodexModelCard, CodexTokenProviderOptions } from "./codex-auth";
7
+ import { CodexUsageLimits } from "./codex-usage";
8
+ /**
9
+ * Models the ChatGPT-backed Codex backend serves.
10
+ *
11
+ * A different namespace from the platform API's — every platform id
12
+ * (`gpt-5.6`, `gpt-4.1-mini`, even `gpt-5.1-codex`) is rejected here with
13
+ * *"model is not supported when using Codex with a ChatGPT account"*. Probed
14
+ * live on 2026-09-09; `(string & {})` keeps a newer model usable without a
15
+ * release, while still autocompleting the known ones.
16
+ */
17
+ export type CodexModel = "gpt-5.6-luna" | "gpt-5.6-sol" | "gpt-5.6-terra" | "gpt-5.5" | "gpt-6-astra" | "codex-auto-review" | (string & Record<never, never>);
18
+ /**
19
+ * Reasoning efforts the Codex models accept — a different set from the platform
20
+ * API's, and uniform across these models rather than per-family. Each model's
21
+ * live list is on `ModelInfo.raw.supported_reasoning_levels`.
22
+ */
23
+ export type CodexReasoningEffort = "low" | "medium" | "high" | "xhigh" | "max";
24
+ export type CodexAgentConfig = Omit<OpenAiAgentConfig, "model" | "reasoningEffort" | "fetch" | "vendor"> & {
25
+ /** @default "gpt-5.6-luna" */
26
+ model?: CodexModel;
27
+ /**
28
+ * How hard the model should think. `medium` if unset — the backend's own
29
+ * default for these models.
30
+ */
31
+ reasoningEffort?: CodexReasoningEffort;
32
+ /**
33
+ * ChatGPT workspace to bill, sent as the `chatgpt-account-id` header. Take it
34
+ * from {@link loadCodexCredentials}; the backend may reject a request without
35
+ * one.
36
+ */
37
+ accountId?: string;
38
+ /**
39
+ * Client identifier sent as `originator`. OpenAI gates parts of the model
40
+ * catalog on this, so the default mirrors the Codex CLI.
41
+ *
42
+ * @default CODEX_ORIGINATOR
43
+ */
44
+ originator?: string;
45
+ /**
46
+ * `client_version` for the models endpoint, which 400s without one and hides
47
+ * models newer than the version claimed.
48
+ *
49
+ * @default CODEX_CLIENT_VERSION
50
+ */
51
+ clientVersion?: string;
52
+ };
53
+ /**
54
+ * Agent for OpenAI models reached through a **ChatGPT subscription** rather
55
+ * than a platform API key.
56
+ *
57
+ * Talks to `https://chatgpt.com/backend-api/codex`, the endpoint OpenAI's Codex
58
+ * CLI uses, so calls are billed against the subscription instead of an API
59
+ * account. It speaks the Responses API, hence the `OpenAiAgent` base — but the
60
+ * two are far enough apart that mixing them in one class meant lying to the
61
+ * type system about which models exist:
62
+ *
63
+ * | | platform | Codex |
64
+ * |---|---|---|
65
+ * | models | `gpt-5.6`, `gpt-4.1-mini`, … | `gpt-5.6-luna/sol/terra`, … — disjoint sets |
66
+ * | body | as written | `instructions` required, `stream: true`, no `max_output_tokens` |
67
+ * | errors | `{error: {…}}` | `{detail: …}` |
68
+ * | terminal event | `output` populated | `output: []`; content arrives as items |
69
+ * | models endpoint | `/v1/models` | `/models?client_version=…` |
70
+ *
71
+ * Nothing here is a documented public API and OpenAI can change it without
72
+ * notice; {@link OpenAiAgent} with a platform key remains the supported path.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * // Reads the credentials `codex login` stored, and keeps the token fresh.
77
+ * const agent = await CodexAgent.fromCodexCli({
78
+ * id: "1",
79
+ * name: "Assistant",
80
+ * description: "A helpful assistant",
81
+ * });
82
+ *
83
+ * console.log(await agent.execute("Hello!"));
84
+ * ```
85
+ */
86
+ export declare class CodexAgent extends OpenAiAgent<OpenAIModel, CodexModelCard> {
87
+ private readonly accountId?;
88
+ private readonly originator;
89
+ private readonly clientVersion;
90
+ private readonly codexBaseURL;
91
+ /**
92
+ * Quota state written by the fetch wrapper installed in the constructor.
93
+ *
94
+ * A holder object rather than a field because the wrapper is built *before*
95
+ * `super()` — the base constructor creates the SDK client, so the wrapper has
96
+ * to exist by then, and `this` is not available yet. `notify` is attached
97
+ * afterwards, once emitting is possible.
98
+ */
99
+ private readonly limits;
100
+ constructor(config: CodexAgentConfig, history?: History);
101
+ /**
102
+ * What the most recent response said about the subscription's remaining
103
+ * allowance — this backend's answer to "what did that cost?".
104
+ *
105
+ * A ChatGPT subscription is not priced per request, so
106
+ * `lastTokenUsage.cost_usd` is undefined here and always will be. What a call
107
+ * spends is plan allowance, reported as two rolling windows (5-hourly and
108
+ * weekly) plus the credit balance that takes over once they are used up.
109
+ *
110
+ * Unlike `lastTokenUsage`, this is **not** reset per run: it describes the
111
+ * account, not the turn, so it keeps the last value seen until another call
112
+ * updates it. `undefined` before the first call, and after calls that carried
113
+ * no quota headers — `listModels()` is one, so only `execute()` /
114
+ * `executeStream()` refresh it. `AgentEvent.USAGE_LIMITS` fires on every
115
+ * update, including the ones on a failed request.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * await agent.execute("Hello!");
120
+ * const limits = agent.lastUsageLimits;
121
+ * console.log(`${limits?.primary?.usedPercent}% of the 5h window used`);
122
+ * ```
123
+ */
124
+ get lastUsageLimits(): CodexUsageLimits | undefined;
125
+ /**
126
+ * Build an agent from the credentials `codex login` stored, wrapped in a
127
+ * provider that refreshes the access token as it ages out.
128
+ *
129
+ * @throws if no credentials are present — run `codex login` first.
130
+ */
131
+ static fromCodexCli(config: Omit<CodexAgentConfig, "apiKey" | "accountId"> & {
132
+ /** Read `auth.json` from somewhere other than `$CODEX_HOME`. */
133
+ codexHome?: string;
134
+ /** Forwarded to {@link createCodexTokenProvider}. */
135
+ tokenOptions?: CodexTokenProviderOptions;
136
+ }, history?: History): Promise<CodexAgent>;
137
+ /** Build an agent from credentials obtained however you like. */
138
+ static fromCredentials(credentials: CodexCredentials, config: Omit<CodexAgentConfig, "apiKey" | "accountId"> & {
139
+ tokenOptions?: CodexTokenProviderOptions;
140
+ }, history?: History): CodexAgent;
141
+ /** This backend refuses `stream: false` outright. */
142
+ protected get forceStreaming(): boolean;
143
+ /**
144
+ * Satisfy the backend's extra body validations, each of which is otherwise a
145
+ * bare `400`: *"Instructions are required"*, *"Input must be a list"*,
146
+ * *"Store must be set to false"*, *"Stream must be set to true"*,
147
+ * *"Unsupported parameter: max_output_tokens"*.
148
+ *
149
+ * `store: false` and a list-shaped `input` already hold at every call site in
150
+ * the base class.
151
+ */
152
+ protected transformRequestParams<T extends {
153
+ input: ResponseInputItem[];
154
+ }>(params: T): T;
155
+ /**
156
+ * List the models this ChatGPT account may drive.
157
+ *
158
+ * Neither the endpoint nor the shape matches the platform API's
159
+ * `/v1/models`: it needs a `client_version` query parameter (400s without
160
+ * one) and returns richer cards — the context window for this account's
161
+ * plan, the reasoning efforts the model accepts, the plans it is available
162
+ * in. The SDK has no method for it, so this goes out through `fetch`.
163
+ *
164
+ * Models whose `minimal_client_version` exceeds {@link clientVersion} are
165
+ * omitted by the server, not here.
166
+ */
167
+ listModels(): Promise<ModelInfo<CodexModelCard>[]>;
168
+ }
169
+ //# sourceMappingURL=CodexAgent.d.ts.map
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodexAgent = void 0;
4
+ const AgentEvent_1 = require("../AgentEvent");
5
+ const AgentError_1 = require("../errors/AgentError");
6
+ const OpenAiAgent_1 = require("./OpenAiAgent");
7
+ const codex_auth_1 = require("./codex-auth");
8
+ const codex_usage_1 = require("./codex-usage");
9
+ /**
10
+ * Agent for OpenAI models reached through a **ChatGPT subscription** rather
11
+ * than a platform API key.
12
+ *
13
+ * Talks to `https://chatgpt.com/backend-api/codex`, the endpoint OpenAI's Codex
14
+ * CLI uses, so calls are billed against the subscription instead of an API
15
+ * account. It speaks the Responses API, hence the `OpenAiAgent` base — but the
16
+ * two are far enough apart that mixing them in one class meant lying to the
17
+ * type system about which models exist:
18
+ *
19
+ * | | platform | Codex |
20
+ * |---|---|---|
21
+ * | models | `gpt-5.6`, `gpt-4.1-mini`, … | `gpt-5.6-luna/sol/terra`, … — disjoint sets |
22
+ * | body | as written | `instructions` required, `stream: true`, no `max_output_tokens` |
23
+ * | errors | `{error: {…}}` | `{detail: …}` |
24
+ * | terminal event | `output` populated | `output: []`; content arrives as items |
25
+ * | models endpoint | `/v1/models` | `/models?client_version=…` |
26
+ *
27
+ * Nothing here is a documented public API and OpenAI can change it without
28
+ * notice; {@link OpenAiAgent} with a platform key remains the supported path.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Reads the credentials `codex login` stored, and keeps the token fresh.
33
+ * const agent = await CodexAgent.fromCodexCli({
34
+ * id: "1",
35
+ * name: "Assistant",
36
+ * description: "A helpful assistant",
37
+ * });
38
+ *
39
+ * console.log(await agent.execute("Hello!"));
40
+ * ```
41
+ */
42
+ class CodexAgent extends OpenAiAgent_1.OpenAiAgent {
43
+ constructor(config, history) {
44
+ const vendorConfig = config.vendorConfig?.openai ?? {};
45
+ const accountId = config.accountId ?? vendorConfig.accountId;
46
+ const originator = config.originator ?? vendorConfig.originator ?? codex_auth_1.CODEX_ORIGINATOR;
47
+ const baseURL = config.baseURL ?? vendorConfig.baseURL ?? codex_auth_1.CODEX_BASE_URL;
48
+ // Filled by the fetch wrapper below and adopted as `this.limits` once
49
+ // `super()` has run.
50
+ const limits = {};
51
+ // Everything host-specific is passed *into* the base constructor rather
52
+ // than supplied by an override: the base runs before this class's fields
53
+ // are assigned, so an override could not read them.
54
+ super({
55
+ ...config,
56
+ model: config.model ?? "gpt-5.6-luna",
57
+ reasoningEffort: config.reasoningEffort,
58
+ baseURL,
59
+ defaultHeaders: {
60
+ ...(accountId ? { "chatgpt-account-id": accountId } : {}),
61
+ "OpenAI-Beta": "responses=experimental",
62
+ originator,
63
+ // Every Codex request is a stream; the SDK would send
64
+ // `application/json`, which no reference client does.
65
+ Accept: "text/event-stream",
66
+ ...config.defaultHeaders,
67
+ },
68
+ // Two wrappers, innermost first: normalise this backend's `{detail: …}`
69
+ // error bodies (which the SDK otherwise drops on the floor — see
70
+ // wrapErrorBodyFetch()), then read the `x-codex-*` quota headers off
71
+ // every response on the way back out.
72
+ fetch: (0, codex_usage_1.observeHeadersFetch)((headers) => {
73
+ const parsed = (0, codex_usage_1.parseCodexUsageLimits)(headers);
74
+ if (!parsed)
75
+ return;
76
+ limits.latest = parsed;
77
+ limits.notify?.(parsed);
78
+ }, (0, OpenAiAgent_1.wrapErrorBodyFetch)()),
79
+ // Cast: the codex-specific keys (accountId, originator, clientVersion)
80
+ // are not part of the base config, and `vendor` is supplied by it.
81
+ }, history);
82
+ this.limits = limits;
83
+ // Only now can the wrapper emit; anything parsed before this point is still
84
+ // on `limits.latest`.
85
+ limits.notify = (usageLimits) => this.emit(AgentEvent_1.AgentEvent.USAGE_LIMITS, usageLimits);
86
+ this.accountId = accountId;
87
+ this.originator = originator;
88
+ this.clientVersion =
89
+ config.clientVersion ?? vendorConfig.clientVersion ?? codex_auth_1.CODEX_CLIENT_VERSION;
90
+ this.codexBaseURL = baseURL;
91
+ }
92
+ /**
93
+ * What the most recent response said about the subscription's remaining
94
+ * allowance — this backend's answer to "what did that cost?".
95
+ *
96
+ * A ChatGPT subscription is not priced per request, so
97
+ * `lastTokenUsage.cost_usd` is undefined here and always will be. What a call
98
+ * spends is plan allowance, reported as two rolling windows (5-hourly and
99
+ * weekly) plus the credit balance that takes over once they are used up.
100
+ *
101
+ * Unlike `lastTokenUsage`, this is **not** reset per run: it describes the
102
+ * account, not the turn, so it keeps the last value seen until another call
103
+ * updates it. `undefined` before the first call, and after calls that carried
104
+ * no quota headers — `listModels()` is one, so only `execute()` /
105
+ * `executeStream()` refresh it. `AgentEvent.USAGE_LIMITS` fires on every
106
+ * update, including the ones on a failed request.
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * await agent.execute("Hello!");
111
+ * const limits = agent.lastUsageLimits;
112
+ * console.log(`${limits?.primary?.usedPercent}% of the 5h window used`);
113
+ * ```
114
+ */
115
+ get lastUsageLimits() {
116
+ return this.limits.latest;
117
+ }
118
+ /**
119
+ * Build an agent from the credentials `codex login` stored, wrapped in a
120
+ * provider that refreshes the access token as it ages out.
121
+ *
122
+ * @throws if no credentials are present — run `codex login` first.
123
+ */
124
+ static async fromCodexCli(config, history) {
125
+ const credentials = await (0, codex_auth_1.loadCodexCredentials)(config.codexHome);
126
+ return CodexAgent.fromCredentials(credentials, config, history);
127
+ }
128
+ /** Build an agent from credentials obtained however you like. */
129
+ static fromCredentials(credentials, config, history) {
130
+ const tokens = (0, codex_auth_1.createCodexTokenProvider)(credentials, config.tokenOptions);
131
+ return new CodexAgent({
132
+ ...config,
133
+ // The function form: the SDK re-invokes it before every request, so a
134
+ // long run outlives the ~1h token.
135
+ apiKey: tokens.getToken,
136
+ accountId: credentials.accountId,
137
+ }, history);
138
+ }
139
+ /** This backend refuses `stream: false` outright. */
140
+ get forceStreaming() {
141
+ return true;
142
+ }
143
+ /**
144
+ * Satisfy the backend's extra body validations, each of which is otherwise a
145
+ * bare `400`: *"Instructions are required"*, *"Input must be a list"*,
146
+ * *"Store must be set to false"*, *"Stream must be set to true"*,
147
+ * *"Unsupported parameter: max_output_tokens"*.
148
+ *
149
+ * `store: false` and a list-shaped `input` already hold at every call site in
150
+ * the base class.
151
+ */
152
+ transformRequestParams(params) {
153
+ // Read from history rather than getSystemMessage(): that is the message
154
+ // being stripped from `input` below, and a caller may have replaced it.
155
+ const systemMessage = this.history.getSystemMessage() ?? this.getSystemMessage();
156
+ // Rejected outright, so it cannot merely be left undefined when the caller
157
+ // set `maxTokens`.
158
+ const { max_output_tokens: _dropped, ...rest } = params;
159
+ return {
160
+ ...rest,
161
+ // Must be present and non-empty.
162
+ instructions: systemMessage?.trim()
163
+ ? systemMessage
164
+ : "You are a helpful assistant.",
165
+ // The system prompt travels in `instructions` now, so drop the copy the
166
+ // transformer put in `input` rather than sending it twice.
167
+ input: params.input.filter((item) => !(typeof item === "object" &&
168
+ item !== null &&
169
+ "role" in item &&
170
+ item.role === "system")),
171
+ };
172
+ }
173
+ /**
174
+ * List the models this ChatGPT account may drive.
175
+ *
176
+ * Neither the endpoint nor the shape matches the platform API's
177
+ * `/v1/models`: it needs a `client_version` query parameter (400s without
178
+ * one) and returns richer cards — the context window for this account's
179
+ * plan, the reasoning efforts the model accepts, the plans it is available
180
+ * in. The SDK has no method for it, so this goes out through `fetch`.
181
+ *
182
+ * Models whose `minimal_client_version` exceeds {@link clientVersion} are
183
+ * omitted by the server, not here.
184
+ */
185
+ async listModels() {
186
+ try {
187
+ const token = await this.resolveApiKey();
188
+ const url = `${this.codexBaseURL}/models?client_version=${encodeURIComponent(this.clientVersion)}`;
189
+ const res = await fetch(url, {
190
+ headers: {
191
+ Authorization: `Bearer ${token}`,
192
+ ...(this.accountId ? { "chatgpt-account-id": this.accountId } : {}),
193
+ originator: this.originator,
194
+ },
195
+ });
196
+ if (!res.ok) {
197
+ const body = await res.text().catch(() => "");
198
+ throw new Error(`${res.status} ${res.statusText}${body ? `: ${body.slice(0, 300)}` : ""}`);
199
+ }
200
+ const data = (await res.json());
201
+ return (data.models ?? []).map((model) => ({
202
+ id: model.slug,
203
+ displayName: model.display_name,
204
+ // The plan's window, not the model's ceiling — `max_context_window` is
205
+ // on `raw` for anyone who needs the larger number.
206
+ contextLength: model.context_window,
207
+ capabilities: {
208
+ chat: true,
209
+ tools: true,
210
+ vision: model.input_modalities?.includes("image"),
211
+ thinking: (model.supported_reasoning_levels?.length ?? 0) > 0,
212
+ },
213
+ raw: model,
214
+ }));
215
+ }
216
+ catch (error) {
217
+ throw new AgentError_1.ExecutionError(`Failed to list Codex models: ${error instanceof Error ? error.message : "Unknown error"}`);
218
+ }
219
+ }
220
+ }
221
+ exports.CodexAgent = CodexAgent;
222
+ //# sourceMappingURL=CodexAgent.js.map