1import { assert, it } from "@effect/vitest";
2import * as Effect from "effect/Effect";
3import { HttpClient, HttpClientResponse } from "effect/http";
4import { chatGptModels } from "./CodexChatGptModels.ts";
5
6it.effect(
7 "uses each selected profile's token and the server's visible catalog order and names",
8 () =>
9 Effect.gen(function* () {
10 const requests: string[] = [];
11 const http = HttpClient.make((request) =>
12 Effect.sync(() => {
13 assert.strictEqual(request.url, "https://api.openai.com/v1/models");
14 requests.push(request.headers.authorization!);
15 return HttpClientResponse.fromWeb(
16 request,
17 new Response(
18 JSON.stringify({
19 models:
20 request.headers.authorization === "Bearer account-a"
21 ? [
22 { slug: "second", display_name: "Second from OpenAI", visibility: "list" },
23 { slug: "hidden", display_name: "Hidden", visibility: "hidden" },
24 { slug: "first", display_name: "First from OpenAI", visibility: "list" },
25 ]
26 : [{ slug: "account-b-only", display_name: "B", visibility: "list" }],
27 }),
28 ),
29 );
30 }),
31 );
32 const native = [
33 {
34 slug: "first",
35 name: "Cached first",
36 isCustom: false,
37 capabilities: { optionDescriptors: [] },
38 },
39 { slug: "not-entitled", name: "Cached other", isCustom: false, capabilities: null },
40 ];
41 const a = yield* chatGptModels("account-a", native).pipe(
42 Effect.provideService(HttpClient.HttpClient, http),
43 );
44 assert.deepEqual(
45 a.map((model) => [model.slug, model.name]),
46 [
47 ["second", "Second from OpenAI"],
48 ["first", "First from OpenAI"],
49 ],
50 );
51 assert.deepEqual(a[1]!.capabilities, native[0]!.capabilities);
52 assert.isNull(a[0]!.capabilities);
53 const b = yield* chatGptModels("account-b", native).pipe(
54 Effect.provideService(HttpClient.HttpClient, http),
55 );
56 assert.deepEqual(
57 b.map((model) => model.slug),
58 ["account-b-only"],
59 );
60 assert.deepEqual(requests, ["Bearer account-a", "Bearer account-b"]);
61 }),
62);
63
64it.effect("does not present a cached catalog as account entitlements when discovery fails", () =>
65 Effect.gen(function* () {
66 const http = HttpClient.make((request) =>
67 Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null, { status: 503 }))),
68 );
69 const error = yield* Effect.flip(
70 chatGptModels("account-a", []).pipe(Effect.provideService(HttpClient.HttpClient, http)),
71 );
72 assert.strictEqual(error._tag, "ChatGptCatalogError");
73 }),
74);