fix: route Keil gateway prompts to Codex stdio (#471)
Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
@@ -2202,6 +2202,12 @@ function detectReadOnlyRunnerIntent(message, options = {}) {
|
|||||||
reason: "Code Agent 安全边界不读取或输出 secret、token、kubeconfig、密码、私钥或环境变量原文。"
|
reason: "Code Agent 安全边界不读取或输出 secret、token、kubeconfig、密码、私钥或环境变量原文。"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (isPcGatewayCodexToolRequest(text)) {
|
||||||
|
return {
|
||||||
|
kind: "none",
|
||||||
|
toolName: "codex-stdio.pc-gateway-wrapper"
|
||||||
|
};
|
||||||
|
}
|
||||||
const m3IoIntent = detectM3IoIntent(text);
|
const m3IoIntent = detectM3IoIntent(text);
|
||||||
if (m3IoIntent) {
|
if (m3IoIntent) {
|
||||||
return m3IoIntent;
|
return m3IoIntent;
|
||||||
@@ -2221,6 +2227,14 @@ function detectReadOnlyRunnerIntent(message, options = {}) {
|
|||||||
return { kind: "none" };
|
return { kind: "none" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPcGatewayCodexToolRequest(text) {
|
||||||
|
const value = String(text ?? "");
|
||||||
|
const mentionsGatewayTool = /(?:\/app\/tools\/hwlab-gateway-shell\.mjs|hwlab-gateway-shell\.mjs|hardware\.invoke\.shell|PC\s*gateway|gws_DESKTOP-[A-Z0-9-]+|cap_windows_cmd_exec|res_windows_host)/iu.test(value);
|
||||||
|
const mentionsWindowsCommand = /(?:Windows\s+cmd|cmd\s*\/c|shell\.exec|hostname|PowerShell|powershell)/iu.test(value);
|
||||||
|
const mentionsWindowsSkill = /(?:C:\\Users\\liang\\\.agents\\skills|\.agents[\\/]+skills|keil-cli\.py|\bKeil\b|MDK-ARM|\.uvprojx|F:\\Work\\constart|job-status)/iu.test(value);
|
||||||
|
return mentionsGatewayTool && (mentionsWindowsCommand || mentionsWindowsSkill);
|
||||||
|
}
|
||||||
|
|
||||||
function detectExternalNetworkIntent(text) {
|
function detectExternalNetworkIntent(text) {
|
||||||
const value = String(text ?? "").trim();
|
const value = String(text ?? "").trim();
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
|
|||||||
@@ -1889,6 +1889,73 @@ test("Code Agent PC gateway prompt reaches Codex stdio instead of internal hardw
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Code Agent Keil gateway prompt is not blocked by M3 IO intent guard", async () => {
|
||||||
|
const calls = [];
|
||||||
|
let providerCalled = false;
|
||||||
|
const fakeCodex = await createFakeCodexCommand();
|
||||||
|
const codexHome = await prepareFakeCodexHome();
|
||||||
|
const registry = createCodeAgentSessionRegistry();
|
||||||
|
const manager = createCodexStdioSessionManager({
|
||||||
|
idFactory: () => "ses_keil_gateway_stdio",
|
||||||
|
createRpcClient: async () => createFakeAppServerClient({
|
||||||
|
calls,
|
||||||
|
responses: ["已通过 PC gateway 调用 Windows Keil skill,success=true,return_code=0,生成 FREQ_Controller_FW.hex。"]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload = await handleCodeAgentChat(
|
||||||
|
{
|
||||||
|
conversationId: "cnv_keil_gateway_stdio",
|
||||||
|
traceId: "trc_keil_gateway_stdio",
|
||||||
|
projectId: "prj_mvp_topology",
|
||||||
|
message: String.raw`请用 /app/tools/hwlab-gateway-shell.mjs 通过 PC gateway 调用 Windows cmd,进入 C:\Users\liang\.agents\skills\keil,然后运行 py -3 keil-cli.py build -p "F:\Work\constart\projects\71-00075-11\FirmWare\MDK-ARM\FREQ_Controller_FW.uvprojx" -t FREQ_Controller_FW;如果返回 job id,请用 py -3 keil-cli.py job-status <job_id> 轮询到终态。`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
now: () => "2026-05-24T14:35:00.000Z",
|
||||||
|
env: {
|
||||||
|
PATH: process.env.PATH,
|
||||||
|
OPENAI_API_KEY: "test-openai-key-material",
|
||||||
|
CODEX_HOME: codexHome,
|
||||||
|
HWLAB_CODE_AGENT_PROVIDER: "codex-stdio",
|
||||||
|
HWLAB_CODE_AGENT_MODEL: "gpt-test",
|
||||||
|
HWLAB_CODE_AGENT_CODEX_COMMAND: fakeCodex.command,
|
||||||
|
HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED: "1",
|
||||||
|
HWLAB_CODE_AGENT_CODEX_STDIO_SUPERVISOR: "repo-owned",
|
||||||
|
HWLAB_CODE_AGENT_CODEX_SANDBOX: "danger-full-access",
|
||||||
|
HWLAB_CODE_AGENT_WORKSPACE: process.cwd(),
|
||||||
|
HWLAB_CODE_AGENT_OPENAI_BASE_URL: "http://172.26.26.227:17680/v1/responses"
|
||||||
|
},
|
||||||
|
sessionRegistry: registry,
|
||||||
|
codexStdioManager: manager,
|
||||||
|
callProvider: async () => {
|
||||||
|
providerCalled = true;
|
||||||
|
throw new Error("text fallback must not be used");
|
||||||
|
},
|
||||||
|
m3IoSkillRequestJson: async () => {
|
||||||
|
throw new Error("Keil gateway prompt must not be routed to M3 IO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
validateCodeAgentChatSchema(payload);
|
||||||
|
assert.equal(payload.status, "completed");
|
||||||
|
assert.equal(payload.provider, "codex-stdio");
|
||||||
|
assert.equal(payload.responseType, undefined);
|
||||||
|
assert.notEqual(payload.capabilityLevel, HWLAB_M3_IO_CAPABILITY_LEVELS.blocked);
|
||||||
|
assert.equal(providerCalled, false);
|
||||||
|
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-shell\.mjs/u);
|
||||||
|
assert.match(turn.args.prompt, /keil-cli\.py build/u);
|
||||||
|
assert.match(turn.args.prompt, /job-status/u);
|
||||||
|
assert.match(turn.args.prompt, /FREQ_Controller_FW\.uvprojx/u);
|
||||||
|
} finally {
|
||||||
|
await rm(fakeCodex.root, { recursive: true, force: true });
|
||||||
|
await rm(codexHome, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function delay(ms) {
|
function delay(ms) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user