fix(cliproxyapi): probe /v1/models for health (CPA 6.x has no /health) (#2189)

Integrated into release/v3.8.0 after syncing the contributor branch and validating tests/unit/cliproxyapi-executor.test.ts locally.
This commit is contained in:
Anton
2026-05-13 00:50:07 +02:00
committed by GitHub
parent 13f7ebce5a
commit a408b30896
2 changed files with 29 additions and 1 deletions

View File

@@ -344,11 +344,18 @@ export class CliproxyapiExecutor extends BaseExecutor {
/**
* Health check — verifies CLIProxyAPI is reachable.
*
* CPA 6.x doesn't expose a /health endpoint; previously we hit /health
* and got 404, which made the dashboard report "CLIProxyAPI not
* detected" even when the service was up and successfully serving
* /v1/messages. Probe /v1/models instead (returns 200 with the
* advertised model list), which is the closest thing CPA has to a
* liveness probe and works on every CPA version we've tested.
*/
async healthCheck(): Promise<{ ok: boolean; latencyMs: number; error?: string }> {
const start = Date.now();
try {
const res = await fetch(`${this.upstreamBaseUrl}/health`, {
const res = await fetch(`${this.upstreamBaseUrl}/v1/models`, {
signal: AbortSignal.timeout(HEALTH_CHECK_TIMEOUT_MS),
});
return {

View File

@@ -296,6 +296,27 @@ describe("CliproxyapiExecutor", () => {
});
});
describe("healthCheck", () => {
it("probes /v1/models instead of /health", async () => {
process.env.CLIPROXYAPI_HOST = "127.0.0.1";
process.env.CLIPROXYAPI_PORT = "8317";
let capturedUrl;
globalThis.fetch = async (url) => {
capturedUrl = String(url);
return new Response(JSON.stringify({ data: [] }), { status: 200 });
};
const exec = new CliproxyapiExecutor();
const result = await exec.healthCheck();
assert.equal(capturedUrl, "http://127.0.0.1:8317/v1/models");
assert.equal(result.ok, true);
assert.equal(result.error, undefined);
assert.ok(result.latencyMs >= 0);
});
});
describe("Anthropic-shape detection", () => {
it("detects Anthropic-shape when top-level system field present", () => {
const exec = new CliproxyapiExecutor();