From 399af47ee83135c60160eb4169723be7acc35a45 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 2 Jun 2026 07:44:10 +0800 Subject: [PATCH] fix: assemble device pod runtime endpoint --- internal/cloud/code-agent-agentrun-adapter.ts | 15 +- .../cloud/code-agent-session-registry.test.ts | 2 + internal/cloud/codex-stdio-session-helpers.ts | 7 + internal/cloud/codex-stdio-session.ts | 1 + internal/cloud/server-agent-chat.test.ts | 24 +- internal/cloud/server-code-agent-http.ts | 77 ++++- skills/device-pod-cli/SKILL.md | 110 +++--- tools/device-pod-cli.test.ts | 115 ++++--- tools/hwlab-cli/client.test.ts | 24 +- tools/src/device-pod-cli-lib.ts | 45 ++- tools/src/hwlab-cli-lib.ts | 106 +++--- tools/src/runtime-endpoint-resolver.ts | 314 ++++++++++++++++++ web/hwlab-cloud-web/app-trace.test.ts | 4 +- 13 files changed, 643 insertions(+), 201 deletions(-) create mode 100644 tools/src/runtime-endpoint-resolver.ts diff --git a/internal/cloud/code-agent-agentrun-adapter.ts b/internal/cloud/code-agent-agentrun-adapter.ts index cef5f06f..a7d1d1c8 100644 --- a/internal/cloud/code-agent-agentrun-adapter.ts +++ b/internal/cloud/code-agent-agentrun-adapter.ts @@ -471,9 +471,20 @@ function buildAgentRunRunnerJobInput({ env, traceId, commandId }) { function buildAgentRunTransientEnv(env = process.env) { const entries = []; - for (const name of ["HWLAB_DEVICE_POD_API_URL", "HWLAB_CLOUD_API_URL", "HWLAB_DEVICE_POD_SESSION_TOKEN"]) { + for (const name of [ + "HWLAB_DEVICE_POD_API_URL", + "HWLAB_CLOUD_API_URL", + "HWLAB_RUNTIME_API_URL", + "HWLAB_RUNTIME_WEB_URL", + "HWLAB_RUNTIME_NAMESPACE", + "HWLAB_RUNTIME_LANE", + "HWLAB_RUNTIME_ENDPOINT_SOURCE", + "HWLAB_RUNTIME_ENDPOINT_LOCKED", + "HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME", + "HWLAB_DEVICE_POD_SESSION_TOKEN" + ]) { const value = firstNonEmpty(env[name]); - if (value) entries.push({ name, value, sensitive: true }); + if (value) entries.push({ name, value, sensitive: name === "HWLAB_DEVICE_POD_SESSION_TOKEN" }); } return entries; } diff --git a/internal/cloud/code-agent-session-registry.test.ts b/internal/cloud/code-agent-session-registry.test.ts index 740ae928..b7f75b7f 100644 --- a/internal/cloud/code-agent-session-registry.test.ts +++ b/internal/cloud/code-agent-session-registry.test.ts @@ -876,6 +876,7 @@ test("Code Agent PC gateway prompt reaches Codex stdio instead of internal hardw 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, /Do not pass --api-base-url, --api-url, --cloud-api-url, --base-url, or session tokens to hwpod/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); @@ -1083,6 +1084,7 @@ test("Code Agent Keil gateway prompt is not blocked by M3 IO intent guard", asyn 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, /hwpod must auto-locate from that assembled environment/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-helpers.ts b/internal/cloud/codex-stdio-session-helpers.ts index 196ce70d..8182e01c 100644 --- a/internal/cloud/codex-stdio-session-helpers.ts +++ b/internal/cloud/codex-stdio-session-helpers.ts @@ -1657,6 +1657,13 @@ export function childProcessEnv(env = process.env) { UNIDESK_SKILLS_PATH: "/app/skills", ...(env.HWLAB_DEVICE_POD_API_URL ? { HWLAB_DEVICE_POD_API_URL: env.HWLAB_DEVICE_POD_API_URL } : {}), ...(env.HWLAB_CLOUD_API_URL ? { HWLAB_CLOUD_API_URL: env.HWLAB_CLOUD_API_URL } : {}), + ...(env.HWLAB_RUNTIME_API_URL ? { HWLAB_RUNTIME_API_URL: env.HWLAB_RUNTIME_API_URL } : {}), + ...(env.HWLAB_RUNTIME_WEB_URL ? { HWLAB_RUNTIME_WEB_URL: env.HWLAB_RUNTIME_WEB_URL } : {}), + ...(env.HWLAB_RUNTIME_NAMESPACE ? { HWLAB_RUNTIME_NAMESPACE: env.HWLAB_RUNTIME_NAMESPACE } : {}), + ...(env.HWLAB_RUNTIME_LANE ? { HWLAB_RUNTIME_LANE: env.HWLAB_RUNTIME_LANE } : {}), + ...(env.HWLAB_RUNTIME_ENDPOINT_SOURCE ? { HWLAB_RUNTIME_ENDPOINT_SOURCE: env.HWLAB_RUNTIME_ENDPOINT_SOURCE } : {}), + ...(env.HWLAB_RUNTIME_ENDPOINT_LOCKED ? { HWLAB_RUNTIME_ENDPOINT_LOCKED: env.HWLAB_RUNTIME_ENDPOINT_LOCKED } : {}), + ...(env.HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME ? { HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME: env.HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME } : {}), ...(env.HWLAB_DEVICE_POD_SESSION_TOKEN ? { HWLAB_DEVICE_POD_SESSION_TOKEN: env.HWLAB_DEVICE_POD_SESSION_TOKEN } : {}), NO_PROXY: noProxy, no_proxy: noProxy, diff --git a/internal/cloud/codex-stdio-session.ts b/internal/cloud/codex-stdio-session.ts index d34aed71..2e544b49 100644 --- a/internal/cloud/codex-stdio-session.ts +++ b/internal/cloud/codex-stdio-session.ts @@ -205,6 +205,7 @@ export const CODEX_STDIO_BOUNDARY_INSTRUCTIONS = [ "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, D601-F103-V2, 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 hwpod for the operation. Use node /app/skills/device-pod-cli/scripts/device-pod-cli.mjs only as a compatibility fallback when hwpod is absent. After selecting the target pod or resuming context, run bootsharp --pod-id before edits, build, or download.", + "Do not pass --api-base-url, --api-url, --cloud-api-url, --base-url, or session tokens to hwpod in HWLAB runners. WEB and AgentRun assemble the current runtime endpoint and credential; hwpod must auto-locate from that assembled environment.", "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 --