Skip to content

Commit 5e95a3d

Browse files
committed
🔀️ Merge branch 'ladislas/feature/292-headroom_proxy-extension'
2 parents cd10bb5 + b26841c commit 5e95a3d

5 files changed

Lines changed: 1045 additions & 0 deletions

File tree

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
import test from "node:test";
2+
import assert from "node:assert/strict";
3+
import {
4+
buildProviderOverrides,
5+
buildProxyArgs,
6+
formatStatus,
7+
getInstallGuidance,
8+
parseHeadroomArgs,
9+
} from "./helpers.ts";
10+
import { HeadroomProxyManager } from "./proxy.ts";
11+
12+
test("parses wrap defaults and env overrides", () => {
13+
assert.deepEqual(parseHeadroomArgs("wrap", {}), {
14+
action: "wrap",
15+
port: 8787,
16+
mode: "token",
17+
binary: "headroom",
18+
});
19+
assert.deepEqual(parseHeadroomArgs("wrap --port 8877 --mode cache --bin /opt/headroom", {}), {
20+
action: "wrap",
21+
port: 8877,
22+
mode: "cache",
23+
binary: "/opt/headroom",
24+
});
25+
assert.deepEqual(parseHeadroomArgs('wrap --bin "/opt/my headroom/headroom" --mode cache', {}), {
26+
action: "wrap",
27+
port: 8787,
28+
mode: "cache",
29+
binary: "/opt/my headroom/headroom",
30+
});
31+
assert.deepEqual(parseHeadroomArgs("wrap --bin /opt/my\\ headroom/headroom", {}), {
32+
action: "wrap",
33+
port: 8787,
34+
mode: "token",
35+
binary: "/opt/my headroom/headroom",
36+
});
37+
assert.deepEqual(parseHeadroomArgs("stop", { HEADROOM_PORT: "9999", HEADROOM_MODE: "cache", HEADROOM_BIN: "hr" }), {
38+
action: "stop",
39+
port: 9999,
40+
mode: "cache",
41+
binary: "hr",
42+
});
43+
});
44+
45+
test("rejects invalid command options", () => {
46+
assert.throws(() => parseHeadroomArgs("wrap --mode fast", {}), /--mode/);
47+
assert.throws(() => parseHeadroomArgs("wrap --port 99999", {}), /--port/);
48+
assert.throws(() => parseHeadroomArgs("wat", {}), /Usage/);
49+
});
50+
51+
test("builds proxy spawn args", () => {
52+
assert.deepEqual(buildProxyArgs({ port: 8877, mode: "cache" }), ["proxy", "--port", "8877", "--mode", "cache"]);
53+
});
54+
55+
test("builds provider overrides for supported Pi providers", () => {
56+
assert.deepEqual(buildProviderOverrides(8787), [
57+
{ provider: "openai-codex", config: { baseUrl: "http://127.0.0.1:8787/v1" } },
58+
{ provider: "openai", config: { baseUrl: "http://127.0.0.1:8787/v1" } },
59+
{ provider: "anthropic", config: { baseUrl: "http://127.0.0.1:8787" } },
60+
]);
61+
});
62+
63+
test("install guidance recommends uv tool install, not npm or pip", () => {
64+
const guidance = getInstallGuidance("headroom");
65+
assert.match(guidance, /uv tool install --python 3\.12 'headroom-ai\[proxy\]'/);
66+
assert.doesNotMatch(guidance, /npm install/);
67+
assert.doesNotMatch(guidance, /pip install/);
68+
});
69+
70+
test("formats status with health and stats summary", () => {
71+
const status = formatStatus({
72+
enabled: true,
73+
managed: true,
74+
baseUrl: "http://127.0.0.1:8787",
75+
health: { status: "healthy", ready: true, version: "0.22.3" },
76+
stats: { summary: { api_requests: 2, compression: { total_tokens_removed: 1234, avg_compression_pct: 42 } } },
77+
});
78+
assert.match(status, /Headroom: enabled/);
79+
assert.match(status, /Proxy: managed by Pi/);
80+
assert.match(status, /Health: healthy/);
81+
assert.match(status, /Requests: 2/);
82+
assert.match(status, /Tokens removed: 1234/);
83+
});
84+
85+
test("proxy manager reuses healthy external proxy without owning it", async () => {
86+
let spawned = false;
87+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
88+
spawn: () => {
89+
spawned = true;
90+
throw new Error("should not spawn");
91+
},
92+
fetchJson: async () => ({ status: "healthy" }),
93+
sleep: async () => {},
94+
});
95+
96+
const result = await manager.ensureRunning();
97+
assert.deepEqual(result, { ok: true, managed: false });
98+
assert.equal(spawned, false);
99+
assert.equal(manager.isManaged, false);
100+
});
101+
102+
test("proxy manager owns and stops only spawned healthy proxy", async () => {
103+
const kills = [];
104+
const child = {
105+
exitCode: null,
106+
kill(signal) {
107+
kills.push(signal ?? "default");
108+
this.exitCode = 0;
109+
return true;
110+
},
111+
on() { return this; },
112+
unref() {},
113+
};
114+
let healthCalls = 0;
115+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
116+
spawn: (command, args) => {
117+
assert.equal(command, "headroom");
118+
assert.deepEqual(args, ["proxy", "--port", "8787", "--mode", "token"]);
119+
return child;
120+
},
121+
fetchJson: async () => {
122+
healthCalls++;
123+
if (healthCalls === 1) throw new Error("not running yet");
124+
return { status: "healthy" };
125+
},
126+
sleep: async () => {},
127+
});
128+
129+
const result = await manager.ensureRunning();
130+
assert.deepEqual(result, { ok: true, managed: true });
131+
assert.equal(manager.isManaged, true);
132+
133+
await manager.stop();
134+
assert.deepEqual(kills, [process.platform === "win32" ? "default" : "SIGTERM"]);
135+
assert.equal(manager.isManaged, false);
136+
});
137+
138+
test("proxy manager does not kill external proxy on stop", async () => {
139+
let killed = false;
140+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
141+
spawn: () => ({ exitCode: null, kill: () => { killed = true; return true; }, on() { return this; } }),
142+
fetchJson: async () => ({ status: "healthy" }),
143+
sleep: async () => {},
144+
});
145+
146+
await manager.ensureRunning();
147+
await manager.stop();
148+
assert.equal(killed, false);
149+
});
150+
151+
test("proxy manager reports spawn errors such as missing headroom binary", async () => {
152+
let errorListener;
153+
const manager = new HeadroomProxyManager({ binary: "missing-headroom", port: 8787, mode: "token" }, {
154+
spawn: () => ({
155+
exitCode: null,
156+
kill: () => true,
157+
on(event, listener) {
158+
if (event === "error") errorListener = listener;
159+
return this;
160+
},
161+
}),
162+
fetchJson: async () => { throw new Error("offline"); },
163+
sleep: async () => { errorListener?.(new Error("spawn missing-headroom ENOENT")); },
164+
});
165+
166+
const result = await manager.ensureRunning();
167+
assert.equal(result.ok, false);
168+
assert.match(result.error.message, /ENOENT/);
169+
});
170+
171+
test("proxy manager kills a spawned proxy that never becomes healthy", async () => {
172+
const kills = [];
173+
const child = {
174+
exitCode: null,
175+
kill(signal) {
176+
kills.push(signal ?? "default");
177+
this.exitCode = 0;
178+
return true;
179+
},
180+
on() { return this; },
181+
};
182+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
183+
spawn: () => child,
184+
fetchJson: async () => { throw new Error("offline"); },
185+
sleep: async () => {},
186+
});
187+
188+
const result = await manager.ensureRunning();
189+
assert.equal(result.ok, false);
190+
assert.deepEqual(kills, [process.platform === "win32" ? "default" : "SIGTERM"]);
191+
assert.equal(manager.isManaged, false);
192+
});
193+
194+
test("proxy manager escalates stubborn managed proxies and suppresses kill races", async () => {
195+
const kills = [];
196+
let first = true;
197+
const child = {
198+
exitCode: null,
199+
kill(signal) {
200+
kills.push(signal ?? "default");
201+
if (first) {
202+
first = false;
203+
return true;
204+
}
205+
throw new Error("ESRCH");
206+
},
207+
on() { return this; },
208+
};
209+
let healthCalls = 0;
210+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
211+
spawn: () => child,
212+
fetchJson: async () => {
213+
healthCalls++;
214+
if (healthCalls === 1) throw new Error("offline");
215+
return { status: "healthy" };
216+
},
217+
sleep: async () => {},
218+
});
219+
220+
await manager.ensureRunning();
221+
await manager.stop();
222+
assert.deepEqual(kills, process.platform === "win32" ? ["default", "default"] : ["SIGTERM", "SIGKILL"]);
223+
assert.equal(manager.isManaged, false);
224+
});
225+
226+
test("proxy manager clears managed state when spawned proxy exits", async () => {
227+
let exitListener;
228+
const child = {
229+
exitCode: null,
230+
kill: () => true,
231+
on(event, listener) {
232+
if (event === "exit") exitListener = listener;
233+
return this;
234+
},
235+
};
236+
let healthCalls = 0;
237+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
238+
spawn: () => child,
239+
fetchJson: async () => {
240+
healthCalls++;
241+
if (healthCalls === 1) throw new Error("offline");
242+
return { status: "healthy" };
243+
},
244+
sleep: async () => {},
245+
});
246+
247+
await manager.ensureRunning();
248+
assert.equal(manager.isManaged, true);
249+
250+
child.exitCode = 0;
251+
exitListener();
252+
assert.equal(manager.isManaged, false);
253+
});
254+
255+
test("proxy manager stops unhealthy managed proxy before restart", async () => {
256+
const kills = [];
257+
const children = [
258+
{
259+
exitCode: null,
260+
kill(signal) {
261+
kills.push(signal ?? "default");
262+
this.exitCode = 0;
263+
return true;
264+
},
265+
on() { return this; },
266+
},
267+
{
268+
exitCode: null,
269+
kill: () => true,
270+
on() { return this; },
271+
},
272+
];
273+
let spawnCount = 0;
274+
let healthCalls = 0;
275+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
276+
spawn: () => children[spawnCount++],
277+
fetchJson: async () => {
278+
healthCalls++;
279+
if (healthCalls === 1 || healthCalls === 3) throw new Error("offline");
280+
return { status: "healthy" };
281+
},
282+
sleep: async () => {},
283+
});
284+
285+
await manager.ensureRunning();
286+
assert.equal(manager.isManaged, true);
287+
288+
await manager.ensureRunning();
289+
assert.equal(spawnCount, 2);
290+
assert.deepEqual(kills, [process.platform === "win32" ? "default" : "SIGTERM"]);
291+
});
292+
293+
test("proxy manager does not claim ownership if spawned proxy exits before external health appears", async () => {
294+
let exitListener;
295+
const child = {
296+
exitCode: null,
297+
kill: () => true,
298+
on(event, listener) {
299+
if (event === "exit") exitListener = listener;
300+
return this;
301+
},
302+
};
303+
let healthCalls = 0;
304+
const manager = new HeadroomProxyManager({ binary: "headroom", port: 8787, mode: "token" }, {
305+
spawn: () => child,
306+
fetchJson: async () => {
307+
healthCalls++;
308+
if (healthCalls === 1) throw new Error("offline");
309+
return { status: "healthy" };
310+
},
311+
sleep: async () => {
312+
if (exitListener && child.exitCode === null) {
313+
child.exitCode = 0;
314+
exitListener();
315+
}
316+
},
317+
});
318+
319+
const result = await manager.ensureRunning();
320+
assert.deepEqual(result, { ok: true, managed: false });
321+
assert.equal(manager.isManaged, false);
322+
});

0 commit comments

Comments
 (0)