Files
pikasTech-unidesk/docs/reference/master-server-ops.md
T
2026-06-12 01:32:40 +00:00

11 KiB

Master Server Ops

This document records master-server architecture and decision rules. Operations commands (Moon Bridge management, profile smoke tests, MiniMax session recovery) have moved to the unidesk-ops skill (~/.agents/skills/unidesk-ops/SKILL.md). Do not place secrets, one-off incident logs, or dated changelog notes here.

Execution Boundary

  • The master server is the production entry point and control plane. Default work on this host is limited to light source edits, Git operations, status checks, health checks, logs, diagnostics, JSON CLI control actions, and local profile wrapper maintenance.
  • Heavy builds and repository-wide checks should run on an external execution surface such as G14, D601, CI/CD, or the target runtime.
  • The local UniDesk checkout at /root/unidesk can be used for lightweight UniDesk CLI/trans/tran/helper changes.

Codex Provider Profiles

dscx, mxcx, and acx are local Codex profile wrappers under /root/.local/bin/. They are host-level tools, not UniDesk service code. acx is the unified multi-model entry; gocx remains the OpenCode Zen Go compatibility entry, and older single-model dscx-go, dfcx-go, and glcx-go wrappers are compatibility entries. Usage commands are in unidesk-ops skill.

  • dscx uses CODEX_HOME=/root/.codex-deepseek-v4-pro, model deepseek-v4-pro, Codex custom provider deepseek, and local Moon Bridge at http://127.0.0.1:38440/v1.
  • mxcx uses CODEX_HOME=/root/.codex-minimax-m3, model MiniMax-M3, Codex custom provider minimax, and local Moon Bridge at http://127.0.0.1:38441/v1.
  • acx uses CODEX_HOME=/root/.codex-acx, default model gpt-5.5-only, Codex custom provider acx, and local ACX router at http://127.0.0.1:38448/v1.
  • gocx uses CODEX_HOME=/root/.codex-opencode-go-all, default model glm-5.1, Codex custom provider opencode, and local Moon Bridge at http://127.0.0.1:38447/v1.
  • dscx-go uses CODEX_HOME=/root/.codex-opencode-go, model deepseek-v4-pro, Codex custom provider opencode, and local Moon Bridge at http://127.0.0.1:38443/v1.
  • dfcx-go uses CODEX_HOME=/root/.codex-opencode-flash, model deepseek-v4-flash, Codex custom provider opencode, and local Moon Bridge at http://127.0.0.1:38444/v1.
  • glcx-go uses CODEX_HOME=/root/.codex-opencode-glm, model glm-5.1, Codex custom provider opencode, and local Moon Bridge at http://127.0.0.1:38446/v1.
  • acx includes all OpenCode Zen Go upstream slugs plus gpt-5.5-only and gpt-5.5-sub2api in one model-catalog.json so Codex can use /model or -m <model> within the same profile.
  • acx routes OpenCode Zen Go models to the existing gocx Moon Bridge, but GPT models do not go through Moon Bridge: gpt-5.5-only uses the direct only OpenAI-compatible Responses endpoint and gpt-5.5-sub2api uses the Sub2API pool endpoint. The ACX router rewrites both GPT model aliases to upstream model gpt-5.5 before forwarding.
  • All wrappers read the upstream API key from the profile auth.json; generated Moon Bridge runtime configs live under the profile .tmp/ directory with mode 0600. Do not copy upstream keys into documentation.
  • Each profile must include model_catalog_json in config.toml pointing to a profile-local model-catalog.json entry for its active model. Missing catalog metadata causes Codex to fall back to default metadata, which lowers the effective context window and prints Model metadata ... not found.
  • Profile context metadata must match the intended upstream limit closely enough for Codex auto-compact to fire before provider rejection. Keep the local profile metadata in sync with the actual model family you are routing to.
  • Current master-server profile baselines:
    • deepseek-v4-pro, deepseek-v4-flash, and GPT profiles exposed through acx use model_context_window = 1000000 and model_auto_compact_token_limit = 900000.
    • Other local Moon Bridge profiles, including glm-5.1, MiniMax-M3, and the non-DeepSeek OpenCode models exposed through acx/gocx, use model_context_window = 200000 and model_auto_compact_token_limit = 180000.
  • Keep the wrapper-generated Moon Bridge models.<slug>.context_window aligned with the profile config.toml and model-catalog.json. If those three diverge, Codex and Moon Bridge may disagree about compaction and admission behavior.
  • hyueapi.com / .hyueapi.com must remain in NO_PROXY / no_proxy for Codex API channels.

Moon Bridge

Moon Bridge is installed as /root/.local/bin/moonbridge. The binary exposes OpenAI Responses endpoints and bridges Codex to provider-specific upstream APIs. Operations commands are in unidesk-ops skill.

The local source copy for the installed patched build is /root/src/moon-bridge-sanitize. When changing Moon Bridge, keep the change narrow, run package-level tests, build a replacement binary, back up the previous binary, then restart affected profile bridges. Default master-server build restrictions still apply.

