diff --git a/src/CodexAcpServer.ts b/src/CodexAcpServer.ts index d27fc15a..66f115a6 100644 --- a/src/CodexAcpServer.ts +++ b/src/CodexAcpServer.ts @@ -42,6 +42,7 @@ import { resolveFastServiceTier, } from "./FastModeConfig"; import packageJson from "../package.json"; +import {isJetBrains2026_1Client} from "./JBUtils"; export interface SessionState { sessionId: string, @@ -90,6 +91,7 @@ export class CodexAcpServer implements acp.Agent { private readonly defaultAuthRequest: CodexAuthRequest | null; private readonly getExitCode: () => number | null; private readonly availableCommands: CodexCommands; + private clientInfo: acp.Implementation | null; private readonly sessions: Map; private readonly pendingMcpStartupSessions: Map; @@ -116,6 +118,7 @@ export class CodexAcpServer implements acp.Agent { this.codexAcpClient = codexAcpClient; this.defaultAuthRequest = defaultAuthRequest ?? null; this.getExitCode = getExitCode ?? (() => null); + this.clientInfo = null; this.availableCommands = new CodexCommands( connection, codexAcpClient, @@ -127,6 +130,7 @@ export class CodexAcpServer implements acp.Agent { _params: acp.InitializeRequest, ): Promise { logger.log("Initialize request received"); + this.clientInfo = _params.clientInfo ?? null; await this.runWithProcessCheck(() => this.codexAcpClient.initialize(_params)); return { protocolVersion: acp.PROTOCOL_VERSION, @@ -382,7 +386,7 @@ export class CodexAcpServer implements acp.Agent { return { models: modelState, modes: modeState, - configOptions: this.createSessionConfigOptions(this.getSessionState(sessionId)), + ...this.createSessionConfigOptionsResponse(this.getSessionState(sessionId)), }; } @@ -398,7 +402,7 @@ export class CodexAcpServer implements acp.Agent { return { models: modelState, modes: modeState, - configOptions: this.createSessionConfigOptions(this.getSessionState(sessionId)), + ...this.createSessionConfigOptionsResponse(this.getSessionState(sessionId)), }; } @@ -458,7 +462,7 @@ export class CodexAcpServer implements acp.Agent { sessionId: sessionId, models: modelState, modes: modeState, - configOptions: this.createSessionConfigOptions(this.getSessionState(sessionId)), + ...this.createSessionConfigOptionsResponse(this.getSessionState(sessionId)), }; } @@ -567,6 +571,22 @@ export class CodexAcpServer implements acp.Agent { ]; } + private createSessionConfigOptionsResponse(sessionState: SessionState): { + configOptions?: Array; + } { + if (!this.isSessionConfigEnabled()) { + return {}; + } + return { + configOptions: this.createSessionConfigOptions(sessionState), + }; + } + + private isSessionConfigEnabled(): boolean { + // Temporarily disabled for JB IDEs 2026.1 due to issues in session_config (LLM-28118) + return !isJetBrains2026_1Client(this.clientInfo); + } + private publishAvailableCommandsAsync(sessionId: string) { void this.availableCommands.publish(sessionId); } diff --git a/src/JBUtils.ts b/src/JBUtils.ts new file mode 100644 index 00000000..86237320 --- /dev/null +++ b/src/JBUtils.ts @@ -0,0 +1,12 @@ +import type * as acp from "@agentclientprotocol/sdk"; + +export function isJetBrains2026_1Client(clientInfo: acp.Implementation | null): boolean { + if (!clientInfo) { + return false; + } + + const platform = clientInfo._meta?.["platform"]; + const isIntelliJPlatform = platform === "intellij"; + const isJetBrainsClient = clientInfo.name.startsWith("JetBrains"); + return (isIntelliJPlatform || isJetBrainsClient) && clientInfo.version.startsWith("2026.1"); +} diff --git a/src/__tests__/CodexACPAgent/fast-mode-config.test.ts b/src/__tests__/CodexACPAgent/fast-mode-config.test.ts index 0e103695..4f35bddc 100644 --- a/src/__tests__/CodexACPAgent/fast-mode-config.test.ts +++ b/src/__tests__/CodexACPAgent/fast-mode-config.test.ts @@ -1,4 +1,5 @@ import {describe, expect, it, vi} from "vitest"; +import * as acp from "@agentclientprotocol/sdk"; import { createCodexMockTestFixture, createTestModel, @@ -13,7 +14,10 @@ import { } from "../../FastModeConfig"; describe("Fast mode session config", () => { - async function createSession(currentServiceTier: "fast" | "flex" | null = null) { + async function createSession( + currentServiceTier: "fast" | "flex" | null = null, + clientInfo: acp.Implementation | null = null + ) { const fixture = createCodexMockTestFixture(); const codexAcpAgent = fixture.getCodexAcpAgent(); const codexAcpClient = fixture.getCodexAcpClient(); @@ -31,6 +35,11 @@ describe("Fast mode session config", () => { currentServiceTier, }); + await codexAcpAgent.initialize({ + protocolVersion: acp.PROTOCOL_VERSION, + clientInfo, + }); + const response = await codexAcpAgent.newSession({cwd: "/test/cwd", mcpServers: []}); return {fixture, codexAcpAgent, codexAcpClient, response}; } @@ -58,6 +67,55 @@ describe("Fast mode session config", () => { expect(codexAcpAgent.getSessionState("session-id").fastModeEnabled).toBe(true); }); + it("omits Fast mode config options for JetBrains 2026.1 IntelliJ clients", async () => { + const {response} = await createSession(null, { + name: "JetBrains.WebStorm", + version: "2026.1.1", + title: "WebStorm 2026.1.1", + _meta: { + platform: "intellij", + }, + }); + + expect(response.configOptions).toBeUndefined(); + }); + + it("omits Fast mode config options for JetBrains 2026.1 clients by name", async () => { + const {response} = await createSession(null, { + name: "JetBrains.IDE", + version: "2026.1", + title: "JetBrains IDE", + }); + + expect(response.configOptions).toBeUndefined(); + }); + + it("keeps Fast mode config options for JetBrains clients outside 2026.1", async () => { + const {response} = await createSession(null, { + name: "JetBrains.WebStorm", + version: "2026.2.0", + title: "WebStorm 2026.2.0", + _meta: { + platform: "intellij", + }, + }); + + expect(response.configOptions).toEqual([createFastModeConfigOption(false)]); + }); + + it("keeps Fast mode config options for non-JetBrains 2026.1 clients", async () => { + const {response} = await createSession(null, { + name: "VSCode", + version: "2026.1.1", + title: "VS Code", + _meta: { + platform: "vscode", + }, + }); + + expect(response.configOptions).toEqual([createFastModeConfigOption(false)]); + }); + it("toggles Fast mode through session config options", async () => { const {codexAcpAgent} = await createSession();