From 7288f39031007f0066639d536a14e51440b2c106 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 28 May 2026 08:45:02 +0800 Subject: [PATCH] fix: bootstrap device pod profiles from canonical skill --- deploy/deploy.json | 2 +- deploy/k8s/base/workloads.yaml | 2 +- docs/reference/device-pod.md | 4 +- internal/cloud/code-agent-chat.mjs | 10 +- .../code-agent-session-registry.test.mjs | 4 + internal/cloud/codex-stdio-session.mjs | 13 +- internal/cloud/server.mjs | 2 +- scripts/artifact-publish.mjs | 4 +- skills/device-pod-cli/SKILL.md | 255 +++++++++++++++++- tools/device-pod-cli.mjs | 145 +++++++++- 10 files changed, 408 insertions(+), 33 deletions(-) diff --git a/deploy/deploy.json b/deploy/deploy.json index 95529979..356f1918 100644 --- a/deploy/deploy.json +++ b/deploy/deploy.json @@ -220,7 +220,7 @@ "NO_PROXY": "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com", "no_proxy": "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com", "OPENAI_API_KEY": "secretRef:hwlab-code-agent-provider/openai-api-key", - "HWLAB_CODE_AGENT_SKILLS_DIRS": "/app/skills:/root/.agents/skills:/home/ubuntu/.agents/skills", + "HWLAB_CODE_AGENT_SKILLS_DIRS": "/app/skills", "HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE": "deepseek", "HWLAB_CODE_AGENT_DEEPSEEK_MODEL": "deepseek-chat", "HWLAB_CODE_AGENT_DEEPSEEK_BASE_URL": "http://hwlab-deepseek-proxy.hwlab-dev.svc.cluster.local:4000/v1/responses", diff --git a/deploy/k8s/base/workloads.yaml b/deploy/k8s/base/workloads.yaml index ffa6fb68..c59597c6 100644 --- a/deploy/k8s/base/workloads.yaml +++ b/deploy/k8s/base/workloads.yaml @@ -216,7 +216,7 @@ }, { "name": "HWLAB_CODE_AGENT_SKILLS_DIRS", - "value": "/app/skills:/root/.agents/skills:/home/ubuntu/.agents/skills" + "value": "/app/skills" }, { "name": "OPENAI_API_KEY", diff --git a/docs/reference/device-pod.md b/docs/reference/device-pod.md index 64d6e125..70a7f759 100644 --- a/docs/reference/device-pod.md +++ b/docs/reference/device-pod.md @@ -60,6 +60,8 @@ HWLAB coder / code agent runner 镜像必须通过正式 CI/CD 预装 device-pod - **device-pod-cli 入口**:runner 内必须预装 `device-pod-cli` skill,稳定入口为 `/app/skills/device-pod-cli/scripts/device-pod-cli.mjs`,其实现指向 `/app/tools/device-pod-cli.mjs`。code agent 应通过该 CLI 读取 workspace 下 `.device-pod/.json`,再走 cloud-api/gateway/device-host-cli 调用设备能力。 - **device-host-cli 资产**:runner 内必须随 `device-pod-cli` skill 打包 Windows 侧自包含 host CLI 资产,稳定路径为 `/app/skills/device-pod-cli/assets/device-host-cli.mjs`。新 Windows 硬件 PC 接入时,不运行独立安装器;code agent 使用预装 cmd 透传入口把该资产发送到目标 workspace 的 `tools\device-host-cli.mjs`,再通过同一 cmd 透传入口执行 `node tools\device-host-cli.mjs health` 验证。 +`/app/skills` 是 HWLAB coder 镜像内 code agent skill 的唯一 canonical 位置。`device-pod-cli` 不再同步到 `/root/.agents/skills`、`/home/ubuntu/.agents/skills` 或 workspace 下的 skill 副本;这些副本会造成 discovery 口径、wrapper 相对路径和 CI/CD 预装内容不同步。默认 prompt、`HWLAB_CODE_AGENT_SKILLS_DIRS`、skill discovery 和验收都必须指向 `/app/skills`。如果某个运行时只能读取 home 目录,应先修复 runner 的 skill discovery 或环境变量,而不是复制第二份 skill。 + `device-host-cli` 不是一次性预装脚本,而是 HWLAB 内部 code agent 可继续热开发的 host 侧工具。DeepSeek、Codex runner 或其他 HWLAB 内部 code agent 在真实硬件闭环中遇到 Keil、debug probe、串口、文件工作区或硬件启动路径不顺手时,优先在目标 Windows workspace 的 `tools\device-host-cli.mjs` 上新增或修复具名设备能力,并通过 `device-pod-cli -> cloud-api -> gateway -> device-host-cli` 的真实链路热验证;验证通过后再把同一实现回填到 `/app/skills/device-pod-cli/assets/device-host-cli.mjs` 对应的 HWLAB repo 资产,进入下一次 CI/CD 预装。不得因为 host CLI 暂时不顺手而把 `device-pod-cli` 退化为泛化 cmd/shell 入口。 目标 Windows workspace 的最小布局为: @@ -71,7 +73,7 @@ HWLAB coder / code agent runner 镜像必须通过正式 CI/CD 预装 device-pod 完成上述布局后,profile 中的 `hostCli` 应指向 `node tools\device-host-cli.mjs`,`device-pod-cli` 才能稳定执行 workspace、debug-probe 和 io-probe 操作。`device-host-cli` 必须自包含,不能在运行时依赖 Windows 侧 skill 目录;Keil、serial-monitor、mklink、文件编辑等 skill 只允许作为实现参考。 -CI/CD 判定口径是:构建产物中同时存在 `/app/tools/tran.mjs`、`/app/tools/hwlab-gateway-tran.mjs`、`/app/tools/device-pod-cli.mjs`、`/app/skills/device-pod-cli/SKILL.md`、`/app/skills/device-pod-cli/scripts/device-pod-cli.mjs` 和 `/app/skills/device-pod-cli/assets/device-host-cli.mjs`,`node /app/tools/tran.mjs --help` 能展示 cmd/ps/upload/download 透传帮助,且 code agent skill discovery 能发现 `device-pod-cli`。只有这些入口都在 runner 中可见,才能称为 HWLAB coder 已具备 device-pod 最小预装能力。 +CI/CD 判定口径是:构建产物中同时存在 `/app/tools/tran.mjs`、`/app/tools/hwlab-gateway-tran.mjs`、`/app/tools/device-pod-cli.mjs`、`/app/skills/device-pod-cli/SKILL.md`、`/app/skills/device-pod-cli/scripts/device-pod-cli.mjs` 和 `/app/skills/device-pod-cli/assets/device-host-cli.mjs`,`node /app/tools/tran.mjs --help` 能展示 cmd/ps/upload/download 透传帮助,`HWLAB_CODE_AGENT_SKILLS_DIRS=/app/skills`,且 code agent skill discovery 从 `/app/skills` 发现 `device-pod-cli`。只有这些入口都在 runner 中可见,才能称为 HWLAB coder 已具备 device-pod 最小预装能力。 ## 四要素 diff --git a/internal/cloud/code-agent-chat.mjs b/internal/cloud/code-agent-chat.mjs index 95c7bcb2..7b9b60d7 100644 --- a/internal/cloud/code-agent-chat.mjs +++ b/internal/cloud/code-agent-chat.mjs @@ -1526,15 +1526,7 @@ function resolveSkillDirs(env = process.env, options = {}) { .filter((dir) => typeof dir === "string" && dir.trim()) .map((dir) => path.resolve(dir.trim())))]; } - return [...new Set([ - ...configured, - path.join(os.homedir(), ".agents", "skills"), - "/root/.agents/skills", - "/home/ubuntu/.agents/skills", - path.join(repoRoot, "skills") - ] - .filter((dir) => typeof dir === "string" && dir.trim()) - .map((dir) => path.resolve(dir.trim())))]; + return [path.resolve("/app/skills")]; } function sanitizeErrorField(key, value) { diff --git a/internal/cloud/code-agent-session-registry.test.mjs b/internal/cloud/code-agent-session-registry.test.mjs index 8b041eed..b6127d0c 100644 --- a/internal/cloud/code-agent-session-registry.test.mjs +++ b/internal/cloud/code-agent-session-registry.test.mjs @@ -791,6 +791,8 @@ test("Code Agent PC gateway prompt reaches Codex stdio instead of internal hardw const turn = calls.find((call) => call.method === "turn/start"); assert.ok(turn, "Codex stdio turn/start should be called"); assert.match(turn.args.prompt, /\/app\/tools\/hwlab-gateway-tran\.mjs/u); + assert.match(turn.args.prompt, /canonical skill location is \/app\/skills\/device-pod-cli\/SKILL\.md/u); + assert.match(turn.args.prompt, /node \/app\/skills\/device-pod-cli\/scripts\/device-pod-cli\.mjs/u); assert.match(turn.args.prompt, /gws_DESKTOP-1MHOD9I:\/f\/work/u); assert.match(turn.args.prompt, /gws_DESKTOP-1MHOD9I:f:\/work\/hwlab\/\.tmp/u); assert.match(turn.args.prompt, /improve \/app\/tools\/hwlab-gateway-tran\.mjs first/u); @@ -924,6 +926,8 @@ test("Code Agent Keil gateway prompt is not blocked by M3 IO intent guard", asyn const turn = calls.find((call) => call.method === "turn/start"); assert.ok(turn, "Codex stdio turn/start should be called"); assert.match(turn.args.prompt, /\/app\/tools\/hwlab-gateway-tran\.mjs/u); + assert.match(turn.args.prompt, /device-pod-cli/u); + assert.match(turn.args.prompt, /\/app\/skills\/device-pod-cli\/SKILL\.md/u); assert.match(turn.args.prompt, /gws_DESKTOP-1MHOD9I:\/f\/work/u); assert.match(turn.args.prompt, /gws_DESKTOP-1MHOD9I:f:\/work\/hwlab\/\.tmp/u); assert.doesNotMatch(turn.args.prompt, /hwlab-gateway-shell\.mjs|--powershell-stdin/u); diff --git a/internal/cloud/codex-stdio-session.mjs b/internal/cloud/codex-stdio-session.mjs index c988bed4..70ece9f5 100644 --- a/internal/cloud/codex-stdio-session.mjs +++ b/internal/cloud/codex-stdio-session.mjs @@ -88,6 +88,8 @@ const CODEX_STDIO_BOUNDARY_INSTRUCTIONS = [ "Use the provided workspace and repo-owned Codex stdio session only.", "Do not read or print secrets, tokens, kubeconfig files, DB URLs, private keys, or raw environment values.", "For hardware, gateway, box-simu, patch-panel, DAP, PWM, Keil, serial, and Windows skill requests, execute the requested work through the repo-owned Codex stdio session with the available tran wrapper, skill CLI, or project tool that actually reaches the target.", + "For any request that mentions device-pod, device-pod-cli, device-host-cli, a device-pod profile, device-pod-71-freq, device-pod-71-00075-11, or a registered device-pod Keil build/download/UART/debug-probe operation, first use the HWLAB internal skill named device-pod-cli. The canonical skill location is /app/skills/device-pod-cli/SKILL.md; read that manifest and run node /app/skills/device-pod-cli/scripts/device-pod-cli.mjs for the operation.", + "When a matching device-pod profile exists, do not bypass device-pod-cli with direct hwlab-gateway-tran.mjs, Windows Keil skills, serial-monitor skills, keil-cli.py, or ad hoc path discovery. Only drop to tran or Windows-side skills when the device-pod-cli skill explicitly says to bootstrap, install, or repair the lower layer.", "For registered PC gateway Windows command or skill requests, use the preloaded tran wrapper: node /app/tools/hwlab-gateway-tran.mjs gws_DESKTOP-1MHOD9I:/f/work [options] -- . The locator before ':' is the gateway session and the path after ':' is the Windows workspace, with /f/work and f:/work both mapping to F:\\work.", "For Windows cmd, call tran as: node /app/tools/hwlab-gateway-tran.mjs gws_DESKTOP-1MHOD9I:/f/work cmd -- . For PowerShell, call tran as: node /app/tools/hwlab-gateway-tran.mjs gws_DESKTOP-1MHOD9I:/f/work ps --