Skip to content

Commit 5177472

Browse files
committed
Config: preserve main route bindings
1 parent 00d846d commit 5177472

4 files changed

Lines changed: 62 additions & 4 deletions

File tree

src/commands/doctor/shared/legacy-config-core-migrate.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
22
import { runPluginSetupConfigMigrations } from "../../../plugins/setup-registry.js";
3-
import { normalizeAgentId } from "../../../routing/session-key.js";
3+
import { DEFAULT_AGENT_ID, normalizeAgentId } from "../../../routing/session-key.js";
44
import { migrateLegacySecretRefEnvMarkers } from "../../../secrets/legacy-secretref-env-marker.js";
55
import { applyChannelDoctorCompatibilityMigrations } from "./channel-legacy-config-migrate.js";
66
import { normalizeBaseCompatibilityConfigValues } from "./legacy-config-compatibility-base.js";
@@ -23,7 +23,10 @@ function pruneBindingsForMissingAgents(cfg: OpenClawConfig, changes: string[]):
2323
return cfg;
2424
}
2525

26-
const agentIds = new Set(validAgents.map((agent) => normalizeAgentId(agent.id)));
26+
const agentIds = new Set([
27+
normalizeAgentId(DEFAULT_AGENT_ID),
28+
...validAgents.map((agent) => normalizeAgentId(agent.id)),
29+
]);
2730
const nextBindings = bindings.filter((binding) => {
2831
const agentId = binding && typeof binding === "object" ? binding.agentId : undefined;
2932
return typeof agentId !== "string" || agentIds.has(normalizeAgentId(agentId));

src/commands/doctor/shared/legacy-config-migrate.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ describe("compatibility binding repair migrate", () => {
4444
expect(res.changes).toContain("Removed 1 binding that referenced missing agents.list ids.");
4545
});
4646

47+
it('preserves bindings for the implicit default agent "main" when agents.list is valid', () => {
48+
const bindings = [
49+
{
50+
type: "route",
51+
agentId: "main",
52+
match: { channel: "discord", accountId: "default" },
53+
},
54+
{
55+
type: "route",
56+
agentId: "main",
57+
match: { channel: "telegram", accountId: "default" },
58+
},
59+
];
60+
61+
const res = normalizeCompatibilityConfigValues({
62+
agents: {
63+
list: [{ id: "codex" }, { id: "claude" }],
64+
},
65+
bindings,
66+
} as OpenClawConfig);
67+
68+
expect(res.config.bindings).toEqual(bindings);
69+
expect(res.changes).not.toContain(
70+
"Removed 2 bindings that referenced missing agents.list ids.",
71+
);
72+
});
73+
4774
it("leaves bindings untouched when agents.list has malformed entries", () => {
4875
const cfg = {
4976
agents: {

src/config/config.schema-regressions.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,31 @@ describe("config schema regressions", () => {
457457
expect(res.ok).toBe(true);
458458
});
459459

460+
it('accepts route bindings to the implicit default agent "main" when agents.list is populated', () => {
461+
const res = validateConfigObject({
462+
agents: {
463+
list: [
464+
{ id: "codex", model: "anthropic/claude-3-5-sonnet" },
465+
{ id: "claude", model: "anthropic/claude-3-5-sonnet" },
466+
],
467+
},
468+
bindings: [
469+
{
470+
type: "route",
471+
agentId: "main",
472+
match: { channel: "discord", accountId: "default" },
473+
},
474+
{
475+
type: "route",
476+
agentId: "main",
477+
match: { channel: "telegram", accountId: "default" },
478+
},
479+
],
480+
});
481+
482+
expect(res.ok).toBe(true);
483+
});
484+
460485
it("accepts bindings that match normalized agents.list ids", () => {
461486
const res = validateConfigObject({
462487
agents: {

src/config/zod-schema.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
import { z } from "zod";
66
import { parseByteSize } from "../cli/parse-bytes.js";
77
import { parseDurationMs } from "../cli/parse-duration.js";
8-
import { normalizeAgentId } from "../routing/session-key.js";
8+
import { DEFAULT_AGENT_ID, normalizeAgentId } from "../routing/session-key.js";
99
import {
1010
isValidControlUiChatMessageMaxWidth,
1111
normalizeControlUiChatMessageMaxWidth,
@@ -1283,7 +1283,10 @@ export const OpenClawSchema = z
12831283
return;
12841284
}
12851285
const agentIds = new Set(agents.map((agent) => agent.id));
1286-
const effectiveAgentIds = new Set(agents.map((agent) => normalizeAgentId(agent.id)));
1286+
const effectiveAgentIds = new Set([
1287+
normalizeAgentId(DEFAULT_AGENT_ID),
1288+
...agents.map((agent) => normalizeAgentId(agent.id)),
1289+
]);
12871290

12881291
// Bindings referencing a missing agent id silently misroute at gateway
12891292
// load time. Match routing's normalized id semantics; otherwise valid

0 commit comments

Comments
 (0)