Skip to content

Commit b334e7e

Browse files
committed
fix(agents): avoid alias setup load for matching refs
1 parent d5ac976 commit b334e7e

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

src/agents/model-runtime-aliases.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
33
import { testing as cliBackendsTesting } from "./cli-backends.js";
44
import { createModelPickerVisibleProviderPredicate } from "./model-picker-visibility.js";
55
import {
6+
areRuntimeModelRefsEquivalent,
67
isCliRuntimeProvider,
78
resolveCliRuntimeExecutionProvider,
89
} from "./model-runtime-aliases.js";
@@ -164,3 +165,24 @@ describe("resolveCliRuntimeExecutionProvider", () => {
164165
expect(isVisibleProvider("acme-cli")).toBe(true);
165166
});
166167
});
168+
169+
describe("areRuntimeModelRefsEquivalent", () => {
170+
afterEach(() => {
171+
cliBackendsTesting.resetDepsForTest();
172+
});
173+
174+
it("does not load setup runtime aliases for already-identical refs", () => {
175+
cliBackendsTesting.setDepsForTest({
176+
resolvePluginSetupRegistry: () => {
177+
throw new Error("setup registry should not load for identical refs");
178+
},
179+
resolveRuntimeCliBackends: () => [],
180+
});
181+
182+
expect(
183+
areRuntimeModelRefsEquivalent("anthropic/claude", "anthropic/claude", {
184+
config: {},
185+
}),
186+
).toBe(true);
187+
});
188+
});

src/agents/model-runtime-aliases.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,26 @@ function normalizeRuntimeModelRefForComparison(
8181
return model ? `${canonicalProvider}/${model}` : canonicalProvider;
8282
}
8383

84+
function normalizeRuntimeModelRefWithoutAlias(raw: string): string {
85+
const trimmed = raw.trim();
86+
const slash = trimmed.indexOf("/");
87+
if (slash <= 0 || slash >= trimmed.length - 1) {
88+
return normalizeProviderId(trimmed);
89+
}
90+
const provider = trimmed.slice(0, slash).trim();
91+
const model = trimmed.slice(slash + 1).trim();
92+
const normalizedProvider = normalizeProviderId(provider);
93+
return model ? `${normalizedProvider}/${model}` : normalizedProvider;
94+
}
95+
8496
export function areRuntimeModelRefsEquivalent(
8597
left: string,
8698
right: string,
8799
options: RuntimeAliasComparisonOptions = {},
88100
): boolean {
101+
if (normalizeRuntimeModelRefWithoutAlias(left) === normalizeRuntimeModelRefWithoutAlias(right)) {
102+
return true;
103+
}
89104
return (
90105
normalizeRuntimeModelRefForComparison(left, options) ===
91106
normalizeRuntimeModelRefForComparison(right, options)

src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,16 @@ describe("runReplyAgent heartbeat followup guard", () => {
270270
runOverrides: { sessionId: "stale-session" },
271271
sessionStore,
272272
});
273+
state.runEmbeddedAgentMock.mockResolvedValueOnce({
274+
payloads: [{ text: "final" }],
275+
meta: {
276+
agentMeta: {
277+
provider: "anthropic",
278+
model: "claude",
279+
usage: { input: 1, output: 1 },
280+
},
281+
},
282+
});
273283

274284
const pending = run();
275285
await new Promise<void>((resolve) => setTimeout(resolve, 0));

0 commit comments

Comments
 (0)