From 5b32a5e19ce573b875ee69b0bf4281dd1e840cee Mon Sep 17 00:00:00 2001 From: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com> Date: Thu, 6 Aug 2026 20:02:30 +0800 Subject: [PATCH 1/3] test: pin usage-log fixture writes to the scratch home --- tests/management-api-logs-metrics.test.ts | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/tests/management-api-logs-metrics.test.ts b/tests/management-api-logs-metrics.test.ts index b24b9e6d3b..d36ee10b16 100644 --- a/tests/management-api-logs-metrics.test.ts +++ b/tests/management-api-logs-metrics.test.ts @@ -1,5 +1,9 @@ -import { afterEach, describe, expect, test } from "bun:test"; +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; import { handleManagementAPI } from "../src/server/management-api"; +import { usageLogPath } from "../src/usage/log"; import { addRequestLog, clearRequestLogsForTests, @@ -154,5 +158,33 @@ describe("GET /api/logs display metrics", () => { const [dto] = await readLogs(); expect(dto!.displayMetrics.cost).toEqual({ kind: "unavailable", reason: "invalid_cache_breakdown" }); }); + + test("fixture usage rows land in the scratch home, never the default location", () => { + // Pins the safety property this file's isolation exists for: addRequestLog + // persists to usage.jsonl, so if the scratch-home hook is ever dropped (or a + // future test logs before it runs), a bare `bun test ` from outside the + // repo writes fixture rows into the developer's real ~/.opencodex log. + const requestId = "safety-pin-usage-log-target"; + addRequestLog(baseEntry({ requestId })); + + const resolvedTarget = usageLogPath(); + expect(resolvedTarget).toBe(join(testDir, "usage.jsonl")); + expect(readFileSync(resolvedTarget, "utf-8")).toContain(requestId); + + // The default location (what the resolver returns with no OPENCODEX_HOME + // override) must never be the write target for this suite. + const previousHome = process.env.OPENCODEX_HOME; + delete process.env.OPENCODEX_HOME; + try { + const defaultTarget = usageLogPath(); + expect(defaultTarget).not.toBe(resolvedTarget); + if (existsSync(defaultTarget)) { + expect(readFileSync(defaultTarget, "utf-8")).not.toContain(requestId); + } + } finally { + if (previousHome === undefined) delete process.env.OPENCODEX_HOME; + else process.env.OPENCODEX_HOME = previousHome; + } + }); }); import { ManagementRequest as Request } from "./helpers/management-auth"; From 64be2051840217556301296034f382aeaf3cc173 Mon Sep 17 00:00:00 2001 From: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com> Date: Tue, 4 Aug 2026 17:53:54 +0800 Subject: [PATCH 2/3] fix(test): isolate usage-log fixtures from the real OpenCodex home --- tests/management-api-logs-metrics.test.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/management-api-logs-metrics.test.ts b/tests/management-api-logs-metrics.test.ts index d36ee10b16..f7077a8951 100644 --- a/tests/management-api-logs-metrics.test.ts +++ b/tests/management-api-logs-metrics.test.ts @@ -14,7 +14,24 @@ import type { OcxConfig } from "../src/types"; const config = { providers: [] } as unknown as OcxConfig; -afterEach(() => clearRequestLogsForTests()); +let testDir = ""; +let previousHome: string | undefined; + +beforeEach(() => { + // addRequestLog persists to usage.jsonl; without a scratch OPENCODEX_HOME a bare + // `bun test ` run from outside the repo (no bunfig preload) writes these + // fixture rows into the real ~/.opencodex log and poisons the GUI Usage page. + previousHome = process.env.OPENCODEX_HOME; + testDir = mkdtempSync(join(tmpdir(), "ocx-logs-metrics-")); + process.env.OPENCODEX_HOME = testDir; +}); + +afterEach(() => { + clearRequestLogsForTests(); + if (previousHome === undefined) delete process.env.OPENCODEX_HOME; + else process.env.OPENCODEX_HOME = previousHome; + if (testDir) rmSync(testDir, { recursive: true, force: true }); +}); async function readLogs(): Promise>> { const url = new URL("http://localhost/api/logs"); From 5bf99550c46b247c23f9f22eb4b7569f9e315afe Mon Sep 17 00:00:00 2001 From: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:52:32 +0800 Subject: [PATCH 3/3] docs(codex-app-models): document Desktop remote allowlist limitation Codex Desktop's remote-server mode filters the model picker against the client's own available_models allowlist (active with the remote use_hidden_models setting), so routed catalog entries that the app-server loads and serves do not appear in the picker. Record the limitation and the two workarounds (set model directly in config.toml, or use CLI/TUI) and sync the section across zh-cn, ko, ru, ja. Refs #241. Upstream: openai/codex#19694. --- .../content/docs/guides/codex-app-models.md | 17 +++++++++++++++++ .../content/docs/ja/guides/codex-app-models.md | 9 +++++++++ .../content/docs/ko/guides/codex-app-models.md | 16 ++++++++++++++++ .../content/docs/ru/guides/codex-app-models.md | 18 ++++++++++++++++++ .../docs/zh-cn/guides/codex-app-models.md | 9 +++++++++ 5 files changed, 69 insertions(+) diff --git a/docs-site/src/content/docs/guides/codex-app-models.md b/docs-site/src/content/docs/guides/codex-app-models.md index 534f97e27a..afece18f0c 100644 --- a/docs-site/src/content/docs/guides/codex-app-models.md +++ b/docs-site/src/content/docs/guides/codex-app-models.md @@ -154,6 +154,23 @@ The featured-model list is separate from the Dashboard's **Sub-agent delegation* controls which overrides Codex offers first; it does not select a model or trigger delegation by itself. +## Desktop remote servers + +Codex Desktop's remote-server mode filters the picker against the client's own +`available_models` allowlist (active when the remote `use_hidden_models` setting is on). Routed +catalog entries are still loaded and served - `model/list` returns them and the bundled CLI reads +them - but the Desktop renderer drops anything that is not on that native-only allowlist before +rendering. opencodex has no hook into that list; the upstream bug is tracked at +[openai/codex#19694](https://github.com/openai/codex/issues/19694). + +Until Desktop exposes a control for the allowlist: + +- Set the model directly in `~/.codex/config.toml` on the remote machine, for example + `model = "input/grok-4.5"`. The picker may show `Custom`, but requests still use the configured + routed model. +- Use Codex CLI or TUI instead of the Desktop picker; they do not apply the allowlist and list + routed models normally. + ## Refreshing model state If the picker still shows stale entries, refresh the catalog and restart the target Codex surface: diff --git a/docs-site/src/content/docs/ja/guides/codex-app-models.md b/docs-site/src/content/docs/ja/guides/codex-app-models.md index 77a93e9fb4..8261d274e8 100644 --- a/docs-site/src/content/docs/ja/guides/codex-app-models.md +++ b/docs-site/src/content/docs/ja/guides/codex-app-models.md @@ -101,6 +101,15 @@ Codex は、ピッカーに表示されるカタログ エントリを `priority 注目モデルのリストは、ダッシュボードの **サブエージェント委任** の選択とは別のものです。 Codex が提供するものを最初にオーバーライドするものを制御します。モデルを選択したり、委任をトリガーしたりすることはありません。 +## Desktop リモートサーバー + +Codex Desktop のリモートサーバーモードでは、クライアント自身の `available_models` 許可リストでピッカーがフィルタリングされます(リモートの `use_hidden_models` 設定が有効な場合)。ルーティングされたカタログエントリは引き続きロードされ提供されます。`model/list` はそれらを返し、バンドルされた CLI も読み取れますが、Desktop レンダラーは表示前にこのネイティブのみの許可リストにないものを破棄します。opencodex はこのリストに介入できません。上流のバグは [openai/codex#19694](https://github.com/openai/codex/issues/19694) で追跡されています。 + +Desktop が許可リストの制御を提供するまでは: + +- リモートマシンの `~/.codex/config.toml` でモデルを直接設定します(例: `model = "input/grok-4.5"`)。ピッカーには `Custom` と表示される場合がありますが、リクエストは設定されたルーティングモデルを使用します。 +- Desktop ピッカーの代わりに Codex CLI または TUI を使用します。これらは許可リストを適用せず、ルーティングモデルを通常どおり一覧表示します。 + ## モデルの状態を更新しています ピッカーに古いエントリがまだ表示されている場合は、カタログを更新し、ターゲットの Codex サーフェスを再起動します。 diff --git a/docs-site/src/content/docs/ko/guides/codex-app-models.md b/docs-site/src/content/docs/ko/guides/codex-app-models.md index f6c454c5ea..4d0f40370d 100644 --- a/docs-site/src/content/docs/ko/guides/codex-app-models.md +++ b/docs-site/src/content/docs/ko/guides/codex-app-models.md @@ -150,6 +150,22 @@ routed `provider/model` id를 최대 다섯 개 선택하고 저장할 수 있 featured-model 목록은 Dashboard의 **Sub-agent delegation** 선택과 별개입니다. Codex가 먼저 보여 줄 override를 정할 뿐, 모델을 고르거나 delegation을 시작하지는 않습니다. +## Desktop 원격 서버 + +Codex Desktop의 원격 서버 모드는 클라이언트 자체 `available_models` 허용 목록으로 picker를 +필터링합니다(원격 `use_hidden_models` 설정이 켜져 있을 때 적용). 라우팅된 카탈로그 항목은 +여전히 로드되고 제공됩니다. `model/list`가 항목을 반환하고 번들 CLI도 읽을 수 있지만, Desktop +렌더러는 표시 전에 이 네이티브 전용 허용 목록에 없는 항목을 버립니다. opencodex는 이 목록에 +개입할 수 없습니다. 업스트림 버그는 +[openai/codex#19694](https://github.com/openai/codex/issues/19694)에서 추적됩니다. + +Desktop이 허용 목록을 제어할 수 있게 될 때까지: + +- 원격 머신의 `~/.codex/config.toml`에서 모델을 직접 설정하세요(예: `model = "input/grok-4.5"`). + picker에는 `Custom`으로 표시될 수 있지만, 요청은 설정된 라우팅 모델을 계속 사용합니다. +- Desktop picker 대신 Codex CLI 또는 TUI를 사용하세요. 이들은 허용 목록을 적용하지 않으며 + 라우팅 모델을 정상적으로 나열합니다. + ## 모델 상태 새로고침 picker에 오래된 항목이 계속 보이면 카탈로그를 새로 쓰고 대상 Codex 서피스를 다시 시작합니다: diff --git a/docs-site/src/content/docs/ru/guides/codex-app-models.md b/docs-site/src/content/docs/ru/guides/codex-app-models.md index 1fad62d418..a93dca2003 100644 --- a/docs-site/src/content/docs/ru/guides/codex-app-models.md +++ b/docs-site/src/content/docs/ru/guides/codex-app-models.md @@ -158,6 +158,24 @@ Codex сортирует видимые в picker'е записи каталог определяет, какие override Codex показывает первыми; он не выбирает модель и не инициирует делегирование сам по себе. +## Удалённые серверы Desktop + +В режиме удалённого сервера Codex Desktop фильтрует picker по собственному списку разрешённых +моделей `available_models` (активируется, когда включена удалённая настройка +`use_hidden_models`). Записи маршрутизированного каталога по-прежнему загружаются и отдаются — +`model/list` возвращает их, и встроенный CLI их читает, — но рендерер Desktop отбрасывает всё, +чего нет в этом списке, ограниченном нативными моделями, ещё до отрисовки. opencodex не может +влиять на этот список; соответствующий upstream-баг отслеживается в +[openai/codex#19694](https://github.com/openai/codex/issues/19694). + +Пока Desktop не предоставит управление этим списком: + +- Задайте модель напрямую в `~/.codex/config.toml` на удалённой машине, например + `model = "input/grok-4.5"`. Picker может показывать `Custom`, но запросы по-прежнему + используют настроенную маршрутизированную модель. +- Используйте Codex CLI или TUI вместо picker в Desktop; они не применяют этот список и + показывают маршрутизированные модели как обычно. + ## Обновление состояния моделей Если picker всё ещё показывает устаревшие записи, обновите каталог и перезапустите нужную diff --git a/docs-site/src/content/docs/zh-cn/guides/codex-app-models.md b/docs-site/src/content/docs/zh-cn/guides/codex-app-models.md index 2e9eaad167..99dfa7e5e8 100644 --- a/docs-site/src/content/docs/zh-cn/guides/codex-app-models.md +++ b/docs-site/src/content/docs/zh-cn/guides/codex-app-models.md @@ -100,6 +100,15 @@ Codex 会按 `priority` 升序对选择器可见的目录条目排序,并把 精选模型列表与 Dashboard 的 **Sub-agent delegation** 选择彼此独立。它只决定 Codex 先提供哪些 override;它不会自己选择模型,也不会触发委派。 +## Desktop 远程服务器 + +Codex Desktop 的远程服务器模式会针对客户端自己的 `available_models` 白名单过滤模型选择器(当远程 `use_hidden_models` 设置启用时生效)。路由目录条目仍然会被加载并对外提供——`model/list` 会返回它们,内置 CLI 也能读取——但 Desktop 渲染层在显示前会丢弃任何不在这个仅包含原生模型的白名单中的条目。opencodex 无法影响这份白名单;上游问题在 [openai/codex#19694](https://github.com/openai/codex/issues/19694) 跟踪中。 + +在 Desktop 提供白名单控制之前: + +- 在远程机器的 `~/.codex/config.toml` 中直接设置模型,例如 `model = "input/grok-4.5"`。选择器可能显示为 `Custom`,但请求仍会使用所配置的路由模型。 +- 改用 Codex CLI 或 TUI,而不是 Desktop 选择器;它们不应用该白名单,会正常列出路由模型。 + ## 刷新模型状态 如果选择器里仍然显示旧条目,请刷新目录并重启目标 Codex 界面: