mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-13 23:56:07 +00:00
fix(config): normalize gemini subagent model writes
This commit is contained in:
@@ -79,6 +79,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Google/Gemini: canonicalize provider-qualified retired Gemini 3 Pro Preview refs during Google forward-compatible model resolution, so emitted config uses `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
|
||||
- Google/Gemini: normalize proxy-prefixed retired Gemini 3 Pro Preview catalog rows, so emitted configs use `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
|
||||
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids inside per-agent model overrides before writing config, so agent-specific config emits `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
|
||||
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids in subagent, heartbeat, compaction, and subagent-tool model config during writes, so current config keeps emitting `google/gemini-3.1-pro-preview`.
|
||||
- Docs/subagents: document `agents.defaults.subagents.announceTimeoutMs` in the sub-agent and configuration references. (#75509) Thanks @akrimm702.
|
||||
- Cron: add direct `cron.get`, `openclaw cron get <id>`, and agent-tool `get` support for inspecting one stored cron job by id. (#75117) Thanks @samzong.
|
||||
- Agents/tools: add per-sender tool policies with canonical channel-scoped sender keys, so operators can restrict dangerous tools by requester identity across global, agent, group, core, bundled, and plugin tool surfaces. (#66933) Thanks @JerranC.
|
||||
|
||||
@@ -177,6 +177,17 @@ describe("config io write prepare", () => {
|
||||
primary: "google/gemini-3-pro-preview",
|
||||
fallbacks: ["google/gemini-3-pro-preview", "openai/gpt-5.5"],
|
||||
},
|
||||
heartbeat: { model: "google/gemini-3-pro-preview" },
|
||||
subagents: {
|
||||
model: {
|
||||
primary: "google/gemini-3-pro-preview",
|
||||
fallbacks: ["google/gemini-3-pro-preview"],
|
||||
},
|
||||
},
|
||||
compaction: {
|
||||
model: "google/gemini-3-pro-preview",
|
||||
memoryFlush: { model: "google/gemini-3-pro-preview" },
|
||||
},
|
||||
models: {
|
||||
"google/gemini-3-pro-preview": {
|
||||
alias: "Gemini",
|
||||
@@ -190,6 +201,8 @@ describe("config io write prepare", () => {
|
||||
primary: "google/gemini-3-pro-preview",
|
||||
fallbacks: ["google/gemini-3-pro-preview"],
|
||||
},
|
||||
heartbeat: { model: "google/gemini-3-pro-preview" },
|
||||
subagents: { model: "google/gemini-3-pro-preview" },
|
||||
models: {
|
||||
"google/gemini-3-pro-preview": {
|
||||
alias: "Ops Gemini",
|
||||
@@ -198,6 +211,14 @@ describe("config io write prepare", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
tools: {
|
||||
subagents: {
|
||||
model: {
|
||||
primary: "google/gemini-3-pro-preview",
|
||||
fallbacks: ["google/gemini-3-pro-preview"],
|
||||
},
|
||||
},
|
||||
},
|
||||
gateway: { port: 18789 },
|
||||
};
|
||||
const runtimeConfig: OpenClawConfig = {
|
||||
@@ -207,6 +228,17 @@ describe("config io write prepare", () => {
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview", "openai/gpt-5.5"],
|
||||
},
|
||||
heartbeat: { model: "google/gemini-3.1-pro-preview" },
|
||||
subagents: {
|
||||
model: {
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview"],
|
||||
},
|
||||
},
|
||||
compaction: {
|
||||
model: "google/gemini-3.1-pro-preview",
|
||||
memoryFlush: { model: "google/gemini-3.1-pro-preview" },
|
||||
},
|
||||
models: {
|
||||
"google/gemini-3.1-pro-preview": {
|
||||
alias: "Gemini",
|
||||
@@ -220,6 +252,8 @@ describe("config io write prepare", () => {
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview"],
|
||||
},
|
||||
heartbeat: { model: "google/gemini-3.1-pro-preview" },
|
||||
subagents: { model: "google/gemini-3.1-pro-preview" },
|
||||
models: {
|
||||
"google/gemini-3.1-pro-preview": {
|
||||
alias: "Ops Gemini",
|
||||
@@ -228,6 +262,14 @@ describe("config io write prepare", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
tools: {
|
||||
subagents: {
|
||||
model: {
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview"],
|
||||
},
|
||||
},
|
||||
},
|
||||
gateway: { port: 18789 },
|
||||
};
|
||||
const persisted = resolvePersistCandidateForWrite({
|
||||
@@ -243,6 +285,15 @@ describe("config io write prepare", () => {
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview", "openai/gpt-5.5"],
|
||||
});
|
||||
expect(persisted.agents?.defaults?.heartbeat?.model).toBe("google/gemini-3.1-pro-preview");
|
||||
expect(persisted.agents?.defaults?.subagents?.model).toEqual({
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview"],
|
||||
});
|
||||
expect(persisted.agents?.defaults?.compaction?.model).toBe("google/gemini-3.1-pro-preview");
|
||||
expect(persisted.agents?.defaults?.compaction?.memoryFlush?.model).toBe(
|
||||
"google/gemini-3.1-pro-preview",
|
||||
);
|
||||
expect(persisted.agents?.defaults?.models).toEqual({
|
||||
"google/gemini-3.1-pro-preview": {
|
||||
alias: "Gemini",
|
||||
@@ -252,11 +303,17 @@ describe("config io write prepare", () => {
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview"],
|
||||
});
|
||||
expect(persisted.agents?.list?.[0]?.heartbeat?.model).toBe("google/gemini-3.1-pro-preview");
|
||||
expect(persisted.agents?.list?.[0]?.subagents?.model).toBe("google/gemini-3.1-pro-preview");
|
||||
expect(persisted.agents?.list?.[0]?.models).toEqual({
|
||||
"google/gemini-3.1-pro-preview": {
|
||||
alias: "Ops Gemini",
|
||||
},
|
||||
});
|
||||
expect(persisted.tools?.subagents?.model).toEqual({
|
||||
primary: "google/gemini-3.1-pro-preview",
|
||||
fallbacks: ["google/gemini-3.1-pro-preview"],
|
||||
});
|
||||
expect(persisted.gateway?.port).toBe(18888);
|
||||
});
|
||||
|
||||
|
||||
@@ -333,23 +333,53 @@ function normalizeAgentModelConfigForWrite(value: unknown): unknown {
|
||||
return mutated ? next : value;
|
||||
}
|
||||
|
||||
function normalizeAgentDefaultModelRefsForWrite(config: unknown): unknown {
|
||||
const defaults = getPathValue(config, ["agents", "defaults"]);
|
||||
if (!isRecord(defaults)) {
|
||||
const AGENT_MODEL_CONFIG_KEYS = [
|
||||
"model",
|
||||
"imageModel",
|
||||
"imageGenerationModel",
|
||||
"videoGenerationModel",
|
||||
"musicGenerationModel",
|
||||
"pdfModel",
|
||||
] as const;
|
||||
|
||||
function normalizeModelConfigPathForWrite(config: unknown, path: string[]): unknown {
|
||||
const value = getPathValue(config, path);
|
||||
if (value === undefined) {
|
||||
return config;
|
||||
}
|
||||
const normalizedModel = normalizeAgentModelConfigForWrite(value);
|
||||
return normalizedModel !== value ? setPathValue(config, path, normalizedModel) : config;
|
||||
}
|
||||
|
||||
function normalizeModelStringPathForWrite(config: unknown, path: string[]): unknown {
|
||||
const value = getPathValue(config, path);
|
||||
if (typeof value !== "string") {
|
||||
return config;
|
||||
}
|
||||
const normalized = normalizeAgentModelRefForConfig(value);
|
||||
return normalized !== value ? setPathValue(config, path, normalized) : config;
|
||||
}
|
||||
|
||||
function normalizeAgentModelRefsAtPathForWrite(config: unknown, path: string[]): unknown {
|
||||
const agent = getPathValue(config, path);
|
||||
if (!isRecord(agent)) {
|
||||
return config;
|
||||
}
|
||||
|
||||
let next = config;
|
||||
if (Object.prototype.hasOwnProperty.call(defaults, "model")) {
|
||||
const normalizedModel = normalizeAgentModelConfigForWrite(defaults.model);
|
||||
if (normalizedModel !== defaults.model) {
|
||||
next = setPathValue(next, ["agents", "defaults", "model"], normalizedModel);
|
||||
}
|
||||
for (const key of AGENT_MODEL_CONFIG_KEYS) {
|
||||
next = normalizeModelConfigPathForWrite(next, [...path, key]);
|
||||
}
|
||||
if (isRecord(defaults.models)) {
|
||||
const normalizedModels = normalizeAgentModelMapForConfig(defaults.models);
|
||||
if (normalizedModels !== defaults.models) {
|
||||
next = setPathValue(next, ["agents", "defaults", "models"], normalizedModels);
|
||||
next = normalizeModelStringPathForWrite(next, [...path, "heartbeat", "model"]);
|
||||
next = normalizeModelConfigPathForWrite(next, [...path, "subagents", "model"]);
|
||||
next = normalizeModelStringPathForWrite(next, [...path, "compaction", "model"]);
|
||||
next = normalizeModelStringPathForWrite(next, [...path, "compaction", "memoryFlush", "model"]);
|
||||
|
||||
const models = getPathValue(next, [...path, "models"]);
|
||||
if (isRecord(models)) {
|
||||
const normalizedModels = normalizeAgentModelMapForConfig(models);
|
||||
if (normalizedModels !== models) {
|
||||
next = setPathValue(next, [...path, "models"], normalizedModels);
|
||||
}
|
||||
}
|
||||
return next;
|
||||
@@ -367,27 +397,23 @@ function normalizeAgentListModelRefsForWrite(config: unknown): unknown {
|
||||
return agent;
|
||||
}
|
||||
|
||||
let nextAgent = agent;
|
||||
if (Object.prototype.hasOwnProperty.call(agent, "model")) {
|
||||
const normalizedModel = normalizeAgentModelConfigForWrite(agent.model);
|
||||
if (normalizedModel !== agent.model) {
|
||||
nextAgent = { ...nextAgent, model: normalizedModel };
|
||||
mutated = true;
|
||||
}
|
||||
const normalized = normalizeAgentModelRefsAtPathForWrite({ agent }, ["agent"]) as {
|
||||
agent: unknown;
|
||||
};
|
||||
if (normalized.agent !== agent) {
|
||||
mutated = true;
|
||||
return normalized.agent;
|
||||
}
|
||||
if (isRecord(agent.models)) {
|
||||
const normalizedModels = normalizeAgentModelMapForConfig(agent.models);
|
||||
if (normalizedModels !== agent.models) {
|
||||
nextAgent = { ...nextAgent, models: normalizedModels };
|
||||
mutated = true;
|
||||
}
|
||||
}
|
||||
return nextAgent;
|
||||
return agent;
|
||||
});
|
||||
|
||||
return mutated ? setPathValue(config, ["agents", "list"], nextList) : config;
|
||||
}
|
||||
|
||||
function normalizeToolsModelRefsForWrite(config: unknown): unknown {
|
||||
return normalizeModelConfigPathForWrite(config, ["tools", "subagents", "model"]);
|
||||
}
|
||||
|
||||
function normalizeModelProviderCatalogRefsForWrite(config: unknown): unknown {
|
||||
const providers = getPathValue(config, ["models", "providers"]);
|
||||
if (!isRecord(providers)) {
|
||||
@@ -429,7 +455,11 @@ function normalizeModelProviderCatalogRefsForWrite(config: unknown): unknown {
|
||||
|
||||
function normalizeModelRefsForWrite(config: unknown): unknown {
|
||||
return normalizeModelProviderCatalogRefsForWrite(
|
||||
normalizeAgentListModelRefsForWrite(normalizeAgentDefaultModelRefsForWrite(config)),
|
||||
normalizeToolsModelRefsForWrite(
|
||||
normalizeAgentListModelRefsForWrite(
|
||||
normalizeAgentModelRefsAtPathForWrite(config, ["agents", "defaults"]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user