Skip to content

Latest commit

 

History

History
110 lines (88 loc) · 10.6 KB

File metadata and controls

110 lines (88 loc) · 10.6 KB

GUI And Management API SOT

Dashboard serving

The bundled React dashboard is built into gui/dist and served by the same Bun proxy. ocx gui starts the proxy when needed and opens http://localhost:<port>.

API ownership

src/server/index.ts authenticates and routes /api/*, then delegates the management surface to src/server/management-api.ts:

Endpoint area Responsibility
Config/settings Read safe config/settings views; mutate supported settings only. Full PUT /api/config is disabled so masked secrets are not round-tripped. PUT /api/settings accepts codexAutoStart and/or streamMode (each optional, at least one required); streamMode persists the #314 stream-shape selection in config.json because Windows services do not inherit shell env.
Startup safety GET /api/startup-health reports whether injected Codex routing is restart-safe, with secret-free service/shim diagnostics. POST /api/startup-action provides allowlisted one-click installation for the background service or launcher shim. On Windows a healthy script shim is CLI-only; Codex Desktop requires the background service for full protection.
Windows tray GET/POST /api/windows-tray controls an owned, per-user HKCU login tray. The tray delegates fixed actions to the CLI and is never a proxy supervisor or restart-protection signal.
Providers Create/update/delete ordinary provider configs and enrich registry metadata. The reserved openai card exposes Pool(default)/Direct account mode; openai-apikey remains the separate API route.
Models Fetch routed model lists, disabled model visibility, and catalog-facing ids.
OAuth Login/status/logout for OAuth-backed providers, plus multiauth account management: GET /api/oauth/accounts, PUT /api/oauth/accounts/active, PUT /api/oauth/accounts/alias, DELETE /api/oauth/accounts list masked accounts per provider, switch the active one, edit its display-only alias, and remove one. Login accepts addAccount: true to force a fresh browser identity. Device flows return a structured deviceCode; the GUI highlights and copies it before the user opens the verification page.
Key providers Expose API-key provider presets for setup and dashboard flows. Multi-key pool per key-auth provider: GET /api/providers/keys, POST /api/providers/keys, PUT /api/providers/keys/active, PUT /api/providers/keys/alias, DELETE /api/providers/keys masked list, add (upsert + activate), switch, rename, and remove keys. provider.apiKey always mirrors the active pool entry so routing stays single-key.
OpenAI account mode Report one OpenAI Codex card with Pool/Direct controls and one API-key card. Mode PATCH persists live without restart or catalog identity changes; Pool owns account/quota controls and Direct uses caller/main login only. Main-account DTOs report real credential presence and terminal needsReauth state instead of treating missing/invalid native auth as an unknown quota.
Subagents Read/write the featured subagentModels list capped at five ids.
V2 / Multi-agent mode GET/PUT /api/v2 — reports/sets the codex multi_agent_v2 feature flag, the 3-state multiAgentMode override (v1/default/v2), and the logical maximum thread count. Selecting v2 enables the native flag and migrates [agents] max_threads to the v2 key; selecting v1 disables it and migrates the same value back. default leaves the native flag unchanged. PUT accepts enabled, multiAgentMode, and/or the compatibility-named maxConcurrentThreadsPerSession; contradictory mode/flag pairs are rejected before writes. Every transition is rollback-safe and resyncs the catalog.
Logs & Debug One sidebar entry (/#logs) with two tabs. Logs tab: request/runtime logs for local diagnosis. Debug tab (/#logs/debug; legacy /#debug deep links redirect there): provider + usage toggles, refresh/follow log viewer. GET/PUT /api/debug; GET /api/debug/logs and GET /api/debug/usage-logs (monotonic after cursor, legacy since accepted). CLI: `ocx debug provider
Usage GET /api/usage aggregate read-only summary derived from ~/.opencodex/usage.jsonl; measured / reported / unreported / unsupported / estimated counts, daily zero-filled grid, model and provider breakdowns. Never exposes prompts.
System GET /api/system/memory — service-process runtime/memory identity (pid, Bun version/revision, platform, RSS/heap/external/ArrayBuffers scalars, observed memory = max(RSS, external, ArrayBuffers), bun:jsc heap context, streamMode + eager-relay gate decision, watchdog snapshot sliced to the last 60 samples). Scalar-only payload; rides the standard management auth gate and must never move to unauthenticated /healthz. Consumed by ocx doctor's Memory/runtime section and the dashboard Memory observability card.
Stop POST /api/stop — restore native Codex, stop any installed service, and exit the proxy.

Provider writes must not round-trip masked API keys as real secrets. Dashboard actions that change model visibility or subagent selection should trigger catalog/cache sync behavior through the server path that owns it.

The UI must show one provider card and one Models group for Codex-login OpenAI, describe Pool and Direct accurately, and keep the main account inside Pool. Public model state keeps virtual Pro ids even though transport logs may additionally report the resolved base model. Detailed rules live in 08_openai-provider-tiers.md.

User aliases are display metadata only. Codex pool aliases live on CodexAccount, OAuth aliases on ProviderAccount, and API-key aliases reuse the existing key label; account ids, credential identity, active selection, and routing never consult these fields. The matching CLI is ocx account alias <provider> <id> <display-name|-> (rename is accepted as a synonym).

Sidebar stop button

The dashboard sidebar includes a stop button that calls POST /api/stop. The button shows a confirmation prompt, then fires the request and accepts the connection drop (the proxy exits). The endpoint restores native Codex config, stops any installed service to prevent respawn, and exits.

Startup safety

The dashboard sidebar exposes a Startup safety page. Its warning state is derived from active Codex routing plus the actual service and launcher-shim installation state; the codexAutoStart preference alone is never presented as proof of restart protection. The page shows copyable repair commands (ocx service install, ocx codex-shim install, and ocx restore). On Windows it can also install an owned, per-user system tray. The resident tray owns only its icon, home-scoped singleton, and HKCU Run registration; fixed proxy actions delegate to the CLI so drain, service conflict handling, native restore, and PID identity remain centralized. Tray presence never makes startup.status protected.

UX boundary

The dashboard is a local control surface, not a separate service. It should reflect the same config and catalog invariants documented in this folder rather than inventing parallel state.

The /#codex-auth add-account modal has a three-step manual-code UX contract on top of the existing OAuth polling API: submit request, waiting-for-login completion, and terminal success/failure. Once POST /api/codex-auth/login/code succeeds, the GUI must keep the input disabled, expose an aria-live status message that the code was accepted, and surface repeated login-status polling network failures as a visible warning instead of silently looking idle again.

Usage accounting

src/usage/log.ts writes append-only JSONL to ~/.opencodex/usage.jsonl with file mode 0o600. src/usage/summary.ts turns that file into the /api/usage shape — totals, daily zero-filled grid, model and provider breakdowns, and measured / reported / unreported / unsupported / estimated counts. Missing usage is never treated as zero. The dashboard Usage tab renders the same shape, and the main Dashboard surfaces a 30d token / coverage summary. The in-memory requestLog is capped at 200 entries and is not the source of truth for aggregation — the JSONL on disk is.

The management API caches only the compact summary for an exact file revision and query; it never retains normalized per-request rows after a response. The cache invalidates on any identity, size, or timestamp change and at the next range expiry or local-day boundary. Rebuilds parse in bounded batches and yield between them, so unrelated management requests remain serviceable even for a large existing log. The Dashboard polls its 30-day usage summary independently once per minute, so usage work cannot delay health/provider/settings state or run every five seconds.

[Decision Log]

  • 목적과 의도: Keep dashboard and management requests responsive as usage.jsonl grows.
  • 기존 구현 및 제약 조건: The JSONL file remains the durable source of truth and may be truncated, replaced, or hand-edited.
  • 검토한 주요 대안: Retain normalized rows, maintain a second database, or cache only revision-keyed summaries and cooperatively rebuild them.
  • 선택한 방식: Keep only bounded summary results, share full reads by exact file identity, yield during parsing, and poll usage separately at a slower cadence.
  • 다른 대안 대신 이 방식을 선택한 이유: It bounds resident heap and avoids a second persistence format while keeping unrelated endpoints responsive.
  • 장점, 단점 및 영향: Unchanged queries are cheap and memory stays bounded; a changed large log still consumes rebuild CPU, but cooperatively and at most once per observed revision/query.

For diagnosing upstream-shape / usage-extraction issues run ocx debug usage on (or set OPENCODEX_USAGE_DEBUG=1 before start). The proxy then writes a rolling debug record per finalized request to ~/.opencodex/usage-debug.jsonl (mode 0o600, auto-trimmed to the most-recent 100 lines once it exceeds 200) with the upstream content-type, body kind (sse / json / other / none), a 2KB body sample, and the extracted usage. Off by default; the hot path is guarded so production stays untouched.

Provider debug logging

Provider transport diagnostics (dropped SSE frames, adapter dial/stream events, etc.) are opt-in: ocx debug provider on / ocx debug provider off on the running proxy, the Debug-page toggle, or OCX_DEBUG=1 on the next start (legacy OCX_DEBUG_FRAMES still enables the same path). Lines use the [ocx:<adapter>:<event>] prefix, go to the proxy terminal, and are buffered for ocx debug provider logs / ocx debug provider logs -f. Usage JSONL tails with ocx debug usage logs [-f]. Separate from provider buffered logs above.