@cochon123/cli2api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/dist/adapters/claude.d.ts +27 -0
  4. package/dist/adapters/claude.js +253 -0
  5. package/dist/adapters/claude.js.map +1 -0
  6. package/dist/adapters/codex.d.ts +51 -0
  7. package/dist/adapters/codex.js +491 -0
  8. package/dist/adapters/codex.js.map +1 -0
  9. package/dist/adapters/cursor.d.ts +31 -0
  10. package/dist/adapters/cursor.js +231 -0
  11. package/dist/adapters/cursor.js.map +1 -0
  12. package/dist/adapters/mock.d.ts +2 -0
  13. package/dist/adapters/mock.js +101 -0
  14. package/dist/adapters/mock.js.map +1 -0
  15. package/dist/adapters/opencode.d.ts +27 -0
  16. package/dist/adapters/opencode.js +208 -0
  17. package/dist/adapters/opencode.js.map +1 -0
  18. package/dist/adapters/registry.d.ts +33 -0
  19. package/dist/adapters/registry.js +99 -0
  20. package/dist/adapters/registry.js.map +1 -0
  21. package/dist/adapters/types.d.ts +18 -0
  22. package/dist/adapters/types.js +35 -0
  23. package/dist/adapters/types.js.map +1 -0
  24. package/dist/config.d.ts +126 -0
  25. package/dist/config.js +121 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js +253 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/openrouter/catalog.d.ts +28 -0
  31. package/dist/openrouter/catalog.js +162 -0
  32. package/dist/openrouter/catalog.js.map +1 -0
  33. package/dist/protocol/openai.d.ts +48 -0
  34. package/dist/protocol/openai.js +236 -0
  35. package/dist/protocol/openai.js.map +1 -0
  36. package/dist/protocol/responses.d.ts +57 -0
  37. package/dist/protocol/responses.js +142 -0
  38. package/dist/protocol/responses.js.map +1 -0
  39. package/dist/protocol/tools.d.ts +7 -0
  40. package/dist/protocol/tools.js +143 -0
  41. package/dist/protocol/tools.js.map +1 -0
  42. package/dist/server/app.d.ts +25 -0
  43. package/dist/server/app.js +425 -0
  44. package/dist/server/app.js.map +1 -0
  45. package/dist/server/listen.d.ts +18 -0
  46. package/dist/server/listen.js +30 -0
  47. package/dist/server/listen.js.map +1 -0
  48. package/dist/session.d.ts +9 -0
  49. package/dist/session.js +39 -0
  50. package/dist/session.js.map +1 -0
  51. package/dist/types.d.ts +192 -0
  52. package/dist/types.js +3 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/util/process.d.ts +38 -0
  55. package/dist/util/process.js +292 -0
  56. package/dist/util/process.js.map +1 -0
  57. package/package.json +65 -0
