





















@@ -5,6 +5,7 @@ import path from "node:path";
55import { setTimeout as sleep } from "node:timers/promises";
66import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
77import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
8+import { redactSensitiveText } from "openclaw/plugin-sdk/logging-core";
89import {
910parseStrictPositiveInteger,
1011resolveTimerTimeoutMs,
@@ -58,6 +59,9 @@ type MatrixQaGatewayChild = {
5859const DEFAULT_MATRIX_QA_RUN_TIMEOUT_MS = 30 * 60_000;
5960const DEFAULT_MATRIX_QA_CLEANUP_TIMEOUT_MS = 90_000;
6061const DEFAULT_MATRIX_QA_CANARY_TIMEOUT_MS = 45_000;
62+const MATRIX_QA_GATEWAY_STDERR_LOG = "gateway.stderr.log";
63+const MATRIX_QA_GATEWAY_DEBUG_MAX_LINES = 6;
64+const MATRIX_QA_GATEWAY_DEBUG_MAX_LINE_CHARS = 700;
61656266type MatrixQaLiveLaneGatewayHarness = {
6367gateway: MatrixQaGatewayChild;
@@ -195,6 +199,44 @@ function writeMatrixQaProgress(message: string) {
195199process.stderr.write(`[matrix-qa] ${message}\n`);
196200}
197201202+function isMatrixQaGatewayDebugRelevantLine(line: string) {
203+return /\b(?:auth|authorization|unauthorized|forbidden|missing|error|fail(?:ed|ure)?|exception|provider|api[-_ ]?key|token|denied|rejected|timeout)\b/iu.test(
204+line,
205+);
206+}
207+208+function trimMatrixQaGatewayDebugLine(line: string) {
209+const redacted = redactSensitiveText(line.trim());
210+return redacted.length > MATRIX_QA_GATEWAY_DEBUG_MAX_LINE_CHARS
211+ ? `${redacted.slice(0, MATRIX_QA_GATEWAY_DEBUG_MAX_LINE_CHARS)}...`
212+ : redacted;
213+}
214+215+function summarizeMatrixQaGatewayStderrLog(stderrText: string) {
216+const lines = stderrText.split(/\r?\n/u).map(trimMatrixQaGatewayDebugLine).filter(Boolean);
217+if (lines.length === 0) {
218+return undefined;
219+}
220+221+const relevantLines = lines.filter(isMatrixQaGatewayDebugRelevantLine);
222+const selectedLines = (relevantLines.length > 0 ? relevantLines : lines).slice(
223+-MATRIX_QA_GATEWAY_DEBUG_MAX_LINES,
224+);
225+return ["gateway stderr tail:", ...selectedLines.map((line) => `- ${line}`)].join("\n");
226+}
227+228+async function readMatrixQaGatewayDebugSummary(debugDirPath: string) {
229+const stderrText = await fs
230+.readFile(path.join(debugDirPath, MATRIX_QA_GATEWAY_STDERR_LOG), "utf8")
231+.catch((error: unknown) => {
232+if ((error as NodeJS.ErrnoException).code === "ENOENT") {
233+return "";
234+}
235+throw error;
236+});
237+return summarizeMatrixQaGatewayStderrLog(stderrText);
238+}
239+198240function parsePositiveMatrixQaEnvMs(name: string, fallback: number) {
199241const raw = process.env[name];
200242if (raw === undefined) {
@@ -1071,11 +1113,16 @@ export async function runMatrixQaLive(params: {
10711113details: cleanupErrors.join("\n"),
10721114});
10731115}
1116+const gatewayDebugSummary = preservedGatewayDebugDirPath
1117+ ? await readMatrixQaGatewayDebugSummary(preservedGatewayDebugDirPath)
1118+ : undefined;
10741119if (preservedGatewayDebugDirPath) {
10751120checks.push({
10761121name: "Matrix gateway debug logs",
10771122status: "pass",
1078-details: `preserved at: ${preservedGatewayDebugDirPath}`,
1123+details: [`preserved at: ${preservedGatewayDebugDirPath}`, gatewayDebugSummary]
1124+.filter(Boolean)
1125+.join("\n"),
10791126});
10801127}
10811128@@ -1189,6 +1236,7 @@ export async function runMatrixQaLive(params: {
11891236details: [
11901237 ...failedChecks.map((check) => `check ${check.name}: ${check.details ?? "failed"}`),
11911238 ...failedScenarios.map((scenario) => `scenario ${scenario.id}: ${scenario.details}`),
1239+ ...(gatewayDebugSummary ? [`gateway debug: ${gatewayDebugSummary}`] : []),
11921240 ...cleanupErrors.map((error) => `cleanup: ${error}`),
11931241],
11941242artifacts: artifactPaths,
@@ -1231,6 +1279,7 @@ export const testing = {
12311279 resolveMatrixQaCanaryTimeoutMs,
12321280 resolveMatrixQaModels,
12331281 shouldWriteMatrixQaProgress,
1282+ summarizeMatrixQaGatewayStderrLog,
12341283 summarizeMatrixQaConfigSnapshot,
12351284 waitForMatrixChannelReady,
12361285 withMatrixQaRunDeadline,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。