fix: align Code Agent heavy request timeouts
This commit is contained in:
@@ -4,7 +4,7 @@ import { createCloudApiServer } from "../../internal/cloud/server.mjs";
|
|||||||
const host = process.env.HWLAB_CLOUD_API_HOST || "0.0.0.0";
|
const host = process.env.HWLAB_CLOUD_API_HOST || "0.0.0.0";
|
||||||
const port = Number.parseInt(process.env.HWLAB_CLOUD_API_PORT || process.env.PORT || "6667", 10);
|
const port = Number.parseInt(process.env.HWLAB_CLOUD_API_PORT || process.env.PORT || "6667", 10);
|
||||||
const commitId = process.env.HWLAB_COMMIT_ID || process.env.HWLAB_GIT_SHA;
|
const commitId = process.env.HWLAB_COMMIT_ID || process.env.HWLAB_GIT_SHA;
|
||||||
const codeAgentTimeoutMs = parseTimeout(process.env.HWLAB_CODE_AGENT_TIMEOUT_MS, 120000, {
|
const codeAgentTimeoutMs = parseTimeout(process.env.HWLAB_CODE_AGENT_TIMEOUT_MS, 150000, {
|
||||||
min: 1000,
|
min: 1000,
|
||||||
max: 300000
|
max: 300000
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { createServer } from "node:http";
|
|||||||
|
|
||||||
const serviceId = "hwlab-edge-proxy";
|
const serviceId = "hwlab-edge-proxy";
|
||||||
const upstream = process.env.HWLAB_EDGE_UPSTREAM || "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667";
|
const upstream = process.env.HWLAB_EDGE_UPSTREAM || "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667";
|
||||||
const proxyTimeoutMs = parseTimeout(process.env.HWLAB_EDGE_PROXY_TIMEOUT_MS, 150000, {
|
const proxyTimeoutMs = parseTimeout(process.env.HWLAB_EDGE_PROXY_TIMEOUT_MS, 180000, {
|
||||||
min: 1000,
|
min: 1000,
|
||||||
max: 300000
|
max: 300000
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-3
@@ -204,7 +204,7 @@
|
|||||||
"HWLAB_M3_PATCH_PANEL_URL": "http://hwlab-patch-panel.hwlab-dev.svc.cluster.local:7301",
|
"HWLAB_M3_PATCH_PANEL_URL": "http://hwlab-patch-panel.hwlab-dev.svc.cluster.local:7301",
|
||||||
"HWLAB_CODE_AGENT_PROVIDER": "codex-stdio",
|
"HWLAB_CODE_AGENT_PROVIDER": "codex-stdio",
|
||||||
"HWLAB_CODE_AGENT_MODEL": "gpt-5.5",
|
"HWLAB_CODE_AGENT_MODEL": "gpt-5.5",
|
||||||
"HWLAB_CODE_AGENT_TIMEOUT_MS": "120000",
|
"HWLAB_CODE_AGENT_TIMEOUT_MS": "150000",
|
||||||
"HWLAB_CODE_AGENT_OPENAI_BASE_URL": "http://172.26.26.227:17680/v1/responses",
|
"HWLAB_CODE_AGENT_OPENAI_BASE_URL": "http://172.26.26.227:17680/v1/responses",
|
||||||
"HWLAB_CODE_AGENT_HWLAB_API_BASE_URL": "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
|
"HWLAB_CODE_AGENT_HWLAB_API_BASE_URL": "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
|
||||||
"HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED": "1",
|
"HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED": "1",
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"HWLAB_ENVIRONMENT": "dev",
|
"HWLAB_ENVIRONMENT": "dev",
|
||||||
"HWLAB_API_BASE_URL": "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
|
"HWLAB_API_BASE_URL": "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
|
||||||
"HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS": "150000",
|
"HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS": "180000",
|
||||||
"HWLAB_COMMIT_ID": "3df89fe",
|
"HWLAB_COMMIT_ID": "3df89fe",
|
||||||
"HWLAB_IMAGE": "127.0.0.1:5000/hwlab/hwlab-cloud-web:3df89fe",
|
"HWLAB_IMAGE": "127.0.0.1:5000/hwlab/hwlab-cloud-web:3df89fe",
|
||||||
"HWLAB_IMAGE_TAG": "3df89fe"
|
"HWLAB_IMAGE_TAG": "3df89fe"
|
||||||
@@ -366,7 +366,7 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"HWLAB_EDGE_LISTEN": "0.0.0.0:6667",
|
"HWLAB_EDGE_LISTEN": "0.0.0.0:6667",
|
||||||
"HWLAB_EDGE_UPSTREAM": "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
|
"HWLAB_EDGE_UPSTREAM": "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
|
||||||
"HWLAB_EDGE_PROXY_TIMEOUT_MS": "150000"
|
"HWLAB_EDGE_PROXY_TIMEOUT_MS": "180000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "HWLAB_CODE_AGENT_TIMEOUT_MS",
|
"name": "HWLAB_CODE_AGENT_TIMEOUT_MS",
|
||||||
"value": "120000"
|
"value": "150000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "HWLAB_CODE_AGENT_OPENAI_BASE_URL",
|
"name": "HWLAB_CODE_AGENT_OPENAI_BASE_URL",
|
||||||
@@ -249,7 +249,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS",
|
"name": "HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS",
|
||||||
"value": "150000"
|
"value": "180000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "HWLAB_COMMIT_ID",
|
"name": "HWLAB_COMMIT_ID",
|
||||||
@@ -826,7 +826,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "HWLAB_EDGE_PROXY_TIMEOUT_MS",
|
"name": "HWLAB_EDGE_PROXY_TIMEOUT_MS",
|
||||||
"value": "150000"
|
"value": "180000"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"readinessProbe": {
|
"readinessProbe": {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import {
|
|||||||
runM3IoSkillCommand
|
runM3IoSkillCommand
|
||||||
} from "../../skills/hwlab-agent-runtime/scripts/src/m3-io-skill-client.mjs";
|
} from "../../skills/hwlab-agent-runtime/scripts/src/m3-io-skill-client.mjs";
|
||||||
|
|
||||||
const DEFAULT_CODE_AGENT_TIMEOUT_MS = 120000;
|
const DEFAULT_CODE_AGENT_TIMEOUT_MS = 150000;
|
||||||
const DEFAULT_CODEX_COMMAND = "codex";
|
const DEFAULT_CODEX_COMMAND = "codex";
|
||||||
const DEFAULT_MODEL = DEV_CODE_AGENT_PROVIDER_CONTRACT.model;
|
const DEFAULT_MODEL = DEV_CODE_AGENT_PROVIDER_CONTRACT.model;
|
||||||
const DEFAULT_PROJECT_ID = "prj_hwlab-cloud-workbench";
|
const DEFAULT_PROJECT_ID = "prj_hwlab-cloud-workbench";
|
||||||
|
|||||||
@@ -955,7 +955,7 @@ export function createCodexMcpJsonLineClient({ command = DEFAULT_CODEX_STDIO_COM
|
|||||||
return Array.isArray(result?.tools) ? result.tools.map((tool) => tool?.name).filter(Boolean) : [];
|
return Array.isArray(result?.tools) ? result.tools.map((tool) => tool?.name).filter(Boolean) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callTool(name, args = {}, timeoutMs = 120000) {
|
async function callTool(name, args = {}, timeoutMs = 150000) {
|
||||||
return request("tools/call", {
|
return request("tools/call", {
|
||||||
name,
|
name,
|
||||||
arguments: args
|
arguments: args
|
||||||
@@ -2365,7 +2365,7 @@ function hasEnvValue(env, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function effectiveTimeout(timeoutMs) {
|
function effectiveTimeout(timeoutMs) {
|
||||||
return Number.isInteger(timeoutMs) && timeoutMs > 0 ? timeoutMs : 120000;
|
return Number.isInteger(timeoutMs) && timeoutMs > 0 ? timeoutMs : 150000;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dropEmpty(value) {
|
function dropEmpty(value) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createServer, request as httpRequest } from "node:http";
|
|||||||
import { buildMetadataFromEnv } from "../build-metadata.mjs";
|
import { buildMetadataFromEnv } from "../build-metadata.mjs";
|
||||||
import { DEV_ENDPOINT, ENVIRONMENT_DEV } from "../protocol/index.mjs";
|
import { DEV_ENDPOINT, ENVIRONMENT_DEV } from "../protocol/index.mjs";
|
||||||
|
|
||||||
const DEFAULT_PROXY_TIMEOUT_MS = 150000;
|
const DEFAULT_PROXY_TIMEOUT_MS = 180000;
|
||||||
|
|
||||||
export function parsePort(value, fallback) {
|
export function parsePort(value, fallback) {
|
||||||
const parsed = Number.parseInt(value ?? "", 10);
|
const parsed = Number.parseInt(value ?? "", 10);
|
||||||
|
|||||||
@@ -258,9 +258,11 @@ test("compact commander summary exposes canPublish/canApply and dry-run devLiveC
|
|||||||
cloudWebDistFreshness: { status: "pass", mismatches: [] },
|
cloudWebDistFreshness: { status: "pass", mismatches: [] },
|
||||||
codeAgentTimeoutReadiness: {
|
codeAgentTimeoutReadiness: {
|
||||||
status: "pass",
|
status: "pass",
|
||||||
frontendTimeoutMs: 35000,
|
frontendTimeoutMs: 180000,
|
||||||
backendTimeoutMs: 120000,
|
backendTimeoutMs: 150000,
|
||||||
requiredFrontendTimeoutMs: 35000,
|
requiredFrontendTimeoutMs: 35000,
|
||||||
|
requiredBackendTimeoutMs: 150000,
|
||||||
|
transportWaitsForBackend: true,
|
||||||
summary: "ready"
|
summary: "ready"
|
||||||
},
|
},
|
||||||
runtimeReport: {
|
runtimeReport: {
|
||||||
@@ -290,9 +292,11 @@ test("compact summary blocks publish on stale Cloud Web source dist", () => {
|
|||||||
cloudWebDistFreshness: { status: "blocked", mismatches: ["index.html"] },
|
cloudWebDistFreshness: { status: "blocked", mismatches: ["index.html"] },
|
||||||
codeAgentTimeoutReadiness: {
|
codeAgentTimeoutReadiness: {
|
||||||
status: "pass",
|
status: "pass",
|
||||||
frontendTimeoutMs: 35000,
|
frontendTimeoutMs: 180000,
|
||||||
backendTimeoutMs: 120000,
|
backendTimeoutMs: 150000,
|
||||||
requiredFrontendTimeoutMs: 35000,
|
requiredFrontendTimeoutMs: 35000,
|
||||||
|
requiredBackendTimeoutMs: 150000,
|
||||||
|
transportWaitsForBackend: true,
|
||||||
summary: "ready"
|
summary: "ready"
|
||||||
},
|
},
|
||||||
runtimeReport: {
|
runtimeReport: {
|
||||||
@@ -322,8 +326,10 @@ test("compact summary separates Code Agent timeout and durable runtime blockers
|
|||||||
codeAgentTimeoutReadiness: {
|
codeAgentTimeoutReadiness: {
|
||||||
status: "blocked",
|
status: "blocked",
|
||||||
frontendTimeoutMs: 4500,
|
frontendTimeoutMs: 4500,
|
||||||
backendTimeoutMs: 120000,
|
backendTimeoutMs: 150000,
|
||||||
requiredFrontendTimeoutMs: 35000,
|
requiredFrontendTimeoutMs: 35000,
|
||||||
|
requiredBackendTimeoutMs: 150000,
|
||||||
|
transportWaitsForBackend: false,
|
||||||
summary: "Code Agent browser timeout is too short."
|
summary: "Code Agent browser timeout is too short."
|
||||||
},
|
},
|
||||||
runtimeReport: {
|
runtimeReport: {
|
||||||
@@ -357,6 +363,38 @@ test("compact summary separates Code Agent timeout and durable runtime blockers
|
|||||||
assert.ok(summary.blockedReasons.some((item) => item.id === "runtime-durable:runtime_durable_adapter_query_blocked"));
|
assert.ok(summary.blockedReasons.some((item) => item.id === "runtime-durable:runtime_durable_adapter_query_blocked"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("compact summary blocks publish when Code Agent transport timeout does not exceed backend timeout", () => {
|
||||||
|
const result = readiness();
|
||||||
|
const summary = buildCommanderReadinessSummary({
|
||||||
|
readiness: result,
|
||||||
|
targetRef: "origin/main",
|
||||||
|
generatedFromCommit: targetSha,
|
||||||
|
explicitLive: false,
|
||||||
|
cloudWebDistFreshness: { status: "pass", mismatches: [] },
|
||||||
|
codeAgentTimeoutReadiness: {
|
||||||
|
status: "blocked",
|
||||||
|
frontendTimeoutMs: 150000,
|
||||||
|
backendTimeoutMs: 150000,
|
||||||
|
requiredFrontendTimeoutMs: 35000,
|
||||||
|
requiredBackendTimeoutMs: 150000,
|
||||||
|
transportWaitsForBackend: false,
|
||||||
|
summary: "Code Agent timeout layering is unsafe."
|
||||||
|
},
|
||||||
|
runtimeReport: {
|
||||||
|
runtimeIdentity: {
|
||||||
|
ready: true,
|
||||||
|
runtime: { durable: true, ready: true },
|
||||||
|
readiness: { ready: true, durability: { ready: true } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(summary.canPublish, false);
|
||||||
|
assert.equal(summary.canApply, false);
|
||||||
|
assert.equal(summary.codeAgentTimeoutReadiness.transportWaitsForBackend, false);
|
||||||
|
assert.ok(summary.blockedReasons.some((item) => item.id === "code-agent-timeout-readiness"));
|
||||||
|
});
|
||||||
|
|
||||||
test("compact summary keeps provider-secret blockers out of publish but blocks apply", () => {
|
test("compact summary keeps provider-secret blockers out of publish but blocks apply", () => {
|
||||||
const result = readiness();
|
const result = readiness();
|
||||||
const summary = buildCommanderReadinessSummary({
|
const summary = buildCommanderReadinessSummary({
|
||||||
@@ -367,9 +405,11 @@ test("compact summary keeps provider-secret blockers out of publish but blocks a
|
|||||||
cloudWebDistFreshness: { status: "pass", mismatches: [] },
|
cloudWebDistFreshness: { status: "pass", mismatches: [] },
|
||||||
codeAgentTimeoutReadiness: {
|
codeAgentTimeoutReadiness: {
|
||||||
status: "pass",
|
status: "pass",
|
||||||
frontendTimeoutMs: 35000,
|
frontendTimeoutMs: 180000,
|
||||||
backendTimeoutMs: 120000,
|
backendTimeoutMs: 150000,
|
||||||
requiredFrontendTimeoutMs: 35000,
|
requiredFrontendTimeoutMs: 35000,
|
||||||
|
requiredBackendTimeoutMs: 150000,
|
||||||
|
transportWaitsForBackend: true,
|
||||||
summary: "ready"
|
summary: "ready"
|
||||||
},
|
},
|
||||||
edgeReport: {
|
edgeReport: {
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ const runtimeKind = process.env.HWLAB_ARTIFACT_KIND || "health-placeholder";
|
|||||||
const entrypoint = process.env.HWLAB_SERVICE_ENTRYPOINT || "";
|
const entrypoint = process.env.HWLAB_SERVICE_ENTRYPOINT || "";
|
||||||
const port = Number.parseInt(process.env.PORT || process.env.HWLAB_PORT || "8080", 10);
|
const port = Number.parseInt(process.env.PORT || process.env.HWLAB_PORT || "8080", 10);
|
||||||
const cloudApiBaseUrl = process.env.HWLAB_API_BASE_URL || "";
|
const cloudApiBaseUrl = process.env.HWLAB_API_BASE_URL || "";
|
||||||
const cloudApiProxyTimeoutMs = parseTimeout(process.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS, 150000, {
|
const cloudApiProxyTimeoutMs = parseTimeout(process.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS, 180000, {
|
||||||
min: 1000,
|
min: 1000,
|
||||||
max: 300000
|
max: 300000
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ test("source/default workbench report cannot claim DEV-LIVE and documents the co
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("Code Agent browser failure classifier emits Chinese timeout/provider/browser categories with traceId", () => {
|
test("Code Agent browser failure classifier emits Chinese timeout/provider/browser categories with traceId", () => {
|
||||||
const timeout = classifyCodeAgentBrowserFailure(new Error("request timed out after 150000ms"), { traceId: "trc_timeout" });
|
const timeout = classifyCodeAgentBrowserFailure(new Error("request timed out after 180000ms"), { traceId: "trc_timeout" });
|
||||||
assert.equal(timeout.category, "timeout");
|
assert.equal(timeout.category, "timeout");
|
||||||
assert.match(timeout.chineseSummary, /超时/u);
|
assert.match(timeout.chineseSummary, /超时/u);
|
||||||
assert.match(timeout.chineseSummary, /trc_timeout/u);
|
assert.match(timeout.chineseSummary, /trc_timeout/u);
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ const expectedBlockedGuardCommand = `${guardCommand} --expect-blocked`;
|
|||||||
const digestPattern = /^sha256:[a-f0-9]{64}$/u;
|
const digestPattern = /^sha256:[a-f0-9]{64}$/u;
|
||||||
const commitPattern = /^[a-f0-9]{7,40}$/u;
|
const commitPattern = /^[a-f0-9]{7,40}$/u;
|
||||||
const minCodeAgentFrontendTimeoutMs = 35000;
|
const minCodeAgentFrontendTimeoutMs = 35000;
|
||||||
const defaultCodeAgentBackendTimeoutMs = 120000;
|
const defaultCodeAgentBackendTimeoutMs = 150000;
|
||||||
|
const minCodeAgentBackendTimeoutMs = 150000;
|
||||||
|
|
||||||
export function normalizeCommit(value) {
|
export function normalizeCommit(value) {
|
||||||
if (typeof value !== "string") return "unknown";
|
if (typeof value !== "string") return "unknown";
|
||||||
@@ -388,6 +389,8 @@ export function buildCommanderReadinessSummary({
|
|||||||
frontendTimeoutMs: null,
|
frontendTimeoutMs: null,
|
||||||
backendTimeoutMs: defaultCodeAgentBackendTimeoutMs,
|
backendTimeoutMs: defaultCodeAgentBackendTimeoutMs,
|
||||||
requiredFrontendTimeoutMs: minCodeAgentFrontendTimeoutMs,
|
requiredFrontendTimeoutMs: minCodeAgentFrontendTimeoutMs,
|
||||||
|
requiredBackendTimeoutMs: minCodeAgentBackendTimeoutMs,
|
||||||
|
transportWaitsForBackend: false,
|
||||||
summary: "Code Agent timeout readiness was not inspected."
|
summary: "Code Agent timeout readiness was not inspected."
|
||||||
};
|
};
|
||||||
const runtimeDurable = classifyRuntimeDurableBlocker(runtimeReport, readiness.runtime);
|
const runtimeDurable = classifyRuntimeDurableBlocker(runtimeReport, readiness.runtime);
|
||||||
@@ -920,15 +923,18 @@ async function inspectCodeAgentTimeoutReadiness(repoRoot) {
|
|||||||
const frontendTimeoutMs = numericSourceConstant(appSource, "DEFAULT_CODE_AGENT_TIMEOUT_MS");
|
const frontendTimeoutMs = numericSourceConstant(appSource, "DEFAULT_CODE_AGENT_TIMEOUT_MS");
|
||||||
const backendTimeoutMs = numericSourceConstant(chatSource, "DEFAULT_CODE_AGENT_TIMEOUT_MS");
|
const backendTimeoutMs = numericSourceConstant(chatSource, "DEFAULT_CODE_AGENT_TIMEOUT_MS");
|
||||||
const frontendReady = Number.isInteger(frontendTimeoutMs) && frontendTimeoutMs >= minCodeAgentFrontendTimeoutMs;
|
const frontendReady = Number.isInteger(frontendTimeoutMs) && frontendTimeoutMs >= minCodeAgentFrontendTimeoutMs;
|
||||||
const backendReady = Number.isInteger(backendTimeoutMs) && backendTimeoutMs >= minCodeAgentFrontendTimeoutMs;
|
const backendReady = Number.isInteger(backendTimeoutMs) && backendTimeoutMs >= minCodeAgentBackendTimeoutMs;
|
||||||
|
const transportWaitsForBackend = Number.isInteger(frontendTimeoutMs) && Number.isInteger(backendTimeoutMs) && frontendTimeoutMs > backendTimeoutMs;
|
||||||
return {
|
return {
|
||||||
status: frontendReady && backendReady ? "pass" : "blocked",
|
status: frontendReady && backendReady && transportWaitsForBackend ? "pass" : "blocked",
|
||||||
frontendTimeoutMs,
|
frontendTimeoutMs,
|
||||||
backendTimeoutMs,
|
backendTimeoutMs,
|
||||||
requiredFrontendTimeoutMs: minCodeAgentFrontendTimeoutMs,
|
requiredFrontendTimeoutMs: minCodeAgentFrontendTimeoutMs,
|
||||||
summary: frontendReady && backendReady
|
requiredBackendTimeoutMs: minCodeAgentBackendTimeoutMs,
|
||||||
? "Code Agent browser/backend timeout budget is ready for provider latency."
|
transportWaitsForBackend,
|
||||||
: "Code Agent browser timeout is too short for provider-backed replies; long requests can be misclassified as failed."
|
summary: frontendReady && backendReady && transportWaitsForBackend
|
||||||
|
? "Code Agent browser/backend timeout budget is ready: browser transport waits for the structured backend result."
|
||||||
|
: "Code Agent timeout layering is unsafe; long requests can be misclassified before cloud-api returns a structured result."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
|
|
||||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||||
const expectedPorts = Object.freeze({ frontend: 16666, api: 16667 });
|
const expectedPorts = Object.freeze({ frontend: 16666, api: 16667 });
|
||||||
|
const codeAgentBackendTimeoutMs = "150000";
|
||||||
|
const codeAgentTransportTimeoutMs = "180000";
|
||||||
const legacyPublicPorts = new Set([6666, 6667]);
|
const legacyPublicPorts = new Set([6666, 6667]);
|
||||||
const duplicateMappingAllowed = new Set(["hwlab-box-simu", "hwlab-gateway-simu"]);
|
const duplicateMappingAllowed = new Set(["hwlab-box-simu", "hwlab-gateway-simu"]);
|
||||||
const tomlBareKeyPattern = /^[A-Za-z0-9_-]+$/u;
|
const tomlBareKeyPattern = /^[A-Za-z0-9_-]+$/u;
|
||||||
@@ -232,7 +234,7 @@ function validateSource(ctx, manifest) {
|
|||||||
expectEqual(ctx, cloudApi?.env?.HWLAB_PUBLIC_ENDPOINT, endpoints.api?.url, "$.services.hwlab-cloud-api.env.HWLAB_PUBLIC_ENDPOINT", "cloud API public endpoint env");
|
expectEqual(ctx, cloudApi?.env?.HWLAB_PUBLIC_ENDPOINT, endpoints.api?.url, "$.services.hwlab-cloud-api.env.HWLAB_PUBLIC_ENDPOINT", "cloud API public endpoint env");
|
||||||
validateCloudApiDbSource(ctx, cloudApi?.env ?? {});
|
validateCloudApiDbSource(ctx, cloudApi?.env ?? {});
|
||||||
validateCloudApiCodeAgentSource(ctx, cloudApi?.env ?? {});
|
validateCloudApiCodeAgentSource(ctx, cloudApi?.env ?? {});
|
||||||
validateCodeAgentProxyTimeoutSource(ctx, { cloudWeb, edgeProxy });
|
validateCodeAgentProxyTimeoutSource(ctx, { cloudApi, cloudWeb, edgeProxy });
|
||||||
validateM3PatchPanelSource(ctx, patchPanel);
|
validateM3PatchPanelSource(ctx, patchPanel);
|
||||||
expectEqual(ctx, cli?.env?.HWLAB_CLI_ENDPOINT, endpoints.api?.url, "$.services.hwlab-cli.env.HWLAB_CLI_ENDPOINT", "CLI endpoint env");
|
expectEqual(ctx, cli?.env?.HWLAB_CLI_ENDPOINT, endpoints.api?.url, "$.services.hwlab-cli.env.HWLAB_CLI_ENDPOINT", "CLI endpoint env");
|
||||||
expectEqual(ctx, tunnelClient?.env?.HWLAB_FRP_PUBLIC_PORT, String(expectedPorts.api), "$.services.hwlab-tunnel-client.env.HWLAB_FRP_PUBLIC_PORT", "tunnel API public port env");
|
expectEqual(ctx, tunnelClient?.env?.HWLAB_FRP_PUBLIC_PORT, String(expectedPorts.api), "$.services.hwlab-tunnel-client.env.HWLAB_FRP_PUBLIC_PORT", "tunnel API public port env");
|
||||||
@@ -377,7 +379,7 @@ function validateCloudApiCodeAgentSource(ctx, env) {
|
|||||||
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
|
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
|
||||||
expectEqual(ctx, env.HWLAB_CODE_AGENT_PROVIDER, contract.codeAgentProvider, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_PROVIDER", "cloud API Code Agent provider");
|
expectEqual(ctx, env.HWLAB_CODE_AGENT_PROVIDER, contract.codeAgentProvider, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_PROVIDER", "cloud API Code Agent provider");
|
||||||
expectEqual(ctx, env.HWLAB_CODE_AGENT_MODEL, contract.model, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_MODEL", "cloud API Code Agent model");
|
expectEqual(ctx, env.HWLAB_CODE_AGENT_MODEL, contract.model, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_MODEL", "cloud API Code Agent model");
|
||||||
expectEqual(ctx, env.HWLAB_CODE_AGENT_TIMEOUT_MS, "120000", "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_TIMEOUT_MS", "cloud API Code Agent hard timeout budget");
|
expectEqual(ctx, env.HWLAB_CODE_AGENT_TIMEOUT_MS, codeAgentBackendTimeoutMs, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_TIMEOUT_MS", "cloud API Code Agent hard timeout budget");
|
||||||
expectEqual(
|
expectEqual(
|
||||||
ctx,
|
ctx,
|
||||||
env.HWLAB_CODE_AGENT_OPENAI_BASE_URL,
|
env.HWLAB_CODE_AGENT_OPENAI_BASE_URL,
|
||||||
@@ -410,9 +412,26 @@ function validateCloudApiCodeAgentSource(ctx, env) {
|
|||||||
expectEqual(ctx, env.OPENAI_API_KEY, codeAgentSecretRefPlaceholder(), "$.services.hwlab-cloud-api.env.OPENAI_API_KEY", "cloud API Code Agent OpenAI Secret reference");
|
expectEqual(ctx, env.OPENAI_API_KEY, codeAgentSecretRefPlaceholder(), "$.services.hwlab-cloud-api.env.OPENAI_API_KEY", "cloud API Code Agent OpenAI Secret reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateCodeAgentProxyTimeoutSource(ctx, { cloudWeb, edgeProxy }) {
|
function validateCodeAgentProxyTimeoutSource(ctx, { cloudApi, cloudWeb, edgeProxy }) {
|
||||||
expectEqual(ctx, cloudWeb?.env?.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS, "150000", "$.services.hwlab-cloud-web.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS", "Cloud Web same-origin Code Agent proxy timeout budget");
|
expectEqual(ctx, cloudWeb?.env?.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS, codeAgentTransportTimeoutMs, "$.services.hwlab-cloud-web.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS", "Cloud Web same-origin Code Agent proxy timeout budget");
|
||||||
expectEqual(ctx, edgeProxy?.env?.HWLAB_EDGE_PROXY_TIMEOUT_MS, "150000", "$.services.hwlab-edge-proxy.env.HWLAB_EDGE_PROXY_TIMEOUT_MS", "edge proxy Code Agent timeout budget");
|
expectEqual(ctx, edgeProxy?.env?.HWLAB_EDGE_PROXY_TIMEOUT_MS, codeAgentTransportTimeoutMs, "$.services.hwlab-edge-proxy.env.HWLAB_EDGE_PROXY_TIMEOUT_MS", "edge proxy Code Agent timeout budget");
|
||||||
|
const backendTimeoutMs = cloudApi?.env?.HWLAB_CODE_AGENT_TIMEOUT_MS;
|
||||||
|
expect(
|
||||||
|
ctx,
|
||||||
|
Number.parseInt(cloudWeb?.env?.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS ?? "0", 10) > Number.parseInt(backendTimeoutMs ?? "0", 10),
|
||||||
|
"code_agent_timeout_layering",
|
||||||
|
"$.services.hwlab-cloud-web.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS",
|
||||||
|
"Cloud Web proxy must wait longer than cloud-api so structured Code Agent timeout wins",
|
||||||
|
{ expected: `>${backendTimeoutMs}`, actual: cloudWeb?.env?.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS }
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
ctx,
|
||||||
|
Number.parseInt(edgeProxy?.env?.HWLAB_EDGE_PROXY_TIMEOUT_MS ?? "0", 10) > Number.parseInt(backendTimeoutMs ?? "0", 10),
|
||||||
|
"code_agent_timeout_layering",
|
||||||
|
"$.services.hwlab-edge-proxy.env.HWLAB_EDGE_PROXY_TIMEOUT_MS",
|
||||||
|
"Edge proxy must wait longer than cloud-api so structured Code Agent timeout wins",
|
||||||
|
{ expected: `>${backendTimeoutMs}`, actual: edgeProxy?.env?.HWLAB_EDGE_PROXY_TIMEOUT_MS }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPlan(source) {
|
function renderPlan(source) {
|
||||||
@@ -553,7 +572,7 @@ function validateCloudApiCodeAgentArtifacts(ctx, workloads) {
|
|||||||
const env = new Map((container?.env ?? []).map((entry) => [entry.name, entry]));
|
const env = new Map((container?.env ?? []).map((entry) => [entry.name, entry]));
|
||||||
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_PROVIDER")?.value, contract.codeAgentProvider, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_PROVIDER", "cloud API workload Code Agent provider");
|
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_PROVIDER")?.value, contract.codeAgentProvider, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_PROVIDER", "cloud API workload Code Agent provider");
|
||||||
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_MODEL")?.value, contract.model, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_MODEL", "cloud API workload Code Agent model");
|
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_MODEL")?.value, contract.model, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_MODEL", "cloud API workload Code Agent model");
|
||||||
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_TIMEOUT_MS")?.value, "120000", "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_TIMEOUT_MS", "cloud API workload Code Agent hard timeout budget");
|
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_TIMEOUT_MS")?.value, codeAgentBackendTimeoutMs, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_TIMEOUT_MS", "cloud API workload Code Agent hard timeout budget");
|
||||||
expectEqual(
|
expectEqual(
|
||||||
ctx,
|
ctx,
|
||||||
env.get("HWLAB_CODE_AGENT_OPENAI_BASE_URL")?.value,
|
env.get("HWLAB_CODE_AGENT_OPENAI_BASE_URL")?.value,
|
||||||
@@ -591,8 +610,25 @@ function validateCodeAgentProxyTimeoutArtifacts(ctx, workloads) {
|
|||||||
const workloadItems = mapByServiceId(listItems(workloads));
|
const workloadItems = mapByServiceId(listItems(workloads));
|
||||||
const cloudWebEnv = new Map((workloadItems.get("hwlab-cloud-web")?.spec?.template?.spec?.containers?.[0]?.env ?? []).map((entry) => [entry.name, entry.value]));
|
const cloudWebEnv = new Map((workloadItems.get("hwlab-cloud-web")?.spec?.template?.spec?.containers?.[0]?.env ?? []).map((entry) => [entry.name, entry.value]));
|
||||||
const edgeProxyEnv = new Map((workloadItems.get("hwlab-edge-proxy")?.spec?.template?.spec?.containers?.[0]?.env ?? []).map((entry) => [entry.name, entry.value]));
|
const edgeProxyEnv = new Map((workloadItems.get("hwlab-edge-proxy")?.spec?.template?.spec?.containers?.[0]?.env ?? []).map((entry) => [entry.name, entry.value]));
|
||||||
expectEqual(ctx, cloudWebEnv.get("HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS"), "150000", "deploy/k8s/base/workloads.yaml.hwlab-cloud-web.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS", "Cloud Web workload same-origin Code Agent proxy timeout budget");
|
const cloudApiEnv = new Map((workloadItems.get("hwlab-cloud-api")?.spec?.template?.spec?.containers?.[0]?.env ?? []).map((entry) => [entry.name, entry.value]));
|
||||||
expectEqual(ctx, edgeProxyEnv.get("HWLAB_EDGE_PROXY_TIMEOUT_MS"), "150000", "deploy/k8s/base/workloads.yaml.hwlab-edge-proxy.env.HWLAB_EDGE_PROXY_TIMEOUT_MS", "edge proxy workload Code Agent timeout budget");
|
expectEqual(ctx, cloudWebEnv.get("HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS"), codeAgentTransportTimeoutMs, "deploy/k8s/base/workloads.yaml.hwlab-cloud-web.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS", "Cloud Web workload same-origin Code Agent proxy timeout budget");
|
||||||
|
expectEqual(ctx, edgeProxyEnv.get("HWLAB_EDGE_PROXY_TIMEOUT_MS"), codeAgentTransportTimeoutMs, "deploy/k8s/base/workloads.yaml.hwlab-edge-proxy.env.HWLAB_EDGE_PROXY_TIMEOUT_MS", "edge proxy workload Code Agent timeout budget");
|
||||||
|
expect(
|
||||||
|
ctx,
|
||||||
|
Number.parseInt(cloudWebEnv.get("HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS") ?? "0", 10) > Number.parseInt(cloudApiEnv.get("HWLAB_CODE_AGENT_TIMEOUT_MS") ?? "0", 10),
|
||||||
|
"code_agent_timeout_layering",
|
||||||
|
"deploy/k8s/base/workloads.yaml.hwlab-cloud-web.env.HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS",
|
||||||
|
"Cloud Web workload proxy timeout must exceed cloud-api Code Agent timeout",
|
||||||
|
{ expected: `>${cloudApiEnv.get("HWLAB_CODE_AGENT_TIMEOUT_MS")}`, actual: cloudWebEnv.get("HWLAB_CLOUD_WEB_PROXY_TIMEOUT_MS") }
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
ctx,
|
||||||
|
Number.parseInt(edgeProxyEnv.get("HWLAB_EDGE_PROXY_TIMEOUT_MS") ?? "0", 10) > Number.parseInt(cloudApiEnv.get("HWLAB_CODE_AGENT_TIMEOUT_MS") ?? "0", 10),
|
||||||
|
"code_agent_timeout_layering",
|
||||||
|
"deploy/k8s/base/workloads.yaml.hwlab-edge-proxy.env.HWLAB_EDGE_PROXY_TIMEOUT_MS",
|
||||||
|
"Edge workload proxy timeout must exceed cloud-api Code Agent timeout",
|
||||||
|
{ expected: `>${cloudApiEnv.get("HWLAB_CODE_AGENT_TIMEOUT_MS")}`, actual: edgeProxyEnv.get("HWLAB_EDGE_PROXY_TIMEOUT_MS") }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildPlan() {
|
async function buildPlan() {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const webRoot = path.join(repoRoot, "web/hwlab-cloud-web");
|
|||||||
const defaultLiveUrl = "http://74.48.78.17:16666/";
|
const defaultLiveUrl = "http://74.48.78.17:16666/";
|
||||||
const helpOwner = "codex_1779444232735_1";
|
const helpOwner = "codex_1779444232735_1";
|
||||||
const legacyFailureWindowMs = 4500;
|
const legacyFailureWindowMs = 4500;
|
||||||
const codeAgentLongTimeoutMs = 150000;
|
const codeAgentLongTimeoutMs = 180000;
|
||||||
const localAgentFixtureDelayMs = 5200;
|
const localAgentFixtureDelayMs = 5200;
|
||||||
const codeAgentE2ePrompts = Object.freeze([
|
const codeAgentE2ePrompts = Object.freeze([
|
||||||
{
|
{
|
||||||
@@ -2565,7 +2565,7 @@ function hasCodeAgentLongTimeoutContract(files) {
|
|||||||
const app = files.app;
|
const app = files.app;
|
||||||
return (
|
return (
|
||||||
/DEFAULT_API_TIMEOUT_MS\s*=\s*4500/u.test(app) &&
|
/DEFAULT_API_TIMEOUT_MS\s*=\s*4500/u.test(app) &&
|
||||||
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*150000/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) &&
|
/async function sendAgentMessage[\s\S]*?fetchJson\("\/v1\/agent\/chat"[\s\S]*?timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/u.test(app) &&
|
||||||
/timeoutMs\s*=\s*API_TIMEOUT_MS/u.test(functionBody(app, "fetchJson")) &&
|
/timeoutMs\s*=\s*API_TIMEOUT_MS/u.test(functionBody(app, "fetchJson")) &&
|
||||||
/timeoutName\s*=\s*path/u.test(functionBody(app, "fetchJson")) &&
|
/timeoutName\s*=\s*path/u.test(functionBody(app, "fetchJson")) &&
|
||||||
@@ -2619,7 +2619,7 @@ function hasCodeAgentConversationUxStates({ app, styles }) {
|
|||||||
/字段缺失:证据不足/u.test(app) &&
|
/字段缺失:证据不足/u.test(app) &&
|
||||||
/当前不能执行/u.test(app) &&
|
/当前不能执行/u.test(app) &&
|
||||||
/DEFAULT_API_TIMEOUT_MS\s*=\s*4500/u.test(app) &&
|
/DEFAULT_API_TIMEOUT_MS\s*=\s*4500/u.test(app) &&
|
||||||
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*150000/u.test(app) &&
|
/DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*180000/u.test(app) &&
|
||||||
/timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/u.test(app) &&
|
/timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/u.test(app) &&
|
||||||
/HWLAB_CLOUD_WEB_CONFIG/u.test(app) &&
|
/HWLAB_CLOUD_WEB_CONFIG/u.test(app) &&
|
||||||
/失败时会保留输入供重试/u.test(app) &&
|
/失败时会保留输入供重试/u.test(app) &&
|
||||||
|
|||||||
@@ -1639,7 +1639,7 @@ function parseTimeout(value) {
|
|||||||
if (!Number.isInteger(parsed) || parsed <= 0) {
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
||||||
throw new Error("--timeout-ms must be a positive integer");
|
throw new Error("--timeout-ms must be a positive integer");
|
||||||
}
|
}
|
||||||
return Math.min(parsed, 120000);
|
return Math.min(parsed, 180000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function worstStatus(statuses) {
|
function worstStatus(statuses) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
} from "./code-agent-m3-evidence.mjs";
|
} from "./code-agent-m3-evidence.mjs";
|
||||||
|
|
||||||
const DEFAULT_API_TIMEOUT_MS = 4500;
|
const DEFAULT_API_TIMEOUT_MS = 4500;
|
||||||
const DEFAULT_CODE_AGENT_TIMEOUT_MS = 150000;
|
const DEFAULT_CODE_AGENT_TIMEOUT_MS = 180000;
|
||||||
const API_TIMEOUT_MS = resolveTimeoutMs("apiTimeoutMs", DEFAULT_API_TIMEOUT_MS, { min: 500, max: 30000 });
|
const API_TIMEOUT_MS = resolveTimeoutMs("apiTimeoutMs", DEFAULT_API_TIMEOUT_MS, { min: 500, max: 30000 });
|
||||||
const CODE_AGENT_TIMEOUT_MS = resolveTimeoutMs("codeAgentTimeoutMs", DEFAULT_CODE_AGENT_TIMEOUT_MS, { min: 50, max: 300000 });
|
const CODE_AGENT_TIMEOUT_MS = resolveTimeoutMs("codeAgentTimeoutMs", DEFAULT_CODE_AGENT_TIMEOUT_MS, { min: 50, max: 300000 });
|
||||||
const rpcReadMethods = Object.freeze([
|
const rpcReadMethods = Object.freeze([
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ assert.match(app, /renderRecords\(state\.liveSurface\)/);
|
|||||||
assert.match(app, /traceId: error\.traceId \|\| traceId/);
|
assert.match(app, /traceId: error\.traceId \|\| traceId/);
|
||||||
assert.match(app, /error\.traceId = (?:traceId|response\.data\?\.traceId \|\| traceId)/);
|
assert.match(app, /error\.traceId = (?:traceId|response\.data\?\.traceId \|\| traceId)/);
|
||||||
assert.match(app, /DEFAULT_API_TIMEOUT_MS\s*=\s*4500/);
|
assert.match(app, /DEFAULT_API_TIMEOUT_MS\s*=\s*4500/);
|
||||||
assert.match(app, /DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*150000/);
|
assert.match(app, /DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*180000/);
|
||||||
assert.match(app, /async function sendAgentMessage[\s\S]*?timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/);
|
assert.match(app, /async function sendAgentMessage[\s\S]*?timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/);
|
||||||
assert.match(functionBody(app, "fetchJson"), /timeoutMs\s*=\s*API_TIMEOUT_MS/);
|
assert.match(functionBody(app, "fetchJson"), /timeoutMs\s*=\s*API_TIMEOUT_MS/);
|
||||||
for (const hardwareTerm of [
|
for (const hardwareTerm of [
|
||||||
@@ -878,7 +878,7 @@ assert.match(app, /createdAt/);
|
|||||||
assert.match(app, /updatedAt/);
|
assert.match(app, /updatedAt/);
|
||||||
assert.match(app, /error\?\.message/);
|
assert.match(app, /error\?\.message/);
|
||||||
assert.match(app, /DEFAULT_API_TIMEOUT_MS\s*=\s*4500/);
|
assert.match(app, /DEFAULT_API_TIMEOUT_MS\s*=\s*4500/);
|
||||||
assert.match(app, /DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*150000/);
|
assert.match(app, /DEFAULT_CODE_AGENT_TIMEOUT_MS\s*=\s*180000/);
|
||||||
assert.match(app, /CODE_AGENT_TIMEOUT_MS/);
|
assert.match(app, /CODE_AGENT_TIMEOUT_MS/);
|
||||||
assert.match(app, /timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/);
|
assert.match(app, /timeoutMs:\s*CODE_AGENT_TIMEOUT_MS/);
|
||||||
assert.match(app, /HWLAB_CLOUD_WEB_CONFIG/);
|
assert.match(app, /HWLAB_CLOUD_WEB_CONFIG/);
|
||||||
|
|||||||
Reference in New Issue
Block a user