mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 04:47:03 -06:00
fix(agents): defer embedded alias normalization (#129700)
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
resolvePreparedModelThinkingCompat,
|
||||
} from "../model-catalog-lookup.js";
|
||||
import type { ModelCatalogEntry } from "../model-catalog.types.js";
|
||||
import { resolveModelCandidateChain } from "../model-fallback-candidates.js";
|
||||
import { resolveInitialEmbeddedRunModel } from "./run/runtime-resolution.js";
|
||||
|
||||
const STATIC_MODEL_ID = "claude-haiku-4-5";
|
||||
@@ -14,6 +15,8 @@ const resolveHookModelSelectionMock = vi.hoisted(() =>
|
||||
modelId,
|
||||
})),
|
||||
);
|
||||
const loadManifestMetadataSnapshotMock = vi.hoisted(() => vi.fn());
|
||||
const normalizeProviderModelIdWithRuntimeMock = vi.hoisted(() => vi.fn(() => undefined));
|
||||
|
||||
const emptyModelRegistry = {
|
||||
find: vi.fn((_provider: string, _modelId: string) => null),
|
||||
@@ -69,7 +72,12 @@ vi.mock("./model.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../provider-model-normalization.runtime.js", () => ({
|
||||
normalizeProviderModelIdWithRuntime: () => undefined,
|
||||
normalizeProviderModelIdWithRuntime: normalizeProviderModelIdWithRuntimeMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/manifest-contract-eligibility.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../../plugins/manifest-contract-eligibility.js")>()),
|
||||
loadManifestMetadataSnapshot: loadManifestMetadataSnapshotMock,
|
||||
}));
|
||||
|
||||
vi.mock("../harness/runtime-plugin.js", () => ({
|
||||
@@ -184,6 +192,8 @@ describe("embedded model resolution consistency", () => {
|
||||
provider,
|
||||
modelId,
|
||||
}));
|
||||
loadManifestMetadataSnapshotMock.mockReset();
|
||||
normalizeProviderModelIdWithRuntimeMock.mockReset().mockReturnValue(undefined);
|
||||
});
|
||||
|
||||
it("resolves an explicit alias configured only on the selected agent", () => {
|
||||
@@ -208,6 +218,72 @@ describe("embedded model resolution consistency", () => {
|
||||
model: "worker-haiku",
|
||||
}),
|
||||
).toEqual({ provider: "anthropic", modelId: "claude-haiku-4-5" });
|
||||
expect(loadManifestMetadataSnapshotMock).not.toHaveBeenCalled();
|
||||
expect(normalizeProviderModelIdWithRuntimeMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("defers custom-provider normalization until prepared manifest policy is available", () => {
|
||||
const config = {
|
||||
agents: {
|
||||
entries: {
|
||||
worker: {
|
||||
model: { primary: "worker-custom" },
|
||||
models: {
|
||||
"custom-provider/legacy-model": { alias: "worker-custom" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const initial = resolveInitialEmbeddedRunModel({
|
||||
config,
|
||||
agentId: "worker",
|
||||
});
|
||||
|
||||
expect(initial).toEqual({
|
||||
provider: "custom-provider",
|
||||
modelId: "legacy-model",
|
||||
});
|
||||
expect(loadManifestMetadataSnapshotMock).not.toHaveBeenCalled();
|
||||
expect(normalizeProviderModelIdWithRuntimeMock).not.toHaveBeenCalled();
|
||||
|
||||
const manifestPlugins = [
|
||||
{
|
||||
modelIdNormalization: {
|
||||
providers: {
|
||||
"custom-provider": {
|
||||
aliases: { "legacy-model": "modern-model" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
expect(
|
||||
resolveModelCandidateChain({
|
||||
cfg: config,
|
||||
agentId: "worker",
|
||||
provider: initial.provider,
|
||||
model: initial.modelId,
|
||||
requestedRouteResolution: "resolved",
|
||||
fallbacksOverride: [],
|
||||
manifestPlugins,
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
provider: "custom-provider",
|
||||
model: "modern-model",
|
||||
routeOrigin: "requested",
|
||||
routeResolution: "resolved",
|
||||
},
|
||||
]);
|
||||
expect(normalizeProviderModelIdWithRuntimeMock).toHaveBeenCalledWith({
|
||||
provider: "custom-provider",
|
||||
plugins: manifestPlugins,
|
||||
context: {
|
||||
provider: "custom-provider",
|
||||
modelId: "modern-model",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("resolves the same undated configured model for chat and manual compaction", async () => {
|
||||
|
||||
@@ -90,9 +90,16 @@ export function resolveInitialEmbeddedRunModel(params: {
|
||||
model?: string;
|
||||
}): { provider: string; modelId: string } {
|
||||
const cfg = params.config ?? {};
|
||||
// Preliminary route identification stays static; prepared metadata owns
|
||||
// plugin and workspace normalization once the runtime context exists.
|
||||
const staticPreliminaryNormalization = {
|
||||
allowManifestNormalization: false,
|
||||
allowPluginNormalization: false,
|
||||
} as const;
|
||||
const configuredDefault = resolveDefaultModelForAgent({
|
||||
cfg,
|
||||
agentId: params.agentId,
|
||||
...staticPreliminaryNormalization,
|
||||
});
|
||||
const explicitProvider = normalizeOptionalString(params.provider);
|
||||
const explicitModel = normalizeOptionalString(params.model);
|
||||
@@ -108,6 +115,7 @@ export function resolveInitialEmbeddedRunModel(params: {
|
||||
cfg,
|
||||
agentId: params.agentId,
|
||||
defaultProvider: provider,
|
||||
...staticPreliminaryNormalization,
|
||||
});
|
||||
const resolved = resolveModelRefFromString({
|
||||
cfg,
|
||||
@@ -115,6 +123,7 @@ export function resolveInitialEmbeddedRunModel(params: {
|
||||
raw: explicitModel,
|
||||
defaultProvider: provider,
|
||||
aliasIndex,
|
||||
...staticPreliminaryNormalization,
|
||||
});
|
||||
return {
|
||||
provider: explicitProvider ?? resolved?.ref.provider ?? provider,
|
||||
|
||||
@@ -9,6 +9,7 @@ export function resolveDefaultModelForAgent(
|
||||
params: {
|
||||
cfg: OpenClawConfig;
|
||||
agentId?: string;
|
||||
allowManifestNormalization?: boolean;
|
||||
allowPluginNormalization?: boolean;
|
||||
} & ModelManifestNormalizationContext,
|
||||
): ModelRef {
|
||||
@@ -17,6 +18,7 @@ export function resolveDefaultModelForAgent(
|
||||
agentId: params.agentId,
|
||||
defaultProvider: DEFAULT_PROVIDER,
|
||||
defaultModel: DEFAULT_MODEL,
|
||||
allowManifestNormalization: params.allowManifestNormalization,
|
||||
allowPluginNormalization: params.allowPluginNormalization,
|
||||
manifestPlugins: params.manifestPlugins,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user