Files
pikasTech-unidesk/docs/reference/master-server-ops.md
T
2026-07-11 11:32:44 +02:00

19 KiB
Raw Blame History

Master Server 运维

本文记录 Master Server 的架构与判定规则。已安装的 Codex wrapper 负责命令语法, 本文负责 profile 边界、安全规则和验收标准。通用 server 生命周期与 GC 命令仍由 unidesk-ops skill 负责。禁止在本文记录 Secret、一次性故障流水或带日期的 changelog。

执行边界

  • Master Server 是生产入口和控制面。
    • 本机默认只执行轻量源码修改、Git 操作、状态检查、健康检查、日志、诊断、 JSON CLI 控制动作和本地 profile wrapper 维护。
  • 重型构建和仓库级检查必须放到 G14、D601、CI/CD 或目标运行面。
  • 本机 /root/unidesk checkout 可用于轻量 UniDesk CLI、transtran 和 helper 修改。

Codex Provider Profile

  • mycxoncx/usr/local/bin/ 下的稳定系统 Codex wrapper。

    • 两者复用同一个系统 codex binary。
    • 两者的认证 home 已隔离,长期约束见“系统 Wrapper 与共享状态”。
  • dscxmxcxacx/root/.local/bin/ 下的隔离 profile wrapper。

    • 它们是 host 级工具,不属于 UniDesk service 代码。
  • acx 是统一多模型入口。

    • gocx 保留为 OpenCode Zen Go 兼容入口。
    • 旧的 dscx-godfcx-goglcx-go 只保留兼容入口。
  • dscx

    • 使用 CODEX_HOME=/root/.codex-deepseek-v4-pro
    • 使用模型 deepseek-v4-pro 和 Codex 自定义 provider deepseek
    • 使用本机 Moon Bridge http://127.0.0.1:38440/v1
  • mxcx

    • 使用 CODEX_HOME=/root/.codex-minimax-m3
    • 使用模型 MiniMax-M3 和 Codex 自定义 provider minimax
    • 使用本机 Moon Bridge http://127.0.0.1:38441/v1
  • acx

    • 使用 CODEX_HOME=/root/.codex-acx
    • 默认模型是 gpt-5.5-only
    • GPT alias 通过 Codex 自定义 provider 直连 OpenAI-compatible Responses 上游;
    • OpenCode Zen Go alias 仍通过本机 ACX router 到达 gocx / Moon Bridge。
  • gocx

    • 使用 CODEX_HOME=/root/.codex-opencode-go-all
    • 默认模型是 glm-5.1
    • 使用 Codex 自定义 provider opencode
    • 使用本机 Moon Bridge http://127.0.0.1:38447/v1
  • dscx-go

    • 使用 CODEX_HOME=/root/.codex-opencode-go
    • 使用模型 deepseek-v4-pro
    • 使用本机 Moon Bridge http://127.0.0.1:38443/v1
  • dfcx-go

    • 使用 CODEX_HOME=/root/.codex-opencode-flash
    • 使用模型 deepseek-v4-flash
    • 使用本机 Moon Bridge http://127.0.0.1:38444/v1
  • glcx-go

    • 使用 CODEX_HOME=/root/.codex-opencode-glm
    • 使用模型 glm-5.1
    • 使用本机 Moon Bridge http://127.0.0.1:38446/v1
  • acxmodel-catalog.json

    • 包含全部 OpenCode Zen Go upstream slug
    • 包含 gpt-5.5-onlygpt-5.5-sub2api
    • 允许在同一 profile 中通过 /model-m <model> 切换。
  • acx 的 GPT 路由:

    • gpt-5.5-only 直连 only OpenAI-compatible Responses endpoint
    • gpt-5.5-sub2api 直连 Sub2API pool endpoint
    • 两者的 upstream model 都是 gpt-5.5
    • GPT 请求禁止经过 Moon Bridge 或 ACX router。
  • GPT direct provider

    • 必须通过 ACX_GPT_DIRECT_API_KEY 一类环境键接收 API key
    • wrapper 从对应的 /root/.codex/auth.json.<profile> 读取;
    • 禁止回退到 /root/.codex-acx/auth.json
    • /root/.codex-acx/auth.json 只允许保存本地 router dummy key。
  • 隔离的 Moon Bridge 与 router wrapper

    • 从 profile auth 文件读取 upstream API key
    • 仅在兼容路径确有需要时由 wrapper 注入环境变量;
    • 生成配置放在 profile 的 .tmp/,权限必须是 0600
    • 此兼容规则不适用于 mycx 的 Pika command-backed auth。
  • 每个 profile

    • 必须在 config.toml 中设置 model_catalog_json
    • 必须指向包含当前模型的 profile-local model-catalog.json
    • 缺失时 Codex 会回退到默认 metadata,并输出 Model metadata ... not found
  • Profile context metadata

    • 必须与真实 upstream limit 对齐;
    • 必须让 Codex auto-compact 在 provider 拒绝请求前触发。
  • 当前 Master Server profile baseline

    • acx 暴露的 GPT profile 使用 model_context_window = 272000model_auto_compact_token_limit = 240000
    • deepseek-v4-prodeepseek-v4-flash 使用 model_context_window = 1000000model_auto_compact_token_limit = 900000
    • glm-5.1MiniMax-M3 及其他本地 Moon Bridge profile 使用 model_context_window = 200000model_auto_compact_token_limit = 180000
  • Wrapper 生成的 Moon Bridge / router metadata

    • 必须与 profile config.tomlmodel-catalog.json 对齐;
    • 不一致时 Codex 与本地 admission layer 会对 compact 和请求大小产生分歧。
  • Codex API 通道的 NO_PROXY / no_proxy

    • 必须保留 hyueapi.com.hyueapi.com

