Files
pikasTech-unidesk/.agents/skills/unidesk-sub2api/references/codex-pool.md
T
2026-07-02 02:43:13 +00:00

10 KiB
Raw Blame History

Codex Pool

codex-pool plan|sync|validate 同时覆盖 k3s target 和 PK01 host-Docker target。PK01 host-Docker 的 sync --confirm 通过 Sub2API admin API 对齐 group、YAML-managed accounts、统一消费 API key、capacity/loadFactor、WebSocket v2 标记和内置 temp_unschedulable 规则;统一消费 key 写入 YAML 声明的 targets[PK01].hostDocker.envPath,不创建 k8s Secret,不部署 sentinel 资源,也不触发 sub2api apply、Docker compose、Caddy reload 或容器重启。sentinel-reportsentinel-probesentinel-image 和部分 trace 能力仍以 k3s target 为主;需要这些能力时显式选择对应 k3s target。

k3s 账号池操作示例:

bun scripts/cli.ts platform-infra sub2api codex-pool plan --target D601
bun scripts/cli.ts platform-infra sub2api codex-pool sync --target D601 --confirm
bun scripts/cli.ts platform-infra sub2api codex-pool validate --target D601
bun scripts/cli.ts platform-infra sub2api codex-pool trace --request-id <requestId>
bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-image status --target D601
bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-image build --target D601 --confirm
bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-probe --target D601 --account unidesk-codex-hy --confirm
bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-report --target D601
bun scripts/cli.ts platform-infra sub2api codex-pool cleanup-probes --target D601 --confirm

config/platform-infra/sub2api-codex-pool.yaml 控制:

  • pool.groupName: Sub2API group 名称。
  • pool.apiKeySecretName / pool.apiKeySecretKey: 统一消费 API key 的 key 名。k3s target 写入对应 namespace 下的 k3s SecretPK01 host-Docker target 写入 config/platform-infra/sub2api.yamltargets[PK01].hostDocker.envPath 声明的 env 文件。
  • pool.minOwnerBalanceUsd: pool key owner 最低余额,sync/validate 会补齐。
  • pool.minOwnerConcurrency: 可选统一消费 API key owner 最低并发;省略时 CLI 自动使用所有已解析账号 capacity 的总和,sync/validate 会补齐。显式 YAML 值只作为 override,仍必须不小于账号 capacity 总和;未显式写 profiles.entries[].capacity 的账号会使用 pool.defaultAccountCapacity 参与求和,不要用提高某个 provider capacity 来掩盖用户并发层 WS 1013。
  • pool.defaultTempUnschedulable: Sub2API 内置请求路径临时不可调度开关和 YAML 规则列表。当前要求是按 YAML 开启通用规则;sync 把 temp_unschedulable_enabled / temp_unschedulable_rules 渲染到 managed accounts,让匹配的 400/5xx/超时/模型路由/加密内容错误短暂冷却当前账号并触发同组 failover。
  • pool.defaultTempUnschedulable 与外部 sentinel.* 分开配置、互不驱动。内置规则负责 near-real-time request-path cooling/failover;哨兵负责 marker health、账号级隔离/恢复和 probe 退避。
  • 外部 sentinel 的写入面只允许通过 Sub2API admin schedulable 接口冻结/恢复账号;不能写入、清理或间接清理 temp_unschedulable_until / temp_unschedulable_reason、rate-limit、overload、model-rate-limit 等 Sub2API 请求路径 runtime 状态,也不能调用 recover-state 作为恢复动作。看到 UI 里的“触发时间/解除时间/规则序号/匹配关键词”临时不可调度状态时,默认先归因到 Sub2API 内置 request-path temp-unschedulable,而不是 sentinel。
  • YAML 只选择和配置 Codex 上游,不声明 schedulable 长期字段;codex-pool sync --confirm 不负责把既有账号恢复为 schedulable=true。既有账号的 schedulable=false 必须由哨兵先同步 Sub2API runtime 状态,再在 marker probe 命中后恢复。
  • profiles.entries: 从 master ~/.codex/ 选择上游 profile 并映射到 Sub2API account。
  • profiles.entries[].capacity: 可选 per-account concurrency override;不写则使用 pool.defaultAccountCapacity。具体数值只以 config/platform-infra/sub2api-codex-pool.yaml 为准,skill 和长期参考只描述规则,不重复写当前值。
  • profiles.entries[].loadFactor: 可选 per-account Sub2API load_factor override;不写则使用 pool.defaultAccountLoadFactor。具体数值只以 config/platform-infra/sub2api-codex-pool.yaml 为准,修改后必须 codex-pool sync --confirmcodex-pool validate
  • profiles.entries[].trustUpstream: 可选账号级哨兵信任标记;默认 false。可信账号使用 sentinel.cadence.trustedSuccessMaxIntervalMinutes 作为连续成功后的最大探测退避,不可信账号使用 sentinel.cadence.untrustedSuccessMaxIntervalMinutes。它只影响哨兵探测频率和状态可见性,不改变 Sub2API account priority/capacity/loadFactor。
  • pool.defaultSentinelProtect: 账号级哨兵保护默认策略;是否启用、连续确认次数、初始延迟、最大延迟和退避倍率都只以 YAML 为准。marker probe 或 gateway failure 触发冻结前会先按该策略做连续 marker 确认,只有全部失败才进入冻结状态机。
  • profiles.entries[].sentinelProtect: 可选账号级哨兵保护覆盖;只用于明确偏离 pool 默认策略。它只影响哨兵冻结判定和 sentinel-report 可见性,不改变 Sub2API account priority/capacity/loadFactor。
  • 除非用户明确要求修改配置,不要仅凭推断改账号 membership、priority、capacity、loadFactor、WebSocket mode 或其他调度策略;先保留 YAML,完成 provenance/runtime evidence 溯源,并把结论写回相关 issue 或 runbook 后再提出变更。
  • Sub2API 是 UniDesk 可读源码和可观测运行面的受控组件;排查 Sub2API 调度、failover、错误传播、临时不可调度或 account selection 时,默认先读当前 Sub2API 源码实现,再用真实 request id、Sub2API 日志和原入口流量验证。不要用 mock upstream、临时 probe account 或测试桩作为默认结论来源;这类探针最多是显式 debug 辅助,不能替代源码链路和真实运行证据。
  • profiles.entries[].tempUnschedulable: 可选 per-account Sub2API 内置临时不可调度覆盖;只用于明确偏离 pool 默认规则,不用它给某个账号特殊优先级或临时绕过通用 failover。
  • profiles.entries[].openaiResponsesWebSocketsV2Mode: 需要 Responses WebSocket v2 的上游才设置,值为 offctx_poolpassthrough
  • profiles.entries[].upstreamUserAgent: 少数要求 Codex CLI User-Agent 的上游才设置,不能含换行。
  • manualAccounts.protected: 已在 Sub2API 手动创建/维护、且必须排除在 UniDesk-managed Codex pool credentials 和 sentinel 控制之外的账号。默认不得改 credentials/status/schedulable/priority/capacity/loadFactor;只有显式声明 proxyBinding 时,sync --confirm 才允许把该账号的 proxy_id 对齐到 YAML 目标的 egress proxy;只有显式声明 groupBinding.source: pool-group 时,才允许把该账号加入统一消费 API key 使用的 pool group。targetIds 可选;省略表示所有 target 都保护该账号,设置后只在匹配 target 上纳入 proxy/group 窄同步和 sentinel-probe 拒绝列表,避免 PK01-only 手动账号漂移卡住 JD01 pool。
  • Sentinel 配置、marker-only 判定、镜像、report/probe 和远端 job/poll 边界见 sentinel.md

