fix: stabilize code agent trace and gateway flow

This commit is contained in:
Codex
2026-05-24 17:06:22 +00:00
parent b71a3cc89e
commit 9b08caa1a2
22 changed files with 795 additions and 226 deletions
@@ -258,10 +258,10 @@ test("compact commander summary exposes canPublish/canApply and dry-run devLiveC
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "pass",
frontendTimeoutMs: 180000,
backendTimeoutMs: 150000,
frontendTimeoutMs: 660000,
backendTimeoutMs: 600000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 150000,
requiredBackendTimeoutMs: 600000,
transportWaitsForBackend: true,
summary: "ready"
},
@@ -292,10 +292,10 @@ test("compact summary blocks publish on stale Cloud Web source dist", () => {
cloudWebDistFreshness: { status: "blocked", mismatches: ["index.html"] },
codeAgentTimeoutReadiness: {
status: "pass",
frontendTimeoutMs: 180000,
backendTimeoutMs: 150000,
frontendTimeoutMs: 660000,
backendTimeoutMs: 600000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 150000,
requiredBackendTimeoutMs: 600000,
transportWaitsForBackend: true,
summary: "ready"
},
@@ -326,9 +326,9 @@ test("compact summary separates Code Agent timeout and durable runtime blockers
codeAgentTimeoutReadiness: {
status: "blocked",
frontendTimeoutMs: 4500,
backendTimeoutMs: 150000,
backendTimeoutMs: 600000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 150000,
requiredBackendTimeoutMs: 600000,
transportWaitsForBackend: false,
summary: "Code Agent browser timeout is too short."
},
@@ -373,10 +373,10 @@ test("compact summary blocks publish when Code Agent transport timeout does not
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "blocked",
frontendTimeoutMs: 150000,
backendTimeoutMs: 150000,
frontendTimeoutMs: 600000,
backendTimeoutMs: 600000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 150000,
requiredBackendTimeoutMs: 600000,
transportWaitsForBackend: false,
summary: "Code Agent timeout layering is unsafe."
},
@@ -405,10 +405,10 @@ test("compact summary keeps provider-secret blockers out of publish but blocks a
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "pass",
frontendTimeoutMs: 180000,
backendTimeoutMs: 150000,
frontendTimeoutMs: 660000,
backendTimeoutMs: 600000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 150000,
requiredBackendTimeoutMs: 600000,
transportWaitsForBackend: true,
summary: "ready"
},
+6 -2
View File
@@ -333,9 +333,9 @@ const runtimeKind = process.env.HWLAB_ARTIFACT_KIND || "health-placeholder";
const entrypoint = process.env.HWLAB_SERVICE_ENTRYPOINT || "";
const port = Number.parseInt(process.env.PORT || process.env.HWLAB_PORT || "8080", 10);
const cloudApiBaseUrl = process.env.HWLAB_API_BASE_URL || "";
const cloudApiProxyTimeoutMs = parseTimeout(process.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS, 180000, {
const cloudApiProxyTimeoutMs = parseTimeout(process.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS, 660000, {
min: 1000,
max: 300000
max: 900000
});
const authUsername = nonEmptyEnv("HWLAB_CLOUD_WEB_AUTH_USERNAME", "admin");
const authPassword = nonEmptyEnv("HWLAB_CLOUD_WEB_AUTH_PASSWORD", "hwlab2026");
@@ -649,6 +649,10 @@ async function proxyCloudApi(request, response, url) {
try {
await requestUpstream(target, request, response, request.method === "GET" ? "" : body, url);
} catch (error) {
if (response.headersSent || response.writableEnded) {
if (!response.writableEnded) response.destroy(error);
return;
}
const timedOut = error.timedOut === true || /timed out after \d+ms/iu.test(error.message);
const code = timedOut ? "cloud_api_proxy_timeout" : "cloud_api_proxy_failed";
const category = timedOut ? "timeout" : "proxy";
@@ -22,8 +22,8 @@ const expectedBlockedGuardCommand = `${guardCommand} --expect-blocked`;
const digestPattern = /^sha256:[a-f0-9]{64}$/u;
const commitPattern = /^[a-f0-9]{7,40}$/u;
const minCodeAgentFrontendTimeoutMs = 35000;
const defaultCodeAgentBackendTimeoutMs = 150000;
const minCodeAgentBackendTimeoutMs = 150000;
const defaultCodeAgentBackendTimeoutMs = 600000;
const minCodeAgentBackendTimeoutMs = 600000;
export function normalizeCommit(value) {
if (typeof value !== "string") return "unknown";
+2 -2
View File
@@ -13,8 +13,8 @@ import {
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const expectedPorts = Object.freeze({ frontend: 16666, api: 16667 });
const codeAgentBackendTimeoutMs = "150000";
const codeAgentTransportTimeoutMs = "180000";
const codeAgentBackendTimeoutMs = "600000";
const codeAgentTransportTimeoutMs = "660000";
const legacyPublicPorts = new Set([6666, 6667]);
const duplicateMappingAllowed = new Set(["hwlab-box-simu", "hwlab-gateway-simu"]);
const tomlBareKeyPattern = /^[A-Za-z0-9_-]+$/u;
@@ -23,7 +23,7 @@ const webRoot = path.join(repoRoot, "web/hwlab-cloud-web");
const defaultLiveUrl = "http://74.48.78.17:16666/";
const helpOwner = "codex_1779444232735_1";
const legacyFailureWindowMs = 4500;
const codeAgentLongTimeoutMs = 180000;
const codeAgentLongTimeoutMs = 600000;
const localAgentFixtureDelayMs = 5200;
const codeAgentE2ePrompts = Object.freeze([
{
@@ -2631,8 +2631,10 @@ function hasCodeAgentLongTimeoutContract(files) {
const app = files.app;
return (
/DEFAULT_API_TIMEOUT_MS\s*=\s*4500/u.test(app) &&
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*180000/u.test(app) &&
/async function sendAgentMessage[\s\S]*?fetchJson\("\/v1\/agent\/chat"[\s\S]*?timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/u.test(app) &&
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*600000/u.test(app) &&
/DEFAULT_CODE_AGENT_SUBMIT_TIMEOUT_MS\s*=\s*60000/u.test(app) &&
/async function sendAgentMessage[\s\S]*?fetchJson\("\/v1\/agent\/chat"[\s\S]*?timeoutMs:\s*CODE_AGENT_SUBMIT_TIMEOUT_MS/u.test(app) &&
/shortConnection:\s*true/u.test(functionBody(app, "sendAgentMessage")) &&
/timeoutMs\s*=\s*API_TIMEOUT_MS/u.test(functionBody(app, "fetchJson")) &&
/timeoutName\s*=\s*path/u.test(functionBody(app, "fetchJson")) &&
/HWLAB_CLOUD_WEB_CONFIG/u.test(app) &&
@@ -2719,8 +2721,8 @@ function hasCodeAgentConversationUxStates({ app, styles }) {
!/function\s+messageAttributionPanel\s*\(/u.test(app) &&
!/codeAgentAttributionFromMessage/u.test(app) &&
/DEFAULT_API_TIMEOUT_MS\s*=\s*4500/u.test(app) &&
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*180000/u.test(app) &&
/timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/u.test(app) &&
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*600000/u.test(app) &&
/timeoutMs:\s*CODE_AGENT_SUBMIT_TIMEOUT_MS/u.test(app) &&
/HWLAB_CLOUD_WEB_CONFIG/u.test(app) &&
/正在处理这次 Code Agent 请求/u.test(app) &&
/旧 4500ms/u.test(app) &&