系统 Wrapper 与共享状态(mycx / oncx

  • mycxoncx

    • 复用同一个系统 codex binary
    • 使用不同的认证 CODEX_HOME
    • 共享 SQLite session index 和 durable transcript。
  • /usr/local/bin/mycx

    • 使用 CODEX_HOME=/root/.codex
    • 选择 profile pika
    • 可写 profile 文件是 /root/.codex/pika.config.toml
  • /usr/local/bin/oncx

    • 使用 CODEX_HOME=/root/.codex-only
    • 使用 CODEX_SQLITE_HOME=/root/.codex
    • 选择 profile only
    • 可写 profile 文件是 /root/.codex-only/only.config.toml
  • oncx 的账号认证:

    • 只使用 /root/.codex-only/auth.json
    • cli_auth_credentials_store 必须是 file
    • forced_login_method 必须是 chatgpt
    • auth.json 权限必须是 0600
    • wrapper 必须清理 OPENAI_API_KEYCODEX_API_KEYCODEX_ACCESS_TOKENCRS_OAI_KEY
    • oncx loginoncx login statusoncx logout 必须直接操作 隔离 home,禁止附加仅适用于 runtime command 的 --profile
  • oncx 的共享状态:

    • /root/.codex-only/sessions 链接到 /root/.codex/sessions
    • /root/.codex-only/archived_sessions 链接到 /root/.codex/archived_sessions
    • history.jsonlskillsplugins 链接到共享 home
    • shell snapshot、认证文件和 profile 配置保持隔离。
  • /root/.codex/config.toml/root/.codex/auth.json

    • codex-pool configure-local 管理;
    • 只代表 Sub2API consumer
    • 禁止作为 oncx 的 ChatGPT 登录凭据。
  • Webterm

    • config/platform-infra/webterm.yaml 启动 mycx
    • YAML 是 target、镜像、端口、启动命令、fallback shell、挂载和公网暴露的唯一真相;
    • 关闭公网暴露:
      • publicExposure.enabled: false 时,DNS、FRP 和 Caddy 字段不参与解析与验证;
      • planstatusvalidate 必须明确返回 skipped
    • target 校验:
      • 按 YAML 中的实际端口和 TERMINAL_SHELL 只读挂载判断;
      • 禁止把 7683、固定挂载数量或其他实例值写入代码门禁。
    • PTY 所有权:
      • nsenterchroot 后必须由唯一的长期交互 Bash 持有 PTY;
      • 禁止让外层非交互 Bash 等待内层交互 Bash,再在内层退出后创建 fallback shell。
    • 启动命令中断:
      • 持有 PTY 的 Bash 必须在启动命令运行期间显式处理 SIGINT
      • 前台子命令退出后继续执行 fallback,再恢复默认 handler
      • fallback shell 必须由原进程 exec,禁止创建新的等待层。
    • Webterm launch check
      • wrapper path 或启动方式变更必须保留原入口;
      • 从真实 Web/xterm 入口启动 mycx、发送 Ctrl+C 并执行 marker
      • 确认会话仍为 running
      • 确认没有 initialize_job_controlno job control 或非主动 logout
    • foreground process group 验证:
      • 使用 Bash 内建 read < /proc/$$/stat 同时读取 pgrptpgid
      • 禁止用外部 ps 读取后直接比较;
      • ps 执行期间会暂时成为 foreground process group,导致错误的不相等结果。
  • Shell startup 文件:

    • 禁止定义同名 function 覆盖这些 executable
    • 禁止在启动时重新生成 profile 文件;
    • wrapper 变更后,旧 Codex 进程必须退出;
    • 旧 shell 必须清除残留 function 或启动新 shell后再验收。
  • Profile-v2 持久化:

    • /modelmodel 与 reasoning effort 写入当前 profile 文件;
    • mycxoncx 必须独立记住最后一次选择;
    • -m-c model...-c model_reasoning_effort... 只允许临时覆盖;
    • 新启动、profile 切换和 resume 必须分别诊断。
  • Codex 官方认证边界:

    • --profile 只覆盖 profile TOML,不隔离 auth.json
    • file-based credential storage 的 auth.jsonCODEX_HOME 决定;
    • 账号登录与 API-key consumer 必须使用不同的 CODEX_HOME
    • 依据见 Codex Manual
  • Session discovery

    • 共享 SQLite 和 transcript 不保证 /resume 结果完全相同;
    • picker 还会按 provider ID、cwd、source 和 archive state 过滤;
    • provider ID 是持久化且大小写敏感的 session bucket key
    • --all 只移除 cwd 限制,不移除 provider 限制;
    • Codex 升级后必须重新验证此契约;
    • resume 使用当前 profile 的有效 model、provider 和 reasoning override
    • resume 不保证恢复 session 最后记录的模型。
  • Rollout JSONL

    • 是 durable history
    • 可以重新填充 SQLite index
    • 禁止只修改 state_5.sqlite 合并 provider bucket
    • history migration 必须停止活动 Codex 进程;
    • 必须用结构化 JSON parser 修改 rollout metadata
    • 必须事务化更新 SQLite index
    • 必须保留 provenance 并在 reindex 后验证相同 session ID 集合。
  • Provider identity

    • 是兼容性契约;
    • 修改 CODEX_HOME、profile name、provider ID 或大小写前必须预检历史;
    • 会产生新隐藏 bucket 时必须告警或阻断;
    • 禁止让不同真实 backend 仅为合并 picker list 而冒充同一 provider。
  • Pika 认证:

    • 必须使用 [model_providers.Pika.auth] 的 command-backed provider auth
    • credential source 是 /root/.codex/auth.json.pika
    • 文件权限必须是 0600
    • 禁止把 Pika API key 导出到 wrapper 或 Codex 环境;
    • shell snapshot 权限必须是 0600
    • shell snapshot 禁止包含可复用 credential
    • 发现 plaintext snapshot 时必须删除副本并轮换 credential。
  • Secret-safe 诊断只允许报告:

    • 有效 CODEX_HOME
    • wrapper path
    • 当前 profile 文件;
    • provider ID
    • model 与 reasoning
    • 按 provider 统计的 session 数量;
    • credential presence 或 fingerprint
    • 相关文件权限。
  • Profile 持久化验收:

    • 选择一个非 baseline /model
    • 退出后重新启动相同 wrapper
    • 确认选择保持;
    • 确认另一 profile 文件未变化;
    • 确认临时 CLI override 不写回 profile。
  • oncx 认证验收:

    • oncx login status 必须显示 Logged in using ChatGPT
    • 注入无效 API-key 环境变量后仍必须显示 ChatGPT 登录;
    • oncx exec --ephemeral '<smoke prompt>' 必须完成真实 Responses turn
    • 共享 codex login status 必须继续显示 Sub2API API-key 登录;
    • 全程禁止输出 token 或完整 API key。
  • mycx 认证验收:

    • 对应 API-key 环境变量缺失时,Pika command-backed auth 仍必须可用。
  • /resume 差异诊断:

    • 先比较 CODEX_HOME、provider ID、cwd、source 和 archive filter
    • 禁止在这些边界未核对前归因为 storage loss 或 cache。

相关调查证据与源码级依据保留在 UniDesk issue #1640,本文是当前长期规则的 唯一权威入口。

Moon Bridge

Moon Bridge 安装在 /root/.local/bin/moonbridge。该 binary 暴露 OpenAI Responses endpoint,并把 Codex 请求桥接到 provider-specific upstream API。已安装的 profile wrapper 负责 bridge 命令语法,本文只记录运行边界。

  • 已安装 patch build 的本地源码:
    • 路径是 /root/src/moon-bridge-sanitize
    • 修改时必须保持范围收敛;
    • 必须运行 package-level test
    • 必须构建 replacement binary
    • 必须备份旧 binary
    • 必须重启受影响的 profile bridge
    • 仍受 Master Server 重型构建限制。

Profile 架构

  • dscx bridge-start
    • 渲染 profile 配置;
    • 127.0.0.1:38440 启动 Moon Bridge。
  • mxcx bridge-start
    • 渲染 profile 配置;
    • 127.0.0.1:38441 启动 Moon Bridge。
  • acx route-start
    • 渲染 ACX router 配置;
    • 127.0.0.1:38448 启动本地 routing service
    • 只服务仍需 OpenCode Zen Go bridge path 的非 GPT alias。
  • gocx bridge-start
    • 渲染多模型 OpenCode Zen Go profile 配置;
    • 127.0.0.1:38447 启动 Moon Bridge。
  • dscx-go bridge-start
    • 127.0.0.1:38443 启动 Moon Bridge。
  • dfcx-go bridge-start
    • 127.0.0.1:38444 启动 Moon Bridge。
  • glcx-go bridge-start
    • 127.0.0.1:38446 启动 Moon Bridge。
  • Wrapper 启动 bridge
    • 使用 setsid
    • 使用 profile-local PID 文件;
    • 日志写入 <CODEX_HOME>/logs/moonbridge/
  • dscx 路由:
    • 通过 Moon Bridge 使用 Anthropic-compatible upstream
    • 使用 deepseek_v4 extension。
  • mxcx 路由:
    • 通过 Moon Bridge 使用 openai-response upstream passthrough。
  • OpenCode Zen Go 路由:
    • acx 把模型路由到 gocx / Moon Bridge
    • gocxdscx-godfcx-goglcx-go 使用 openai-chat upstream
    • upstream 是 https://opencode.ai/zen/go/v1/chat/completions
    • Codex 侧保持 wire_api = "responses"
  • acx GPT 路由:
    • 必须直连 OpenAI-compatible Responses endpoint
    • 禁止经过 Moon Bridge 或本地 ACX router
    • GPT mode 下 acx status 必须报告 mode=gpt-direct
    • 必须报告 routerRequired=false
    • 127.0.0.1:38448 不应存在 listener。
  • OpenCode Zen Go model ID
    • 必须使用 upstream slug,例如 glm-5.1
    • GLM-5.1 一类 display name 不是 profile model identifier。
  • OpenCode Zen Go bridge
    • 禁止保留手写 bridge script
    • 禁止保留静态替代 moonbridge.config.yml
    • 唯一支持路径是 wrapper 生成的 .tmp/moonbridge.generated.yml/root/.local/bin/moonbridge
    • 生成的 provider 配置必须显式设置 user_agent
  • Moon Bridge context-window admission
    • oversized request 必须在本地 Responses path 被拒绝;
    • 预期状态是 HTTP 400
    • 错误类型是 invalid_request_error
    • 错误 code 是 context_length_exceeded
    • 禁止表现为 upstream-translated 502 Bad Gateway
  • MiniMax
    • 未经 tool-enabled smoke 证明可用,禁止把 Codex CLI 切到 openai-chat

Profile 验收

  • *-go raw-smoke
    • 直接验证 upstream OpenCode Zen Go Chat Completions API。
  • *-go bridge-smoke
    • 验证本地 Moon Bridge 的 /v1/responses translation path。
  • *-go exec '在吗'
    • 验证真实 Codex profile
    • 输出禁止包含 Model metadata ... not found
    • 最新 session 必须使用 profile catalog 提供的 model_context_window
  • ACX GPT 验收:
    • 使用 acx statusacx modelsacx gpt-only exec '在吗'acx gpt-sub2api exec '在吗' 和 默认 acx exec '在吗'
    • 必须完成真实 Codex Responses turn
    • repeated 或 resume traffic 必须出现非零 cached_input_tokens
    • 禁止依赖 127.0.0.1:38448 listener。
  • ACX OpenCode Zen Go alias 验收:
    • 使用 acx route-startacx route-statusacx modelsacx -m <opencode-model> exec '在吗'
    • 验证 router 到 gocx 的路径。
  • gocx 模型验收:
    • 使用 gocx raw-smoke [model]
    • 使用 gocx bridge-smoke [model]
    • 使用 gocx -m <model> exec '在吗'
    • 省略 [model] 时默认使用 glm-5.1
  • ReasoningSummaryDelta without active item
    • 是 reasoning summary event 的独立 adapter noise
    • 不等同于 model metadata 缺失;
    • 不能单独证明 profile 不可用。

OpenAI Responses Tool Argument Sanitizer

  • Moon Bridge
    • 负责 MiniMax 风格错误 tool argument JSON 的在线 sanitizer
    • 作用于 openai-response passthrough path
    • 是第一道防线;
    • wrapper-level session cleanup 只处理 sanitizer 安装前已损坏的 JSONL。
  • Sanitizer
    • 递归扫描 ResponsesRequest.input
    • upstream 前修复 tool-call arguments
    • 在 completed event 中修复 response-side arguments
    • 禁止修改 delta chunk
    • 无法恢复时回退到 {}
    • response rewrite 必须删除 upstream Content-Length

MiniMax Session 恢复

  • mxcx
    • 为损坏的 MiniMax-backed session JSONL 提供 cleanup 与 guard layer
    • wrapper 负责命令语法;
    • 本节只记录行为规则。
  • mxcx resume
    • 调用 Codex 前自动执行 session-cleansession-guard
    • 使用 CODEX_HOME=/root/.codex-minimax-m3
  • session-clean
    • 只处理无效 tool-call arguments
    • 包括 malformed JSON、MiniMax sentinel text 和 schema-invalid case
    • 必须保留行顺序、非 tool message、reasoning、output、token record 和 session metadata
    • 禁止 compact、summarize、truncate 或 reorder transcript。
  • 新的无效 arguments
    • 必须由 Moon Bridge sanitizer 在线阻止;
    • session-clean 只用于恢复既有损坏 session。
  • session-guard
    • 注入 mxcx-minimax-tool-and-apply-patch-guard-v2
    • 禁止重复注入。

MiniMax Apply-Patch 操作

  • MiniMax-backed session
    • 必须使用与其他 agent 相同的 UniDesk 远端文本 patch 契约;
    • route 在前,operation 在后;
    • 默认使用 apply-patch v2。
  • 稳定写入形式:
    • trans <provider>:/absolute/workspace apply-patch < patch.diff
  • 只读检查:
    • 使用 trans <provider>:/absolute/workspace nl -ba file 或同等有界命令。
  • apply-patch 报告 failed to find expected lines 时:
    • 先读取目标当前精确内容;
    • 再用更小的 Update File hunk 重试;
    • 或使用 @@ <unique anchor>
    • 或拆成多个小 hunk
    • 这是正常 stale-context 恢复,禁止因此切换工具。
  • 文本 patch 失败时禁止使用:
    • download / upload
    • 远端 Python、Perl 或 sed heredoc
    • cat >tee 整文件覆盖;
    • apply-patch-v1
  • 仅在以下情况允许例外:
    • apply-patch 本身不可用;
    • 目标不是文本;
    • 目标是批量机械生成内容。