Skip to content

Commit 5b8c0c9

Browse files
committed
test(auth): prove manual key transport on the wire
1 parent b717435 commit 5b8c0c9

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

src/agent/proxy-auth-wire.test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { mkdtempSync, rmSync } from "node:fs";
2+
import { type AddressInfo, createServer } from "node:http";
3+
import { tmpdir } from "node:os";
4+
import { join } from "node:path";
5+
import { completeSimple } from "@earendil-works/pi-ai";
6+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
7+
import { CredentialsStore } from "../auth/credentials.js";
8+
import { resolveConfig } from "./config.js";
9+
10+
describe("manual proxy authentication on the wire", () => {
11+
const requests: Array<Record<string, string | string[] | undefined>> = [];
12+
let server: ReturnType<typeof createServer>;
13+
let baseUrl: string;
14+
15+
beforeAll(async () => {
16+
server = createServer((req, res) => {
17+
requests.push(req.headers);
18+
res.writeHead(200, { "Content-Type": "text/event-stream" });
19+
res.write(
20+
`data: ${JSON.stringify({
21+
id: "chatcmpl-auth",
22+
object: "chat.completion.chunk",
23+
created: Math.floor(Date.now() / 1000),
24+
model: "d4f",
25+
choices: [{ index: 0, delta: { role: "assistant", content: "authenticated" }, finish_reason: null }],
26+
})}\n\n`,
27+
);
28+
res.write(
29+
`data: ${JSON.stringify({
30+
id: "chatcmpl-auth",
31+
object: "chat.completion.chunk",
32+
created: Math.floor(Date.now() / 1000),
33+
model: "d4f",
34+
choices: [{ index: 0, delta: {}, finish_reason: "stop" }],
35+
})}\n\n`,
36+
);
37+
res.end("data: [DONE]\n\n");
38+
});
39+
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
40+
const address = server.address() as AddressInfo;
41+
baseUrl = `http://127.0.0.1:${address.port}/inference`;
42+
});
43+
44+
afterAll(async () => {
45+
await new Promise<void>((resolve, reject) => {
46+
server.close((error) => (error ? reject(error) : resolve()));
47+
});
48+
});
49+
50+
it("sends X-API-Key through the real OpenAI-compatible transport", async () => {
51+
const dataRoot = mkdtempSync(join(tmpdir(), "codebase-proxy-wire-"));
52+
try {
53+
const credentials = new CredentialsStore({ dataRoot });
54+
credentials.save({
55+
accessToken: "cb_test_wire",
56+
scopes: ["inference"],
57+
source: "manual",
58+
});
59+
const config = resolveConfig({
60+
env: { CODEBASE_PROXY_BASE_URL: baseUrl },
61+
credentials,
62+
});
63+
64+
const response = await completeSimple(
65+
config.model,
66+
{ messages: [{ role: "user", content: [{ type: "text", text: "hello" }], timestamp: Date.now() }] },
67+
{ apiKey: config.apiKey },
68+
);
69+
70+
expect(response.content).toContainEqual({ type: "text", text: "authenticated" });
71+
expect(requests).toHaveLength(1);
72+
expect(requests[0]["x-api-key"]).toBe("cb_test_wire");
73+
} finally {
74+
rmSync(dataRoot, { recursive: true, force: true });
75+
}
76+
});
77+
});

0 commit comments

Comments
 (0)