mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-21 05:32:53 +00:00
fix: clear stalled model resolution lanes
This commit is contained in:
@@ -22,6 +22,10 @@ type DynamicModelContext = {
|
||||
};
|
||||
|
||||
type ResolvedModelLike = Record<string, unknown>;
|
||||
type NormalizedTransportLike = {
|
||||
api?: string | null;
|
||||
baseUrl?: string;
|
||||
};
|
||||
|
||||
type ProviderRuntimeTestMockOptions = {
|
||||
clearHookCache?: () => void;
|
||||
@@ -78,6 +82,42 @@ function normalizeDynamicModel(params: { provider: string; model: ResolvedModelL
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function normalizeTransport(params: {
|
||||
provider: string;
|
||||
context: { api?: string | null; baseUrl?: string };
|
||||
}): NormalizedTransportLike | undefined {
|
||||
const isNativeOpenAiTransport =
|
||||
params.context.api === "openai-completions" &&
|
||||
(params.context.baseUrl === OPENAI_BASE_URL ||
|
||||
(params.provider === "openai" && !params.context.baseUrl));
|
||||
const isNativeXaiTransport =
|
||||
params.context.api === "openai-completions" &&
|
||||
(params.context.baseUrl === XAI_BASE_URL ||
|
||||
(params.provider === "xai" && !params.context.baseUrl));
|
||||
if (
|
||||
params.context.api === "google-generative-ai" &&
|
||||
params.context.baseUrl === "https://generativelanguage.googleapis.com"
|
||||
) {
|
||||
return {
|
||||
api: params.context.api,
|
||||
baseUrl: GOOGLE_GENERATIVE_AI_BASE_URL,
|
||||
};
|
||||
}
|
||||
if (isNativeOpenAiTransport) {
|
||||
return {
|
||||
api: "openai-responses",
|
||||
baseUrl: params.context.baseUrl,
|
||||
};
|
||||
}
|
||||
if (isNativeXaiTransport) {
|
||||
return {
|
||||
api: "openai-responses",
|
||||
baseUrl: params.context.baseUrl,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function buildDynamicModel(
|
||||
params: DynamicModelContext,
|
||||
options: Required<
|
||||
@@ -384,38 +424,38 @@ export function createProviderRuntimeTestMock(options: ProviderRuntimeTestMockOp
|
||||
model: params.context.model as ResolvedModelLike,
|
||||
})
|
||||
: undefined,
|
||||
applyProviderResolvedTransportWithPlugin: (params: {
|
||||
provider: string;
|
||||
config?: unknown;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
context: { model: unknown };
|
||||
}) => {
|
||||
const model = params.context.model as ResolvedModelLike;
|
||||
const normalized = normalizeTransport({
|
||||
provider: params.provider,
|
||||
context: {
|
||||
api: model.api as string | null | undefined,
|
||||
baseUrl: model.baseUrl as string | undefined,
|
||||
},
|
||||
});
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
const nextApi = normalized.api ?? model.api;
|
||||
const nextBaseUrl = normalized.baseUrl ?? model.baseUrl;
|
||||
if (nextApi === model.api && nextBaseUrl === model.baseUrl) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...model,
|
||||
api: nextApi,
|
||||
baseUrl: nextBaseUrl,
|
||||
};
|
||||
},
|
||||
normalizeProviderTransportWithPlugin: (params: {
|
||||
provider: string;
|
||||
context: { api?: string | null; baseUrl?: string };
|
||||
}) => {
|
||||
if (
|
||||
params.context.api === "google-generative-ai" &&
|
||||
params.context.baseUrl === "https://generativelanguage.googleapis.com"
|
||||
) {
|
||||
return {
|
||||
api: params.context.api,
|
||||
baseUrl: GOOGLE_GENERATIVE_AI_BASE_URL,
|
||||
};
|
||||
}
|
||||
if (
|
||||
params.context.api === "openai-completions" &&
|
||||
(params.provider === "openai" || params.context.baseUrl === OPENAI_BASE_URL)
|
||||
) {
|
||||
return {
|
||||
api: "openai-responses",
|
||||
baseUrl: params.context.baseUrl,
|
||||
};
|
||||
}
|
||||
if (
|
||||
params.context.api === "openai-completions" &&
|
||||
(params.provider === "xai" || params.context.baseUrl === XAI_BASE_URL)
|
||||
) {
|
||||
return {
|
||||
api: "openai-responses",
|
||||
baseUrl: params.context.baseUrl,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}) => normalizeTransport(params),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1106,6 +1106,15 @@ describe("resolveModel", () => {
|
||||
buildProviderUnknownModelHintWithPlugin: () => undefined,
|
||||
prepareProviderDynamicModel: async () => {},
|
||||
runProviderDynamicModel: () => undefined,
|
||||
applyProviderResolvedTransportWithPlugin: ({ provider, context }) =>
|
||||
provider === "xai" &&
|
||||
context.model.api === "openai-completions" &&
|
||||
context.model.baseUrl === "https://api.x.ai/v1"
|
||||
? {
|
||||
...context.model,
|
||||
api: "openai-responses",
|
||||
}
|
||||
: undefined,
|
||||
normalizeProviderResolvedModelWithPlugin: ({ provider, context }) =>
|
||||
provider === "xai" ? (context.model as never) : undefined,
|
||||
normalizeProviderTransportWithPlugin: () => undefined,
|
||||
|
||||
@@ -105,6 +105,36 @@ function sanitizeModelHeaders(
|
||||
return Object.keys(next).length > 0 ? next : undefined;
|
||||
}
|
||||
|
||||
function applyResolvedTransportFallback(params: {
|
||||
provider: string;
|
||||
cfg?: OpenClawConfig;
|
||||
runtimeHooks: ProviderRuntimeHooks;
|
||||
model: Model<Api>;
|
||||
}): Model<Api> | undefined {
|
||||
const normalized = params.runtimeHooks.normalizeProviderTransportWithPlugin({
|
||||
provider: params.provider,
|
||||
config: params.cfg,
|
||||
context: {
|
||||
provider: params.provider,
|
||||
api: params.model.api,
|
||||
baseUrl: params.model.baseUrl,
|
||||
},
|
||||
}) as { api?: Api | null; baseUrl?: string } | undefined;
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
const nextApi = normalizeResolvedTransportApi(normalized.api) ?? params.model.api;
|
||||
const nextBaseUrl = normalized.baseUrl ?? params.model.baseUrl;
|
||||
if (nextApi === params.model.api && nextBaseUrl === params.model.baseUrl) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...params.model,
|
||||
api: nextApi,
|
||||
baseUrl: nextBaseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeResolvedModel(params: {
|
||||
provider: string;
|
||||
model: Model<Api>;
|
||||
@@ -153,9 +183,18 @@ function normalizeResolvedModel(params: {
|
||||
model: (compatNormalized ?? pluginNormalized ?? normalizedInputModel) as never,
|
||||
},
|
||||
}) as Model<Api> | undefined;
|
||||
const fallbackTransportNormalized =
|
||||
transportNormalized ??
|
||||
applyResolvedTransportFallback({
|
||||
provider: params.provider,
|
||||
cfg: params.cfg,
|
||||
runtimeHooks,
|
||||
model: compatNormalized ?? pluginNormalized ?? normalizedInputModel,
|
||||
});
|
||||
return normalizeResolvedProviderModel({
|
||||
provider: params.provider,
|
||||
model: transportNormalized ?? compatNormalized ?? pluginNormalized ?? normalizedInputModel,
|
||||
model:
|
||||
fallbackTransportNormalized ?? compatNormalized ?? pluginNormalized ?? normalizedInputModel,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,13 @@ const SETUP_BARREL_GUARDS: GuardedSource[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const CHANNEL_CONFIG_SCHEMA_GUARDS: GuardedSource[] = [
|
||||
{
|
||||
path: bundledPluginFile("tlon", "src/config-schema.ts"),
|
||||
forbiddenPatterns: [/["']openclaw\/plugin-sdk\/core["']/],
|
||||
},
|
||||
];
|
||||
|
||||
const LOCAL_EXTENSION_API_BARREL_GUARDS = [
|
||||
"acpx",
|
||||
"bluebubbles",
|
||||
@@ -469,6 +476,15 @@ describe("channel import guardrails", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps channel config schemas off the broad core sdk barrel", () => {
|
||||
for (const source of CHANNEL_CONFIG_SCHEMA_GUARDS) {
|
||||
const text = readSource(source.path);
|
||||
for (const pattern of source.forbiddenPatterns) {
|
||||
expect(text, `${source.path} should not match ${pattern}`).not.toMatch(pattern);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps bundled extension source files off root and compat plugin-sdk imports", () => {
|
||||
for (const file of collectExtensionSourceFiles()) {
|
||||
const analysis = getSourceAnalysis(file);
|
||||
|
||||
Reference in New Issue
Block a user