sync --confirm 会登录 Sub2API admin、创建/更新 group、创建/更新 YAML 中的 unidesk-codex-* accounts,并创建/复用统一 API key。k3s target 还会写入统一 API key Secret 并部署/更新哨兵资源;PK01 host-Docker target 只写 Sub2API runtime 和 host-Docker env 文件。sync 不把既有 managed account 直接恢复为 schedulable=true。恢复只由哨兵在读取 Sub2API runtime schedulable=false 后触发 recovery probe,并在 marker 命中时执行。sync 默认不删除 YAML 中缺席的 managed account。只有明确退役上游时才使用 sync --confirm --prune-removed 删除缺席且 extra.unidesk_managed=trueunidesk-codex-* account。对 manualAccounts.protectedsync 只执行 YAML 显式允许的窄同步;当前允许项是从目标 egressProxy 创建/更新 Sub2API internal proxy 记录并绑定 proxy_id,以及把受保护手动账号加入当前 pool.groupName。它仍不接管该账号凭据、status、schedulable、priority/capacity/loadFactor 或哨兵状态。若受保护手动账号在运行面缺失,sync/validate 会报告 manual account drift;不要自动创建、删除、接管或从 YAML 移除该账号。

trace --request-id <requestId> 是只读 request 追溯报表,不触发 probe、不修改账号。默认输出请求开始/最终状态、failover、account_select_failed、窗口内 account_temp_unschedulable、admin schedulable 写入计数和当前账号快照;reason=failover-attempted-no-candidate 表示 Sub2API 已进入自动切号,但排除当前失败账号后没有可用候选。需要机器处理时使用 --raw,需要原始匹配行时加 --show-lines

对已支持的 k3s targetsync --confirmvalidate 和 sentinel 操作可能超过单次 SSH/runtime 短连接窗口;远端 job/poll 边界见 sentinel.md

不要给 UniDesk-managed Codex accounts 开 Sub2API pool_mode。UniDesk 期望的 failover 是把失败账号临时标记为 unschedulable,让同组其他账号接手;pool_mode 会重试同一个 account path。

WebSocket v2 是账号能力集合,不是调度 pin。openaiResponsesWebSocketsV2Mode 只声明该账号可承担 Codex Responses WSv2 链路;只有 localCodex.supportsWebSockets=true / localCodex.responsesWebSocketsV2=true 时,codex-pool validate 才必须看到至少一个 webSocketsV2.schedulableEnabled 账号。真实可用性仍以 direct Codex WSv2 probe、Sub2API 日志和原入口 Codex smoke 为准。

Codex 启动时反复出现 WebSocket reconnect、HTTPS fallback、websocket closed by server before response.completed,或 Sub2API 日志出现 openai.websocket_proxy_failed / openai.websocket_account_select_failed / 上游 WS handshake 4xx/5xx 时,先按运行证据定位具体 account 和 transport。若账号的 WSv2 握手失败,优先只在 YAML 中把该账号的 openaiResponsesWebSocketsV2Mode 收敛为 off;若没有任何 direct Codex WSv2 probe 通过,则同时把 localCodex.supportsWebSocketslocalCodex.responsesWebSocketsV2 收敛为 false,再 codex-pool sync --confirm。不要顺手改 membership、priority、capacity、Secret 或代码 fallback。