@hellcoder/companion 0.105.1-preview.20260624135426.10d7236 → 0.105.1

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.
package/server/routes.ts CHANGED
@@ -3,6 +3,7 @@ import { getCookie, setCookie } from "hono/cookie";
3
3
  import { streamSSE } from "hono/streaming";
4
4
  import { execSync } from "node:child_process";
5
5
  import { resolveBinary } from "./path-resolver.js";
6
+ import { fetchCodexModels } from "./codex-models.js";
6
7
  import { join, dirname } from "node:path";
7
8
  import { fileURLToPath } from "node:url";
8
9
  import { homedir } from "node:os";
@@ -1203,39 +1204,52 @@ export function createRoutes(
1203
1204
  return c.json(backends);
1204
1205
  });
1205
1206
 
1206
- api.get("/backends/:id/models", (c) => {
1207
+ api.get("/backends/:id/models", async (c) => {
1207
1208
  const backendId = c.req.param("id");
1208
1209
 
1209
1210
  if (backendId === "codex") {
1210
- // Read Codex model list from its local cache file
1211
- const cachePath = join(homedir(), ".codex", "models_cache.json");
1212
- if (!existsSync(cachePath)) {
1213
- return c.json({ error: "Codex models cache not found. Run codex once to populate it." }, 404);
1214
- }
1211
+ // Fetch the live model list from the Codex app-server. Recent Codex
1212
+ // releases no longer write ~/.codex/models_cache.json and instead serve
1213
+ // models over the app-server `model/list` RPC — so we query the CLI
1214
+ // directly. Falls back to the legacy cache file if the RPC yields nothing.
1215
1215
  try {
1216
- const raw = readFileSync(cachePath, "utf-8");
1217
- const cache = JSON.parse(raw) as {
1218
- models: Array<{
1219
- slug: string;
1220
- display_name?: string;
1221
- description?: string;
1222
- visibility?: string;
1223
- priority?: number;
1224
- }>;
1225
- };
1226
- // Only return visible models, sorted by priority
1227
- const models = cache.models
1228
- .filter((m) => m.visibility === "list")
1229
- .sort((a, b) => (a.priority ?? 99) - (b.priority ?? 99))
1230
- .map((m) => ({
1231
- value: m.slug,
1232
- label: m.display_name || m.slug,
1233
- description: m.description || "",
1234
- }));
1235
- return c.json(models);
1236
- } catch (e) {
1237
- return c.json({ error: "Failed to parse Codex models cache" }, 500);
1216
+ const models = await fetchCodexModels();
1217
+ if (models.length > 0) {
1218
+ return c.json(models.map((m) => ({ value: m.value, label: m.label, description: m.description })));
1219
+ }
1220
+ } catch {
1221
+ // fall through to legacy cache / 404
1238
1222
  }
1223
+
1224
+ const cachePath = join(homedir(), ".codex", "models_cache.json");
1225
+ if (existsSync(cachePath)) {
1226
+ try {
1227
+ const raw = readFileSync(cachePath, "utf-8");
1228
+ const cache = JSON.parse(raw) as {
1229
+ models: Array<{
1230
+ slug: string;
1231
+ display_name?: string;
1232
+ description?: string;
1233
+ visibility?: string;
1234
+ priority?: number;
1235
+ }>;
1236
+ };
1237
+ const models = cache.models
1238
+ .filter((m) => m.visibility === "list")
1239
+ .sort((a, b) => (a.priority ?? 99) - (b.priority ?? 99))
1240
+ .map((m) => ({
1241
+ value: m.slug,
1242
+ label: m.display_name || m.slug,
1243
+ description: m.description || "",
1244
+ }));
1245
+ if (models.length > 0) return c.json(models);
1246
+ } catch {
1247
+ // ignore parse errors and fall through
1248
+ }
1249
+ }
1250
+
1251
+ // Nothing available — the frontend falls back to its static CODEX_MODELS list.
1252
+ return c.json({ error: "Codex models unavailable. Ensure the codex CLI is installed and authenticated." }, 404);
1239
1253
  }
1240
1254
 
1241
1255
  // Claude models are hardcoded on the frontend