diff --git a/package-lock.json b/package-lock.json index 0da3a52d..9a11d65b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,29 +9,29 @@ "version": "0.0.31", "license": "ISC", "dependencies": { - "@openai/codex": "^0.114.0" + "@agentclientprotocol/sdk": "^0.12.0", + "@openai/codex": "^0.114.0", + "diff": "^8.0.3", + "open": "^11.0.0", + "vscode-jsonrpc": "^8.2.1" }, "bin": { "codex-acp": "dist/index.js" }, "devDependencies": { - "@agentclientprotocol/sdk": "^0.12.0", + "@openai/codex": "^0.118.0", "@types/node": "^24.10.1", - "diff": "^8.0.3", "esbuild": "^0.25.0", "mcp-hello-world": "^1.1.2", - "open": "^11.0.0", "tsx": "^4.20.6", "typescript": "^5.9.3", - "vitest": "^4.0.10", - "vscode-jsonrpc": "^8.2.1" + "vitest": "^4.0.10" } }, "node_modules/@agentclientprotocol/sdk": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-0.12.0.tgz", "integrity": "sha512-V8uH/KK1t7utqyJmTA7y7DzKu6+jKFIXM+ZVouz8E55j8Ej2RV42rEvPKn3/PpBJlliI5crcGk1qQhZ7VwaepA==", - "dev": true, "license": "Apache-2.0", "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" @@ -818,9 +818,10 @@ } }, "node_modules/@openai/codex": { - "version": "0.114.0", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0.tgz", - "integrity": "sha512-HMo8LRR6CtfKkaa28xvFK6eOarmBFTDfsrS9GJtEoaspGGemFok494CpafDspiTZaHZZGHfSUe5SWTUxYq7OaA==", + "version": "0.118.0", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0.tgz", + "integrity": "sha512-oJhNOsP/Vu7DBUhodpP15z60cCZv3sKORqUn1+pepleqSTmc0zXJZSjz6fQOLzny9Ra6sRcvprFFKmQ3Q6+E6w==", + "dev": true, "license": "Apache-2.0", "bin": { "codex": "bin/codex.js" @@ -829,22 +830,23 @@ "node": ">=16" }, "optionalDependencies": { - "@openai/codex-darwin-arm64": "npm:@openai/codex@0.114.0-darwin-arm64", - "@openai/codex-darwin-x64": "npm:@openai/codex@0.114.0-darwin-x64", - "@openai/codex-linux-arm64": "npm:@openai/codex@0.114.0-linux-arm64", - "@openai/codex-linux-x64": "npm:@openai/codex@0.114.0-linux-x64", - "@openai/codex-win32-arm64": "npm:@openai/codex@0.114.0-win32-arm64", - "@openai/codex-win32-x64": "npm:@openai/codex@0.114.0-win32-x64" + "@openai/codex-darwin-arm64": "npm:@openai/codex@0.118.0-darwin-arm64", + "@openai/codex-darwin-x64": "npm:@openai/codex@0.118.0-darwin-x64", + "@openai/codex-linux-arm64": "npm:@openai/codex@0.118.0-linux-arm64", + "@openai/codex-linux-x64": "npm:@openai/codex@0.118.0-linux-x64", + "@openai/codex-win32-arm64": "npm:@openai/codex@0.118.0-win32-arm64", + "@openai/codex-win32-x64": "npm:@openai/codex@0.118.0-win32-x64" } }, "node_modules/@openai/codex-darwin-arm64": { "name": "@openai/codex", - "version": "0.114.0-darwin-arm64", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-darwin-arm64.tgz", - "integrity": "sha512-c9dlgo9O+66alr3s3G36fKE3KaO2+xrLZ/QcU3oujDruV86pqgVSEK2njHi+WIyyOa6m2AyWxdaHLEbKxPCNRg==", + "version": "0.118.0-darwin-arm64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0-darwin-arm64.tgz", + "integrity": "sha512-sxq7Q2q9YiJN1wNrzvFRCC5oQKXPVUvu9Ejg6SI/CvyyI9YdtyLTO633wQJALGB7XQfT+3tyM5nNBivnSzLA3Q==", "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -856,12 +858,13 @@ }, "node_modules/@openai/codex-darwin-x64": { "name": "@openai/codex", - "version": "0.114.0-darwin-x64", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-darwin-x64.tgz", - "integrity": "sha512-oPAPeZSaJZ1AQneFPSJu44uqbZr63Bxut9FOTWZwuSqYx4YEees7i0HJmJcqQc0XnCbYtHJdqo/i07Uv374NLw==", + "version": "0.118.0-darwin-x64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0-darwin-x64.tgz", + "integrity": "sha512-iIvrqzsh1iJmVfqyYwLZBiuh0MkN1Suqniz9hBfmRmE6txMWhRVfigb9SMBiOkfCW1C4sjBwLCsCSzg11rvppQ==", "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -873,12 +876,13 @@ }, "node_modules/@openai/codex-linux-arm64": { "name": "@openai/codex", - "version": "0.114.0-linux-arm64", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-linux-arm64.tgz", - "integrity": "sha512-oUFZGZgMiEqmo85C+dfhckpVApH25alLWfwBgfKr2IRgdx/tovy8vN101f6kj01E6nDDe4LfJdNSZGtZht4fRA==", + "version": "0.118.0-linux-arm64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0-linux-arm64.tgz", + "integrity": "sha512-YKWmIqLBu9mmBhN3JHQNkLzk0BtAtV6LBPvhnL5eeHkNrChvA6PKrhsjy0O7wvRkiByZY/1dD14qVdAUfxcbiA==", "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -890,12 +894,13 @@ }, "node_modules/@openai/codex-linux-x64": { "name": "@openai/codex", - "version": "0.114.0-linux-x64", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-linux-x64.tgz", - "integrity": "sha512-MF6RhxfBoccccd5CYII2C7TL2TvYzombBQhanDZfQAajr6n7IuoazCmoHDlrFHS4AcSw9bYA4MRlrwEjbEjgsw==", + "version": "0.118.0-linux-x64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0-linux-x64.tgz", + "integrity": "sha512-vzU2d/gwAmZbf/DnwVzfQiNN3Ri04XpaZiJkHElIvGoqFbdrxRQFYTtslGDISYIO3o+POADZcFZIfamFsZj9yQ==", "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -907,12 +912,13 @@ }, "node_modules/@openai/codex-win32-arm64": { "name": "@openai/codex", - "version": "0.114.0-win32-arm64", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-win32-arm64.tgz", - "integrity": "sha512-CnRMHopj3en9aqQ2UaDW7EgpEGkxHdZVLLRq2cOy5D0HyuzF6Qb6595ADoFVJHEmPeN5Iz/KUbiGs5GLDjUwOA==", + "version": "0.118.0-win32-arm64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0-win32-arm64.tgz", + "integrity": "sha512-AU7GPVFqd0Ml3P2OXfy6K6TONcxfCZLUh1zjYkkoPGWJ4A3BVMkOmMP9CAdSiQsnU/RQfdV/9IGqo1xwUQDdjA==", "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -924,12 +930,13 @@ }, "node_modules/@openai/codex-win32-x64": { "name": "@openai/codex", - "version": "0.114.0-win32-x64", - "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-win32-x64.tgz", - "integrity": "sha512-ztRsH5Z+gPVZ5ZInx6HzXsTFFkuEdjk3Ay0UGVOhRRCWvevXQi/SL4eU8hwysCYrs8K/WRq3mo4c95w9zQ2wLw==", + "version": "0.118.0-win32-x64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.118.0-win32-x64.tgz", + "integrity": "sha512-9vKW1ANQxIUsLpiY0VsOM+1avZjqxDZgqgxKABJHWRlLMuaSykwXexf8Hqq+BnYFfmn0d6MjxTuE1UtVvg9caw==", "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1285,6 +1292,7 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1528,7 +1536,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, "license": "MIT", "dependencies": { "run-applescript": "^7.0.0" @@ -1686,7 +1693,6 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", - "dev": true, "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -1703,7 +1709,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -1716,7 +1721,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -1750,7 +1754,6 @@ "version": "8.0.3", "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -1936,6 +1939,7 @@ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -2290,7 +2294,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" @@ -2306,7 +2309,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", - "dev": true, "license": "MIT", "engines": { "node": ">=20" @@ -2319,7 +2321,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "license": "MIT", "dependencies": { "is-docker": "^3.0.0" @@ -2345,7 +2346,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -2579,7 +2579,6 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", - "dev": true, "license": "MIT", "dependencies": { "default-browser": "^5.4.0", @@ -2643,6 +2642,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2693,7 +2693,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", - "dev": true, "license": "MIT", "engines": { "node": ">=20" @@ -2894,7 +2893,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -2936,8 +2934,7 @@ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/send": { "version": "0.19.2", @@ -3201,6 +3198,7 @@ "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" @@ -3286,6 +3284,7 @@ "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -3437,7 +3436,6 @@ "version": "8.2.1", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz", "integrity": "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" @@ -3487,7 +3485,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.0.tgz", "integrity": "sha512-3sFIGLiaDP7rTO4xh3g+b3AzhYDIUGGywE/WsmqzJWDxus5aJXVnPTNC/6L+r2WzrwXqVOdD262OaO+cEyPMSQ==", - "dev": true, "license": "MIT", "dependencies": { "is-wsl": "^3.1.0", @@ -3504,8 +3501,8 @@ "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index d5371c63..7fa0ebaf 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "license": "ISC", "type": "module", "devDependencies": { + "@openai/codex": "^0.118.0", "esbuild": "^0.25.0", "@types/node": "^24.10.1", "mcp-hello-world": "^1.1.2", diff --git a/src/CodexAcpClient.ts b/src/CodexAcpClient.ts index 8451ffd0..47d76716 100644 --- a/src/CodexAcpClient.ts +++ b/src/CodexAcpClient.ts @@ -4,6 +4,7 @@ import * as acp from "@agentclientprotocol/sdk"; import {type McpServer, RequestError} from "@agentclientprotocol/sdk"; import type {ApprovalHandler, CodexAppServerClient} from "./CodexAppServerClient"; import open from "open"; +import type {Disposable} from "vscode-jsonrpc"; import type { ClientInfo, ReasoningEffort, @@ -15,6 +16,8 @@ import {AgentMode} from "./AgentMode"; import path from "node:path"; import {logger} from "./Logger"; import type { + AccountLoginCompletedNotification, + AccountUpdatedNotification, GetAccountResponse, ListMcpServerStatusParams, ListMcpServerStatusResponse, @@ -34,11 +37,12 @@ import type {AuthenticationLogoutResponse, AuthenticationStatusResponse} from ". * Converts ACP requests into corresponding app-server operations. */ export class CodexAcpClient { - private readonly codexClient: CodexAppServerClient; private readonly config: JsonObject; private readonly modelProvider: string | null; private gatewayConfig: GatewayConfig | null; + private pendingLoginCompleted: Promise | null = null; + private pendingAccountUpdated: Promise | null = null; constructor(codexClient: CodexAppServerClient, codexConfig?: JsonObject, modelProvider?: string) { @@ -69,19 +73,27 @@ export class CodexAcpClient { } switch (authRequest.methodId) { - case "api-key": + case "api-key": { if (!authRequest._meta || !authRequest._meta["api-key"]) throw RequestError.invalidRequest(); + const loginCompletedPromise = this.awaitNextLoginCompleted(); await this.codexClient.accountLogin({ type: "apiKey", apiKey: authRequest._meta["api-key"].apiKey }); - break; - case "chat-gpt": + this.gatewayConfig = null; + const result = await loginCompletedPromise; + return result.success; + } + case "chat-gpt": { + const loginCompletedPromise = this.awaitNextLoginCompleted(); const loginResponse = await this.codexClient.accountLogin({type: "chatgpt"}); if (loginResponse.type == "chatgpt") { await open(loginResponse.authUrl); } - break; + this.gatewayConfig = null; + const result = await loginCompletedPromise; + return result.success; + } case "gateway": if (!authRequest._meta) throw RequestError.invalidRequest(); @@ -111,9 +123,7 @@ export class CodexAcpClient { // Reset the gateway config to null if another authentication method was used this.gatewayConfig = null; - - const result = await this.codexClient.awaitLoginCompleted() - return result.success; + return false; } @@ -154,8 +164,9 @@ export class CodexAcpClient { } async logout(): Promise { + const accountUpdatedPromise = this.awaitNextAccountUpdated(); await this.codexClient.accountLogout(); - await this.codexClient.awaitAccountUpdated(); + await accountUpdatedPromise; return {}; } @@ -259,9 +270,13 @@ export class CodexAcpClient { }; } - async awaitMcpServers(): Promise>{ - const response = await this.codexClient.awaitMcpStartup(); - return response.ready; + async awaitMcpStartup(mcpStartupVersion: number): Promise> { + const startup = await this.codexClient.awaitMcpStartup(mcpStartupVersion); + return startup.ready; + } + + getMcpStartupCompleteVersion(): number { + return this.codexClient.getMcpStartupCompleteVersion(); } private createSessionConfig(projectPath: string, mcpServers: Array): JsonObject { @@ -380,6 +395,49 @@ export class CodexAcpClient { return this.codexClient.listSkills(params ?? {}); } + private async awaitNextLoginCompleted(): Promise { + if (this.pendingLoginCompleted !== null) { + return await this.pendingLoginCompleted; + } + this.pendingLoginCompleted = this.awaitSingleNotification( + "account/login/completed", + (event: AccountLoginCompletedNotification) => event, + ); + try { + return await this.pendingLoginCompleted; + } finally { + this.pendingLoginCompleted = null; + } + } + + private async awaitNextAccountUpdated(): Promise { + if (this.pendingAccountUpdated !== null) { + return await this.pendingAccountUpdated; + } + this.pendingAccountUpdated = this.awaitSingleNotification( + "account/updated", + (event: AccountUpdatedNotification) => event, + ); + try { + return await this.pendingAccountUpdated; + } finally { + this.pendingAccountUpdated = null; + } + } + + private async awaitSingleNotification( + method: "account/login/completed" | "account/updated", + mapEvent: (event: T) => T, + ): Promise { + return await new Promise((resolve) => { + let disposable: Disposable | undefined; + disposable = this.codexClient.connection.onNotification(method, (event: T) => { + disposable?.dispose(); + resolve(mapEvent(event)); + }); + }); + } + async listMcpServers(params: ListMcpServerStatusParams = { cursor: null, limit: null }): Promise { return this.codexClient.listMcpServerStatus(params); } diff --git a/src/CodexAcpServer.ts b/src/CodexAcpServer.ts index 24e916fd..3b695fa1 100644 --- a/src/CodexAcpServer.ts +++ b/src/CodexAcpServer.ts @@ -10,7 +10,7 @@ import {CodexApprovalHandler} from "./CodexApprovalHandler"; import {CodexAuthMethods, type CodexAuthRequest} from "./CodexAuthMethod"; import {CodexAcpClient, type SessionMetadata, type SessionMetadataWithThread} from "./CodexAcpClient"; import {ACPSessionConnection, type UpdateSessionEvent} from "./ACPSessionConnection"; -import type {Account, CollabAgentToolCallStatus, Model, RateLimitSnapshot, Thread, ThreadItem, UserInput, ReasoningEffortOption} from "./app-server/v2"; +import type {Account, CollabAgentToolCallStatus, Model, Thread, ThreadItem, UserInput, ReasoningEffortOption} from "./app-server/v2"; import type {RateLimitsMap} from "./RateLimitsMap"; import type {InputModality, ReasoningEffort} from "./app-server"; import {ModelId} from "./ModelId"; @@ -127,7 +127,7 @@ export class CodexAcpServer implements acp.Agent { async getOrCreateSession(request: acp.NewSessionRequest | acp.ResumeSessionRequest): Promise<[SessionId, SessionModelState, SessionModeState]> { await this.checkAuthorization(); - const pendingMcpServers: Promise> = this.codexAcpClient.awaitMcpServers(); + const mcpStartupVersion = this.codexAcpClient.getMcpStartupCompleteVersion(); let sessionMetadata: SessionMetadata; if ("sessionId" in request) { @@ -140,8 +140,7 @@ export class CodexAcpServer implements acp.Agent { const accountResponse = await this.runWithProcessCheck(() => this.codexAcpClient.getAccount()); const {sessionId, currentModelId, models} = sessionMetadata; - logger.log(`Waiting MCP servers to start...`) - const sessionMcpServers = await pendingMcpServers; + const sessionMcpServers = await this.resolveSessionMcpServers(request.mcpServers ?? [], mcpStartupVersion, "sessionId" in request); const currentModel = this.findCurrentModel(models, currentModelId); const sessionState: SessionState = { sessionId: sessionId, @@ -332,7 +331,7 @@ export class CodexAcpServer implements acp.Agent { thread: Thread; }> { await this.checkAuthorization(); - const pendingMcpServers: Promise> = this.codexAcpClient.awaitMcpServers(); + const mcpStartupVersion = this.codexAcpClient.getMcpStartupCompleteVersion(); logger.log(`Load existing session: ${request.sessionId}...`); const sessionMetadata: SessionMetadataWithThread = await this.runWithProcessCheck(() => @@ -341,8 +340,7 @@ export class CodexAcpServer implements acp.Agent { const accountResponse = await this.runWithProcessCheck(() => this.codexAcpClient.getAccount()); const {sessionId, currentModelId, models, thread} = sessionMetadata; - logger.log("Waiting MCP servers to start..."); - const sessionMcpServers = await pendingMcpServers; + const sessionMcpServers = await this.resolveSessionMcpServers(request.mcpServers ?? [], mcpStartupVersion, true); const currentModel = this.findCurrentModel(models, currentModelId); const sessionState: SessionState = { sessionId: sessionId, @@ -389,6 +387,8 @@ export class CodexAcpServer implements acp.Agent { switch (item.type) { case "userMessage": return this.createUserMessageUpdates(item); + case "hookPrompt": + return []; case "agentMessage": return [{ sessionUpdate: "agent_message_chunk", @@ -601,6 +601,26 @@ export class CodexAcpServer implements acp.Agent { return sessionState; } + private async resolveSessionMcpServers( + mcpServers: Array, + mcpStartupVersion: number, + recoverFromStartup: boolean, + ): Promise> { + // Explicit MCP servers from the request are the primary source of truth for the session. + const requestedServerNames = getRequestedMcpServerNames(mcpServers); + if (requestedServerNames.length > 0) { + return requestedServerNames; + } + // Fresh sessions without MCP config should not inherit any session MCP state. + if (!recoverFromStartup) { + return []; + } + // loadSession/resumeSession may omit mcpServers; in that case recover the ready names + // from the startup event associated with this thread start/resume checkpoint. + logger.log("Recovering MCP servers from startup state..."); + return await this.runWithProcessCheck(() => this.codexAcpClient.awaitMcpStartup(mcpStartupVersion)); + } + async prompt(params: acp.PromptRequest): Promise { logger.log("Prompt received", { sessionId: params.sessionId, @@ -747,3 +767,7 @@ export class CodexAcpServer implements acp.Agent { } } } + +function getRequestedMcpServerNames(mcpServers: Array): Array { + return Array.from(new Set(mcpServers.map(server => server.name))); +} diff --git a/src/CodexAppServerClient.ts b/src/CodexAppServerClient.ts index c091c2e0..d9c9fda0 100644 --- a/src/CodexAppServerClient.ts +++ b/src/CodexAppServerClient.ts @@ -1,8 +1,9 @@ import {type MessageConnection, RequestType} from "vscode-jsonrpc/node"; import type { - ClientRequest, ConversationId, + ClientRequest, InitializeParams, - InitializeResponse, McpStartupCompleteEvent, + InitializeResponse, + McpStartupCompleteEvent, ServerNotification } from "./app-server"; import type { @@ -52,11 +53,6 @@ const FileChangeApprovalRequest = new RequestType< void >('item/fileChange/requestApproval'); -/** - * Poorly supported/deprecated event types - */ -export type McpStartupCompleteNotification = { method: "codex/event/mcp_startup_complete", params: { id?: string, msg: McpStartupCompleteEvent & { type:"mcp_startup_complete" }, conversationId?: ConversationId } } - /** * A type-safe client over the Codex App Server's JSON-RPC API. * Maps each request to its expected response and exposes clear, typed methods for supported JSON-RPC operations. @@ -64,16 +60,27 @@ export type McpStartupCompleteNotification = { method: "codex/event/mcp_startup_ export class CodexAppServerClient { readonly connection: MessageConnection; private approvalHandlers = new Map(); + private mcpStartupCompleteVersion = 0; + private lastMcpStartupComplete: McpStartupCompleteEvent | null = null; + private readonly mcpStartupCompleteResolvers: Array> = []; constructor(connection: MessageConnection) { this.connection = connection; this.connection.onUnhandledNotification((data) => { - const serverNotification = data as ServerNotification ?? null; - if (serverNotification) { - this.notify(serverNotification); + if (isMcpStartupCompleteNotification(data)) { + this.mcpStartupCompleteVersion += 1; + this.lastMcpStartupComplete = data.params.msg; + this.resolveSignal(data.params.msg, this.mcpStartupCompleteVersion, this.mcpStartupCompleteResolvers); + for (const callback of this.codexEventHandlers) { + callback({ eventType: "notification", ...data }); + } + return; } + + const serverNotification = data as ServerNotification; + this.notify(serverNotification); for (const callback of this.codexEventHandlers) { - callback({ eventType: "notification", ...serverNotification}); + callback({ eventType: "notification", ...serverNotification }); } }); @@ -146,28 +153,17 @@ export class CodexAppServerClient { return await this.sendRequest({ method: "config/read", params: params }); } - async awaitLoginCompleted(): Promise { - return await new Promise((resolve) => { - this.connection.onNotification("account/login/completed", (event: AccountLoginCompletedNotification) => { - resolve(event); - }); - }); + getMcpStartupCompleteVersion(): number { + return this.mcpStartupCompleteVersion; } - async awaitAccountUpdated(): Promise { - return await new Promise((resolve) => { - this.connection.onNotification("account/updated", (event: AccountUpdatedNotification) => { - resolve(event); - }); - }); - } - - async awaitMcpStartup(): Promise { - return await new Promise((resolve) => { - this.connection.onNotification("codex/event/mcp_startup_complete", (event: McpStartupCompleteNotification["params"]) => { - resolve(event.msg); - }); - }); + async awaitMcpStartup(afterVersion: number): Promise { + return await this.awaitSignal( + this.lastMcpStartupComplete, + this.mcpStartupCompleteVersion, + afterVersion, + this.mcpStartupCompleteResolvers + ); } async accountRead(params: GetAccountParams): Promise { @@ -211,6 +207,36 @@ export class CodexAppServerClient { } } + private resolveSignal( + event: T, + version: number, + resolvers: Array> + ): void { + const pendingResolvers: Array> = []; + for (const resolver of resolvers) { + if (resolver.afterVersion < version) { + resolver.resolve(event); + } else { + pendingResolvers.push(resolver); + } + } + resolvers.splice(0, resolvers.length, ...pendingResolvers); + } + + private async awaitSignal( + lastEvent: T | null, + currentVersion: number, + afterVersion: number, + resolvers: Array> + ): Promise { + if (lastEvent !== null && currentVersion > afterVersion) { + return lastEvent; + } + return await new Promise((resolve) => { + resolvers.push({afterVersion, resolve}); + }); + } + private async sendRequest(request: CodexRequest): Promise { for (const callback of this.codexEventHandlers) { callback({ eventType: "request", ...request}); @@ -229,10 +255,32 @@ export class CodexAppServerClient { } } -export type CodexConnectionEvent = { eventType: "request" } & CodexRequest | { eventType: "response" } & unknown | { eventType: "notification" } & ServerNotification; +export type CodexConnectionEvent = + | ({ eventType: "request" } & CodexRequest) + | ({ eventType: "response" } & unknown) + | ({ eventType: "notification" } & (ServerNotification | McpStartupCompleteNotification)); type CodexRequest = DistributiveOmit type DistributiveOmit = T extends any ? Omit : never; + +type SignalResolver = { + afterVersion: number; + resolve: (event: T) => void; +}; + +type McpStartupCompleteNotification = { + method: "codex/event/mcp_startup_complete", + params: { + msg: McpStartupCompleteEvent & { type: "mcp_startup_complete" } + } +}; + +function isMcpStartupCompleteNotification(value: unknown): value is McpStartupCompleteNotification { + return typeof value === "object" + && value !== null + && "method" in value + && value.method === "codex/event/mcp_startup_complete"; +} diff --git a/src/CodexEventHandler.ts b/src/CodexEventHandler.ts index 89e88de7..00e27310 100644 --- a/src/CodexEventHandler.ts +++ b/src/CodexEventHandler.ts @@ -89,6 +89,8 @@ export class CodexEventHandler { case "item/commandExecution/outputDelta": return this.createCommandOutputDeltaEvent(notification.params); case "command/exec/outputDelta": + case "item/autoApprovalReview/started": + case "item/autoApprovalReview/completed": case "hook/started": case "hook/completed": return null; @@ -102,6 +104,8 @@ export class CodexEventHandler { case "item/mcpToolCall/progress": case "serverRequest/resolved": case "account/updated": + case "fs/changed": + case "mcpServer/startupStatus/updated": return null; case "account/rateLimits/updated": this.handleRateLimitsUpdated(notification.params); @@ -123,6 +127,7 @@ export class CodexEventHandler { case "thread/closed": case "thread/realtime/started": case "thread/realtime/itemAdded": + case "thread/realtime/transcriptUpdated": case "thread/realtime/outputAudio/delta": case "thread/realtime/error": case "thread/realtime/closed": @@ -189,6 +194,7 @@ export class CodexEventHandler { return await createDynamicToolCallUpdate(event.item); case "collabAgentToolCall": case "userMessage": + case "hookPrompt": case "agentMessage": case "reasoning": case "webSearch": @@ -226,6 +232,7 @@ export class CodexEventHandler { } case "collabAgentToolCall": case "userMessage": + case "hookPrompt": case "agentMessage": case "webSearch": case "imageView": diff --git a/src/__tests__/CodexACPAgent/CodexAcpClient.test.ts b/src/__tests__/CodexACPAgent/CodexAcpClient.test.ts index a8179e7b..94883384 100644 --- a/src/__tests__/CodexACPAgent/CodexAcpClient.test.ts +++ b/src/__tests__/CodexACPAgent/CodexAcpClient.test.ts @@ -30,7 +30,27 @@ async function overrideCodexHome(configToml: string, run: () => Promise): } else { process.env[CODEX_HOME_ENV] = previousCodexHome; } - fs.rmSync(codexHome, { recursive: true, force: true }); + await removeDirectoryWithRetry(codexHome); + } +} + +async function removeDirectoryWithRetry(directory: string): Promise { + let lastError: NodeJS.ErrnoException | null = null; + for (let attempt = 0; attempt < 5; attempt += 1) { + try { + fs.rmSync(directory, { recursive: true, force: true }); + return; + } catch (error) { + const err = error as NodeJS.ErrnoException; + if (err.code !== "ENOTEMPTY" && err.code !== "EBUSY") { + throw err; + } + lastError = err; + await new Promise((resolve) => setTimeout(resolve, 50 * (attempt + 1))); + } + } + if (lastError) { + throw lastError; } } @@ -42,7 +62,7 @@ describe('ACP server test', { timeout: 40_000 }, () => { vi.clearAllMocks(); }); - const ignoredFields = ["thread", "cwd", "id", "createdAt", "path", "threadId", "userAgent", "sandbox", "conversationId", "origins", "supportedReasoningEfforts", "reasoningEffort", "model", "readOnlyAccess"]; + const ignoredFields = ["thread", "cwd", "id", "createdAt", "path", "threadId", "userAgent", "sandbox", "conversationId", "origins", "supportedReasoningEfforts", "reasoningEffort", "model", "readOnlyAccess", "approvalsReviewer"]; it.skip('should start conversation', async () => { const codexAcpAgent = fixture.getCodexAcpAgent(); @@ -95,9 +115,51 @@ describe('ACP server test', { timeout: 40_000 }, () => { const newSessionResponse = await codexAcpAgent.newSession({cwd: "", mcpServers: []}); expect(newSessionResponse.sessionId).toBeDefined() - const transportDump = keyFixture.getCodexConnectionDump([...ignoredFields, "upgrade"]); - await expect(transportDump).toMatchFileSnapshot("data/auth-with-key.json"); - + const transportEvents = keyFixture.getCodexConnectionEvents([...ignoredFields, "upgrade"]); + const transportMethods = transportEvents.flatMap(event => "method" in event ? [event.method] : []); + const loginRequest = transportEvents.find(event => + event.eventType === "request" && + "method" in event && + event.method === "account/login/start" + ); + const loginResponse = transportEvents.find(event => + event.eventType === "response" && + "type" in event && + event.type === "apiKey" + ); + const threadStartResponse = transportEvents.find(event => + event.eventType === "response" && + "modelProvider" in event && + "approvalPolicy" in event + ); + expect(transportMethods).toEqual([ + "account/login/start", + "account/read", + "account/updated", + "thread/start", + "model/list", + "thread/started", + "account/read", + "skills/list", + ]); + expect(loginRequest).toEqual({ + eventType: "request", + method: "account/login/start", + params: { + type: "apiKey", + apiKey: "TOKEN", + } + }); + expect(loginResponse).toEqual({ + eventType: "response", + type: "apiKey", + }); + expect(threadStartResponse).toMatchObject({ + eventType: "response", + modelProvider: "openai", + approvalPolicy: "on-request", + approvalsReviewer: "approvalsReviewer", + }); const authenticatedResponse = await keyFixture.getCodexAcpAgent().extMethod("authentication/status", {}); expect(authenticatedResponse).toEqual({type: "api-key"}); @@ -108,31 +170,34 @@ describe('ACP server test', { timeout: 40_000 }, () => { }); it('should authenticate with a gateway', async () => { - const codexAcpAgent = fixture.getCodexAcpAgent(); - - await codexAcpAgent.initialize({protocolVersion: 1}); - await fixture.getCodexAcpClient().logout(); + await overrideCodexHome('cli_auth_credentials_store = "file"', async () => { + const gatewayFixture = createTestFixture(); + const codexAcpAgent = gatewayFixture.getCodexAcpAgent(); - const authRequest: CodexAuthRequest = { - methodId: "gateway", - _meta: { - "gateway": { - baseUrl: "https://www.example.com", - headers: { - "Custom-Auth-Header": "TOKEN" + await codexAcpAgent.initialize({protocolVersion: 1}); + await gatewayFixture.getCodexAcpClient().logout(); + + const authRequest: CodexAuthRequest = { + methodId: "gateway", + _meta: { + "gateway": { + baseUrl: "https://www.example.com", + headers: { + "Custom-Auth-Header": "TOKEN" + } } } - } - }; + }; - await codexAcpAgent.authenticate(authRequest); - expect(await fixture.getCodexAcpClient().authRequired()).toBe(false); + await codexAcpAgent.authenticate(authRequest); + expect(await gatewayFixture.getCodexAcpClient().authRequired()).toBe(false); - const authenticatedResponse = await fixture.getCodexAcpAgent().extMethod("authentication/status", {}); - expect(authenticatedResponse).toEqual({type: "gateway", name: "custom-gateway"}); + const authenticatedResponse = await gatewayFixture.getCodexAcpAgent().extMethod("authentication/status", {}); + expect(authenticatedResponse).toEqual({type: "gateway", name: "custom-gateway"}); - const newSessionResponse = await codexAcpAgent.newSession({cwd: "", mcpServers: []}); - expect(newSessionResponse.sessionId).toBeDefined() + const newSessionResponse = await codexAcpAgent.newSession({cwd: "", mcpServers: []}); + expect(newSessionResponse.sessionId).toBeDefined() + }); }) it('prefetches session additional skill roots before thread start', async () => { @@ -188,6 +253,30 @@ describe('ACP server test', { timeout: 40_000 }, () => { expect(listSkillsSpy.mock.invocationCallOrder[0]!).toBeLessThan(threadStartSpy.mock.invocationCallOrder[0]!); }); + it('waits for mcp startup completion and returns ready servers', async () => { + const mockFixture = createCodexMockTestFixture(); + const codexAcpClient = mockFixture.getCodexAcpClient(); + const codexAppServerClient = mockFixture.getCodexAppServerClient(); + + const startupPromise = codexAcpClient.awaitMcpStartup(codexAppServerClient.getMcpStartupCompleteVersion()); + + mockFixture.sendServerNotification({ + method: "codex/event/mcp_startup_complete", + params: { + msg: { + type: "mcp_startup_complete", + ready: ["alpha", "beta"], + failed: [], + cancelled: [], + } + } + }); + + const mcpServers = await startupPromise; + + expect(mcpServers).toEqual(["alpha", "beta"]); + }); + it('prefetches session additional skill roots before turn start', async () => { const mockFixture = createCodexMockTestFixture(); const codexAcpAgent = mockFixture.getCodexAcpAgent(); diff --git a/src/__tests__/CodexACPAgent/command-action-events.test.ts b/src/__tests__/CodexACPAgent/command-action-events.test.ts index 6e4456a7..c697d980 100644 --- a/src/__tests__/CodexACPAgent/command-action-events.test.ts +++ b/src/__tests__/CodexACPAgent/command-action-events.test.ts @@ -31,6 +31,7 @@ describe('CodexEventHandler - command action events', () => { command: 'ls /test/project', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [ { @@ -65,6 +66,7 @@ describe('CodexEventHandler - command action events', () => { command: 'ls', cwd: '/test/project', processId: null, + source: 'agent', status: 'completed', commandActions: [ { @@ -99,6 +101,7 @@ describe('CodexEventHandler - command action events', () => { command: 'rg "Service" src', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [ { @@ -134,6 +137,7 @@ describe('CodexEventHandler - command action events', () => { command: 'rg "Service"', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [ { @@ -169,6 +173,7 @@ describe('CodexEventHandler - command action events', () => { command: 'rg --files -g "*service*"', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [ { @@ -204,6 +209,7 @@ describe('CodexEventHandler - command action events', () => { command: 'rg', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [ { diff --git a/src/__tests__/CodexACPAgent/data/auth-with-key.json b/src/__tests__/CodexACPAgent/data/auth-with-key.json index b9a34c96..751ccde8 100644 --- a/src/__tests__/CodexACPAgent/data/auth-with-key.json +++ b/src/__tests__/CodexACPAgent/data/auth-with-key.json @@ -232,4 +232,4 @@ "eventType": "request", "method": "skills/list", "params": {} -} \ No newline at end of file +} diff --git a/src/__tests__/CodexACPAgent/fuzzy-file-search-events.test.ts b/src/__tests__/CodexACPAgent/fuzzy-file-search-events.test.ts index e1e870af..02d8561c 100644 --- a/src/__tests__/CodexACPAgent/fuzzy-file-search-events.test.ts +++ b/src/__tests__/CodexACPAgent/fuzzy-file-search-events.test.ts @@ -31,8 +31,8 @@ describe("CodexEventHandler - fuzzy file search events", () => { sessionId: "search-1", query: "event handler", files: [ - { root: "/repo", path: "src/CodexEventHandler.ts", file_name: "CodexEventHandler.ts", score: 0.98, indices: [0, 1] }, - { root: "/repo", path: "src/CodexToolCallMapper.ts", file_name: "CodexToolCallMapper.ts", score: 0.85, indices: [2, 3] }, + { root: "/repo", path: "src/CodexEventHandler.ts", match_type: "file", file_name: "CodexEventHandler.ts", score: 0.98, indices: [0, 1] }, + { root: "/repo", path: "src/CodexToolCallMapper.ts", match_type: "file", file_name: "CodexToolCallMapper.ts", score: 0.85, indices: [2, 3] }, ], }, }; @@ -42,7 +42,7 @@ describe("CodexEventHandler - fuzzy file search events", () => { sessionId: "search-1", query: "event handler", files: [ - { root: "/repo", path: "src/CodexEventHandler.ts", file_name: "CodexEventHandler.ts", score: 0.99, indices: [0, 1] }, + { root: "/repo", path: "src/CodexEventHandler.ts", match_type: "file", file_name: "CodexEventHandler.ts", score: 0.99, indices: [0, 1] }, ], }, }; diff --git a/src/__tests__/CodexACPAgent/list-sessions.test.ts b/src/__tests__/CodexACPAgent/list-sessions.test.ts index 32390314..ac2a9f6e 100644 --- a/src/__tests__/CodexACPAgent/list-sessions.test.ts +++ b/src/__tests__/CodexACPAgent/list-sessions.test.ts @@ -65,6 +65,20 @@ describe("CodexACPAgent - list sessions", () => { }; const response = await codexAcpAgent.unstable_listSessions(params); + expect(codexAppServerClient.threadList).toHaveBeenCalledWith(expect.objectContaining({ + sourceKinds: [ + "cli", + "vscode", + "exec", + "appServer", + "subAgent", + "subAgentReview", + "subAgentCompact", + "subAgentThreadSpawn", + "subAgentOther", + "unknown", + ], + })); await expect(JSON.stringify(response, null, 2)).toMatchFileSnapshot( "data/list-sessions.json" ); diff --git a/src/__tests__/CodexACPAgent/load-session.test.ts b/src/__tests__/CodexACPAgent/load-session.test.ts index 9be09697..951cb86e 100644 --- a/src/__tests__/CodexACPAgent/load-session.test.ts +++ b/src/__tests__/CodexACPAgent/load-session.test.ts @@ -15,7 +15,7 @@ describe("CodexACPAgent - loadSession", () => { account: null, requiresOpenaiAuth: false, }); - codexAcpClient.awaitMcpServers = vi.fn().mockResolvedValue([]); + codexAcpClient.awaitMcpStartup = vi.fn().mockResolvedValue([]); codexAcpClient.listSkills = vi.fn().mockResolvedValue({ data: [] }); const model: Model = { @@ -76,6 +76,7 @@ describe("CodexACPAgent - loadSession", () => { id: "item-agent-1", text: "Hello!", phase: null, + memoryCitation: null, }, { type: "reasoning", @@ -89,6 +90,7 @@ describe("CodexACPAgent - loadSession", () => { command: "ls", cwd: "/test/project", processId: null, + source: "agent", status: "completed", commandActions: [], aggregatedOutput: null, @@ -161,4 +163,77 @@ describe("CodexACPAgent - loadSession", () => { "data/load-session-history.json" ); }); + + it("should recover session mcp servers during loadSession when request omits them", async () => { + const fixture = createCodexMockTestFixture(); + const codexAcpAgent = fixture.getCodexAcpAgent(); + const codexAcpClient = fixture.getCodexAcpClient(); + const codexAppServerClient = fixture.getCodexAppServerClient(); + + codexAcpClient.authRequired = vi.fn().mockResolvedValue(false); + codexAcpClient.getAccount = vi.fn().mockResolvedValue({ + account: null, + requiresOpenaiAuth: false, + }); + codexAcpClient.listSkills = vi.fn().mockResolvedValue({ data: [] }); + + const awaitMcpStartupSpy = vi.spyOn(codexAcpClient, "awaitMcpStartup").mockResolvedValue(["persisted-mcp"]); + + const model: Model = { + id: "gpt-5.2", + model: "gpt-5.2", + upgrade: null, + upgradeInfo: null, + availabilityNux: null, + displayName: "GPT-5.2", + description: "Test model", + hidden: false, + supportedReasoningEfforts: [{ reasoningEffort: "medium", description: "Medium" }], + defaultReasoningEffort: "medium", + inputModalities: ["text"], + supportsPersonality: false, + isDefault: true, + }; + + codexAppServerClient.listModels = vi.fn().mockResolvedValue({ + data: [model], + nextCursor: null, + }); + codexAppServerClient.threadResume = vi.fn().mockResolvedValue({ + thread: { + id: "session-1", + preview: "", + ephemeral: false, + modelProvider: "openai", + createdAt: 0, + updatedAt: 0, + status: { type: "idle" }, + path: null, + cwd: "/test/project", + cliVersion: "0.0.0", + source: "cli", + agentNickname: null, + agentRole: null, + gitInfo: null, + name: null, + turns: [], + }, + model: model.id, + modelProvider: "openai", + cwd: "/test/project", + approvalPolicy: "never", + sandbox: { type: "dangerFullAccess" }, + reasoningEffort: model.defaultReasoningEffort, + }); + + await codexAcpAgent.initialize({ protocolVersion: 1 }); + await codexAcpAgent.loadSession({ + sessionId: "session-1", + cwd: "/test/project", + mcpServers: [], + }); + + expect(awaitMcpStartupSpy).toHaveBeenCalledWith(0); + expect(codexAcpAgent.getSessionState("session-1").sessionMcpServers).toEqual(["persisted-mcp"]); + }); }); diff --git a/src/__tests__/CodexACPAgent/mcp-session.test.ts b/src/__tests__/CodexACPAgent/mcp-session.test.ts index fa5d223a..84865074 100644 --- a/src/__tests__/CodexACPAgent/mcp-session.test.ts +++ b/src/__tests__/CodexACPAgent/mcp-session.test.ts @@ -26,8 +26,8 @@ describe('MCP session configuration', { timeout: 40_000 }, () => { fixture.clearAcpConnectionDump(); await codexAcpAgent.prompt({sessionId: newSessionResponse.sessionId, prompt: [{type: "text", text: "/mcp"}]}); const transportDump = fixture.getAcpConnectionDump([]); - console.log(transportDump) - expect(transportDump).contain("Configured MCP servers:\\n- test-mcp"); + expect(transportDump).contain("Configured MCP servers:"); + expect(transportDump).contain("- test-mcp"); }); }); diff --git a/src/__tests__/CodexACPAgent/model-filtering.test.ts b/src/__tests__/CodexACPAgent/model-filtering.test.ts index 9cdc00ba..4499b370 100644 --- a/src/__tests__/CodexACPAgent/model-filtering.test.ts +++ b/src/__tests__/CodexACPAgent/model-filtering.test.ts @@ -82,7 +82,6 @@ describe("Model filtering", () => { models, }); vi.spyOn(codexAcpClient, "getAccount").mockResolvedValue({account: null, requiresOpenaiAuth: false}); - vi.spyOn(codexAcpClient, "awaitMcpServers").mockResolvedValue([]); const newSessionResponse = await codexAcpAgent.newSession({ cwd: "", mcpServers: [] }); const sessionModels = newSessionResponse.models; diff --git a/src/__tests__/CodexACPAgent/terminal-output-events.test.ts b/src/__tests__/CodexACPAgent/terminal-output-events.test.ts index e9063865..05a8fb26 100644 --- a/src/__tests__/CodexACPAgent/terminal-output-events.test.ts +++ b/src/__tests__/CodexACPAgent/terminal-output-events.test.ts @@ -31,6 +31,7 @@ describe('CodexEventHandler - terminal output events', () => { command: 'ls -la', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [], aggregatedOutput: null, @@ -67,6 +68,7 @@ describe('CodexEventHandler - terminal output events', () => { command, cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [], aggregatedOutput: null, @@ -114,6 +116,7 @@ describe('CodexEventHandler - terminal output events', () => { command: 'ls -la', cwd: '/test/project', processId: 'pid-456', + source: 'agent', status: 'completed', commandActions: [], aggregatedOutput: 'file1.txt\nfile2.txt\nfile3.txt\n', @@ -142,6 +145,7 @@ describe('CodexEventHandler - terminal output events', () => { command: 'cat nonexistent.txt', cwd: '/test/project', processId: 'pid-789', + source: 'agent', status: 'failed', commandActions: [], aggregatedOutput: 'cat: nonexistent.txt: No such file or directory', @@ -196,6 +200,7 @@ describe('CodexEventHandler - terminal output events', () => { command: 'echo hello', cwd: '/test/project', processId: null, + source: 'agent', status: 'inProgress', commandActions: [], aggregatedOutput: null, @@ -226,6 +231,7 @@ describe('CodexEventHandler - terminal output events', () => { command: 'echo hello', cwd: '/test/project', processId: 'pid-123', + source: 'agent', status: 'completed', commandActions: [], aggregatedOutput: 'hello\n', diff --git a/src/__tests__/acp-test-utils.ts b/src/__tests__/acp-test-utils.ts index c28dec2b..a25138b0 100644 --- a/src/__tests__/acp-test-utils.ts +++ b/src/__tests__/acp-test-utils.ts @@ -40,6 +40,7 @@ export interface TestFixture { getCodexAcpAgent(): CodexAcpServer, onCodexConnectionEvent(handler: (event: CodexConnectionEvent) => void): void, + getCodexConnectionEvents(ignoredFields: string[], options?: CodexConnectionDumpOptions): CodexConnectionEvent[], getCodexConnectionDump(ignoredFields: string[], options?: CodexConnectionDumpOptions): string, clearCodexConnectionDump(): void, @@ -90,11 +91,11 @@ export function createBaseTestFixture(config: ConnectionConfig): TestFixture { getCodexAcpClient(): CodexAcpClient { return codexAcpClient; }, - getCodexConnectionDump(ignoredFields: string[], options?: CodexConnectionDumpOptions): string { + getCodexConnectionEvents(ignoredFields: string[], options?: CodexConnectionDumpOptions): CodexConnectionEvent[] { const placeholderResponseMethods = new Set(options?.placeholderResponseMethods ?? []); const pendingRequestMethods: string[] = []; - const filteredEvents = transportEvents.flatMap((event) => { + return transportEvents.flatMap((event) => { switch (event.eventType) { case "request": pendingRequestMethods.push(event.method); @@ -105,14 +106,17 @@ export function createBaseTestFixture(config: ConnectionConfig): TestFixture { return [{ eventType: "response" as const, placeholder: requestMethod, - }]; + } as CodexConnectionEvent]; } break; } - return [event]; + return [anonymizeValue(event, [], new Set(ignoredFields)) as CodexConnectionEvent]; }); - return createArrayDump(filteredEvents, ignoredFields); + }, + getCodexConnectionDump(ignoredFields: string[], options?: CodexConnectionDumpOptions): string { + const filteredEvents = this.getCodexConnectionEvents(ignoredFields, options); + return createArrayDump(filteredEvents, []); }, onCodexConnectionEvent(handler: (event: CodexConnectionEvent) => void): void { codexEventHandlers.push(handler); @@ -154,7 +158,7 @@ export function createTestFixture(): TestFixture { } export interface CodexMockTestFixture extends TestFixture { - sendServerNotification(notification: ServerNotification): void, + sendServerNotification(notification: ServerNotification | Record): void, sendServerRequest(method: string, params: unknown): Promise, setPermissionResponse(response: RequestPermissionResponse): void, } @@ -210,7 +214,7 @@ export function createCodexMockTestFixture(): CodexMockTestFixture { return { ...baseFixture, - sendServerNotification(notification: ServerNotification): void { + sendServerNotification(notification: ServerNotification | Record): void { if (unhandledNotificationHandler) { unhandledNotificationHandler(notification); } @@ -229,34 +233,32 @@ export function createCodexMockTestFixture(): CodexMockTestFixture { } export function createObjectDump(obj: any, anonymizedFields: string[] = []) { - const fieldsToAnonymize = new Set(anonymizedFields); - - function anonymizeValue(value: any, path: string[]): any { - if (value === null || typeof value !== "object") { - return value; - } + return JSON.stringify(anonymizeValue(obj, [], new Set(anonymizedFields)), null, 2); +} - if (Array.isArray(value)) { - return value.map((item, index) => anonymizeValue(item, [...path, String(index)])); - } +export function createArrayDump(objects: any[], anonymizedFields: string[]): string { + return objects.map(event => createObjectDump(event, anonymizedFields)).join("\n"); +} - return Object.fromEntries( - Object.entries(value).map(([key, val]) => { - const nextPath = [...path, key]; - const pathKey = nextPath.join("."); - if (fieldsToAnonymize.has(key) || fieldsToAnonymize.has(pathKey)) { - return [key, key]; - } - return [key, anonymizeValue(val, nextPath)]; - }) - ); +function anonymizeValue(value: any, path: string[], fieldsToAnonymize: Set): any { + if (value === null || typeof value !== "object") { + return value; } - return JSON.stringify(anonymizeValue(obj, []), null, 2); -} + if (Array.isArray(value)) { + return value.map((item, index) => anonymizeValue(item, [...path, String(index)], fieldsToAnonymize)); + } -export function createArrayDump(objects: any[], anonymizedFields: string[]): string { - return objects.map(event => createObjectDump(event, anonymizedFields)).join("\n"); + return Object.fromEntries( + Object.entries(value).map(([key, val]) => { + const nextPath = [...path, key]; + const pathKey = nextPath.join("."); + if (fieldsToAnonymize.has(key) || fieldsToAnonymize.has(pathKey)) { + return [key, key]; + } + return [key, anonymizeValue(val, nextPath, fieldsToAnonymize)]; + }) + ); } /** diff --git a/src/app-server/AgentPath.ts b/src/app-server/AgentPath.ts new file mode 100644 index 00000000..6e55ce69 --- /dev/null +++ b/src/app-server/AgentPath.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AgentPath = string; diff --git a/src/app-server/ClientRequest.ts b/src/app-server/ClientRequest.ts index 5fa8f27b..e33a9863 100644 --- a/src/app-server/ClientRequest.ts +++ b/src/app-server/ClientRequest.ts @@ -16,10 +16,20 @@ import type { CommandExecWriteParams } from "./v2/CommandExecWriteParams"; import type { ConfigBatchWriteParams } from "./v2/ConfigBatchWriteParams"; import type { ConfigReadParams } from "./v2/ConfigReadParams"; import type { ConfigValueWriteParams } from "./v2/ConfigValueWriteParams"; +import type { ExperimentalFeatureEnablementSetParams } from "./v2/ExperimentalFeatureEnablementSetParams"; import type { ExperimentalFeatureListParams } from "./v2/ExperimentalFeatureListParams"; import type { ExternalAgentConfigDetectParams } from "./v2/ExternalAgentConfigDetectParams"; import type { ExternalAgentConfigImportParams } from "./v2/ExternalAgentConfigImportParams"; import type { FeedbackUploadParams } from "./v2/FeedbackUploadParams"; +import type { FsCopyParams } from "./v2/FsCopyParams"; +import type { FsCreateDirectoryParams } from "./v2/FsCreateDirectoryParams"; +import type { FsGetMetadataParams } from "./v2/FsGetMetadataParams"; +import type { FsReadDirectoryParams } from "./v2/FsReadDirectoryParams"; +import type { FsReadFileParams } from "./v2/FsReadFileParams"; +import type { FsRemoveParams } from "./v2/FsRemoveParams"; +import type { FsUnwatchParams } from "./v2/FsUnwatchParams"; +import type { FsWatchParams } from "./v2/FsWatchParams"; +import type { FsWriteFileParams } from "./v2/FsWriteFileParams"; import type { GetAccountParams } from "./v2/GetAccountParams"; import type { ListMcpServerStatusParams } from "./v2/ListMcpServerStatusParams"; import type { LoginAccountParams } from "./v2/LoginAccountParams"; @@ -27,12 +37,11 @@ import type { McpServerOauthLoginParams } from "./v2/McpServerOauthLoginParams"; import type { ModelListParams } from "./v2/ModelListParams"; import type { PluginInstallParams } from "./v2/PluginInstallParams"; import type { PluginListParams } from "./v2/PluginListParams"; +import type { PluginReadParams } from "./v2/PluginReadParams"; import type { PluginUninstallParams } from "./v2/PluginUninstallParams"; import type { ReviewStartParams } from "./v2/ReviewStartParams"; import type { SkillsConfigWriteParams } from "./v2/SkillsConfigWriteParams"; import type { SkillsListParams } from "./v2/SkillsListParams"; -import type { SkillsRemoteReadParams } from "./v2/SkillsRemoteReadParams"; -import type { SkillsRemoteWriteParams } from "./v2/SkillsRemoteWriteParams"; import type { ThreadArchiveParams } from "./v2/ThreadArchiveParams"; import type { ThreadCompactStartParams } from "./v2/ThreadCompactStartParams"; import type { ThreadForkParams } from "./v2/ThreadForkParams"; @@ -43,6 +52,7 @@ import type { ThreadReadParams } from "./v2/ThreadReadParams"; import type { ThreadResumeParams } from "./v2/ThreadResumeParams"; import type { ThreadRollbackParams } from "./v2/ThreadRollbackParams"; import type { ThreadSetNameParams } from "./v2/ThreadSetNameParams"; +import type { ThreadShellCommandParams } from "./v2/ThreadShellCommandParams"; import type { ThreadStartParams } from "./v2/ThreadStartParams"; import type { ThreadUnarchiveParams } from "./v2/ThreadUnarchiveParams"; import type { ThreadUnsubscribeParams } from "./v2/ThreadUnsubscribeParams"; @@ -54,4 +64,4 @@ import type { WindowsSandboxSetupStartParams } from "./v2/WindowsSandboxSetupSta /** * Request from the client to the server. */ -export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "plugin/uninstall", id: RequestId, params: PluginUninstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, }; +export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/shellCommand", id: RequestId, params: ThreadShellCommandParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "plugin/read", id: RequestId, params: PluginReadParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "fs/readFile", id: RequestId, params: FsReadFileParams, } | { "method": "fs/writeFile", id: RequestId, params: FsWriteFileParams, } | { "method": "fs/createDirectory", id: RequestId, params: FsCreateDirectoryParams, } | { "method": "fs/getMetadata", id: RequestId, params: FsGetMetadataParams, } | { "method": "fs/readDirectory", id: RequestId, params: FsReadDirectoryParams, } | { "method": "fs/remove", id: RequestId, params: FsRemoveParams, } | { "method": "fs/copy", id: RequestId, params: FsCopyParams, } | { "method": "fs/watch", id: RequestId, params: FsWatchParams, } | { "method": "fs/unwatch", id: RequestId, params: FsUnwatchParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "plugin/uninstall", id: RequestId, params: PluginUninstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "experimentalFeature/enablement/set", id: RequestId, params: ExperimentalFeatureEnablementSetParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, }; diff --git a/src/app-server/FuzzyFileSearchMatchType.ts b/src/app-server/FuzzyFileSearchMatchType.ts new file mode 100644 index 00000000..60e92f92 --- /dev/null +++ b/src/app-server/FuzzyFileSearchMatchType.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FuzzyFileSearchMatchType = "file" | "directory"; diff --git a/src/app-server/FuzzyFileSearchResult.ts b/src/app-server/FuzzyFileSearchResult.ts index e841dbfa..0ff6bf45 100644 --- a/src/app-server/FuzzyFileSearchResult.ts +++ b/src/app-server/FuzzyFileSearchResult.ts @@ -1,8 +1,9 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { FuzzyFileSearchMatchType } from "./FuzzyFileSearchMatchType"; /** * Superset of [`codex_file_search::FileMatch`] */ -export type FuzzyFileSearchResult = { root: string, path: string, file_name: string, score: number, indices: Array | null, }; +export type FuzzyFileSearchResult = { root: string, path: string, match_type: FuzzyFileSearchMatchType, file_name: string, score: number, indices: Array | null, }; diff --git a/src/app-server/InitializeCapabilities.ts b/src/app-server/InitializeCapabilities.ts index a6ac24ef..125b4b1f 100644 --- a/src/app-server/InitializeCapabilities.ts +++ b/src/app-server/InitializeCapabilities.ts @@ -12,6 +12,6 @@ export type InitializeCapabilities = { experimentalApi: boolean, /** * Exact notification method names that should be suppressed for this - * connection (for example `codex/event/session_configured`). + * connection (for example `thread/started`). */ optOutNotificationMethods?: Array | null, }; diff --git a/src/app-server/InitializeResponse.ts b/src/app-server/InitializeResponse.ts index 8a6bec66..c1d0a822 100644 --- a/src/app-server/InitializeResponse.ts +++ b/src/app-server/InitializeResponse.ts @@ -1,5 +1,20 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "./AbsolutePathBuf"; -export type InitializeResponse = { userAgent: string, }; +export type InitializeResponse = { userAgent: string, +/** + * Absolute path to the server's $CODEX_HOME directory. + */ +codexHome: AbsolutePathBuf, +/** + * Platform family for the running app-server target, for example + * `"unix"` or `"windows"`. + */ +platformFamily: string, +/** + * Operating system for the running app-server target, for example + * `"macos"`, `"linux"`, or `"windows"`. + */ +platformOs: string, }; diff --git a/src/app-server/PlanType.ts b/src/app-server/PlanType.ts index 9f622d0f..ad5bcab3 100644 --- a/src/app-server/PlanType.ts +++ b/src/app-server/PlanType.ts @@ -2,4 +2,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type PlanType = "free" | "go" | "plus" | "pro" | "team" | "business" | "enterprise" | "edu" | "unknown"; +export type PlanType = "free" | "go" | "plus" | "pro" | "team" | "self_serve_business_usage_based" | "business" | "enterprise_cbp_usage_based" | "enterprise" | "edu" | "unknown"; diff --git a/src/app-server/RealtimeConversationVersion.ts b/src/app-server/RealtimeConversationVersion.ts new file mode 100644 index 00000000..cedc4bbe --- /dev/null +++ b/src/app-server/RealtimeConversationVersion.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RealtimeConversationVersion = "v1" | "v2"; diff --git a/src/app-server/ResponseItem.ts b/src/app-server/ResponseItem.ts index dc424859..e9ab2a84 100644 --- a/src/app-server/ResponseItem.ts +++ b/src/app-server/ResponseItem.ts @@ -2,7 +2,7 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { ContentItem } from "./ContentItem"; -import type { FunctionCallOutputPayload } from "./FunctionCallOutputPayload"; +import type { FunctionCallOutputBody } from "./FunctionCallOutputBody"; import type { GhostCommit } from "./GhostCommit"; import type { LocalShellAction } from "./LocalShellAction"; import type { LocalShellStatus } from "./LocalShellStatus"; @@ -15,4 +15,4 @@ export type ResponseItem = { "type": "message", role: string, content: Array | null, * Optional additional permissions requested for this command. */ additionalPermissions?: AdditionalPermissionProfile | null, -/** - * Optional skill metadata when the approval was triggered by a skill script. - */ -skillMetadata?: CommandExecutionRequestApprovalSkillMetadata | null, /** * Optional proposed execpolicy amendment to allow similar commands without prompting. */ diff --git a/src/app-server/v2/CommandExecutionSource.ts b/src/app-server/v2/CommandExecutionSource.ts new file mode 100644 index 00000000..9432841f --- /dev/null +++ b/src/app-server/v2/CommandExecutionSource.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CommandExecutionSource = "agent" | "userShell" | "unifiedExecStartup" | "unifiedExecInteraction"; diff --git a/src/app-server/v2/Config.ts b/src/app-server/v2/Config.ts index fb5d6ecb..508fe84e 100644 --- a/src/app-server/v2/Config.ts +++ b/src/app-server/v2/Config.ts @@ -9,10 +9,15 @@ import type { Verbosity } from "../Verbosity"; import type { WebSearchMode } from "../WebSearchMode"; import type { JsonValue } from "../serde_json/JsonValue"; import type { AnalyticsConfig } from "./AnalyticsConfig"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { ProfileV2 } from "./ProfileV2"; import type { SandboxMode } from "./SandboxMode"; import type { SandboxWorkspaceWrite } from "./SandboxWorkspaceWrite"; import type { ToolsV2 } from "./ToolsV2"; -export type Config = {model: string | null, review_model: string | null, model_context_window: bigint | null, model_auto_compact_token_limit: bigint | null, model_provider: string | null, approval_policy: AskForApproval | null, sandbox_mode: SandboxMode | null, sandbox_workspace_write: SandboxWorkspaceWrite | null, forced_chatgpt_workspace_id: string | null, forced_login_method: ForcedLoginMethod | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, profile: string | null, profiles: { [key in string]?: ProfileV2 }, instructions: string | null, developer_instructions: string | null, compact_prompt: string | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, service_tier: ServiceTier | null, analytics: AnalyticsConfig | null} & ({ [key in string]?: number | string | boolean | Array | { [key in string]?: JsonValue } | null }); +export type Config = {model: string | null, review_model: string | null, model_context_window: bigint | null, model_auto_compact_token_limit: bigint | null, model_provider: string | null, approval_policy: AskForApproval | null, /** + * [UNSTABLE] Optional default for where approval requests are routed for + * review. + */ +approvals_reviewer: ApprovalsReviewer | null, sandbox_mode: SandboxMode | null, sandbox_workspace_write: SandboxWorkspaceWrite | null, forced_chatgpt_workspace_id: string | null, forced_login_method: ForcedLoginMethod | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, profile: string | null, profiles: { [key in string]?: ProfileV2 }, instructions: string | null, developer_instructions: string | null, compact_prompt: string | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, service_tier: ServiceTier | null, analytics: AnalyticsConfig | null} & ({ [key in string]?: number | string | boolean | Array | { [key in string]?: JsonValue } | null }); diff --git a/src/app-server/v2/DynamicToolSpec.ts b/src/app-server/v2/DynamicToolSpec.ts index 8b39793f..18596e31 100644 --- a/src/app-server/v2/DynamicToolSpec.ts +++ b/src/app-server/v2/DynamicToolSpec.ts @@ -3,4 +3,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { JsonValue } from "../serde_json/JsonValue"; -export type DynamicToolSpec = { name: string, description: string, inputSchema: JsonValue, }; +export type DynamicToolSpec = { name: string, description: string, inputSchema: JsonValue, deferLoading?: boolean, }; diff --git a/src/app-server/v2/ExperimentalFeatureEnablementSetParams.ts b/src/app-server/v2/ExperimentalFeatureEnablementSetParams.ts new file mode 100644 index 00000000..cd9ced0b --- /dev/null +++ b/src/app-server/v2/ExperimentalFeatureEnablementSetParams.ts @@ -0,0 +1,12 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ExperimentalFeatureEnablementSetParams = { +/** + * Process-wide runtime feature enablement keyed by canonical feature name. + * + * Only named features are updated. Omitted features are left unchanged. + * Send an empty map for a no-op. + */ +enablement: { [key in string]?: boolean }, }; diff --git a/src/app-server/v2/ExperimentalFeatureEnablementSetResponse.ts b/src/app-server/v2/ExperimentalFeatureEnablementSetResponse.ts new file mode 100644 index 00000000..903576d9 --- /dev/null +++ b/src/app-server/v2/ExperimentalFeatureEnablementSetResponse.ts @@ -0,0 +1,9 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ExperimentalFeatureEnablementSetResponse = { +/** + * Feature enablement entries updated by this request. + */ +enablement: { [key in string]?: boolean }, }; diff --git a/src/app-server/v2/FsChangedNotification.ts b/src/app-server/v2/FsChangedNotification.ts new file mode 100644 index 00000000..2e9bd0d6 --- /dev/null +++ b/src/app-server/v2/FsChangedNotification.ts @@ -0,0 +1,17 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Filesystem watch notification emitted for `fs/watch` subscribers. + */ +export type FsChangedNotification = { +/** + * Watch identifier returned by `fs/watch`. + */ +watchId: string, +/** + * File or directory paths associated with this event. + */ +changedPaths: Array, }; diff --git a/src/app-server/v2/FsCopyParams.ts b/src/app-server/v2/FsCopyParams.ts new file mode 100644 index 00000000..8f1ec8d4 --- /dev/null +++ b/src/app-server/v2/FsCopyParams.ts @@ -0,0 +1,21 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Copy a file or directory tree on the host filesystem. + */ +export type FsCopyParams = { +/** + * Absolute source path. + */ +sourcePath: AbsolutePathBuf, +/** + * Absolute destination path. + */ +destinationPath: AbsolutePathBuf, +/** + * Required for directory copies; ignored for file copies. + */ +recursive?: boolean, }; diff --git a/src/app-server/v2/FsCopyResponse.ts b/src/app-server/v2/FsCopyResponse.ts new file mode 100644 index 00000000..3e3061a8 --- /dev/null +++ b/src/app-server/v2/FsCopyResponse.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Successful response for `fs/copy`. + */ +export type FsCopyResponse = Record; diff --git a/src/app-server/v2/FsCreateDirectoryParams.ts b/src/app-server/v2/FsCreateDirectoryParams.ts new file mode 100644 index 00000000..2afc9950 --- /dev/null +++ b/src/app-server/v2/FsCreateDirectoryParams.ts @@ -0,0 +1,17 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Create a directory on the host filesystem. + */ +export type FsCreateDirectoryParams = { +/** + * Absolute directory path to create. + */ +path: AbsolutePathBuf, +/** + * Whether parent directories should also be created. Defaults to `true`. + */ +recursive?: boolean | null, }; diff --git a/src/app-server/v2/FsCreateDirectoryResponse.ts b/src/app-server/v2/FsCreateDirectoryResponse.ts new file mode 100644 index 00000000..5d251b71 --- /dev/null +++ b/src/app-server/v2/FsCreateDirectoryResponse.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Successful response for `fs/createDirectory`. + */ +export type FsCreateDirectoryResponse = Record; diff --git a/src/app-server/v2/FsGetMetadataParams.ts b/src/app-server/v2/FsGetMetadataParams.ts new file mode 100644 index 00000000..38e46c7b --- /dev/null +++ b/src/app-server/v2/FsGetMetadataParams.ts @@ -0,0 +1,13 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Request metadata for an absolute path. + */ +export type FsGetMetadataParams = { +/** + * Absolute path to inspect. + */ +path: AbsolutePathBuf, }; diff --git a/src/app-server/v2/FsGetMetadataResponse.ts b/src/app-server/v2/FsGetMetadataResponse.ts new file mode 100644 index 00000000..351c6462 --- /dev/null +++ b/src/app-server/v2/FsGetMetadataResponse.ts @@ -0,0 +1,24 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Metadata returned by `fs/getMetadata`. + */ +export type FsGetMetadataResponse = { +/** + * Whether the path currently resolves to a directory. + */ +isDirectory: boolean, +/** + * Whether the path currently resolves to a regular file. + */ +isFile: boolean, +/** + * File creation time in Unix milliseconds when available, otherwise `0`. + */ +createdAtMs: number, +/** + * File modification time in Unix milliseconds when available, otherwise `0`. + */ +modifiedAtMs: number, }; diff --git a/src/app-server/v2/FsReadDirectoryEntry.ts b/src/app-server/v2/FsReadDirectoryEntry.ts new file mode 100644 index 00000000..2696d7a4 --- /dev/null +++ b/src/app-server/v2/FsReadDirectoryEntry.ts @@ -0,0 +1,20 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * A directory entry returned by `fs/readDirectory`. + */ +export type FsReadDirectoryEntry = { +/** + * Direct child entry name only, not an absolute or relative path. + */ +fileName: string, +/** + * Whether this entry resolves to a directory. + */ +isDirectory: boolean, +/** + * Whether this entry resolves to a regular file. + */ +isFile: boolean, }; diff --git a/src/app-server/v2/FsReadDirectoryParams.ts b/src/app-server/v2/FsReadDirectoryParams.ts new file mode 100644 index 00000000..770eea3a --- /dev/null +++ b/src/app-server/v2/FsReadDirectoryParams.ts @@ -0,0 +1,13 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * List direct child names for a directory. + */ +export type FsReadDirectoryParams = { +/** + * Absolute directory path to read. + */ +path: AbsolutePathBuf, }; diff --git a/src/app-server/v2/FsReadDirectoryResponse.ts b/src/app-server/v2/FsReadDirectoryResponse.ts new file mode 100644 index 00000000..878e858f --- /dev/null +++ b/src/app-server/v2/FsReadDirectoryResponse.ts @@ -0,0 +1,13 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { FsReadDirectoryEntry } from "./FsReadDirectoryEntry"; + +/** + * Directory entries returned by `fs/readDirectory`. + */ +export type FsReadDirectoryResponse = { +/** + * Direct child entries in the requested directory. + */ +entries: Array, }; diff --git a/src/app-server/v2/FsReadFileParams.ts b/src/app-server/v2/FsReadFileParams.ts new file mode 100644 index 00000000..f389b44f --- /dev/null +++ b/src/app-server/v2/FsReadFileParams.ts @@ -0,0 +1,13 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Read a file from the host filesystem. + */ +export type FsReadFileParams = { +/** + * Absolute path to read. + */ +path: AbsolutePathBuf, }; diff --git a/src/app-server/v2/FsReadFileResponse.ts b/src/app-server/v2/FsReadFileResponse.ts new file mode 100644 index 00000000..075d1269 --- /dev/null +++ b/src/app-server/v2/FsReadFileResponse.ts @@ -0,0 +1,12 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Base64-encoded file contents returned by `fs/readFile`. + */ +export type FsReadFileResponse = { +/** + * File contents encoded as base64. + */ +dataBase64: string, }; diff --git a/src/app-server/v2/FsRemoveParams.ts b/src/app-server/v2/FsRemoveParams.ts new file mode 100644 index 00000000..c9f02eb0 --- /dev/null +++ b/src/app-server/v2/FsRemoveParams.ts @@ -0,0 +1,21 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Remove a file or directory tree from the host filesystem. + */ +export type FsRemoveParams = { +/** + * Absolute path to remove. + */ +path: AbsolutePathBuf, +/** + * Whether directory removal should recurse. Defaults to `true`. + */ +recursive?: boolean | null, +/** + * Whether missing paths should be ignored. Defaults to `true`. + */ +force?: boolean | null, }; diff --git a/src/app-server/v2/FsRemoveResponse.ts b/src/app-server/v2/FsRemoveResponse.ts new file mode 100644 index 00000000..981c28fa --- /dev/null +++ b/src/app-server/v2/FsRemoveResponse.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Successful response for `fs/remove`. + */ +export type FsRemoveResponse = Record; diff --git a/src/app-server/v2/FsUnwatchParams.ts b/src/app-server/v2/FsUnwatchParams.ts new file mode 100644 index 00000000..b21befdb --- /dev/null +++ b/src/app-server/v2/FsUnwatchParams.ts @@ -0,0 +1,12 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Stop filesystem watch notifications for a prior `fs/watch`. + */ +export type FsUnwatchParams = { +/** + * Watch identifier returned by `fs/watch`. + */ +watchId: string, }; diff --git a/src/app-server/v2/FsUnwatchResponse.ts b/src/app-server/v2/FsUnwatchResponse.ts new file mode 100644 index 00000000..02507d2c --- /dev/null +++ b/src/app-server/v2/FsUnwatchResponse.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Successful response for `fs/unwatch`. + */ +export type FsUnwatchResponse = Record; diff --git a/src/app-server/v2/FsWatchParams.ts b/src/app-server/v2/FsWatchParams.ts new file mode 100644 index 00000000..d6d956b2 --- /dev/null +++ b/src/app-server/v2/FsWatchParams.ts @@ -0,0 +1,13 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Start filesystem watch notifications for an absolute path. + */ +export type FsWatchParams = { +/** + * Absolute file or directory path to watch. + */ +path: AbsolutePathBuf, }; diff --git a/src/app-server/v2/FsWatchResponse.ts b/src/app-server/v2/FsWatchResponse.ts new file mode 100644 index 00000000..19272728 --- /dev/null +++ b/src/app-server/v2/FsWatchResponse.ts @@ -0,0 +1,17 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Created watch handle returned by `fs/watch`. + */ +export type FsWatchResponse = { +/** + * Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`. + */ +watchId: string, +/** + * Canonicalized path associated with the watch. + */ +path: AbsolutePathBuf, }; diff --git a/src/app-server/v2/FsWriteFileParams.ts b/src/app-server/v2/FsWriteFileParams.ts new file mode 100644 index 00000000..7c22abdb --- /dev/null +++ b/src/app-server/v2/FsWriteFileParams.ts @@ -0,0 +1,17 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +/** + * Write a file on the host filesystem. + */ +export type FsWriteFileParams = { +/** + * Absolute path to write. + */ +path: AbsolutePathBuf, +/** + * File contents encoded as base64. + */ +dataBase64: string, }; diff --git a/src/app-server/v2/FsWriteFileResponse.ts b/src/app-server/v2/FsWriteFileResponse.ts new file mode 100644 index 00000000..ad0ce283 --- /dev/null +++ b/src/app-server/v2/FsWriteFileResponse.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Successful response for `fs/writeFile`. + */ +export type FsWriteFileResponse = Record; diff --git a/src/app-server/v2/GrantedPermissionProfile.ts b/src/app-server/v2/GrantedPermissionProfile.ts index 84a9aa37..3ae6c605 100644 --- a/src/app-server/v2/GrantedPermissionProfile.ts +++ b/src/app-server/v2/GrantedPermissionProfile.ts @@ -3,6 +3,5 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { AdditionalFileSystemPermissions } from "./AdditionalFileSystemPermissions"; import type { AdditionalNetworkPermissions } from "./AdditionalNetworkPermissions"; -import type { GrantedMacOsPermissions } from "./GrantedMacOsPermissions"; -export type GrantedPermissionProfile = { network?: AdditionalNetworkPermissions, fileSystem?: AdditionalFileSystemPermissions, macos?: GrantedMacOsPermissions, }; +export type GrantedPermissionProfile = { network?: AdditionalNetworkPermissions, fileSystem?: AdditionalFileSystemPermissions, }; diff --git a/src/app-server/v2/GuardianApprovalReview.ts b/src/app-server/v2/GuardianApprovalReview.ts new file mode 100644 index 00000000..e26282be --- /dev/null +++ b/src/app-server/v2/GuardianApprovalReview.ts @@ -0,0 +1,12 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { GuardianApprovalReviewStatus } from "./GuardianApprovalReviewStatus"; +import type { GuardianRiskLevel } from "./GuardianRiskLevel"; + +/** + * [UNSTABLE] Temporary guardian approval review payload used by + * `item/autoApprovalReview/*` notifications. This shape is expected to change + * soon. + */ +export type GuardianApprovalReview = { status: GuardianApprovalReviewStatus, riskScore: number | null, riskLevel: GuardianRiskLevel | null, rationale: string | null, }; diff --git a/src/app-server/v2/GuardianApprovalReviewStatus.ts b/src/app-server/v2/GuardianApprovalReviewStatus.ts new file mode 100644 index 00000000..b98578b2 --- /dev/null +++ b/src/app-server/v2/GuardianApprovalReviewStatus.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * [UNSTABLE] Lifecycle state for a guardian approval review. + */ +export type GuardianApprovalReviewStatus = "inProgress" | "approved" | "denied" | "aborted"; diff --git a/src/app-server/v2/GuardianRiskLevel.ts b/src/app-server/v2/GuardianRiskLevel.ts new file mode 100644 index 00000000..1b0a945f --- /dev/null +++ b/src/app-server/v2/GuardianRiskLevel.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * [UNSTABLE] Risk level assigned by guardian approval review. + */ +export type GuardianRiskLevel = "low" | "medium" | "high"; diff --git a/src/app-server/v2/HookEventName.ts b/src/app-server/v2/HookEventName.ts index d07429a9..b97c709b 100644 --- a/src/app-server/v2/HookEventName.ts +++ b/src/app-server/v2/HookEventName.ts @@ -2,4 +2,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type HookEventName = "sessionStart" | "stop"; +export type HookEventName = "preToolUse" | "postToolUse" | "sessionStart" | "userPromptSubmit" | "stop"; diff --git a/src/app-server/v2/HookPromptFragment.ts b/src/app-server/v2/HookPromptFragment.ts new file mode 100644 index 00000000..2c6b18ac --- /dev/null +++ b/src/app-server/v2/HookPromptFragment.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HookPromptFragment = { text: string, hookRunId: string, }; diff --git a/src/app-server/v2/ItemGuardianApprovalReviewCompletedNotification.ts b/src/app-server/v2/ItemGuardianApprovalReviewCompletedNotification.ts new file mode 100644 index 00000000..ac4ae1b7 --- /dev/null +++ b/src/app-server/v2/ItemGuardianApprovalReviewCompletedNotification.ts @@ -0,0 +1,15 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { JsonValue } from "../serde_json/JsonValue"; +import type { GuardianApprovalReview } from "./GuardianApprovalReview"; + +/** + * [UNSTABLE] Temporary notification payload for guardian automatic approval + * review. This shape is expected to change soon. + * + * TODO(ccunningham): Attach guardian review state to the reviewed tool item's + * lifecycle instead of sending separate standalone review notifications so the + * app-server API can persist and replay review state via `thread/read`. + */ +export type ItemGuardianApprovalReviewCompletedNotification = { threadId: string, turnId: string, targetItemId: string, review: GuardianApprovalReview, action: JsonValue | null, }; diff --git a/src/app-server/v2/ItemGuardianApprovalReviewStartedNotification.ts b/src/app-server/v2/ItemGuardianApprovalReviewStartedNotification.ts new file mode 100644 index 00000000..b2296268 --- /dev/null +++ b/src/app-server/v2/ItemGuardianApprovalReviewStartedNotification.ts @@ -0,0 +1,15 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { JsonValue } from "../serde_json/JsonValue"; +import type { GuardianApprovalReview } from "./GuardianApprovalReview"; + +/** + * [UNSTABLE] Temporary notification payload for guardian automatic approval + * review. This shape is expected to change soon. + * + * TODO(ccunningham): Attach guardian review state to the reviewed tool item's + * lifecycle instead of sending separate standalone review notifications so the + * app-server API can persist and replay review state via `thread/read`. + */ +export type ItemGuardianApprovalReviewStartedNotification = { threadId: string, turnId: string, targetItemId: string, review: GuardianApprovalReview, action: JsonValue | null, }; diff --git a/src/app-server/v2/LoginAccountParams.ts b/src/app-server/v2/LoginAccountParams.ts index ef668f9c..9fcb01f9 100644 --- a/src/app-server/v2/LoginAccountParams.ts +++ b/src/app-server/v2/LoginAccountParams.ts @@ -2,7 +2,7 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type LoginAccountParams = { "type": "apiKey", apiKey: string, } | { "type": "chatgpt" } | { "type": "chatgptAuthTokens", +export type LoginAccountParams = { "type": "apiKey", apiKey: string, } | { "type": "chatgpt" } | { "type": "chatgptDeviceCode" } | { "type": "chatgptAuthTokens", /** * Access token (JWT) supplied by the client. * This token is used for backend API requests and email extraction. diff --git a/src/app-server/v2/LoginAccountResponse.ts b/src/app-server/v2/LoginAccountResponse.ts index cd79f6c8..651f171e 100644 --- a/src/app-server/v2/LoginAccountResponse.ts +++ b/src/app-server/v2/LoginAccountResponse.ts @@ -6,4 +6,12 @@ export type LoginAccountResponse = { "type": "apiKey", } | { "type": "chatgpt", /** * URL the client should open in a browser to initiate the OAuth flow. */ -authUrl: string, } | { "type": "chatgptAuthTokens", }; +authUrl: string, } | { "type": "chatgptDeviceCode", loginId: string, +/** + * URL the client should open in a browser to complete device code authorization. + */ +verificationUrl: string, +/** + * One-time code the user must enter after signing in. + */ +userCode: string, } | { "type": "chatgptAuthTokens", }; diff --git a/src/app-server/v2/MarketplaceInterface.ts b/src/app-server/v2/MarketplaceInterface.ts new file mode 100644 index 00000000..f82dc179 --- /dev/null +++ b/src/app-server/v2/MarketplaceInterface.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type MarketplaceInterface = { displayName: string | null, }; diff --git a/src/app-server/v2/MarketplaceLoadErrorInfo.ts b/src/app-server/v2/MarketplaceLoadErrorInfo.ts new file mode 100644 index 00000000..3e60e214 --- /dev/null +++ b/src/app-server/v2/MarketplaceLoadErrorInfo.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +export type MarketplaceLoadErrorInfo = { marketplacePath: AbsolutePathBuf, message: string, }; diff --git a/src/app-server/v2/McpServerStartupState.ts b/src/app-server/v2/McpServerStartupState.ts new file mode 100644 index 00000000..c62babca --- /dev/null +++ b/src/app-server/v2/McpServerStartupState.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type McpServerStartupState = "starting" | "ready" | "failed" | "cancelled"; diff --git a/src/app-server/v2/McpServerStatusUpdatedNotification.ts b/src/app-server/v2/McpServerStatusUpdatedNotification.ts new file mode 100644 index 00000000..42f5881c --- /dev/null +++ b/src/app-server/v2/McpServerStatusUpdatedNotification.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { McpServerStartupState } from "./McpServerStartupState"; + +export type McpServerStatusUpdatedNotification = { name: string, status: McpServerStartupState, error: string | null, }; diff --git a/src/app-server/v2/MemoryCitation.ts b/src/app-server/v2/MemoryCitation.ts new file mode 100644 index 00000000..7657e29f --- /dev/null +++ b/src/app-server/v2/MemoryCitation.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { MemoryCitationEntry } from "./MemoryCitationEntry"; + +export type MemoryCitation = { entries: Array, threadIds: Array, }; diff --git a/src/app-server/v2/MemoryCitationEntry.ts b/src/app-server/v2/MemoryCitationEntry.ts new file mode 100644 index 00000000..9b9ce172 --- /dev/null +++ b/src/app-server/v2/MemoryCitationEntry.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type MemoryCitationEntry = { path: string, lineStart: number, lineEnd: number, note: string, }; diff --git a/src/app-server/v2/NetworkDomainPermission.ts b/src/app-server/v2/NetworkDomainPermission.ts new file mode 100644 index 00000000..2ea44392 --- /dev/null +++ b/src/app-server/v2/NetworkDomainPermission.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type NetworkDomainPermission = "allow" | "deny"; diff --git a/src/app-server/v2/NetworkRequirements.ts b/src/app-server/v2/NetworkRequirements.ts index 1f1653c2..5fc942be 100644 --- a/src/app-server/v2/NetworkRequirements.ts +++ b/src/app-server/v2/NetworkRequirements.ts @@ -1,5 +1,32 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NetworkDomainPermission } from "./NetworkDomainPermission"; +import type { NetworkUnixSocketPermission } from "./NetworkUnixSocketPermission"; -export type NetworkRequirements = { enabled: boolean | null, httpPort: number | null, socksPort: number | null, allowUpstreamProxy: boolean | null, dangerouslyAllowNonLoopbackProxy: boolean | null, dangerouslyAllowAllUnixSockets: boolean | null, allowedDomains: Array | null, deniedDomains: Array | null, allowUnixSockets: Array | null, allowLocalBinding: boolean | null, }; +export type NetworkRequirements = { enabled: boolean | null, httpPort: number | null, socksPort: number | null, allowUpstreamProxy: boolean | null, dangerouslyAllowNonLoopbackProxy: boolean | null, dangerouslyAllowAllUnixSockets: boolean | null, +/** + * Canonical network permission map for `experimental_network`. + */ +domains: { [key in string]?: NetworkDomainPermission } | null, +/** + * When true, only managed allowlist entries are respected while managed + * network enforcement is active. + */ +managedAllowedDomainsOnly: boolean | null, +/** + * Legacy compatibility view derived from `domains`. + */ +allowedDomains: Array | null, +/** + * Legacy compatibility view derived from `domains`. + */ +deniedDomains: Array | null, +/** + * Canonical unix socket permission map for `experimental_network`. + */ +unixSockets: { [key in string]?: NetworkUnixSocketPermission } | null, +/** + * Legacy compatibility view derived from `unix_sockets`. + */ +allowUnixSockets: Array | null, allowLocalBinding: boolean | null, }; diff --git a/src/app-server/v2/NetworkUnixSocketPermission.ts b/src/app-server/v2/NetworkUnixSocketPermission.ts new file mode 100644 index 00000000..466c6e5f --- /dev/null +++ b/src/app-server/v2/NetworkUnixSocketPermission.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type NetworkUnixSocketPermission = "allow" | "none"; diff --git a/src/app-server/v2/NonSteerableTurnKind.ts b/src/app-server/v2/NonSteerableTurnKind.ts new file mode 100644 index 00000000..2624df2b --- /dev/null +++ b/src/app-server/v2/NonSteerableTurnKind.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type NonSteerableTurnKind = "review" | "compact"; diff --git a/src/app-server/v2/PermissionsRequestApprovalParams.ts b/src/app-server/v2/PermissionsRequestApprovalParams.ts index cde277f1..efdefead 100644 --- a/src/app-server/v2/PermissionsRequestApprovalParams.ts +++ b/src/app-server/v2/PermissionsRequestApprovalParams.ts @@ -1,6 +1,6 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { AdditionalPermissionProfile } from "./AdditionalPermissionProfile"; +import type { RequestPermissionProfile } from "./RequestPermissionProfile"; -export type PermissionsRequestApprovalParams = { threadId: string, turnId: string, itemId: string, reason: string | null, permissions: AdditionalPermissionProfile, }; +export type PermissionsRequestApprovalParams = { threadId: string, turnId: string, itemId: string, reason: string | null, permissions: RequestPermissionProfile, }; diff --git a/src/app-server/v2/PluginAuthPolicy.ts b/src/app-server/v2/PluginAuthPolicy.ts new file mode 100644 index 00000000..5b90e9c3 --- /dev/null +++ b/src/app-server/v2/PluginAuthPolicy.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PluginAuthPolicy = "ON_INSTALL" | "ON_USE"; diff --git a/src/app-server/v2/PluginDetail.ts b/src/app-server/v2/PluginDetail.ts new file mode 100644 index 00000000..4bfd35fe --- /dev/null +++ b/src/app-server/v2/PluginDetail.ts @@ -0,0 +1,9 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; +import type { AppSummary } from "./AppSummary"; +import type { PluginSummary } from "./PluginSummary"; +import type { SkillSummary } from "./SkillSummary"; + +export type PluginDetail = { marketplaceName: string, marketplacePath: AbsolutePathBuf, summary: PluginSummary, description: string | null, skills: Array, apps: Array, mcpServers: Array, }; diff --git a/src/app-server/v2/PluginInstallParams.ts b/src/app-server/v2/PluginInstallParams.ts index 86326b13..190dee04 100644 --- a/src/app-server/v2/PluginInstallParams.ts +++ b/src/app-server/v2/PluginInstallParams.ts @@ -3,4 +3,8 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { AbsolutePathBuf } from "../AbsolutePathBuf"; -export type PluginInstallParams = { marketplacePath: AbsolutePathBuf, pluginName: string, }; +export type PluginInstallParams = { marketplacePath: AbsolutePathBuf, pluginName: string, +/** + * When true, apply the remote plugin change before the local install flow. + */ +forceRemoteSync?: boolean, }; diff --git a/src/app-server/v2/PluginInstallPolicy.ts b/src/app-server/v2/PluginInstallPolicy.ts new file mode 100644 index 00000000..d624f38e --- /dev/null +++ b/src/app-server/v2/PluginInstallPolicy.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PluginInstallPolicy = "NOT_AVAILABLE" | "AVAILABLE" | "INSTALLED_BY_DEFAULT"; diff --git a/src/app-server/v2/PluginInstallResponse.ts b/src/app-server/v2/PluginInstallResponse.ts index 08c61f37..b88119d4 100644 --- a/src/app-server/v2/PluginInstallResponse.ts +++ b/src/app-server/v2/PluginInstallResponse.ts @@ -2,5 +2,6 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { AppSummary } from "./AppSummary"; +import type { PluginAuthPolicy } from "./PluginAuthPolicy"; -export type PluginInstallResponse = { appsNeedingAuth: Array, }; +export type PluginInstallResponse = { authPolicy: PluginAuthPolicy, appsNeedingAuth: Array, }; diff --git a/src/app-server/v2/PluginInterface.ts b/src/app-server/v2/PluginInterface.ts index f9f016d0..cea42d29 100644 --- a/src/app-server/v2/PluginInterface.ts +++ b/src/app-server/v2/PluginInterface.ts @@ -3,4 +3,9 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { AbsolutePathBuf } from "../AbsolutePathBuf"; -export type PluginInterface = { displayName: string | null, shortDescription: string | null, longDescription: string | null, developerName: string | null, category: string | null, capabilities: Array, websiteUrl: string | null, privacyPolicyUrl: string | null, termsOfServiceUrl: string | null, defaultPrompt: string | null, brandColor: string | null, composerIcon: AbsolutePathBuf | null, logo: AbsolutePathBuf | null, screenshots: Array, }; +export type PluginInterface = { displayName: string | null, shortDescription: string | null, longDescription: string | null, developerName: string | null, category: string | null, capabilities: Array, websiteUrl: string | null, privacyPolicyUrl: string | null, termsOfServiceUrl: string | null, +/** + * Starter prompts for the plugin. Capped at 3 entries with a maximum of + * 128 characters per entry. + */ +defaultPrompt: Array | null, brandColor: string | null, composerIcon: AbsolutePathBuf | null, logo: AbsolutePathBuf | null, screenshots: Array, }; diff --git a/src/app-server/v2/PluginListParams.ts b/src/app-server/v2/PluginListParams.ts index 078feca2..07ecee5e 100644 --- a/src/app-server/v2/PluginListParams.ts +++ b/src/app-server/v2/PluginListParams.ts @@ -8,4 +8,9 @@ export type PluginListParams = { * Optional working directories used to discover repo marketplaces. When omitted, * only home-scoped marketplaces and the official curated marketplace are considered. */ -cwds?: Array | null, }; +cwds?: Array | null, +/** + * When true, reconcile the official curated marketplace against the remote plugin state + * before listing marketplaces. + */ +forceRemoteSync?: boolean, }; diff --git a/src/app-server/v2/PluginListResponse.ts b/src/app-server/v2/PluginListResponse.ts index 7c3cc692..7ae5f8e5 100644 --- a/src/app-server/v2/PluginListResponse.ts +++ b/src/app-server/v2/PluginListResponse.ts @@ -1,6 +1,7 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { MarketplaceLoadErrorInfo } from "./MarketplaceLoadErrorInfo"; import type { PluginMarketplaceEntry } from "./PluginMarketplaceEntry"; -export type PluginListResponse = { marketplaces: Array, }; +export type PluginListResponse = { marketplaces: Array, marketplaceLoadErrors: Array, remoteSyncError: string | null, featuredPluginIds: Array, }; diff --git a/src/app-server/v2/PluginMarketplaceEntry.ts b/src/app-server/v2/PluginMarketplaceEntry.ts index 32042d1d..c0ab75b8 100644 --- a/src/app-server/v2/PluginMarketplaceEntry.ts +++ b/src/app-server/v2/PluginMarketplaceEntry.ts @@ -2,6 +2,7 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { AbsolutePathBuf } from "../AbsolutePathBuf"; +import type { MarketplaceInterface } from "./MarketplaceInterface"; import type { PluginSummary } from "./PluginSummary"; -export type PluginMarketplaceEntry = { name: string, path: AbsolutePathBuf, plugins: Array, }; +export type PluginMarketplaceEntry = { name: string, path: AbsolutePathBuf, interface: MarketplaceInterface | null, plugins: Array, }; diff --git a/src/app-server/v2/PluginReadParams.ts b/src/app-server/v2/PluginReadParams.ts new file mode 100644 index 00000000..cd669687 --- /dev/null +++ b/src/app-server/v2/PluginReadParams.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; + +export type PluginReadParams = { marketplacePath: AbsolutePathBuf, pluginName: string, }; diff --git a/src/app-server/v2/PluginReadResponse.ts b/src/app-server/v2/PluginReadResponse.ts new file mode 100644 index 00000000..841b916e --- /dev/null +++ b/src/app-server/v2/PluginReadResponse.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PluginDetail } from "./PluginDetail"; + +export type PluginReadResponse = { plugin: PluginDetail, }; diff --git a/src/app-server/v2/PluginSummary.ts b/src/app-server/v2/PluginSummary.ts index baefe10d..1eb443c5 100644 --- a/src/app-server/v2/PluginSummary.ts +++ b/src/app-server/v2/PluginSummary.ts @@ -1,7 +1,9 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PluginAuthPolicy } from "./PluginAuthPolicy"; +import type { PluginInstallPolicy } from "./PluginInstallPolicy"; import type { PluginInterface } from "./PluginInterface"; import type { PluginSource } from "./PluginSource"; -export type PluginSummary = { id: string, name: string, source: PluginSource, installed: boolean, enabled: boolean, interface: PluginInterface | null, }; +export type PluginSummary = { id: string, name: string, source: PluginSource, installed: boolean, enabled: boolean, installPolicy: PluginInstallPolicy, authPolicy: PluginAuthPolicy, interface: PluginInterface | null, }; diff --git a/src/app-server/v2/PluginUninstallParams.ts b/src/app-server/v2/PluginUninstallParams.ts index e7f52c0e..b92a21c9 100644 --- a/src/app-server/v2/PluginUninstallParams.ts +++ b/src/app-server/v2/PluginUninstallParams.ts @@ -2,4 +2,8 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type PluginUninstallParams = { pluginId: string, }; +export type PluginUninstallParams = { pluginId: string, +/** + * When true, apply the remote plugin change before the local uninstall flow. + */ +forceRemoteSync?: boolean, }; diff --git a/src/app-server/v2/ProfileV2.ts b/src/app-server/v2/ProfileV2.ts index f2c72b3a..7afe3e0c 100644 --- a/src/app-server/v2/ProfileV2.ts +++ b/src/app-server/v2/ProfileV2.ts @@ -7,7 +7,13 @@ import type { ServiceTier } from "../ServiceTier"; import type { Verbosity } from "../Verbosity"; import type { WebSearchMode } from "../WebSearchMode"; import type { JsonValue } from "../serde_json/JsonValue"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { ToolsV2 } from "./ToolsV2"; -export type ProfileV2 = { model: string | null, model_provider: string | null, approval_policy: AskForApproval | null, service_tier: ServiceTier | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, chatgpt_base_url: string | null, } & ({ [key in string]?: number | string | boolean | Array | { [key in string]?: JsonValue } | null }); +export type ProfileV2 = {model: string | null, model_provider: string | null, approval_policy: AskForApproval | null, /** + * [UNSTABLE] Optional profile-level override for where approval requests + * are routed for review. If omitted, the enclosing config default is + * used. + */ +approvals_reviewer: ApprovalsReviewer | null, service_tier: ServiceTier | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, chatgpt_base_url: string | null} & ({ [key in string]?: number | string | boolean | Array | { [key in string]?: JsonValue } | null }); diff --git a/src/app-server/v2/RequestPermissionProfile.ts b/src/app-server/v2/RequestPermissionProfile.ts new file mode 100644 index 00000000..2bf8d8df --- /dev/null +++ b/src/app-server/v2/RequestPermissionProfile.ts @@ -0,0 +1,7 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AdditionalFileSystemPermissions } from "./AdditionalFileSystemPermissions"; +import type { AdditionalNetworkPermissions } from "./AdditionalNetworkPermissions"; + +export type RequestPermissionProfile = { network: AdditionalNetworkPermissions | null, fileSystem: AdditionalFileSystemPermissions | null, }; diff --git a/src/app-server/v2/SessionSource.ts b/src/app-server/v2/SessionSource.ts index b35b421f..852e6ded 100644 --- a/src/app-server/v2/SessionSource.ts +++ b/src/app-server/v2/SessionSource.ts @@ -3,4 +3,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { SubAgentSource } from "../SubAgentSource"; -export type SessionSource = "cli" | "vscode" | "exec" | "appServer" | { "subAgent": SubAgentSource } | "unknown"; +export type SessionSource = "cli" | "vscode" | "exec" | "appServer" | { "custom": string } | { "subAgent": SubAgentSource } | "unknown"; diff --git a/src/app-server/v2/SkillSummary.ts b/src/app-server/v2/SkillSummary.ts new file mode 100644 index 00000000..ea373935 --- /dev/null +++ b/src/app-server/v2/SkillSummary.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SkillInterface } from "./SkillInterface"; + +export type SkillSummary = { name: string, description: string, shortDescription: string | null, interface: SkillInterface | null, path: string, enabled: boolean, }; diff --git a/src/app-server/v2/SkillsConfigWriteParams.ts b/src/app-server/v2/SkillsConfigWriteParams.ts index 5a4bcf9b..273d593c 100644 --- a/src/app-server/v2/SkillsConfigWriteParams.ts +++ b/src/app-server/v2/SkillsConfigWriteParams.ts @@ -1,5 +1,14 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AbsolutePathBuf } from "../AbsolutePathBuf"; -export type SkillsConfigWriteParams = { path: string, enabled: boolean, }; +export type SkillsConfigWriteParams = { +/** + * Path-based selector. + */ +path?: AbsolutePathBuf | null, +/** + * Name-based selector. + */ +name?: string | null, enabled: boolean, }; diff --git a/src/app-server/v2/ThreadForkParams.ts b/src/app-server/v2/ThreadForkParams.ts index b071bc85..a7ba3118 100644 --- a/src/app-server/v2/ThreadForkParams.ts +++ b/src/app-server/v2/ThreadForkParams.ts @@ -3,6 +3,7 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { ServiceTier } from "../ServiceTier"; import type { JsonValue } from "../serde_json/JsonValue"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxMode } from "./SandboxMode"; @@ -22,7 +23,11 @@ export type ThreadForkParams = {threadId: string, /** path?: string | null, /** * Configuration overrides for the forked thread, if any. */ -model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, /** +model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /** + * Override where approval requests are routed for review on this thread + * and subsequent turns. + */ +approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean, /** * If true, persist additional rollout EventMsg variants required to * reconstruct a richer thread history on subsequent resume/fork/read. */ diff --git a/src/app-server/v2/ThreadForkResponse.ts b/src/app-server/v2/ThreadForkResponse.ts index 6125448c..00dade9f 100644 --- a/src/app-server/v2/ThreadForkResponse.ts +++ b/src/app-server/v2/ThreadForkResponse.ts @@ -3,8 +3,13 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { ReasoningEffort } from "../ReasoningEffort"; import type { ServiceTier } from "../ServiceTier"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxPolicy } from "./SandboxPolicy"; import type { Thread } from "./Thread"; -export type ThreadForkResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string, approvalPolicy: AskForApproval, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, }; +export type ThreadForkResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string, approvalPolicy: AskForApproval, +/** + * Reviewer currently used for approval requests on this thread. + */ +approvalsReviewer: ApprovalsReviewer, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, }; diff --git a/src/app-server/v2/ThreadItem.ts b/src/app-server/v2/ThreadItem.ts index 488c07e5..9202f372 100644 --- a/src/app-server/v2/ThreadItem.ts +++ b/src/app-server/v2/ThreadItem.ts @@ -2,23 +2,27 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { MessagePhase } from "../MessagePhase"; +import type { ReasoningEffort } from "../ReasoningEffort"; import type { JsonValue } from "../serde_json/JsonValue"; import type { CollabAgentState } from "./CollabAgentState"; import type { CollabAgentTool } from "./CollabAgentTool"; import type { CollabAgentToolCallStatus } from "./CollabAgentToolCallStatus"; import type { CommandAction } from "./CommandAction"; +import type { CommandExecutionSource } from "./CommandExecutionSource"; import type { CommandExecutionStatus } from "./CommandExecutionStatus"; import type { DynamicToolCallOutputContentItem } from "./DynamicToolCallOutputContentItem"; import type { DynamicToolCallStatus } from "./DynamicToolCallStatus"; import type { FileUpdateChange } from "./FileUpdateChange"; +import type { HookPromptFragment } from "./HookPromptFragment"; import type { McpToolCallError } from "./McpToolCallError"; import type { McpToolCallResult } from "./McpToolCallResult"; import type { McpToolCallStatus } from "./McpToolCallStatus"; +import type { MemoryCitation } from "./MemoryCitation"; import type { PatchApplyStatus } from "./PatchApplyStatus"; import type { UserInput } from "./UserInput"; import type { WebSearchAction } from "./WebSearchAction"; -export type ThreadItem = { "type": "userMessage", id: string, content: Array, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array, content: Array, } | { "type": "commandExecution", id: string, +export type ThreadItem = { "type": "userMessage", id: string, content: Array, } | { "type": "hookPrompt", id: string, fragments: Array, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, memoryCitation: MemoryCitation | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array, content: Array, } | { "type": "commandExecution", id: string, /** * The command to be executed. */ @@ -30,7 +34,7 @@ cwd: string, /** * Identifier for the underlying PTY process (when available). */ -processId: string | null, status: CommandExecutionStatus, +processId: string | null, source: CommandExecutionSource, status: CommandExecutionStatus, /** * A best-effort parsing of the command to understand the action(s) it will perform. * This returns a list of CommandAction objects because a single shell command may @@ -82,7 +86,15 @@ receiverThreadIds: Array, * Prompt text sent as part of the collab tool call, when available. */ prompt: string | null, +/** + * Model requested for the spawned agent, when applicable. + */ +model: string | null, +/** + * Reasoning effort requested for the spawned agent, when applicable. + */ +reasoningEffort: ReasoningEffort | null, /** * Last known status of the target agents, when available. */ -agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: string, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, }; +agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: string, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, savedPath?: string, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, }; diff --git a/src/app-server/v2/ThreadRealtimeAudioChunk.ts b/src/app-server/v2/ThreadRealtimeAudioChunk.ts index 078f6422..eefb79dd 100644 --- a/src/app-server/v2/ThreadRealtimeAudioChunk.ts +++ b/src/app-server/v2/ThreadRealtimeAudioChunk.ts @@ -5,4 +5,4 @@ /** * EXPERIMENTAL - thread realtime audio chunk. */ -export type ThreadRealtimeAudioChunk = { data: string, sampleRate: number, numChannels: number, samplesPerChannel: number | null, }; +export type ThreadRealtimeAudioChunk = { data: string, sampleRate: number, numChannels: number, samplesPerChannel: number | null, itemId: string | null, }; diff --git a/src/app-server/v2/ThreadRealtimeStartedNotification.ts b/src/app-server/v2/ThreadRealtimeStartedNotification.ts index 736ecde1..d4941006 100644 --- a/src/app-server/v2/ThreadRealtimeStartedNotification.ts +++ b/src/app-server/v2/ThreadRealtimeStartedNotification.ts @@ -1,8 +1,9 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RealtimeConversationVersion } from "../RealtimeConversationVersion"; /** * EXPERIMENTAL - emitted when thread realtime startup is accepted. */ -export type ThreadRealtimeStartedNotification = { threadId: string, sessionId: string | null, }; +export type ThreadRealtimeStartedNotification = { threadId: string, sessionId: string | null, version: RealtimeConversationVersion, }; diff --git a/src/app-server/v2/ThreadRealtimeTranscriptUpdatedNotification.ts b/src/app-server/v2/ThreadRealtimeTranscriptUpdatedNotification.ts new file mode 100644 index 00000000..d2940029 --- /dev/null +++ b/src/app-server/v2/ThreadRealtimeTranscriptUpdatedNotification.ts @@ -0,0 +1,9 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * EXPERIMENTAL - flat transcript delta emitted whenever realtime + * transcript text changes. + */ +export type ThreadRealtimeTranscriptUpdatedNotification = { threadId: string, role: string, text: string, }; diff --git a/src/app-server/v2/ThreadResumeParams.ts b/src/app-server/v2/ThreadResumeParams.ts index cc12020b..770344de 100644 --- a/src/app-server/v2/ThreadResumeParams.ts +++ b/src/app-server/v2/ThreadResumeParams.ts @@ -5,6 +5,7 @@ import type { Personality } from "../Personality"; import type { ResponseItem } from "../ResponseItem"; import type { ServiceTier } from "../ServiceTier"; import type { JsonValue } from "../serde_json/JsonValue"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxMode } from "./SandboxMode"; @@ -31,7 +32,11 @@ history?: Array | null, /** path?: string | null, /** * Configuration overrides for the resumed thread, if any. */ -model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /** +model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /** + * Override where approval requests are routed for review on this thread + * and subsequent turns. + */ +approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /** * If true, persist additional rollout EventMsg variants required to * reconstruct a richer thread history on subsequent resume/fork/read. */ diff --git a/src/app-server/v2/ThreadResumeResponse.ts b/src/app-server/v2/ThreadResumeResponse.ts index 91ca8241..ba70bd8f 100644 --- a/src/app-server/v2/ThreadResumeResponse.ts +++ b/src/app-server/v2/ThreadResumeResponse.ts @@ -3,8 +3,13 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { ReasoningEffort } from "../ReasoningEffort"; import type { ServiceTier } from "../ServiceTier"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxPolicy } from "./SandboxPolicy"; import type { Thread } from "./Thread"; -export type ThreadResumeResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string, approvalPolicy: AskForApproval, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, }; +export type ThreadResumeResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string, approvalPolicy: AskForApproval, +/** + * Reviewer currently used for approval requests on this thread. + */ +approvalsReviewer: ApprovalsReviewer, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, }; diff --git a/src/app-server/v2/ThreadShellCommandParams.ts b/src/app-server/v2/ThreadShellCommandParams.ts new file mode 100644 index 00000000..8c50612c --- /dev/null +++ b/src/app-server/v2/ThreadShellCommandParams.ts @@ -0,0 +1,12 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ThreadShellCommandParams = { threadId: string, +/** + * Shell command string evaluated by the thread's configured shell. + * Unlike `command/exec`, this intentionally preserves shell syntax + * such as pipes, redirects, and quoting. This runs unsandboxed with full + * access rather than inheriting the thread sandbox policy. + */ +command: string, }; diff --git a/src/app-server/v2/ThreadShellCommandResponse.ts b/src/app-server/v2/ThreadShellCommandResponse.ts new file mode 100644 index 00000000..9c54b458 --- /dev/null +++ b/src/app-server/v2/ThreadShellCommandResponse.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ThreadShellCommandResponse = Record; diff --git a/src/app-server/v2/ThreadStartParams.ts b/src/app-server/v2/ThreadStartParams.ts index db73763e..61f501ad 100644 --- a/src/app-server/v2/ThreadStartParams.ts +++ b/src/app-server/v2/ThreadStartParams.ts @@ -4,10 +4,15 @@ import type { Personality } from "../Personality"; import type { ServiceTier } from "../ServiceTier"; import type { JsonValue } from "../serde_json/JsonValue"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxMode } from "./SandboxMode"; -export type ThreadStartParams = {model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, serviceName?: string | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, ephemeral?: boolean | null, /** +export type ThreadStartParams = {model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /** + * Override where approval requests are routed for review on this thread + * and subsequent turns. + */ +approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, serviceName?: string | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, ephemeral?: boolean | null, /** * If true, opt into emitting raw Responses API items on the event stream. * This is for internal use only (e.g. Codex Cloud). */ diff --git a/src/app-server/v2/ThreadStartResponse.ts b/src/app-server/v2/ThreadStartResponse.ts index f4882ce6..ee97bdf4 100644 --- a/src/app-server/v2/ThreadStartResponse.ts +++ b/src/app-server/v2/ThreadStartResponse.ts @@ -3,8 +3,13 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { ReasoningEffort } from "../ReasoningEffort"; import type { ServiceTier } from "../ServiceTier"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxPolicy } from "./SandboxPolicy"; import type { Thread } from "./Thread"; -export type ThreadStartResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string, approvalPolicy: AskForApproval, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, }; +export type ThreadStartResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string, approvalPolicy: AskForApproval, +/** + * Reviewer currently used for approval requests on this thread. + */ +approvalsReviewer: ApprovalsReviewer, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, }; diff --git a/src/app-server/v2/TurnStartParams.ts b/src/app-server/v2/TurnStartParams.ts index b8bf7ea6..8f57a5e6 100644 --- a/src/app-server/v2/TurnStartParams.ts +++ b/src/app-server/v2/TurnStartParams.ts @@ -7,6 +7,7 @@ import type { ReasoningEffort } from "../ReasoningEffort"; import type { ReasoningSummary } from "../ReasoningSummary"; import type { ServiceTier } from "../ServiceTier"; import type { JsonValue } from "../serde_json/JsonValue"; +import type { ApprovalsReviewer } from "./ApprovalsReviewer"; import type { AskForApproval } from "./AskForApproval"; import type { SandboxPolicy } from "./SandboxPolicy"; import type { UserInput } from "./UserInput"; @@ -18,6 +19,10 @@ cwd?: string | null, /** * Override the approval policy for this turn and subsequent turns. */ approvalPolicy?: AskForApproval | null, /** + * Override where approval requests are routed for review on this turn and + * subsequent turns. + */ +approvalsReviewer?: ApprovalsReviewer | null, /** * Override the sandbox policy for this turn and subsequent turns. */ sandboxPolicy?: SandboxPolicy | null, /** diff --git a/src/app-server/v2/index.ts b/src/app-server/v2/index.ts index 5f9ee1ff..02917c23 100644 --- a/src/app-server/v2/index.ts +++ b/src/app-server/v2/index.ts @@ -21,6 +21,7 @@ export type { AppSummary } from "./AppSummary"; export type { AppToolApproval } from "./AppToolApproval"; export type { AppToolsConfig } from "./AppToolsConfig"; export type { ApprovalDecision } from "./ApprovalDecision"; +export type { ApprovalsReviewer } from "./ApprovalsReviewer"; export type { AppsConfig } from "./AppsConfig"; export type { AppsDefaultConfig } from "./AppsDefaultConfig"; export type { AppsListParams } from "./AppsListParams"; @@ -57,6 +58,7 @@ export type { CommandExecutionRequestAcceptSettings } from "./CommandExecutionRe export type { CommandExecutionRequestApprovalParams } from "./CommandExecutionRequestApprovalParams"; export type { CommandExecutionRequestApprovalResponse } from "./CommandExecutionRequestApprovalResponse"; export type { CommandExecutionRequestApprovalSkillMetadata } from "./CommandExecutionRequestApprovalSkillMetadata"; +export type { CommandExecutionSource } from "./CommandExecutionSource"; export type { CommandExecutionStatus } from "./CommandExecutionStatus"; export type { CommandRiskLevel } from "./CommandRiskLevel"; export type { Config } from "./Config"; @@ -84,6 +86,8 @@ export type { DynamicToolSpec } from "./DynamicToolSpec"; export type { ErrorNotification } from "./ErrorNotification"; export type { ExecPolicyAmendment } from "./ExecPolicyAmendment"; export type { ExperimentalFeature } from "./ExperimentalFeature"; +export type { ExperimentalFeatureEnablementSetParams } from "./ExperimentalFeatureEnablementSetParams"; +export type { ExperimentalFeatureEnablementSetResponse } from "./ExperimentalFeatureEnablementSetResponse"; export type { ExperimentalFeatureListParams } from "./ExperimentalFeatureListParams"; export type { ExperimentalFeatureListResponse } from "./ExperimentalFeatureListResponse"; export type { ExperimentalFeatureStage } from "./ExperimentalFeatureStage"; @@ -100,12 +104,35 @@ export type { FileChangeOutputDeltaNotification } from "./FileChangeOutputDeltaN export type { FileChangeRequestApprovalParams } from "./FileChangeRequestApprovalParams"; export type { FileChangeRequestApprovalResponse } from "./FileChangeRequestApprovalResponse"; export type { FileUpdateChange } from "./FileUpdateChange"; +export type { FsChangedNotification } from "./FsChangedNotification"; +export type { FsCopyParams } from "./FsCopyParams"; +export type { FsCopyResponse } from "./FsCopyResponse"; +export type { FsCreateDirectoryParams } from "./FsCreateDirectoryParams"; +export type { FsCreateDirectoryResponse } from "./FsCreateDirectoryResponse"; +export type { FsGetMetadataParams } from "./FsGetMetadataParams"; +export type { FsGetMetadataResponse } from "./FsGetMetadataResponse"; +export type { FsReadDirectoryEntry } from "./FsReadDirectoryEntry"; +export type { FsReadDirectoryParams } from "./FsReadDirectoryParams"; +export type { FsReadDirectoryResponse } from "./FsReadDirectoryResponse"; +export type { FsReadFileParams } from "./FsReadFileParams"; +export type { FsReadFileResponse } from "./FsReadFileResponse"; +export type { FsRemoveParams } from "./FsRemoveParams"; +export type { FsRemoveResponse } from "./FsRemoveResponse"; +export type { FsUnwatchParams } from "./FsUnwatchParams"; +export type { FsUnwatchResponse } from "./FsUnwatchResponse"; +export type { FsWatchParams } from "./FsWatchParams"; +export type { FsWatchResponse } from "./FsWatchResponse"; +export type { FsWriteFileParams } from "./FsWriteFileParams"; +export type { FsWriteFileResponse } from "./FsWriteFileResponse"; export type { GetAccountParams } from "./GetAccountParams"; export type { GetAccountRateLimitsResponse } from "./GetAccountRateLimitsResponse"; export type { GetAccountResponse } from "./GetAccountResponse"; export type { GitInfo } from "./GitInfo"; export type { GrantedMacOsPermissions } from "./GrantedMacOsPermissions"; export type { GrantedPermissionProfile } from "./GrantedPermissionProfile"; +export type { GuardianApprovalReview } from "./GuardianApprovalReview"; +export type { GuardianApprovalReviewStatus } from "./GuardianApprovalReviewStatus"; +export type { GuardianRiskLevel } from "./GuardianRiskLevel"; export type { HazelnutScope } from "./HazelnutScope"; export type { HookCompletedNotification } from "./HookCompletedNotification"; export type { HookEventName } from "./HookEventName"; @@ -113,11 +140,14 @@ export type { HookExecutionMode } from "./HookExecutionMode"; export type { HookHandlerType } from "./HookHandlerType"; export type { HookOutputEntry } from "./HookOutputEntry"; export type { HookOutputEntryKind } from "./HookOutputEntryKind"; +export type { HookPromptFragment } from "./HookPromptFragment"; export type { HookRunStatus } from "./HookRunStatus"; export type { HookRunSummary } from "./HookRunSummary"; export type { HookScope } from "./HookScope"; export type { HookStartedNotification } from "./HookStartedNotification"; export type { ItemCompletedNotification } from "./ItemCompletedNotification"; +export type { ItemGuardianApprovalReviewCompletedNotification } from "./ItemGuardianApprovalReviewCompletedNotification"; +export type { ItemGuardianApprovalReviewStartedNotification } from "./ItemGuardianApprovalReviewStartedNotification"; export type { ItemStartedNotification } from "./ItemStartedNotification"; export type { ListMcpServerStatusParams } from "./ListMcpServerStatusParams"; export type { ListMcpServerStatusResponse } from "./ListMcpServerStatusResponse"; @@ -126,6 +156,8 @@ export type { ListMcpServersResponse } from "./ListMcpServersResponse"; export type { LoginAccountParams } from "./LoginAccountParams"; export type { LoginAccountResponse } from "./LoginAccountResponse"; export type { LogoutAccountResponse } from "./LogoutAccountResponse"; +export type { MarketplaceInterface } from "./MarketplaceInterface"; +export type { MarketplaceLoadErrorInfo } from "./MarketplaceLoadErrorInfo"; export type { McpAuthStatus } from "./McpAuthStatus"; export type { McpElicitationArrayType } from "./McpElicitationArrayType"; export type { McpElicitationBooleanSchema } from "./McpElicitationBooleanSchema"; @@ -157,11 +189,15 @@ export type { McpServerOauthLoginCompletedNotification } from "./McpServerOauthL export type { McpServerOauthLoginParams } from "./McpServerOauthLoginParams"; export type { McpServerOauthLoginResponse } from "./McpServerOauthLoginResponse"; export type { McpServerRefreshResponse } from "./McpServerRefreshResponse"; +export type { McpServerStartupState } from "./McpServerStartupState"; export type { McpServerStatus } from "./McpServerStatus"; +export type { McpServerStatusUpdatedNotification } from "./McpServerStatusUpdatedNotification"; export type { McpToolCallError } from "./McpToolCallError"; export type { McpToolCallProgressNotification } from "./McpToolCallProgressNotification"; export type { McpToolCallResult } from "./McpToolCallResult"; export type { McpToolCallStatus } from "./McpToolCallStatus"; +export type { MemoryCitation } from "./MemoryCitation"; +export type { MemoryCitationEntry } from "./MemoryCitationEntry"; export type { MergeStrategy } from "./MergeStrategy"; export type { Model } from "./Model"; export type { ModelAvailabilityNux } from "./ModelAvailabilityNux"; @@ -173,9 +209,12 @@ export type { ModelUpgradeInfo } from "./ModelUpgradeInfo"; export type { NetworkAccess } from "./NetworkAccess"; export type { NetworkApprovalContext } from "./NetworkApprovalContext"; export type { NetworkApprovalProtocol } from "./NetworkApprovalProtocol"; +export type { NetworkDomainPermission } from "./NetworkDomainPermission"; export type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment"; export type { NetworkPolicyRuleAction } from "./NetworkPolicyRuleAction"; export type { NetworkRequirements } from "./NetworkRequirements"; +export type { NetworkUnixSocketPermission } from "./NetworkUnixSocketPermission"; +export type { NonSteerableTurnKind } from "./NonSteerableTurnKind"; export type { OverriddenMetadata } from "./OverriddenMetadata"; export type { PatchApplyStatus } from "./PatchApplyStatus"; export type { PatchChangeKind } from "./PatchChangeKind"; @@ -183,12 +222,17 @@ export type { PermissionGrantScope } from "./PermissionGrantScope"; export type { PermissionsRequestApprovalParams } from "./PermissionsRequestApprovalParams"; export type { PermissionsRequestApprovalResponse } from "./PermissionsRequestApprovalResponse"; export type { PlanDeltaNotification } from "./PlanDeltaNotification"; +export type { PluginAuthPolicy } from "./PluginAuthPolicy"; +export type { PluginDetail } from "./PluginDetail"; export type { PluginInstallParams } from "./PluginInstallParams"; +export type { PluginInstallPolicy } from "./PluginInstallPolicy"; export type { PluginInstallResponse } from "./PluginInstallResponse"; export type { PluginInterface } from "./PluginInterface"; export type { PluginListParams } from "./PluginListParams"; export type { PluginListResponse } from "./PluginListResponse"; export type { PluginMarketplaceEntry } from "./PluginMarketplaceEntry"; +export type { PluginReadParams } from "./PluginReadParams"; +export type { PluginReadResponse } from "./PluginReadResponse"; export type { PluginSource } from "./PluginSource"; export type { PluginSummary } from "./PluginSummary"; export type { PluginUninstallParams } from "./PluginUninstallParams"; @@ -204,6 +248,7 @@ export type { ReasoningSummaryPartAddedNotification } from "./ReasoningSummaryPa export type { ReasoningSummaryTextDeltaNotification } from "./ReasoningSummaryTextDeltaNotification"; export type { ReasoningTextDeltaNotification } from "./ReasoningTextDeltaNotification"; export type { RemoteSkillSummary } from "./RemoteSkillSummary"; +export type { RequestPermissionProfile } from "./RequestPermissionProfile"; export type { ResidencyRequirement } from "./ResidencyRequirement"; export type { ReviewDelivery } from "./ReviewDelivery"; export type { ReviewStartParams } from "./ReviewStartParams"; @@ -223,6 +268,7 @@ export type { SkillMetadata } from "./SkillMetadata"; export type { SkillRequestApprovalParams } from "./SkillRequestApprovalParams"; export type { SkillRequestApprovalResponse } from "./SkillRequestApprovalResponse"; export type { SkillScope } from "./SkillScope"; +export type { SkillSummary } from "./SkillSummary"; export type { SkillToolDependency } from "./SkillToolDependency"; export type { SkillsChangedNotification } from "./SkillsChangedNotification"; export type { SkillsConfigWriteParams } from "./SkillsConfigWriteParams"; @@ -268,12 +314,15 @@ export type { ThreadRealtimeErrorNotification } from "./ThreadRealtimeErrorNotif export type { ThreadRealtimeItemAddedNotification } from "./ThreadRealtimeItemAddedNotification"; export type { ThreadRealtimeOutputAudioDeltaNotification } from "./ThreadRealtimeOutputAudioDeltaNotification"; export type { ThreadRealtimeStartedNotification } from "./ThreadRealtimeStartedNotification"; +export type { ThreadRealtimeTranscriptUpdatedNotification } from "./ThreadRealtimeTranscriptUpdatedNotification"; export type { ThreadResumeParams } from "./ThreadResumeParams"; export type { ThreadResumeResponse } from "./ThreadResumeResponse"; export type { ThreadRollbackParams } from "./ThreadRollbackParams"; export type { ThreadRollbackResponse } from "./ThreadRollbackResponse"; export type { ThreadSetNameParams } from "./ThreadSetNameParams"; export type { ThreadSetNameResponse } from "./ThreadSetNameResponse"; +export type { ThreadShellCommandParams } from "./ThreadShellCommandParams"; +export type { ThreadShellCommandResponse } from "./ThreadShellCommandResponse"; export type { ThreadSortKey } from "./ThreadSortKey"; export type { ThreadSourceKind } from "./ThreadSourceKind"; export type { ThreadStartParams } from "./ThreadStartParams"; diff --git a/src/login.ts b/src/login.ts index 7de446d3..a46bdf89 100644 --- a/src/login.ts +++ b/src/login.ts @@ -89,6 +89,7 @@ async function login(options: LoginOptions): Promise { } logger.log("Starting ChatGPT login..."); + const loginCompletedPromise = waitForNextLoginCompleted(appServerClient); const loginResponse = await appServerClient.accountLogin({type: "chatgpt"}); if (loginResponse.type === "chatgpt") { @@ -100,7 +101,7 @@ async function login(options: LoginOptions): Promise { } logger.log("Waiting for login completion..."); - const result = await appServerClient.awaitLoginCompleted(); + const result = await loginCompletedPromise; if (result.success) { logger.log("Login successful!"); @@ -115,6 +116,14 @@ async function login(options: LoginOptions): Promise { } } +function waitForNextLoginCompleted(appServerClient: CodexAppServerClient): Promise<{ success: boolean }> { + return new Promise((resolve) => { + appServerClient.connection.onNotification("account/login/completed", (event: { success: boolean }) => { + resolve(event); + }); + }); +} + /** * Run the login command with the given CLI arguments. * @param args CLI arguments after "login" command (e.g., ["--client-name", "AIA"])