mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 04:20:34 +00:00
refactor: unify inbound debounce policy and split gateway/models helpers
This commit is contained in:
@@ -111,6 +111,95 @@ async function readJson(pathname: string): Promise<unknown> {
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveProvidersForModelsJson(params: {
|
||||
cfg: OpenClawConfig;
|
||||
agentDir: string;
|
||||
}): Promise<Record<string, ProviderConfig>> {
|
||||
const { cfg, agentDir } = params;
|
||||
const explicitProviders = cfg.models?.providers ?? {};
|
||||
const implicitProviders = await resolveImplicitProviders({ agentDir, explicitProviders });
|
||||
const providers: Record<string, ProviderConfig> = mergeProviders({
|
||||
implicit: implicitProviders,
|
||||
explicit: explicitProviders,
|
||||
});
|
||||
|
||||
const implicitBedrock = await resolveImplicitBedrockProvider({ agentDir, config: cfg });
|
||||
if (implicitBedrock) {
|
||||
const existing = providers["amazon-bedrock"];
|
||||
providers["amazon-bedrock"] = existing
|
||||
? mergeProviderModels(implicitBedrock, existing)
|
||||
: implicitBedrock;
|
||||
}
|
||||
|
||||
const implicitCopilot = await resolveImplicitCopilotProvider({ agentDir });
|
||||
if (implicitCopilot && !providers["github-copilot"]) {
|
||||
providers["github-copilot"] = implicitCopilot;
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
function mergeWithExistingProviderSecrets(params: {
|
||||
nextProviders: Record<string, ProviderConfig>;
|
||||
existingProviders: Record<string, NonNullable<ModelsConfig["providers"]>[string]>;
|
||||
}): Record<string, ProviderConfig> {
|
||||
const { nextProviders, existingProviders } = params;
|
||||
const mergedProviders: Record<string, ProviderConfig> = {};
|
||||
for (const [key, entry] of Object.entries(existingProviders)) {
|
||||
mergedProviders[key] = entry;
|
||||
}
|
||||
for (const [key, newEntry] of Object.entries(nextProviders)) {
|
||||
const existing = existingProviders[key] as
|
||||
| (NonNullable<ModelsConfig["providers"]>[string] & {
|
||||
apiKey?: string;
|
||||
baseUrl?: string;
|
||||
})
|
||||
| undefined;
|
||||
if (!existing) {
|
||||
mergedProviders[key] = newEntry;
|
||||
continue;
|
||||
}
|
||||
const preserved: Record<string, unknown> = {};
|
||||
if (typeof existing.apiKey === "string" && existing.apiKey) {
|
||||
preserved.apiKey = existing.apiKey;
|
||||
}
|
||||
if (typeof existing.baseUrl === "string" && existing.baseUrl) {
|
||||
preserved.baseUrl = existing.baseUrl;
|
||||
}
|
||||
mergedProviders[key] = { ...newEntry, ...preserved };
|
||||
}
|
||||
return mergedProviders;
|
||||
}
|
||||
|
||||
async function resolveProvidersForMode(params: {
|
||||
mode: NonNullable<ModelsConfig["mode"]>;
|
||||
targetPath: string;
|
||||
providers: Record<string, ProviderConfig>;
|
||||
}): Promise<Record<string, ProviderConfig>> {
|
||||
if (params.mode !== "merge") {
|
||||
return params.providers;
|
||||
}
|
||||
const existing = await readJson(params.targetPath);
|
||||
if (!isRecord(existing) || !isRecord(existing.providers)) {
|
||||
return params.providers;
|
||||
}
|
||||
const existingProviders = existing.providers as Record<
|
||||
string,
|
||||
NonNullable<ModelsConfig["providers"]>[string]
|
||||
>;
|
||||
return mergeWithExistingProviderSecrets({
|
||||
nextProviders: params.providers,
|
||||
existingProviders,
|
||||
});
|
||||
}
|
||||
|
||||
async function readRawFile(pathname: string): Promise<string> {
|
||||
try {
|
||||
return await fs.readFile(pathname, "utf8");
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export async function ensureOpenClawModelsJson(
|
||||
config?: OpenClawConfig,
|
||||
agentDirOverride?: string,
|
||||
@@ -124,23 +213,7 @@ export async function ensureOpenClawModelsJson(
|
||||
// through the full loadConfig() pipeline which applies these.
|
||||
applyConfigEnvVars(cfg);
|
||||
|
||||
const explicitProviders = cfg.models?.providers ?? {};
|
||||
const implicitProviders = await resolveImplicitProviders({ agentDir, explicitProviders });
|
||||
const providers: Record<string, ProviderConfig> = mergeProviders({
|
||||
implicit: implicitProviders,
|
||||
explicit: explicitProviders,
|
||||
});
|
||||
const implicitBedrock = await resolveImplicitBedrockProvider({ agentDir, config: cfg });
|
||||
if (implicitBedrock) {
|
||||
const existing = providers["amazon-bedrock"];
|
||||
providers["amazon-bedrock"] = existing
|
||||
? mergeProviderModels(implicitBedrock, existing)
|
||||
: implicitBedrock;
|
||||
}
|
||||
const implicitCopilot = await resolveImplicitCopilotProvider({ agentDir });
|
||||
if (implicitCopilot && !providers["github-copilot"]) {
|
||||
providers["github-copilot"] = implicitCopilot;
|
||||
}
|
||||
const providers = await resolveProvidersForModelsJson({ cfg, agentDir });
|
||||
|
||||
if (Object.keys(providers).length === 0) {
|
||||
return { agentDir, wrote: false };
|
||||
@@ -148,53 +221,18 @@ export async function ensureOpenClawModelsJson(
|
||||
|
||||
const mode = cfg.models?.mode ?? DEFAULT_MODE;
|
||||
const targetPath = path.join(agentDir, "models.json");
|
||||
|
||||
let mergedProviders = providers;
|
||||
let existingRaw = "";
|
||||
if (mode === "merge") {
|
||||
const existing = await readJson(targetPath);
|
||||
if (isRecord(existing) && isRecord(existing.providers)) {
|
||||
const existingProviders = existing.providers as Record<
|
||||
string,
|
||||
NonNullable<ModelsConfig["providers"]>[string]
|
||||
>;
|
||||
mergedProviders = {};
|
||||
for (const [key, entry] of Object.entries(existingProviders)) {
|
||||
mergedProviders[key] = entry;
|
||||
}
|
||||
for (const [key, newEntry] of Object.entries(providers)) {
|
||||
const existing = existingProviders[key] as
|
||||
| (NonNullable<ModelsConfig["providers"]>[string] & {
|
||||
apiKey?: string;
|
||||
baseUrl?: string;
|
||||
})
|
||||
| undefined;
|
||||
if (existing) {
|
||||
const preserved: Record<string, unknown> = {};
|
||||
if (typeof existing.apiKey === "string" && existing.apiKey) {
|
||||
preserved.apiKey = existing.apiKey;
|
||||
}
|
||||
if (typeof existing.baseUrl === "string" && existing.baseUrl) {
|
||||
preserved.baseUrl = existing.baseUrl;
|
||||
}
|
||||
mergedProviders[key] = { ...newEntry, ...preserved };
|
||||
} else {
|
||||
mergedProviders[key] = newEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const mergedProviders = await resolveProvidersForMode({
|
||||
mode,
|
||||
targetPath,
|
||||
providers,
|
||||
});
|
||||
|
||||
const normalizedProviders = normalizeProviders({
|
||||
providers: mergedProviders,
|
||||
agentDir,
|
||||
});
|
||||
const next = `${JSON.stringify({ providers: normalizedProviders }, null, 2)}\n`;
|
||||
try {
|
||||
existingRaw = await fs.readFile(targetPath, "utf8");
|
||||
} catch {
|
||||
existingRaw = "";
|
||||
}
|
||||
const existingRaw = await readRawFile(targetPath);
|
||||
|
||||
if (existingRaw === next) {
|
||||
return { agentDir, wrote: false };
|
||||
|
||||
Reference in New Issue
Block a user