Profile architecture:

  • dscx bridge-start renders profile config and starts Moon Bridge on 127.0.0.1:38440.
  • mxcx bridge-start renders profile config and starts Moon Bridge on 127.0.0.1:38441.
  • acx route-start renders the ACX router config and starts the local routing service on 127.0.0.1:38448.
  • gocx bridge-start renders multi-model OpenCode Zen Go profile config and starts Moon Bridge on 127.0.0.1:38447.
  • dscx-go bridge-start renders profile config and starts Moon Bridge on 127.0.0.1:38443.
  • dfcx-go bridge-start renders profile config and starts Moon Bridge on 127.0.0.1:38444.
  • glcx-go bridge-start renders profile config and starts Moon Bridge on 127.0.0.1:38446.
  • The wrappers start Moon Bridge with setsid and a profile-local PID file.
  • Logs are written under <CODEX_HOME>/logs/moonbridge/.
  • dscx routes DeepSeek through Moon Bridge using Anthropic-compatible upstream + deepseek_v4 extension.
  • mxcx routes MiniMax through Moon Bridge using openai-response upstream passthrough.
  • acx routes OpenCode Zen Go models to gocx/Moon Bridge. gocx, dscx-go, dfcx-go, and glcx-go route OpenCode Zen Go through Moon Bridge using openai-chat upstream at https://opencode.ai/zen/go/v1/chat/completions. The Codex side remains wire_api = "responses" against the local Moon Bridge URL.
  • acx routes GPT aliases directly to OpenAI-compatible Responses endpoints and must not send GPT traffic through Moon Bridge.
  • OpenCode Zen Go model IDs must use the upstream slug, such as glm-5.1; display names such as GLM-5.1 are not profile model identifiers.
  • Do not keep local handwritten bridge scripts, static alternate moonbridge.config.yml files, or other sidecar proxy paths for OpenCode Zen Go profiles. The only supported runtime path is wrapper-generated .tmp/moonbridge.generated.yml plus /root/.local/bin/moonbridge.
  • For OpenCode Zen Go profiles, set an explicit user_agent in the generated Moon Bridge provider config. The upstream may reject default client signatures.
  • Moon Bridge now performs a local context-window admission check on the Responses path before forwarding oversized requests upstream. The expected failure shape for an oversized prompt is local HTTP 400 with invalid_request_error and code context_length_exceeded, not an upstream-translated 502 Bad Gateway.
  • Do not switch MiniMax to openai-chat for Codex CLI unless tool-enabled smoke proves it works.

Profile validation:

  • *-go raw-smoke verifies the upstream OpenCode Zen Go Chat Completions API directly.
  • *-go bridge-smoke verifies local Moon Bridge's /v1/responses translation path.
  • *-go exec '在吗' verifies the actual Codex profile. Passing output must not contain Model metadata ... not found; latest session records should show model_context_window derived from the profile catalog, not fallback metadata.
  • acx doctor, acx route-status, acx models, and acx -m <model> exec '在吗' verify the unified ACX profile. Use a small real Responses request through http://127.0.0.1:38448/v1/responses to verify a GPT alias because GPT traffic intentionally bypasses Moon Bridge.
  • gocx raw-smoke [model], gocx bridge-smoke [model], and gocx -m <model> exec '在吗' verify specific OpenCode Zen Go models. Omitting [model] uses the default glm-5.1.
  • ReasoningSummaryDelta without active item in Codex stderr is a separate adapter noise from reasoning summary events. It is not the same failure as missing model metadata and does not by itself prove the profile is unusable.

OpenAI Responses Tool Argument Sanitizer

Moon Bridge owns the online sanitizer for MiniMax-style bad tool argument JSON on the openai-response passthrough path. This is the first line of defense; wrapper-level session cleanup is only for JSONL that was already corrupted before the sanitizer was installed.

Sanitizer rules: recursively scans ResponsesRequest.input, repairs tool-call arguments before upstream, repairs response-side arguments in completed events (not delta chunks), falls back to {} on unrecoverable input. Response rewriting drops upstream Content-Length.

MiniMax Session Recovery

mxcx includes a cleanup and guard layer for corrupted MiniMax-backed session JSONL. Recovery operations commands are in unidesk-ops skill. This section only documents behavioral rules.

  • mxcx resume auto-runs session-clean + session-guard before invoking Codex. Uses CODEX_HOME=/root/.codex-minimax-m3 profile.
  • session-clean is strictly scoped to invalid tool-call arguments: malformed JSON, MiniMax sentinel text, and schema-invalid cases. Must preserve line order, non-tool messages, reasoning, outputs, token records, and session metadata. Must not compact/summarize/truncate/reorder transcript.
  • New invalid arguments should be prevented online by Moon Bridge sanitizer. Use session-clean only to recover already-written sessions.
  • session-guard injects mxcx-minimax-tool-and-apply-patch-guard-v2, avoiding duplicates.

MiniMax Apply-Patch Operations

MiniMax-backed sessions must use the same UniDesk remote text patch contract as other agents: route first, operation second, and apply-patch v2 by default. The stable write shape is trans <provider>:/absolute/workspace apply-patch < patch.diff; read-only inspection may use trans <provider>:/absolute/workspace script -- 'nl -ba file' or equivalent bounded commands.

  • If apply-patch reports failed to find expected lines, first read the exact current target block, then retry with a smaller Update File hunk, an @@ <unique anchor> hint, or multiple small hunks. This is normal stale-context recovery, not a reason to switch tools.
  • Do not recover text patch failures by using download / upload, remote Python/Perl/sed heredocs, cat > / tee whole-file rewrites, or apply-patch-v1, unless apply-patch itself is unavailable or the target is non-text / bulk mechanical generated content.