diff --git a/scripts/e2e/parallels/linux-smoke.ts b/scripts/e2e/parallels/linux-smoke.ts index 8ca8c7ed72f..0fc3ab45884 100755 --- a/scripts/e2e/parallels/linux-smoke.ts +++ b/scripts/e2e/parallels/linux-smoke.ts @@ -12,9 +12,7 @@ import { parseBoolEnv, parseMode, parseProvider, - modelTransportConfigJson, - providerIdFromModelId, - providerTimeoutConfigJson, + modelProviderConfigBatchJson, repoRoot, resolveHostIp, resolveHostPort, @@ -690,22 +688,14 @@ rm -rf /root/.openclaw/test-bad-plugin`); private verifyLocalTurn(): void { this.guestExec(["openclaw", "models", "set", this.auth.modelId]); - const providerId = providerIdFromModelId(this.auth.modelId) || this.options.provider; - const providerTimeoutConfig = providerTimeoutConfigJson(this.auth.modelId, "linux"); - if (providerTimeoutConfig) { - this.guestBash( - `openclaw config set ${shellQuote(`models.providers.${providerId}`)} ${shellQuote( - providerTimeoutConfig, - )} --strict-json`, - ); - } - const modelTransportConfig = modelTransportConfigJson(this.auth.modelId); - if (modelTransportConfig) { - this.guestBash( - `openclaw config set ${shellQuote( - `agents.defaults.models.${this.auth.modelId}`, - )} ${shellQuote(modelTransportConfig)} --strict-json`, - ); + const modelProviderConfigBatch = modelProviderConfigBatchJson(this.auth.modelId, "linux"); + if (modelProviderConfigBatch) { + this.guestBash(`provider_config_batch="$(mktemp)" +cat >"$provider_config_batch" <<'JSON' +${modelProviderConfigBatch} +JSON +openclaw config set --batch-file "$provider_config_batch" --strict-json +rm -f "$provider_config_batch"`); } this.guestExec([ "openclaw", diff --git a/scripts/e2e/parallels/macos-smoke.ts b/scripts/e2e/parallels/macos-smoke.ts index 2705d149d0a..66bb5a26e58 100755 --- a/scripts/e2e/parallels/macos-smoke.ts +++ b/scripts/e2e/parallels/macos-smoke.ts @@ -11,9 +11,7 @@ import { packOpenClaw, parseMode, parseProvider, - modelTransportConfigJson, - providerIdFromModelId, - providerTimeoutConfigJson, + modelProviderConfigBatchJson, resolveHostIp, resolveHostPort, resolveLatestVersion, @@ -974,22 +972,16 @@ exit 1`); private verifyTurn(): void { this.guestExec([guestNode, guestOpenClawEntry, "models", "set", this.auth.modelId]); - const providerId = providerIdFromModelId(this.auth.modelId) || this.options.provider; - const providerTimeoutConfig = providerTimeoutConfigJson(this.auth.modelId, "macos"); - if (providerTimeoutConfig) { - this.guestSh( - `${shellQuote(guestNode)} ${shellQuote(guestOpenClawEntry)} config set ${shellQuote( - `models.providers.${providerId}`, - )} ${shellQuote(providerTimeoutConfig)} --strict-json`, - ); - } - const modelTransportConfig = modelTransportConfigJson(this.auth.modelId); - if (modelTransportConfig) { - this.guestSh( - `${shellQuote(guestNode)} ${shellQuote(guestOpenClawEntry)} config set ${shellQuote( - `agents.defaults.models.${this.auth.modelId}`, - )} ${shellQuote(modelTransportConfig)} --strict-json`, - ); + const modelProviderConfigBatch = modelProviderConfigBatchJson(this.auth.modelId, "macos"); + if (modelProviderConfigBatch) { + this.guestSh(`provider_config_batch="$(mktemp)" +cat >"$provider_config_batch" <<'JSON' +${modelProviderConfigBatch} +JSON +${shellQuote(guestNode)} ${shellQuote( + guestOpenClawEntry, + )} config set --batch-file "$provider_config_batch" --strict-json +rm -f "$provider_config_batch"`); } this.guestExec([ guestNode, diff --git a/scripts/e2e/parallels/npm-update-scripts.ts b/scripts/e2e/parallels/npm-update-scripts.ts index 9f31ca41add..e6e76244d83 100644 --- a/scripts/e2e/parallels/npm-update-scripts.ts +++ b/scripts/e2e/parallels/npm-update-scripts.ts @@ -5,11 +5,7 @@ import { windowsModelProviderTimeoutScript, windowsOpenClawResolver, } from "./powershell.ts"; -import { - modelTransportConfigJson, - providerIdFromModelId, - providerTimeoutConfigJson, -} from "./provider-auth.ts"; +import { modelProviderConfigBatchJson } from "./provider-auth.ts"; import type { Platform, ProviderAuth } from "./types.ts"; export interface NpmUpdateScriptInput { @@ -23,25 +19,20 @@ function posixModelProviderConfigCommands( modelId: string, platform: Platform, ): string { - const commands: string[] = []; - const providerId = providerIdFromModelId(modelId); - const configJson = providerTimeoutConfigJson(modelId, platform); - if (providerId && configJson) { - commands.push( - `${command} config set ${shellQuote(`models.providers.${providerId}`)} ${shellQuote( - configJson, - )} --strict-json`, - ); + const batchJson = modelProviderConfigBatchJson(modelId, platform); + if (!batchJson) { + return ""; } - const transportJson = modelTransportConfigJson(modelId); - if (transportJson) { - commands.push( - `${command} config set ${shellQuote(`agents.defaults.models.${modelId}`)} ${shellQuote( - transportJson, - )} --strict-json`, - ); - } - return commands.join("\n"); + return `provider_config_batch="$(mktemp)" +cat >"$provider_config_batch" <<'JSON' +${batchJson} +JSON +set +e +${command} config set --batch-file "$provider_config_batch" --strict-json +provider_config_exit=$? +set -e +rm -f "$provider_config_batch" +if [ "$provider_config_exit" -ne 0 ]; then exit "$provider_config_exit"; fi`; } function posixAssertAgentOkScript(command: string, input: NpmUpdateScriptInput, sessionId: string) { diff --git a/scripts/e2e/parallels/provider-auth.ts b/scripts/e2e/parallels/provider-auth.ts index dcdbd4805b8..872029b80bc 100644 --- a/scripts/e2e/parallels/provider-auth.ts +++ b/scripts/e2e/parallels/provider-auth.ts @@ -122,6 +122,26 @@ export function modelTransportConfigJson(modelId: string): string { }); } +export function modelProviderConfigBatchJson(modelId: string, platform: Platform): string { + const commands: Array<{ path: string; value: unknown }> = []; + const providerId = providerIdFromModelId(modelId); + const providerConfig = providerTimeoutConfigJson(modelId, platform); + if (providerId && providerConfig) { + commands.push({ + path: `models.providers.${providerId}`, + value: JSON.parse(providerConfig) as unknown, + }); + } + const modelTransportConfig = modelTransportConfigJson(modelId); + if (modelTransportConfig) { + commands.push({ + path: `agents.defaults.models.${modelId}`, + value: JSON.parse(modelTransportConfig) as unknown, + }); + } + return commands.length === 0 ? "" : JSON.stringify(commands); +} + export function parseProvider(value: string): Provider { if (value === "openai" || value === "anthropic" || value === "minimax") { return value; diff --git a/test/scripts/parallels-smoke-model.test.ts b/test/scripts/parallels-smoke-model.test.ts index e5f566b0313..b449d74bf6f 100644 --- a/test/scripts/parallels-smoke-model.test.ts +++ b/test/scripts/parallels-smoke-model.test.ts @@ -321,10 +321,10 @@ console.log(JSON.stringify(result)); expect(script, scriptPath).toContain("minimal"); expect(script, scriptPath).toContain("finalAssistant(Raw|Visible)Text"); } - expect(readFileSync(TS_PATHS.macos, "utf8")).toContain("providerTimeoutConfigJson"); - expect(readFileSync(TS_PATHS.macos, "utf8")).toContain("modelTransportConfigJson"); - expect(readFileSync(TS_PATHS.linux, "utf8")).toContain("providerTimeoutConfigJson"); - expect(readFileSync(TS_PATHS.linux, "utf8")).toContain("modelTransportConfigJson"); + expect(readFileSync(TS_PATHS.macos, "utf8")).toContain("modelProviderConfigBatchJson"); + expect(readFileSync(TS_PATHS.macos, "utf8")).toContain("config set --batch-file"); + expect(readFileSync(TS_PATHS.linux, "utf8")).toContain("modelProviderConfigBatchJson"); + expect(readFileSync(TS_PATHS.linux, "utf8")).toContain("config set --batch-file"); expect(readFileSync(TS_PATHS.windows, "utf8")).toContain("windowsModelProviderTimeoutScript"); expect(readFileSync(TS_PATHS.powershell, "utf8")).toContain("config set --batch-file"); @@ -336,8 +336,8 @@ console.log(JSON.stringify(result)); expect(npmUpdateScripts).toContain("finalAssistant(Raw|Visible)Text"); expect(npmUpdateScripts).toContain("posixAssertAgentOkScript"); expect(npmUpdateScripts).toContain("windowsModelProviderTimeoutScript"); - expect(npmUpdateScripts).toContain("modelTransportConfigJson"); - expect(npmUpdateScripts).toContain("agents.defaults.models.${modelId}"); + expect(npmUpdateScripts).toContain("modelProviderConfigBatchJson"); + expect(npmUpdateScripts).toContain("config set --batch-file"); }); it("clears phase timers and applies phase deadlines to guest commands", () => {