Files
openclaw/src/agents/subagent-spawn-plan.ts
2026-04-28 04:25:31 +01:00

86 lines
2.7 KiB
TypeScript

import { formatThinkingLevels } from "../auto-reply/thinking.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { resolveSubagentSpawnModelSelection } from "./model-selection.js";
import { resolveSubagentThinkingOverride } from "./subagent-spawn-thinking.js";
export function splitModelRef(ref?: string) {
if (!ref) {
return { provider: undefined, model: undefined };
}
const trimmed = ref.trim();
if (!trimmed) {
return { provider: undefined, model: undefined };
}
const slash = trimmed.indexOf("/");
if (slash > 0 && slash < trimmed.length - 1) {
const provider = trimmed.slice(0, slash);
const model = trimmed.slice(slash + 1);
return { provider, model };
}
const provider = undefined;
const model = trimmed;
if (model) {
return { provider, model };
}
return { provider: undefined, model: trimmed };
}
export function resolveConfiguredSubagentRunTimeoutSeconds(params: {
cfg: OpenClawConfig;
runTimeoutSeconds?: number;
}) {
const cfgSubagentTimeout =
typeof params.cfg?.agents?.defaults?.subagents?.runTimeoutSeconds === "number" &&
Number.isFinite(params.cfg.agents.defaults.subagents.runTimeoutSeconds)
? Math.max(0, Math.floor(params.cfg.agents.defaults.subagents.runTimeoutSeconds))
: 0;
return typeof params.runTimeoutSeconds === "number" && Number.isFinite(params.runTimeoutSeconds)
? Math.max(0, Math.floor(params.runTimeoutSeconds))
: cfgSubagentTimeout;
}
export function resolveSubagentModelAndThinkingPlan(params: {
cfg: OpenClawConfig;
targetAgentId: string;
targetAgentConfig?: unknown;
modelOverride?: string;
thinkingOverrideRaw?: string;
}) {
const resolvedModel = resolveSubagentSpawnModelSelection({
cfg: params.cfg,
agentId: params.targetAgentId,
modelOverride: params.modelOverride,
});
const thinkingPlan = resolveSubagentThinkingOverride({
cfg: params.cfg,
targetAgentConfig: params.targetAgentConfig,
thinkingOverrideRaw: params.thinkingOverrideRaw,
});
if (thinkingPlan.status === "error") {
const { provider, model } = splitModelRef(resolvedModel);
const hint = formatThinkingLevels(provider, model);
return {
status: "error" as const,
resolvedModel,
error: `Invalid thinking level "${thinkingPlan.thinkingCandidateRaw}". Use one of: ${hint}.`,
};
}
return {
status: "ok" as const,
resolvedModel,
modelApplied: Boolean(resolvedModel),
thinkingOverride: thinkingPlan.thinkingOverride,
initialSessionPatch: {
...(resolvedModel
? {
model: resolvedModel,
modelOverrideSource: params.modelOverride?.trim() ? "user" : "auto",
}
: {}),
...thinkingPlan.initialSessionPatch,
},
};
}