fix(config): repair retired llm timeout key

This commit is contained in:
Peter Steinberger
2026-04-27 10:39:46 +01:00
parent a50edbdc60
commit 531a0ddfe4
7 changed files with 70 additions and 2 deletions

View File

@@ -17,6 +17,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Config/doctor: stop masking unknown-key validation diagnostics such as `agents.defaults.llm`, and have `openclaw doctor --fix` remove the retired `agents.defaults.llm` timeout block. Thanks @aidiffuser.
- CLI/plugins: preserve unversioned ClawHub install specs so `plugins update` can follow newer ClawHub releases instead of pinning to the initially resolved version. Fixes #63010; supersedes #58426. Thanks @kangsen1234 and @robinspt.
- Memory-core/subagents: tag plugin-created subagent sessions with their plugin owner so dreaming narrative cleanup can delete its own ephemeral sessions without granting broad admin session deletion. Fixes #72712. Thanks @BSG2000.
- Gateway/models: move local-provider pricing opt-outs, OpenRouter/LiteLLM aliases, and proxy passthrough pricing lookup into plugin manifest metadata so core no longer carries extension-specific pricing tables. Thanks @codex.

View File

@@ -194,6 +194,7 @@ That stages grounded durable candidates into the short-term dreaming store while
- `identity` → `agents.list[].identity`
- `agent.*` → `agents.defaults` + `tools.*` (tools/elevated/exec/sandbox/subagents)
- `agent.model`/`allowedModels`/`modelAliases`/`modelFallbacks`/`imageModelFallbacks` → `agents.defaults.models` + `agents.defaults.model.primary/fallbacks` + `agents.defaults.imageModel.primary/fallbacks`
- remove `agents.defaults.llm`; use `models.providers.<id>.timeoutSeconds` for slow provider/model timeouts
- `browser.ssrfPolicy.allowPrivateNetwork` → `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`
- `browser.profiles.*.driver: "extension"` → `"existing-session"`
- remove `browser.relayBindHost` (legacy extension relay setting)

View File

@@ -57,6 +57,18 @@ function deprecatedCompatRecord<Code extends string>(
// doctor fixes, and replacement notes should be revalidated against the current
// architecture because ownership and config footprint can shift during rollout.
export const DOCTOR_DEPRECATION_COMPAT_RECORDS = [
deprecatedCompatRecord({
code: "doctor-agent-llm-timeout",
owner: "agent-runtime",
introduced: "2026-04-27",
source: "agents.defaults.llm.idleTimeoutSeconds",
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.agents.ts",
replacement: "models.providers.<id>.timeoutSeconds",
docsPath: "/gateway/config-agents",
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
notes:
"The old agent-level idle timeout knob was collapsed into provider request timeout handling.",
}),
deprecatedCompatRecord({
code: "doctor-agent-runtime-embedded-harness",
owner: "agent-runtime",

View File

@@ -98,6 +98,26 @@ describe("legacy migrate mention routing", () => {
});
describe("legacy migrate sandbox scope aliases", () => {
it("removes legacy agents.defaults.llm timeout config", () => {
const res = migrateLegacyConfigForTest({
agents: {
defaults: {
model: { primary: "openai/gpt-5.4" },
llm: {
idleTimeoutSeconds: 120,
},
},
},
});
expect(res.changes).toContain(
"Removed agents.defaults.llm; model idle timeout now follows models.providers.<id>.timeoutSeconds.",
);
expect(res.config?.agents?.defaults).toEqual({
model: { primary: "openai/gpt-5.4" },
});
});
it("moves legacy embeddedHarness runtime policy into agentRuntime", () => {
const res = migrateLegacyConfigForTest({
agents: {

View File

@@ -69,6 +69,15 @@ const LEGACY_AGENT_RUNTIME_POLICY_RULES: LegacyConfigRule[] = [
},
];
const LEGACY_AGENT_LLM_TIMEOUT_RULES: LegacyConfigRule[] = [
{
path: ["agents", "defaults", "llm"],
message:
'agents.defaults.llm is legacy; use models.providers.<id>.timeoutSeconds for slow model/provider timeouts. Run "openclaw doctor --fix".',
match: (value) => getRecord(value) !== null,
},
];
function sandboxScopeFromPerSession(perSession: boolean): "session" | "shared" {
return perSession ? "session" : "shared";
}
@@ -194,6 +203,21 @@ function migrateLegacyAgentRuntimePolicy(
}
export const LEGACY_CONFIG_MIGRATIONS_RUNTIME_AGENTS: LegacyConfigMigrationSpec[] = [
defineLegacyConfigMigration({
id: "agents.defaults.llm->models.providers.timeoutSeconds",
describe: "Remove legacy agents.defaults.llm timeout config",
legacyRules: LEGACY_AGENT_LLM_TIMEOUT_RULES,
apply: (raw, changes) => {
const defaults = getRecord(getRecord(raw.agents)?.defaults);
if (!defaults || getRecord(defaults.llm) === null) {
return;
}
delete defaults.llm;
changes.push(
"Removed agents.defaults.llm; model idle timeout now follows models.providers.<id>.timeoutSeconds.",
);
},
}),
defineLegacyConfigMigration({
id: "agents.embeddedHarness->agentRuntime",
describe: "Move legacy embeddedHarness runtime policy to agentRuntime",

View File

@@ -107,6 +107,15 @@ describe("redactSensitiveText", () => {
expect(output).toBe("TOKEN=***");
});
it("does not redact lowercase key diagnostics", () => {
const input = 'agents.defaults: Unrecognized key: "llm"';
const output = redactSensitiveText(input, {
mode: "tools",
patterns: defaults,
});
expect(output).toBe(input);
});
it("redacts private key blocks", () => {
const input = [
"-----BEGIN PRIVATE KEY-----",

View File

@@ -11,8 +11,9 @@ const DEFAULT_REDACT_KEEP_START = 6;
const DEFAULT_REDACT_KEEP_END = 4;
const DEFAULT_REDACT_PATTERNS: string[] = [
// ENV-style assignments.
String.raw`\b[A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD)\b\s*[=:]\s*(["']?)([^\s"'\\]+)\1`,
// ENV-style assignments. Keep this case-sensitive so diagnostics like
// `Unrecognized key: "llm"` do not lose the actual config key.
String.raw`/\b[A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD)\b\s*[=:]\s*(["']?)([^\s"'\\]+)\1/g`,
// JSON fields.
String.raw`"(?:apiKey|token|secret|password|passwd|accessToken|refreshToken)"\s*:\s*"([^"]+)"`,
// CLI flags.