package/dist/index.js ADDED
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env node
2
+ import { randomUUID } from "node:crypto";
3
+ import { Command } from "commander";
4
+ import { createRegistry } from "./adapters/registry.js";
5
+ import { collectChatText } from "./adapters/types.js";
6
+ import { listen } from "./server/listen.js";
7
+ import { normalizeChatRequest } from "./protocol/openai.js";
8
+ import { configPathFromArgv, loadConfig, withoutConfigArg } from "./config.js";
9
+ import { transformToolEvents } from "./protocol/tools.js";
10
+ const DEFAULT_PORT = 3927;
11
+ let loadedConfig;
12
+ try {
13
+ loadedConfig = await loadConfig({ explicitPath: configPathFromArgv(process.argv.slice(2)) });
14
+ }
15
+ catch (error) {
16
+ console.error(error instanceof Error ? error.message : error);
17
+ process.exit(1);
18
+ }
19
+ function env(name) {
20
+ const v = process.env[name];
21
+ return v && v.length ? v : undefined;
22
+ }
23
+ function isAdapterId(value) {
24
+ return value === "mock" || value === "codex" || value === "opencode" || value === "cursor" || value === "claude";
25
+ }
26
+ function buildRegistry(opts) {
27
+ const defaultAdapter = opts.adapter ?? env("CLI2API_ADAPTER") ?? loadedConfig.defaultAdapter ?? "mock";
28
+ return createRegistry({
29
+ defaultAdapter: isAdapterId(defaultAdapter) ? defaultAdapter : "mock",
30
+ modelAliases: loadedConfig.modelAliases,
31
+ modelRoutes: loadedConfig.openRouter?.modelRoutes,
32
+ codex: {
33
+ binary: opts.codexBin ?? env("CLI2API_CODEX_BIN") ?? loadedConfig.binaries?.codex ?? "codex",
34
+ cwd: opts.cwd ?? env("CLI2API_CWD") ?? loadedConfig.cwd,
35
+ },
36
+ opencode: {
37
+ binary: opts.opencodeBin ?? env("CLI2API_OPENCODE_BIN") ?? loadedConfig.binaries?.opencode ?? "opencode",
38
+ cwd: opts.cwd ?? env("CLI2API_CWD") ?? loadedConfig.cwd,
39
+ },
40
+ cursor: {
41
+ binary: opts.cursorBin ?? env("CLI2API_CURSOR_BIN") ?? loadedConfig.binaries?.cursor ?? "cursor-agent",
42
+ cwd: opts.cwd ?? env("CLI2API_CWD") ?? loadedConfig.cwd,
43
+ },
44
+ claude: {
45
+ binary: opts.claudeBin ?? env("CLI2API_CLAUDE_BIN") ?? loadedConfig.binaries?.claude ?? "claude",
46
+ cwd: opts.cwd ?? env("CLI2API_CWD") ?? loadedConfig.cwd,
47
+ },
48
+ });
49
+ }
50
+ function printJson(data) {
51
+ process.stdout.write(JSON.stringify(data, null, 2) + "\n");
52
+ }
53
+ const program = new Command();
54
+ program
55
+ .name("cli2api")
56
+ .description("Local OpenAI-compatible gateway for coding CLIs (localhost only)")
57
+ .version("0.1.0")
58
+ .option("--config <path>", "JSON config path (also CLI2API_CONFIG)");
59
+ program
60
+ .command("serve")
61
+ .description("Start the local OpenAI-compatible HTTP server")
62
+ .option("-p, --port <port>", "Port to listen on", String(Number(env("CLI2API_PORT")) || loadedConfig.port || DEFAULT_PORT))
63
+ .option("-H, --host <host>", "Host to bind (loopback only)", "127.0.0.1")
64
+ .option("-a, --adapter <id>", "Default adapter (mock|codex|opencode|cursor|claude)", env("CLI2API_ADAPTER") ?? loadedConfig.defaultAdapter ?? "mock")
65
+ .option("-t, --token <token>", "Bearer token (also CLI2API_TOKEN); auto-generated if omitted", env("CLI2API_TOKEN") ?? loadedConfig.token)
66
+ .option("--codex-bin <path>", "Codex binary path", env("CLI2API_CODEX_BIN"))
67
+ .option("--opencode-bin <path>", "OpenCode binary path", env("CLI2API_OPENCODE_BIN"))
68
+ .option("--cursor-bin <path>", "Cursor Agent binary path", env("CLI2API_CURSOR_BIN"))
69
+ .option("--claude-bin <path>", "Claude Code binary path", env("CLI2API_CLAUDE_BIN"))
70
+ .option("--cwd <dir>", "Working directory for CLI adapters", env("CLI2API_CWD") ?? loadedConfig.cwd)
71
+ .option("--openrouter-catalog <mode>", "OpenRouter model catalog: runnable|mirror", env("CLI2API_OPENROUTER_CATALOG") ?? loadedConfig.openRouter?.catalogMode ?? "runnable")
72
+ .option("-v, --verbose", "Log requests", false)
73
+ .action(async (opts) => {
74
+ if (opts.openrouterCatalog !== "runnable" && opts.openrouterCatalog !== "mirror") {
75
+ console.error(`Invalid --openrouter-catalog value: ${opts.openrouterCatalog}. Expected runnable or mirror.`);
76
+ process.exit(1);
77
+ }
78
+ const registry = buildRegistry({
79
+ adapter: opts.adapter,
80
+ codexBin: opts.codexBin,
81
+ opencodeBin: opts.opencodeBin,
82
+ cursorBin: opts.cursorBin,
83
+ claudeBin: opts.claudeBin,
84
+ cwd: opts.cwd,
85
+ });
86
+ const port = Number(opts.port) || DEFAULT_PORT;
87
+ const tokenProvided = Boolean(opts.token);
88
+ const token = opts.token || randomUUID();
89
+ try {
90
+ const server = await listen({
91
+ registry,
92
+ host: opts.host,
93
+ port,
94
+ adapter: opts.adapter,
95
+ token,
96
+ verbose: opts.verbose,
97
+ openRouter: {
98
+ defaultModel: loadedConfig.openRouter?.defaultModel,
99
+ mode: opts.openrouterCatalog === "mirror" ? "mirror" : "runnable",
100
+ annotateAvailability: loadedConfig.openRouter?.annotateAvailability ?? true,
101
+ metadataUrl: loadedConfig.openRouter?.metadataUrl,
102
+ metadataTtlSeconds: loadedConfig.openRouter?.metadataTtlSeconds,
103
+ metadataCachePath: loadedConfig.openRouter?.metadataCachePath,
104
+ apiKey: env("OPENROUTER_API_KEY"),
105
+ },
106
+ });
107
+ const base = `http://${server.host}:${server.port}`;
108
+ console.error(`cli2api listening on ${base}`);
109
+ console.error(` adapters: ${registry.list().map((a) => a.id).join(", ")} (default: ${registry.defaultAdapterId})`);
110
+ if (loadedConfig.loadedPaths.length)
111
+ console.error(` config: ${loadedConfig.loadedPaths.join(", ")}`);
112
+ console.error(` health: ${base}/health`);
113
+ console.error(` models: ${base}/v1/models`);
114
+ console.error(` chat: ${base}/v1/chat/completions`);
115
+ console.error(` openrouter: ${base}/api/v1 (catalog: ${opts.openrouterCatalog})`);
116
+ if (!tokenProvided) {
117
+ console.error(` token: ${token} (generated for this session — set CLI2API_TOKEN to pin it)`);
118
+ }
119
+ console.error("");
120
+ console.error("Env swap:");
121
+ console.error(` OPENAI_BASE_URL=${base}/v1`);
122
+ console.error(` OPENAI_API_KEY=${token}`);
123
+ console.error(` OPENAI_MODEL=${opts.adapter === "mock" ? "mock/echo" : `${opts.adapter}/default`}`);
124
+ const shutdown = () => {
125
+ console.error("\nshutting down…");
126
+ server.close();
127
+ process.exit(0);
128
+ };
129
+ process.on("SIGINT", shutdown);
130
+ process.on("SIGTERM", shutdown);
131
+ }
132
+ catch (err) {
133
+ console.error(err instanceof Error ? err.message : err);
134
+ process.exit(1);
135
+ }
136
+ });
137
+ program
138
+ .command("doctor")
139
+ .description("Check installed adapters / CLIs")
140
+ .option("-a, --adapter <id>", "Only check one adapter")
141
+ .option("--codex-bin <path>", "Codex binary path", env("CLI2API_CODEX_BIN"))
142
+ .option("--opencode-bin <path>", "OpenCode binary path", env("CLI2API_OPENCODE_BIN"))
143
+ .option("--cursor-bin <path>", "Cursor Agent binary path", env("CLI2API_CURSOR_BIN"))
144
+ .option("--claude-bin <path>", "Claude Code binary path", env("CLI2API_CLAUDE_BIN"))
145
+ .option("--json", "Machine-readable JSON", false)
146
+ .action(async (opts) => {
147
+ const registry = buildRegistry({
148
+ adapter: opts.adapter,
149
+ codexBin: opts.codexBin,
150
+ opencodeBin: opts.opencodeBin,
151
+ cursorBin: opts.cursorBin,
152
+ claudeBin: opts.claudeBin,
153
+ });
154
+ const adapters = opts.adapter
155
+ ? [registry.get(opts.adapter)].filter(Boolean)
156
+ : registry.list();
157
+ if (!adapters.length) {
158
+ console.error(`Unknown adapter: ${opts.adapter}`);
159
+ process.exit(1);
160
+ }
161
+ const reports = await Promise.all(adapters.map((a) => a.doctor()));
162
+ if (opts.json) {
163
+ printJson({ ok: reports.every((r) => r.ok), adapters: reports });
164
+ }
165
+ else {
166
+ for (const r of reports) {
167
+ console.log(`${r.ok ? "ok" : "FAIL"} ${r.adapter}${r.version ? ` (${r.version})` : ""}`);
168
+ for (const c of r.checks) {
169
+ console.log(` [${c.ok ? "ok" : "x"}] ${c.name}${c.detail ? ` — ${c.detail}` : ""}`);
170
+ }
171
+ }
172
+ }
173
+ process.exit(reports.every((r) => r.ok) ? 0 : 1);
174
+ });
175
+ program
176
+ .command("models")
177
+ .description("List models exposed by adapters")
178
+ .option("--json", "Machine-readable JSON", false)
179
+ .option("--codex-bin <path>", "Codex binary path", env("CLI2API_CODEX_BIN"))
180
+ .option("--opencode-bin <path>", "OpenCode binary path", env("CLI2API_OPENCODE_BIN"))
181
+ .option("--cursor-bin <path>", "Cursor Agent binary path", env("CLI2API_CURSOR_BIN"))
182
+ .option("--claude-bin <path>", "Claude Code binary path", env("CLI2API_CLAUDE_BIN"))
183
+ .action(async (opts) => {
184
+ const registry = buildRegistry({
185
+ codexBin: opts.codexBin,
186
+ opencodeBin: opts.opencodeBin,
187
+ cursorBin: opts.cursorBin,
188
+ claudeBin: opts.claudeBin,
189
+ });
190
+ const models = await registry.listModels();
191
+ if (opts.json)
192
+ printJson({ object: "list", data: models });
193
+ else
194
+ for (const m of models)
195
+ console.log(m.id + (m.description ? ` # ${m.description}` : ""));
196
+ });
197
+ program
198
+ .command("completion")
199
+ .description("One-shot smoke completion (no server)")
200
+ .requiredOption("-p, --prompt <text>", "User prompt")
201
+ .option("-m, --model <id>", "Model id", "mock/echo")
202
+ .option("-a, --adapter <id>", "Force adapter")
203
+ .option("--codex-bin <path>", "Codex binary path", env("CLI2API_CODEX_BIN"))
204
+ .option("--opencode-bin <path>", "OpenCode binary path", env("CLI2API_OPENCODE_BIN"))
205
+ .option("--cursor-bin <path>", "Cursor Agent binary path", env("CLI2API_CURSOR_BIN"))
206
+ .option("--claude-bin <path>", "Claude Code binary path", env("CLI2API_CLAUDE_BIN"))
207
+ .option("--cwd <dir>", "Working directory for CLI adapters", env("CLI2API_CWD"))
208
+ .option("--json", "Print full result as JSON", false)
209
+ .action(async (opts) => {
210
+ const registry = buildRegistry({
211
+ adapter: opts.adapter,
212
+ codexBin: opts.codexBin,
213
+ opencodeBin: opts.opencodeBin,
214
+ cursorBin: opts.cursorBin,
215
+ claudeBin: opts.claudeBin,
216
+ cwd: opts.cwd,
217
+ });
218
+ const body = {
219
+ model: opts.model,
220
+ messages: [{ role: "user", content: opts.prompt }],
221
+ };
222
+ const originalReq = normalizeChatRequest(body);
223
+ const req = registry.normalizeRequest(originalReq);
224
+ const adapter = registry.resolve(req.model, opts.adapter);
225
+ const result = await collectChatText(transformToolEvents(adapter.chat(req, new AbortController().signal), req));
226
+ if (opts.json) {
227
+ printJson({ adapter: adapter.id, model: originalReq.model, resolvedModel: req.model, ...result });
228
+ }
229
+ else if (result.error) {
230
+ console.error(result.error);
231
+ process.exit(1);
232
+ }
233
+ else {
234
+ process.stdout.write(result.text + (result.text.endsWith("\n") ? "" : "\n"));
235
+ }
236
+ if (result.error)
237
+ process.exit(1);
238
+ });
239
+ program
240
+ .command("adapters")
241
+ .description("List registered adapters")
242
+ .option("--json", "Machine-readable JSON", false)
243
+ .action((opts) => {
244
+ const registry = buildRegistry({});
245
+ const list = registry.list().map((a) => ({ id: a.id, description: a.description }));
246
+ if (opts.json)
247
+ printJson(list);
248
+ else
249
+ for (const a of list)
250
+ console.log(`${a.id}\t${a.description}`);
251
+ });
252
+ await program.parseAsync(withoutConfigArg(process.argv));
253
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,gBAAgB,EAAqB,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,IAAI,YAA0B,CAAC;AAC/B,IAAI,CAAC;IACH,YAAY,GAAG,MAAM,UAAU,CAAC,EAAE,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC/F,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACvC,CAAC;AAED,SAAS,WAAW,CAAC,KAAyB;IAC5C,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,QAAQ,CAAC;AACnH,CAAC;AAWD,SAAS,aAAa,CAAC,IAAwB;IAC7C,MAAM,cAAc,GAAI,IAAI,CAAC,OAAiC,IAAK,GAAG,CAAC,iBAAiB,CAA2B,IAAI,YAAY,CAAC,cAAc,IAAI,MAAM,CAAC;IAC7J,OAAO,cAAc,CAAC;QACpB,cAAc,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM;QACrE,YAAY,EAAE,YAAY,CAAC,YAAY;QACvC,WAAW,EAAE,YAAY,CAAC,UAAU,EAAE,WAAW;QACjD,KAAK,EAAE;YACL,MAAM,EAAE,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,mBAAmB,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,KAAK,IAAI,OAAO;YAC5F,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,GAAG;SACxD;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC,sBAAsB,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,QAAQ,IAAI,UAAU;YACxG,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,GAAG;SACxD;QACD,MAAM,EAAE;YACN,MAAM,EAAE,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,oBAAoB,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,cAAc;YACtG,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,GAAG;SACxD;QACD,MAAM,EAAE;YACN,MAAM,EAAE,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,oBAAoB,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,QAAQ;YAChG,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,GAAG;SACxD;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,IAAa;IAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,kEAAkE,CAAC;KAC/E,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,iBAAiB,EAAE,wCAAwC,CAAC,CAAC;AAEvE,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,IAAI,YAAY,CAAC,CAAC;KAC1H,MAAM,CAAC,mBAAmB,EAAE,8BAA8B,EAAE,WAAW,CAAC;KACxE,MAAM,CAAC,oBAAoB,EAAE,qDAAqD,EAAE,GAAG,CAAC,iBAAiB,CAAC,IAAI,YAAY,CAAC,cAAc,IAAI,MAAM,CAAC;KACpJ,MAAM,CAAC,qBAAqB,EAAE,8DAA8D,EAAE,GAAG,CAAC,eAAe,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC;KACzI,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;KAC3E,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,GAAG,CAAC,sBAAsB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,0BAA0B,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,yBAAyB,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACnF,MAAM,CAAC,aAAa,EAAE,oCAAoC,EAAE,GAAG,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC;KACnG,MAAM,CAAC,6BAA6B,EAAE,2CAA2C,EAAE,GAAG,CAAC,4BAA4B,CAAC,IAAI,YAAY,CAAC,UAAU,EAAE,WAAW,IAAI,UAAU,CAAC;KAC3K,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,KAAK,CAAC;KAC9C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,IAAI,CAAC,iBAAiB,KAAK,UAAU,IAAI,IAAI,CAAC,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QACjF,OAAO,CAAC,KAAK,CAAC,uCAAuC,IAAI,CAAC,iBAAiB,gCAAgC,CAAC,CAAC;QAC7G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,GAAG,EAAE,IAAI,CAAC,GAAG;KACd,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC;IAC/C,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAW,IAAI,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC;YAC1B,QAAQ;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE;gBACV,YAAY,EAAE,YAAY,CAAC,UAAU,EAAE,YAAY;gBACnD,IAAI,EAAE,IAAI,CAAC,iBAAiB,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU;gBACjE,oBAAoB,EAAE,YAAY,CAAC,UAAU,EAAE,oBAAoB,IAAI,IAAI;gBAC3E,WAAW,EAAE,YAAY,CAAC,UAAU,EAAE,WAAW;gBACjD,kBAAkB,EAAE,YAAY,CAAC,UAAU,EAAE,kBAAkB;gBAC/D,iBAAiB,EAAE,YAAY,CAAC,UAAU,EAAE,iBAAiB;gBAC7D,MAAM,EAAE,GAAG,CAAC,oBAAoB,CAAC;aAClC;SACF,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,UAAU,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,eAAe,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,QAAQ,CAAC,gBAAgB,GAAG,CAAC,CAAC;QACpH,IAAI,YAAY,CAAC,WAAW,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,eAAe,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzG,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,YAAY,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,sBAAsB,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,iBAAiB,IAAI,sBAAsB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QACpF,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,eAAe,KAAK,8DAA8D,CAAC,CAAC;QACpG,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,qBAAqB,IAAI,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,kBAAkB,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,UAAU,EAAE,CAAC,CAAC;QAErG,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,oBAAoB,EAAE,wBAAwB,CAAC;KACtD,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;KAC3E,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,GAAG,CAAC,sBAAsB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,0BAA0B,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,yBAAyB,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACnF,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO;QAC3B,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QAC9C,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEpB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACpE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3F,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;KAC3E,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,GAAG,CAAC,sBAAsB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,0BAA0B,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,yBAAyB,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACnF,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;IAC3C,IAAI,IAAI,CAAC,IAAI;QAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;;QACtD,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjG,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,uCAAuC,CAAC;KACpD,cAAc,CAAC,qBAAqB,EAAE,aAAa,CAAC;KACpD,MAAM,CAAC,kBAAkB,EAAE,UAAU,EAAE,WAAW,CAAC;KACnD,MAAM,CAAC,oBAAoB,EAAE,eAAe,CAAC;KAC7C,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;KAC3E,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,GAAG,CAAC,sBAAsB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,0BAA0B,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACpF,MAAM,CAAC,qBAAqB,EAAE,yBAAyB,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACnF,MAAM,CAAC,aAAa,EAAE,oCAAoC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;KAC/E,MAAM,CAAC,QAAQ,EAAE,2BAA2B,EAAE,KAAK,CAAC;KACpD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,GAAG,EAAE,IAAI,CAAC,GAAG;KACd,CAAC,CAAC;IACH,MAAM,IAAI,GAAG;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;KAC5D,CAAC;IACF,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAChH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACpG,CAAC;SAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,MAAM,QAAQ,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACpF,IAAI,IAAI,CAAC,IAAI;QAAE,SAAS,CAAC,IAAI,CAAC,CAAC;;QAC1B,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEL,MAAM,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { AdapterRegistry } from "../adapters/registry.js";
2
+ export type OpenRouterCatalogMode = "runnable" | "mirror";
3
+ export interface OpenRouterCatalogOptions {
4
+ mode?: OpenRouterCatalogMode;
5
+ annotateAvailability?: boolean;
6
+ metadataUrl?: string;
7
+ metadataTtlSeconds?: number;
8
+ metadataCachePath?: string;
9
+ apiKey?: string;
10
+ fetchImpl?: typeof fetch;
11
+ }
12
+ export declare class OpenRouterCatalog {
13
+ private readonly registry;
14
+ private readonly mode;
15
+ private readonly annotateAvailability;
16
+ private readonly metadataUrl;
17
+ private readonly ttlMs;
18
+ private readonly path;
19
+ private readonly apiKey?;
20
+ private readonly fetchImpl;
21
+ private memory?;
22
+ private refresh?;
23
+ constructor(registry: AdapterRegistry, opts?: OpenRouterCatalogOptions);
24
+ private readCache;
25
+ private fetchCatalog;
26
+ private upstream;
27
+ list(query?: URLSearchParams): Promise<Array<Record<string, unknown>>>;
28
+ }
@@ -0,0 +1,162 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join, resolve } from "node:path";
4
+ const DEFAULT_METADATA_URL = "https://openrouter.ai/api/v1/models";
5
+ const DEFAULT_TTL_SECONDS = 86_400;
6
+ const LOCALLY_SUPPORTED_PARAMETERS = ["tools", "tool_choice", "reasoning", "include_reasoning"];
7
+ function isRecord(value) {
8
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9
+ }
10
+ function modelId(model) {
11
+ return typeof model.id === "string" ? model.id : undefined;
12
+ }
13
+ function cachePath(path) {
14
+ if (path)
15
+ return resolve(path);
16
+ const cacheHome = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
17
+ return join(cacheHome, "cli2api", "openrouter-models.json");
18
+ }
19
+ function annotate(model, registry) {
20
+ const id = modelId(model) ?? "";
21
+ const route = registry.modelRoutes[id];
22
+ const available = Boolean(route) || registry.isExplicitlyRoutable(id);
23
+ return {
24
+ ...model,
25
+ cli2api: {
26
+ available,
27
+ ...(route ? { adapter: route.adapter, local_model: route.model } : {}),
28
+ },
29
+ };
30
+ }
31
+ function filterModels(models, query) {
32
+ if (!query)
33
+ return models;
34
+ const q = query.get("q")?.trim().toLowerCase();
35
+ const supported = query.get("supported_parameters")?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
36
+ const input = query.get("input_modalities")?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
37
+ const output = query.get("output_modalities")?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
38
+ return models.filter((model) => {
39
+ if (q) {
40
+ const haystack = `${String(model.id ?? "")} ${String(model.name ?? "")} ${String(model.description ?? "")}`.toLowerCase();
41
+ if (!haystack.includes(q))
42
+ return false;
43
+ }
44
+ const parameters = Array.isArray(model.supported_parameters) ? model.supported_parameters : [];
45
+ if (supported.some((parameter) => !parameters.includes(parameter)))
46
+ return false;
47
+ const architecture = isRecord(model.architecture) ? model.architecture : {};
48
+ const inputModalities = Array.isArray(architecture.input_modalities) ? architecture.input_modalities : [];
49
+ const outputModalities = Array.isArray(architecture.output_modalities) ? architecture.output_modalities : [];
50
+ if (input.some((modality) => !inputModalities.includes(modality)))
51
+ return false;
52
+ if (output.some((modality) => !outputModalities.includes(modality)))
53
+ return false;
54
+ return true;
55
+ });
56
+ }
57
+ export class OpenRouterCatalog {
58
+ registry;
59
+ mode;
60
+ annotateAvailability;
61
+ metadataUrl;
62
+ ttlMs;
63
+ path;
64
+ apiKey;
65
+ fetchImpl;
66
+ memory;
67
+ refresh;
68
+ constructor(registry, opts = {}) {
69
+ this.registry = registry;
70
+ this.mode = opts.mode ?? "runnable";
71
+ this.annotateAvailability = opts.annotateAvailability ?? true;
72
+ this.metadataUrl = opts.metadataUrl ?? DEFAULT_METADATA_URL;
73
+ this.ttlMs = (opts.metadataTtlSeconds ?? DEFAULT_TTL_SECONDS) * 1000;
74
+ this.path = cachePath(opts.metadataCachePath);
75
+ this.apiKey = opts.apiKey;
76
+ this.fetchImpl = opts.fetchImpl ?? fetch;
77
+ }
78
+ async readCache() {
79
+ if (this.memory)
80
+ return this.memory;
81
+ try {
82
+ const parsed = JSON.parse(await readFile(this.path, "utf8"));
83
+ if (!isRecord(parsed)
84
+ || parsed.sourceUrl !== this.metadataUrl
85
+ || typeof parsed.fetchedAt !== "number"
86
+ || !Array.isArray(parsed.data))
87
+ return undefined;
88
+ const data = parsed.data.filter(isRecord);
89
+ this.memory = { sourceUrl: this.metadataUrl, fetchedAt: parsed.fetchedAt, data };
90
+ return this.memory;
91
+ }
92
+ catch {
93
+ return undefined;
94
+ }
95
+ }
96
+ async fetchCatalog() {
97
+ try {
98
+ const headers = {};
99
+ const metadataOrigin = new URL(this.metadataUrl).origin;
100
+ const maySendOpenRouterKey = metadataOrigin === "https://openrouter.ai";
101
+ if (this.apiKey && maySendOpenRouterKey)
102
+ headers.Authorization = `Bearer ${this.apiKey}`;
103
+ const response = await this.fetchImpl(this.metadataUrl, {
104
+ headers,
105
+ redirect: maySendOpenRouterKey ? "error" : "follow",
106
+ signal: AbortSignal.timeout(5_000),
107
+ });
108
+ if (!response.ok)
109
+ return undefined;
110
+ const payload = await response.json();
111
+ if (!isRecord(payload) || !Array.isArray(payload.data))
112
+ return undefined;
113
+ const envelope = { sourceUrl: this.metadataUrl, fetchedAt: Date.now(), data: payload.data.filter(isRecord) };
114
+ this.memory = envelope;
115
+ try {
116
+ await mkdir(dirname(this.path), { recursive: true });
117
+ await writeFile(this.path, JSON.stringify(envelope), "utf8");
118
+ }
119
+ catch {
120
+ // A read-only cache directory must not break the local API.
121
+ }
122
+ return envelope;
123
+ }
124
+ catch {
125
+ return undefined;
126
+ }
127
+ }
128
+ async upstream() {
129
+ const cached = await this.readCache();
130
+ if (cached && Date.now() - cached.fetchedAt < this.ttlMs)
131
+ return cached;
132
+ this.refresh ??= this.fetchCatalog().finally(() => { this.refresh = undefined; });
133
+ const fresh = await this.refresh;
134
+ return fresh ?? cached;
135
+ }
136
+ async list(query) {
137
+ const local = await this.registry.listModels();
138
+ const shouldLoadUpstream = this.mode === "mirror" || Object.keys(this.registry.modelRoutes).length > 0;
139
+ const upstreamSnapshot = shouldLoadUpstream ? await this.upstream() : undefined;
140
+ const upstream = upstreamSnapshot?.data ?? [];
141
+ if (this.mode === "mirror") {
142
+ const models = this.annotateAvailability
143
+ ? upstream.map((model) => annotate(model, this.registry))
144
+ : upstream;
145
+ return filterModels(models, query);
146
+ }
147
+ const upstreamById = new Map(upstream.map((model) => [modelId(model), model]));
148
+ const seen = new Set();
149
+ const models = local.flatMap((fallback) => {
150
+ if (seen.has(fallback.id))
151
+ return [];
152
+ seen.add(fallback.id);
153
+ const actual = upstreamById.get(fallback.id);
154
+ const merged = actual
155
+ ? { ...actual, supported_parameters: LOCALLY_SUPPORTED_PARAMETERS.filter((parameter) => Array.isArray(actual.supported_parameters) && actual.supported_parameters.includes(parameter)) }
156
+ : { ...fallback, supported_parameters: LOCALLY_SUPPORTED_PARAMETERS };
157
+ return [this.annotateAvailability ? annotate(merged, this.registry) : merged];
158
+ });
159
+ return filterModels(models, query);
160
+ }
161
+ }
162
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/openrouter/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { ChatCompletionChunk, ChatCompletionRequest, ChatCompletionResponse, ChatMessage, NormalizedChatRequest, ToolCall } from "../types.js";
2
+ export declare function messageContentToText(content: ChatMessage["content"]): string;
3
+ /** Flatten OpenAI chat messages into a single prompt for CLI backends. */
4
+ export declare function messagesToPrompt(messages: ChatMessage[]): string;
5
+ /** Build the CLI prompt, avoiding replay of old turns when resuming a native session. */
6
+ export declare function requestToPrompt(req: NormalizedChatRequest): string;
7
+ /** Extract just the last user message (useful for agent-mode CLIs). */
8
+ export declare function lastUserMessage(messages: ChatMessage[]): string;
9
+ export declare function parseModelId(model: string): {
10
+ adapter?: string;
11
+ modelLocal: string;
12
+ };
13
+ export declare function normalizeChatRequest(body: ChatCompletionRequest): NormalizedChatRequest;
14
+ export declare function completionId(prefix?: string): string;
15
+ export declare function buildCompletionResponse(opts: {
16
+ id: string;
17
+ model: string;
18
+ content: string;
19
+ finishReason?: "stop" | "length" | "tool_calls" | "error";
20
+ usage?: ChatCompletionResponse["usage"];
21
+ toolCalls?: ToolCall[];
22
+ reasoning?: string;
23
+ openRouter?: boolean;
24
+ }): ChatCompletionResponse;
25
+ export declare function buildChunk(opts: {
26
+ id: string;
27
+ model: string;
28
+ delta?: {
29
+ role?: "assistant";
30
+ content?: string;
31
+ reasoning?: string;
32
+ reasoning_content?: string;
33
+ tool_calls?: Array<{
34
+ index: number;
35
+ id?: string;
36
+ type?: "function";
37
+ function?: {
38
+ name?: string;
39
+ arguments?: string;
40
+ };
41
+ }>;
42
+ };
43
+ finishReason?: "stop" | "length" | "tool_calls" | "error" | null;
44
+ usage?: ChatCompletionResponse["usage"];
45
+ openRouter?: boolean;
46
+ emptyChoices?: boolean;
47
+ }): ChatCompletionChunk;
48
+ export declare function sseLine(data: unknown): string;