Skip to content

Commit 97db265

Browse files
Aleksandr Slapoguzovslapoguzov
authored andcommitted
LLM-24555 Update codex to 0.99.0
1 parent 100f5e6 commit 97db265

50 files changed

Lines changed: 702 additions & 98 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-lock.json

Lines changed: 120 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"license": "ISC",
2929
"type": "module",
3030
"devDependencies": {
31-
"@openai/codex": "^0.98.0",
31+
"@openai/codex": "^0.99.0",
3232
"@types/node": "^24.10.1",
3333
"mcp-hello-world": "^1.1.2",
3434
"tsx": "^4.20.6",

src/CodexAcpServer.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import {CodexEventHandler} from "./CodexEventHandler";
99
import {CodexApprovalHandler} from "./CodexApprovalHandler";
1010
import {CodexAuthMethods, type CodexAuthRequest} from "./CodexAuthMethod";
1111
import {CodexAcpClient, type SessionMetadata} from "./CodexAcpClient";
12-
import type {Account, Model, RateLimitSnapshot} from "./app-server/v2";
13-
import type {ReasoningEffort} from "./app-server";
12+
import type {Account, Model, ReasoningEffortOption} from "./app-server/v2";
13+
import type {RateLimitsMap} from "./RateLimitsMap";
14+
import type {InputModality, ReasoningEffort} from "./app-server";
1415
import {ModelId} from "./ModelId";
1516
import {AgentMode} from "./AgentMode";
1617
import type {TokenCount} from "./TokenCount";
@@ -21,12 +22,14 @@ import {logger} from "./Logger";
2122
export interface SessionState {
2223
sessionId: string,
2324
currentModelId: string,
25+
supportedReasoningEfforts: Array<ReasoningEffortOption>,
26+
supportedInputModalities: Array<InputModality>,
2427
agentMode: AgentMode,
2528
currentTurnId: string | null;
2629
lastTokenUsage: TokenCount | null;
2730
totalTokenUsage: TokenCount | null;
2831
modelContextWindow: number | null;
29-
rateLimits: RateLimitSnapshot | null;
32+
rateLimits: RateLimitsMap | null;
3033
account: Account | null;
3134
cwd: string;
3235
sessionMcpServers?: Array<string>;
@@ -117,9 +120,12 @@ export class CodexAcpServer implements acp.Agent {
117120
const {sessionId, currentModelId, models} = sessionMetadata;
118121
logger.log(`Waiting MCP servers to start...`)
119122
const sessionMcpServers = await pendingMcpServers;
123+
const currentModel = this.findCurrentModel(models, currentModelId);
120124
const sessionState: SessionState = {
121125
sessionId: sessionId,
122126
currentModelId: currentModelId,
127+
supportedReasoningEfforts: currentModel?.supportedReasoningEfforts ?? [],
128+
supportedInputModalities: currentModel?.inputModalities ?? ["text", "image"],
123129
agentMode: AgentMode.getInitialAgentMode(),
124130
currentTurnId: null,
125131
lastTokenUsage: null,
@@ -237,6 +243,8 @@ export class CodexAcpServer implements acp.Agent {
237243
}
238244

239245
sessionState.currentModelId = ModelId.fromComponents(model, reasoningEffort).toString();
246+
sessionState.supportedReasoningEfforts = model.supportedReasoningEfforts;
247+
sessionState.supportedInputModalities = model.inputModalities;
240248

241249
return {};
242250
}
@@ -245,6 +253,11 @@ export class CodexAcpServer implements acp.Agent {
245253
void this.availableCommands.publish(sessionId);
246254
}
247255

256+
private findCurrentModel(models: Model[], currentModelId: string): Model | undefined {
257+
const modelId = ModelId.fromString(currentModelId);
258+
return models.find(m => m.id === modelId.model);
259+
}
260+
248261
private createModelState(availableModels: Model[], selectedModelId: string): SessionModelState {
249262
const allowedModels = availableModels
250263
.flatMap((model) =>
@@ -292,14 +305,22 @@ export class CodexAcpServer implements acp.Agent {
292305
};
293306
}
294307

295-
const disableSummary = sessionState.account?.type === "apiKey"
308+
const modelId = ModelId.fromString(sessionState.currentModelId);
309+
const modelLacksReasoning = sessionState.supportedReasoningEfforts.length > 0
310+
&& sessionState.supportedReasoningEfforts.every(e => e.reasoningEffort === "none");
311+
312+
const disableSummary = sessionState.account?.type === "apiKey" || modelLacksReasoning;
296313
if (disableSummary) {
297-
logger.log("Disable reasoning.summary because API key is used", {sessionId: params.sessionId});
314+
logger.log("Disable reasoning.summary", {
315+
sessionId: params.sessionId,
316+
reason: sessionState.account?.type === "apiKey" ? "API key" : "model lacks reasoning"
317+
});
298318
}
299319

300-
320+
if (!sessionState.supportedInputModalities.includes("image") && params.prompt.some(b => b.type === "image")) {
321+
throw RequestError.invalidRequest("The current model does not support image input");
322+
}
301323
const agentMode = sessionState.agentMode;
302-
const modelId = ModelId.fromString(sessionState.currentModelId);
303324
const turnCompleted = await this.runWithProcessCheck(
304325
() => this.codexAcpClient.sendPrompt(params, agentMode, modelId, disableSummary));
305326

src/CodexCommands.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {ACPSessionConnection} from "./ACPSessionConnection";
44
import type {CodexAcpClient} from "./CodexAcpClient";
55
import type {RateLimitSnapshot, SkillsListEntry} from "./app-server/v2";
66
import type {SessionState} from "./CodexAcpServer";
7+
import type {RateLimitsMap} from "./RateLimitsMap";
78
import type {TokenCount} from "./TokenCount";
89
import {logger} from "./Logger";
910

@@ -233,7 +234,7 @@ export class CodexCommands {
233234
return "API key configured";
234235
}
235236
if (account.type === "chatgpt") {
236-
return `ChatGPT (${account.email})`;
237+
return `ChatGPT ${account.planType} (${account.email})`;
237238
}
238239
return "unknown";
239240
}
@@ -259,36 +260,47 @@ export class CodexCommands {
259260
return `${percentLeft}% left (${usedFormatted} used / ${totalFormatted})`;
260261
}
261262

262-
private formatRateLimitLines(rateLimits: RateLimitSnapshot | null): string[] {
263-
if (!rateLimits) {
263+
private formatRateLimitLines(rateLimits: RateLimitsMap | null): string[] {
264+
if (!rateLimits || rateLimits.size === 0) {
264265
return [`**Limits:** data not available yet`];
265266
}
266267

267268
const lines: string[] = [];
268269

270+
for (const [, entry] of rateLimits) {
271+
lines.push(...this.formatSingleRateLimit(entry.limitName, entry.snapshot));
272+
}
273+
274+
return lines.length > 0 ? lines : [`**Limits:** data not available yet`];
275+
}
276+
277+
private formatSingleRateLimit(limitName: string, rateLimits: RateLimitSnapshot): string[] {
278+
const lines: string[] = [];
279+
const prefix = limitName ? `${limitName} ` : "";
280+
269281
if (rateLimits.primary) {
270282
const percentLeft = Math.round(100 - rateLimits.primary.usedPercent);
271283
const resetText = this.formatResetTime(rateLimits.primary.resetsAt);
272284
const label = this.formatWindowLabel(rateLimits.primary.windowDurationMins);
273-
lines.push(`**${label}:** ${percentLeft}% left${resetText}`);
285+
lines.push(`**${prefix}${label}:** ${percentLeft}% left${resetText}`);
274286
}
275287

276288
if (rateLimits.secondary) {
277289
const percentLeft = Math.round(100 - rateLimits.secondary.usedPercent);
278290
const resetText = this.formatResetTime(rateLimits.secondary.resetsAt);
279291
const label = this.formatWindowLabel(rateLimits.secondary.windowDurationMins);
280-
lines.push(`**${label}:** ${percentLeft}% left${resetText}`);
292+
lines.push(`**${prefix}${label}:** ${percentLeft}% left${resetText}`);
281293
}
282294

283295
if (rateLimits.credits) {
284296
if (rateLimits.credits.unlimited) {
285-
lines.push(`**Credits:** unlimited`);
297+
lines.push(`**${prefix}Credits:** unlimited`);
286298
} else if (rateLimits.credits.balance) {
287-
lines.push(`**Credits:** ${rateLimits.credits.balance}`);
299+
lines.push(`**${prefix}Credits:** ${rateLimits.credits.balance}`);
288300
}
289301
}
290302

291-
return lines.length > 0 ? lines : [`**Limits:** data not available yet`];
303+
return lines;
292304
}
293305

294306
private formatWindowLabel(windowDurationMins: number | null): string {

src/CodexEventHandler.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ export class CodexEventHandler {
120120
case "configWarning":
121121
return await this.createConfigWarningEvent(notification.params);
122122
case "thread/compacted":
123+
return {
124+
sessionUpdate: "agent_message_chunk",
125+
content: {
126+
type: "text",
127+
text: "*Context compacted to fit the model's context window.*\n\n"
128+
}
129+
};
123130
case "windows/worldWritableWarning":
124131
case "account/login/completed":
125132
case "authStatusChange":
@@ -131,6 +138,7 @@ export class CodexEventHandler {
131138
case "thread/started":
132139
case "thread/name/updated":
133140
case "item/plan/delta":
141+
case "app/list/updated":
134142
return null;
135143
}
136144
}
@@ -450,6 +458,13 @@ export class CodexEventHandler {
450458
}
451459

452460
private handleRateLimitsUpdated(params: AccountRateLimitsUpdatedNotification): void {
453-
this.sessionState.rateLimits = params.rateLimits;
461+
if (!this.sessionState.rateLimits) {
462+
this.sessionState.rateLimits = new Map();
463+
}
464+
this.sessionState.rateLimits.set(params.limitId, {
465+
limitId: params.limitId,
466+
limitName: params.limitName,
467+
snapshot: params.rateLimits,
468+
});
454469
}
455470
}

src/RateLimitsMap.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type {RateLimitSnapshot} from "./app-server/v2";
2+
3+
export type RateLimitEntry = {
4+
limitId: string;
5+
limitName: string;
6+
snapshot: RateLimitSnapshot;
7+
};
8+
9+
export type RateLimitsMap = Map<string, RateLimitEntry>;

0 commit comments

Comments
 (0)