























@@ -335,12 +335,14 @@ class LinuxSmoke {
335335await this.phase("fresh.onboard-ref", 180, () => this.runRefOnboard());
336336await this.phase("fresh.inject-bad-plugin", 90, () => this.injectBadPluginFixture());
337337await this.phase("fresh.gateway-start", 240, () => this.startGatewayBackground());
338-await this.phase("fresh.bad-plugin-diagnostic", 90, () => this.verifyBadPluginDiagnostic());
338+await this.phase("fresh.bad-plugin-diagnostic", 90, () =>
339+this.verifyBadPluginDiagnostic("fresh"),
340+);
339341await this.phase("fresh.gateway-status", 240, () => this.verifyGatewayStatus());
340342this.status.freshGateway = "pass";
341343await this.phase(
342344"fresh.first-local-agent-turn",
343-Number(process.env.OPENCLAW_PARALLELS_LINUX_AGENT_TIMEOUT_S || 300),
345+Number(process.env.OPENCLAW_PARALLELS_LINUX_AGENT_TIMEOUT_S || 900),
344346() => this.verifyLocalTurn(),
345347);
346348this.status.freshAgent = "pass";
@@ -362,12 +364,14 @@ class LinuxSmoke {
362364await this.phase("upgrade.inject-bad-plugin", 90, () => this.injectBadPluginFixture());
363365await this.phase("upgrade.onboard-ref", 180, () => this.runRefOnboard());
364366await this.phase("upgrade.gateway-start", 240, () => this.startGatewayBackground());
365-await this.phase("upgrade.bad-plugin-diagnostic", 90, () => this.verifyBadPluginDiagnostic());
367+await this.phase("upgrade.bad-plugin-diagnostic", 90, () =>
368+this.verifyBadPluginDiagnostic("upgrade"),
369+);
366370await this.phase("upgrade.gateway-status", 240, () => this.verifyGatewayStatus());
367371this.status.upgradeGateway = "pass";
368372await this.phase(
369373"upgrade.first-local-agent-turn",
370-Number(process.env.OPENCLAW_PARALLELS_LINUX_AGENT_TIMEOUT_S || 300),
374+Number(process.env.OPENCLAW_PARALLELS_LINUX_AGENT_TIMEOUT_S || 900),
371375() => this.verifyLocalTurn(),
372376);
373377this.status.upgradeAgent = "pass";
@@ -550,17 +554,18 @@ plugin_dir = "/root/.openclaw/test-bad-plugin"
550554if plugin_dir not in paths:
551555 paths.append(plugin_dir)
552556allow = plugins.get("allow")
553-if isinstance(allow, list) and "test-bad-plugin" not in allow:
554- allow.append("test-bad-plugin")
557+if not isinstance(allow, list):
558+ allow = plugins["allow"] = ["openai"]
559+for plugin_id in ("test-bad-plugin", "openai"):
560+ if plugin_id not in allow:
561+ allow.append(plugin_id)
555562config_path.write_text(json.dumps(config, indent=2) + "\n")
556563PY`);
557564}
558565559566private startGatewayBackground(): void {
560567const bonjourEnv = this.disableBonjour ? " OPENCLAW_DISABLE_BONJOUR=1" : "";
561-this.guestExec([
562-"bash",
563-"-lc",
568+this.guestBash(
564569String.raw`pkill -f "openclaw gateway run" >/dev/null 2>&1 || true
565570rm -f /tmp/openclaw-parallels-linux-gateway.log
566571setsid sh -lc ` +
@@ -570,7 +575,7 @@ setsid sh -lc ` +
570575 )} openclaw gateway run --bind loopback --port 18789 --force >/tmp/openclaw-parallels-linux-gateway.log 2>&1`,
571576) +
572577String.raw` >/dev/null 2>&1 < /dev/null &`,
573-]);
578+);
574579const deadline = Date.now() + 240_000;
575580while (Date.now() < deadline) {
576581if (this.showGatewayStatusCompat(false)) {
@@ -635,12 +640,34 @@ setsid sh -lc ` +
635640throw new Error("gateway status did not become RPC-ready");
636641}
637642638-private verifyBadPluginDiagnostic(): void {
639-this.guestExec([
640-"bash",
641-"-lc",
642-'grep -F "failed to load setup entry" /tmp/openclaw-parallels-linux-gateway.log',
643-]);
643+private async verifyBadPluginDiagnostic(lane: "fresh" | "upgrade"): Promise<void> {
644+const warning =
645+"channel plugin manifest declares test-bad-plugin without channelConfigs metadata";
646+const gatewayStartLog = await readFile(
647+path.join(this.runDir, `${lane}.gateway-start.log`),
648+"utf8",
649+);
650+if (!gatewayStartLog.includes(warning)) {
651+throw new Error(`bad plugin diagnostic missing: ${warning}`);
652+}
653+this.log(warning);
654+this.guestBash(String.raw`set -euo pipefail
655+python3 - <<'PY'
656+import json
657+from pathlib import Path
658+config_path = Path("/root/.openclaw/openclaw.json")
659+config = json.loads(config_path.read_text()) if config_path.exists() else {}
660+plugins = config.setdefault("plugins", {})
661+load = plugins.setdefault("load", {})
662+paths = load.get("paths")
663+if isinstance(paths, list):
664+ load["paths"] = [path for path in paths if path != "/root/.openclaw/test-bad-plugin"]
665+allow = plugins.get("allow")
666+if isinstance(allow, list):
667+ plugins["allow"] = [plugin_id for plugin_id in allow if plugin_id != "test-bad-plugin"]
668+config_path.write_text(json.dumps(config, indent=2) + "\n")
669+PY
670+rm -rf /root/.openclaw/test-bad-plugin`);
644671}
645672646673private verifyLocalTurn(): void {
@@ -654,21 +681,15 @@ setsid sh -lc ` +
654681"--strict-json",
655682]);
656683this.prepareAgentWorkspace();
657-this.guestExec([
658-"/bin/sh",
659-"-lc",
684+this.guestBash(
660685`exec /usr/bin/env ${shellQuote(`${this.auth.apiKeyEnv}=${this.auth.apiKeyValue}`)} openclaw agent --local --agent main --session-id parallels-linux-smoke --message ${shellQuote(
661686 "Reply with exact ASCII text OK only.",
662687 )} --json`,
663-]);
688+);
664689}
665690666691private prepareAgentWorkspace(): void {
667-this.guestExec([
668-"/bin/sh",
669-"-lc",
670-posixAgentWorkspaceScript("Parallels Linux smoke test assistant."),
671-]);
692+this.guestBash(posixAgentWorkspaceScript("Parallels Linux smoke test assistant."));
672693}
673694674695private async extractLastVersion(phaseId: string): Promise<string> {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。