diff --git a/.agents/skills/unidesk-sub2api/SKILL.md b/.agents/skills/unidesk-sub2api/SKILL.md new file mode 100644 index 00000000..09b390ec --- /dev/null +++ b/.agents/skills/unidesk-sub2api/SKILL.md @@ -0,0 +1,140 @@ +--- +name: unidesk-sub2api +description: UniDesk Sub2API 平台运维技能。用户提到 Sub2API、sub2api、platform-infra sub2api、Codex pool、统一 API key、Sub2API FRP 暴露、Sub2API 管理 UI、配置 master ~/.codex 走 Sub2API、添加/删除 Codex 上游账号、校验 Sub2API /v1/models 时使用。 +--- + +# UniDesk Sub2API + +UniDesk 在 G14 k3s `platform-infra` namespace 运维 Sub2API。日常操作统一使用 UniDesk CLI,不直接写 Kubernetes 资源或手工调用 Sub2API 管理 API。 + +**固定入口**: `cd /root/unidesk && bun scripts/cli.ts platform-infra sub2api ...` + +## 先读边界 + +- 仓库长期开发边界见 `docs/reference/platform-infra.md`,本 skill 承担日常操作手册。 +- 配置真相是 YAML:`config/platform-infra/sub2api.yaml` 和 `config/platform-infra/sub2api-codex-pool.yaml`。 +- Runtime 在 `G14:k3s` 的 `platform-infra` namespace;master server 只是控制端和消费者,不部署 Sub2API/PostgreSQL/Redis。 +- Secret、`~/.codex/config.toml*`、`~/.codex/auth.json*` 是运行时输入或本地状态,不提交。 +- 输出只能包含 Secret 路径、长度、preview/fingerprint;禁止打印完整 API key、admin password、JWT secret、TOTP key。 + +## 部署与状态 + +```bash +bun scripts/cli.ts platform-infra sub2api plan +bun scripts/cli.ts platform-infra sub2api apply --dry-run +bun scripts/cli.ts platform-infra sub2api apply --confirm +bun scripts/cli.ts platform-infra sub2api status +bun scripts/cli.ts platform-infra sub2api validate +``` + +- `plan` 读取 `config/platform-infra/sub2api.yaml`,渲染 `src/components/platform-infra/sub2api/sub2api.k8s.yaml`,检查 no Ingress/NodePort/LoadBalancer/hostPort/hostNetwork/resource limits。 +- `apply --confirm` 默认创建异步 job;按返回的 `job status` 命令轮询,再跑 `status` 和 `validate`。 +- `status --full|--raw` 只在需要展开远端 stdout/stderr 或原始 JSON 时使用。 +- `validate` 是按需验收,不是连续可用性探针。 + +## 镜像升级 + +1. 修改 `config/platform-infra/sub2api.yaml` 的 `image.repository`、`image.tag` 或 `pullPolicy`。 +2. 执行 `sub2api plan`,确认策略检查通过。 +3. 执行 `sub2api apply --confirm`,轮询 job 完成。 +4. 执行 `sub2api status`,确认运行镜像等于 YAML 声明。 +5. 执行 `sub2api validate` 或 `codex-pool validate` 做入口验收。 + +不要把镜像版本写进脚本常量、JSON 或 manifest 模板。 + +## Codex Pool + +```bash +bun scripts/cli.ts platform-infra sub2api codex-pool plan +bun scripts/cli.ts platform-infra sub2api codex-pool sync --confirm +bun scripts/cli.ts platform-infra sub2api codex-pool validate +``` + +`config/platform-infra/sub2api-codex-pool.yaml` 控制: + +- `pool.groupName`: Sub2API group 名称。 +- `pool.apiKeySecretName` / `pool.apiKeySecretKey`: 统一消费 API key 的 k3s Secret 位置,默认 `platform-infra/sub2api-codex-pool-api-key.API_KEY`。 +- `pool.minOwnerBalanceUsd`: pool key owner 最低余额,sync/validate 会补齐。 +- `profiles.entries`: 从 master `~/.codex/` 选择上游 profile 并映射到 Sub2API account。 +- `profiles.entries[].openaiResponsesWebSocketsV2Mode`: 需要 Responses WebSocket v2 的上游才设置,值为 `off`、`ctx_pool` 或 `passthrough`。 +- `profiles.entries[].upstreamUserAgent`: 少数要求 Codex CLI User-Agent 的上游才设置,不能含换行。 + +`sync --confirm` 会登录 Sub2API admin、创建/更新 group、创建/更新 YAML 中的 `unidesk-codex-*` accounts、创建/复用统一 API key Secret,并删除 YAML 中已移除且 `extra.unidesk_managed=true` 的 `unidesk-codex-*` account。 + +## 添加上游 + +1. 在 master `~/.codex/` 准备 profile 文件,例如 `config.toml.` 和 `auth.json.`。 +2. 在 `config/platform-infra/sub2api-codex-pool.yaml` 添加 `profiles.entries` 项,指定 `profile`、`accountName`、`configFile`、`authFile`。 +3. 如需要,给该项加 `priority`、`openaiResponsesWebSocketsV2Mode` 或 `upstreamUserAgent`。 +4. 跑 `codex-pool plan`,确认 profile 可读、`base_url` 和 API key 来源有效,且 stdout 未泄露完整 key。 +5. 跑 `codex-pool sync --confirm`。 +6. 跑 `codex-pool validate`。 + +普通新增上游是 YAML 操作,不走 CI/CD,不改代码。只有需要新增可复用 schema 能力时才修改 `scripts/src/platform-infra-sub2api-codex.ts`。 + +## 删除上游 + +1. 从 `config/platform-infra/sub2api-codex-pool.yaml` 删除对应 `profiles.entries` 项。 +2. 跑 `codex-pool plan` 检查 desired 列表。 +3. 跑 `codex-pool sync --confirm`。 +4. 确认输出 `accounts.pruned` 只包含期望删除项。 +5. 跑 `codex-pool validate`。 + +CLI 只会 prune `name` 以 `unidesk-codex-` 开头且 `extra.unidesk_managed=true` 的缺席账号。 + +## FRP 暴露 + +```bash +bun scripts/cli.ts platform-infra sub2api codex-pool expose +bun scripts/cli.ts platform-infra sub2api codex-pool expose --confirm +``` + +- 由 `publicExposure` YAML 控制。默认公共端是 `publicBaseUrl`,master 本地消费端是 `masterBaseUrl`。 +- `expose --confirm` 只为 YAML 指定的 `remotePort` 补 master `frps` allow port,并在 G14 创建/更新 `sub2api-frpc`。 +- 同一个 FRP TCP 入口同时暴露 OpenAI-compatible API 和 Sub2API 管理 UI `/login`。不要另开第二个管理端口,除非 YAML 明确声明新的暴露决策。 +- Sub2API Kubernetes Service 继续保持 ClusterIP。 + +## 配置 master Codex 消费端 + +```bash +bun scripts/cli.ts platform-infra sub2api codex-pool configure-local +bun scripts/cli.ts platform-infra sub2api codex-pool configure-local --confirm +``` + +`configure-local --confirm` 会: + +- 从 `platform-infra/.` 读取统一 API key。 +- 把当前 `~/.codex/config.toml` 和 `~/.codex/auth.json` 备份为 `.`,默认 `.pre-sub2api`。 +- 重写默认 `~/.codex` 消费端,指向 `publicExposure.masterBaseUrl`,provider 名称和 wire API 来自 `localCodex`。 +- 用统一 key 做一次 gateway 验证。 + +防递归规则:`profiles.entries` 中 default 上游应指向 `config.toml.pre-sub2api` / `auth.json.pre-sub2api`,不要把已经改成 Sub2API consumer 的默认文件再导回上游池。 + +## 验收口径 + +部署 closeout 至少包含: + +- `sub2api status`:Deployment/StatefulSet/Service/Secret 可见,运行镜像与 YAML 一致。 +- `sub2api validate`:app、PostgreSQL、Redis 和 service proxy 基础检查通过。 +- `codex-pool validate`:统一 key 的 `GET /v1/models` 成功,owner balance 已满足 YAML 最小值。 +- 若 `publicExposure.enabled=true`,确认 FRP path 可用;`expose --confirm` 会用未带 key 的 public `/v1/models` 401 作为网关可达性探针。 + +如果要证明真实模型请求可用,使用最小 `/v1/responses` 或等价 Codex smoke。不要把 group-level `/v1/models` 成功解释成每个上游 account 都健康。 + +## 排障 + +- profile invalid:先修 `~/.codex/config.toml.` 的 `base_url`、`wire_api`、`model` 或 `auth.json.` 的 API key;不要在 YAML 中写密钥。 +- pool key 401:跑 `codex-pool sync --confirm` 重建 Sub2API key 与 k3s Secret 绑定,再跑 `codex-pool validate`。 +- FRP 不通:先看 `codex-pool expose --confirm` 输出的 `masterFrps`、`sub2api-frpc` 和 public 401 probe;需要低层证据时只用 `trans G14:k3s` 做 bounded 查询。 +- default profile 递归:检查 YAML default entry 是否使用 `*.pre-sub2api` 备份文件;必要时恢复备份后重新 `configure-local --confirm`。 +- 上游需要 WebSocket v2:只给该 profile 配 `openaiResponsesWebSocketsV2Mode: ctx_pool|passthrough`,跑 `sync --confirm`。 +- 上游要求 Codex User-Agent:只给该 profile 配 `upstreamUserAgent`,跑 `sync --confirm`。 + +## 禁止事项 + +- 不用原生 `kubectl apply/delete/patch` 作为正式操作入口。 +- 不在 master server 部署或运行 Sub2API/PostgreSQL/Redis。 +- 不新增 Ingress、NodePort、LoadBalancer、hostPort、hostNetwork 或宽 FRP 端口段。 +- 不给 Sub2API manifest 添加 CPU/memory limits,除非有新的 YAML 化明确决策。 +- 不打印完整 API key、admin password 或 Secret 明文。 +- 不把普通上游增删做成代码变更、CI/CD、feature flag 或兼容双路径。 diff --git a/.agents/skills/unidesk-sub2api/agents/openai.yaml b/.agents/skills/unidesk-sub2api/agents/openai.yaml new file mode 100644 index 00000000..32e0717a --- /dev/null +++ b/.agents/skills/unidesk-sub2api/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "UniDesk Sub2API" + short_description: "Operate UniDesk Sub2API and Codex pool" + default_prompt: "Use $unidesk-sub2api to operate the UniDesk Sub2API Codex pool safely." + +policy: + allow_implicit_invocation: true diff --git a/AGENTS.md b/AGENTS.md index b2eb71cd..3f26eb5b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 ## P0 最高优先级:G14 platform-infra 规则 -- P0: `platform-infra` 是 G14 k3s 上 UniDesk 运维的平台基础设施 namespace;Sub2API、Codex pool、FRP 暴露、统一消费 API key 和后续平台基础设施迁移的长期边界、路由与探针口径统一见 `docs/reference/platform-infra.md`,Sub2API 日常操作统一见 `$unidesk-sub2api`(`~/.agents/skills/unidesk-sub2api/SKILL.md`)。 +- P0: `platform-infra` 是 G14 k3s 上 UniDesk 运维的平台基础设施 namespace;Sub2API、Codex pool、FRP 暴露、统一消费 API key 和后续平台基础设施迁移的长期边界、路由与探针口径统一见 `docs/reference/platform-infra.md`,Sub2API 日常操作统一见 `$unidesk-sub2api`(`.agents/skills/unidesk-sub2api/SKILL.md`)。 - P0: `devops-infra` 仅作为既有控制面基础设施逐步迁移来源,不再作为新增平台服务的默认 namespace;新增/迁移必须优先落到 `platform-infra`,并通过 `config/platform-infra/*.yaml` 与 `bun scripts/cli.ts platform-infra ...` 受控。 ## P0 最高优先级:CaseRun 无服务与单步调试规则 @@ -267,7 +267,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `docs/reference/code-queue-supervision.md`:Code Queue 居中调度、并发队列拆分、运行中监控、基础设施缺陷分流和验收收口规则。 - `docs/reference/hwlab.md`:HWLAB 指挥侧固定 workspace、G14 主运行面、D601 legacy/硬件桥接边界、最小 device-agent/gateway 桥接模型和受控发布边界。 - `docs/reference/g14.md`:G14 provider 节点、k3s 控制桥、legacy DEV/PROD 退役边界、当前 HWLAB runtime lane、device-agent 手动实验边界、Code Queue/CI 候选目标和节点本地 VPN proxy bootstrap 边界。 -- `docs/reference/platform-infra.md`:G14 `platform-infra` namespace、YAML-first shared service 配置、Sub2API/Codex pool、FRP 暴露和 on-demand availability probe 开发边界;Sub2API 日常操作统一见 `$unidesk-sub2api`(`~/.agents/skills/unidesk-sub2api/SKILL.md`)。 +- `docs/reference/platform-infra.md`:G14 `platform-infra` namespace、YAML-first shared service 配置、Sub2API/Codex pool、FRP 暴露和 on-demand availability probe 开发边界;Sub2API 日常操作统一见 `$unidesk-sub2api`(`.agents/skills/unidesk-sub2api/SKILL.md`)。 - `docs/reference/g14-observability-infra.md`:G14 原生 k3s 上 Prometheus Operator、`devops-infra` 监控基础设施、跨 namespace scrape 声明和安全边界。 - `docs/reference/gc.md`:UniDesk 主 server 和 provider 磁盘 GC、G14/HWLAB registry retention、safe-stop 线和长期防膨胀收益规则。 - `docs/reference/observability.md`:服务日志、任务活性、通用性能指标 API 和性能面板的可观测性规则。 diff --git a/docs/reference/cli.md b/docs/reference/cli.md index b316ac8a..0975a875 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -68,7 +68,7 @@ CI/CD、GitOps、rollout、artifact 发布、PR 合并后的 runtime lane 滚动 - `hwlab g14 git-mirror status|apply|sync|flush [--dry-run|--confirm]` 是 `devops-infra` git mirror/relay 的受控维护入口:`apply` 渲染并 server-side apply `devops-infra/git-mirror.yaml`,同时删除遗留 `git-mirror-hwlab-sync` CronJob;`sync` 创建一次性 manual Job,把 GitHub allowlist refs 拉入本地 mirror;`flush` 创建一次性 manual Job,把本地 `v0.2-gitops` 快进推回 GitHub。 `status` 返回 read/write URL、last sync/write/flush、本地 ref、GitHub staging ref 和 pending flush 状态,并在 `cache.summary` 给出 `localV02`、`localGitops`、`githubGitops`、`pendingFlush`、`flushNeeded`、`githubInSync` 和下一条受控 `flushCommand`。confirmed `sync` 和 `flush` 默认创建 `.state/jobs/` 异步 job 并立刻返回可查询状态,只有现场同步调试才显式加 `--wait`;mirror 不设置 CronJob。 如果 PipelineRun 的 `gitops-promote` 阶段报 git mirror 控制面漂移或 refs 不一致,先执行 `hwlab g14 git-mirror apply --confirm` 重新应用当前 `devops-infra/git-mirror.yaml` hook/ConfigMap,再执行 `hwlab g14 git-mirror sync --confirm --wait` 复核 refs;失败的同名 PipelineRun 只能通过 `hwlab g14 control-plane cleanup-runs --lane --pipeline-run --confirm` 受控清理后重试,不要用原生 `kubectl delete` 或手工改 mirror hook。修复后仍必须用 `control-plane status --pipeline-run ` 和 `git-mirror status` 分别确认 runtime closeout 与 GitHub flush。 -- `platform-infra sub2api plan|apply|status|validate|codex-pool` 是 G14 `platform-infra` namespace 内 Sub2API 的受控入口。镜像版本由 `config/platform-infra/sub2api.yaml` 控制,Codex 上游池、统一 API key Secret、FRP 公网端口和 master `~/.codex` 消费端由 `config/platform-infra/sub2api-codex-pool.yaml` 控制;完整日常部署、上游增删、FRP 暴露、local Codex 配置、验收和排障步骤统一见 `$unidesk-sub2api`(`~/.agents/skills/unidesk-sub2api/SKILL.md`)。`docs/reference/platform-infra.md` 只保留 namespace、YAML-first、路由、Secret 脱敏和探针开发边界。 +- `platform-infra sub2api plan|apply|status|validate|codex-pool` 是 G14 `platform-infra` namespace 内 Sub2API 的受控入口。镜像版本由 `config/platform-infra/sub2api.yaml` 控制,Codex 上游池、统一 API key Secret、FRP 公网端口和 master `~/.codex` 消费端由 `config/platform-infra/sub2api-codex-pool.yaml` 控制;完整日常部署、上游增删、FRP 暴露、local Codex 配置、验收和排障步骤统一见 `$unidesk-sub2api`(`.agents/skills/unidesk-sub2api/SKILL.md`)。`docs/reference/platform-infra.md` 只保留 namespace、YAML-first、路由、Secret 脱敏和探针开发边界。 - `hwlab g14 observability status|apply|query|targets|boundary|closeout [--lane v02] [--promql ] [--expect-count N] [--expect-value V] [--dry-run|--confirm]` 是 G14 `devops-infra` 共享监控基础设施和 HWLAB v0.2 监控 closeout 的受控入口。`apply` 固定安装 Prometheus Operator `v0.91.0`、Prometheus `v3.12.0`、Prometheus 发现 RBAC、`devops-infra` 内 Prometheus 实例和 ClusterIP query Service,并给被允许发现的 workload namespace 打低风险 label;它不把 Prometheus、Grafana 或 Alertmanager 部署到 `hwlab-v02`,也不接管 HWLAB runtime Deployment/Service。`status` 只读汇总 CRD、operator Deployment、Prometheus CR/pod/service、`hwlab-v02` ServiceMonitor/PrometheusRule 和 bounded `up` 查询;`query` 只通过 Kubernetes service proxy 查询 Prometheus,支持 `--expect-count` / `--expect-value` 输出 `assertion`、bad values 和 missing/extra series;`targets` 汇总 ServiceMonitor/PrometheusRule、metrics sidecar readiness/restart、三层指标值和 `metrics.k8s.io` 当前 CPU/内存资源快照;`boundary` 验证 workload namespace 没有 Prometheus/Alertmanager,并对 `19666/19667` 公网 `/metrics` 做负向验证;`closeout` 聚合平台 ready、scrape reachable、sidecar serving、business health probe、resource snapshot、namespace boundary 和 public metrics exposure 语义结论。长期边界见 `docs/reference/g14-observability-infra.md`。 - `hwlab g14 tools-image status|build --name ci-node-tools --tag [--dockerfile deploy/ci/hwlab-ci-node-tools.Dockerfile] [--dry-run|--confirm]` 是 G14 固定 HWLAB CI tools image 的受控 host build/push 入口;构建和 push 只发生在 G14 host 与本地 registry,不在 master server 构建,也不把 `apk add`/runtime install 塞进 Tekton PipelineRun。 - `trans gh:/owner/repo ...` 把 GitHub issue/PR 映射成只读/受控写入的虚拟文本目录,适合日报、PR 正文和 issue 正文的小补丁维护:`trans gh:/pikasTech/HWLAB ls` 展示 `pr/` 与 `issue/`,`trans gh:/pikasTech/HWLAB/pr ls [--limit N] [--full]` 和 `trans gh:/pikasTech/HWLAB/issue ls [--limit N] [--full]` 展示条目状态、楼层数、正文长度和标题,`trans gh:/pikasTech/HWLAB/pr/507 ls` 展示单个 PR 的一楼正文文件,`trans gh:/pikasTech/HWLAB/505/1 cat|rg|patch-apply` 兼容旧式 issue/PR number route。`patch-apply` 使用 UniDesk 默认 apply-patch v2 的虚拟文件 executor,把正文一楼映射为 `body.md`,写回仍走 `bun scripts/cli.ts gh issue/pr update` 的 guard/concurrency 规则;`rm` 对正文一楼结构化拒绝,避免误删 issue/PR 正文。大正文读取必须展开 UniDesk gh dump 文件,否则 `cat/rg/patch-apply` 会误读为空,这是 `gh:` 虚拟文件接口的 P0 可见性契约。 diff --git a/docs/reference/platform-infra.md b/docs/reference/platform-infra.md index 911787e0..f420a6ea 100644 --- a/docs/reference/platform-infra.md +++ b/docs/reference/platform-infra.md @@ -12,7 +12,7 @@ ## Sub2API Deployment Boundary - Sub2API is a G14 platform service operated by UniDesk in namespace `platform-infra`. It is not a HWLAB lane workload, AgentRun workload, D601 service, or master server daemon. -- The canonical deployment entrypoint is `bun scripts/cli.ts platform-infra sub2api plan|apply|status|validate|codex-pool`; daily operation procedures live in `$unidesk-sub2api` at `~/.agents/skills/unidesk-sub2api/SKILL.md`. This reference keeps only development boundaries and project-specific source-of-truth rules. +- The canonical deployment entrypoint is `bun scripts/cli.ts platform-infra sub2api plan|apply|status|validate|codex-pool`; daily operation procedures live in `$unidesk-sub2api` at `.agents/skills/unidesk-sub2api/SKILL.md`. This reference keeps only development boundaries and project-specific source-of-truth rules. - Raw `kubectl` through `trans G14:k3s` is only for bounded diagnosis and evidence, not a formal mutate path. - The image version is controlled by `config/platform-infra/sub2api.yaml`. Image update procedures are daily operations owned by `$unidesk-sub2api`; the development boundary is that image choices remain YAML-controlled. - Sub2API should stay ClusterIP-only by default. Do not add Ingress, NodePort, LoadBalancer, or broad FRP exposure unless a YAML-controlled public exposure decision exists.