fix(coding-agent): fail fast when RPC startup exits early

This commit is contained in:
can1357
2026-02-20 11:00:38 +01:00
parent 6bf59bf89c
commit c8230be4a7
3 changed files with 27 additions and 16 deletions
+5 -7
View File
@@ -1,17 +1,15 @@
# Changelog
## [Unreleased]
### Changed
- Implemented time-budget-based retry strategy for Google Gemini rate limits (429 errors), allowing retries within a 5-minute window instead of a fixed attempt cap
- Set default `maxRetries` to 5 for Anthropic, Azure OpenAI, and OpenAI client configurations to improve resilience against transient failures
### Fixed
- Improved error messages for OAuth token refresh failures by including detailed error information from the provider
- Separated rate limit and usage limit error handling to provide distinct user-friendly messages for ChatGPT rate limits vs subscription usage limits
- Changed 429 retry strategy for OpenAI Codex to use a 5-minute time budget when the server provides a retry delay, instead of a fixed 5-attempt cap
### Changed
- Increased SDK retry attempts to 5 for OpenAI, Azure OpenAI, and Anthropic clients (was SDK default of 2)
- Changed 429 retry strategy for OpenAI Codex and Google Gemini CLI to use a 5-minute time budget when the server provides a retry delay, instead of a fixed attempt cap
## [12.14.0] - 2026-02-19
### Added
@@ -134,15 +134,11 @@ export class RpcClient {
// Wait a moment for process to initialize
await Bun.sleep(100);
try {
const exitCode = await Promise.race([this.#process.exited, Bun.sleep(500).then(() => null)]);
if (exitCode !== null) {
throw new Error(
`Agent process exited immediately with code ${exitCode}. Stderr: ${this.#process.peekStderr()}`,
);
}
} catch {
// Process still running, which is what we want
const exitCode = await Promise.race([this.#process.exited, Bun.sleep(500).then(() => null)]);
if (exitCode !== null) {
throw new Error(
`Agent process exited immediately with code ${exitCode}. Stderr: ${this.#process.peekStderr()}`,
);
}
}
@@ -0,0 +1,17 @@
import { describe, expect, test } from "bun:test";
import * as path from "node:path";
import { RpcClient } from "@oh-my-pi/pi-coding-agent/modes/rpc/rpc-client";
describe("RpcClient.start", () => {
test("rejects when RPC process exits immediately", async () => {
using client = new RpcClient({
cliPath: path.join(import.meta.dir, "..", "src", "cli.ts"),
cwd: path.join(import.meta.dir, ".."),
provider: "__missing_provider__",
model: "claude-sonnet-4-5",
env: { PI_NO_TITLE: "1" },
});
await expect(client.start()).rejects.toThrow('Unknown provider "__missing_provider__"');
});
});