feat(config): support object-style fallback_models with per-model settings
Add support for object-style entries in fallback_models arrays, enabling per-model configuration of variant, reasoningEffort, temperature, top_p, maxTokens, and thinking settings. - Zod schema for FallbackModelObject with full validation - normalizeFallbackModels() and flattenToFallbackModelStrings() utilities - Provider-agnostic model resolution pipeline with fallback chain - Session prompt params state management - Fallback chain construction with prefix-match lookup - Integration across delegate-task, background-agent, and plugin layers
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import type { DelegateTaskArgs } from "./types"
|
||||
import type { ExecutorContext } from "./executor-types"
|
||||
import type { DelegatedModelConfig } from "./types"
|
||||
import { isPlanFamily } from "./constants"
|
||||
import { SISYPHUS_JUNIOR_AGENT } from "./sisyphus-junior-agent"
|
||||
import { normalizeModelFormat } from "../../shared/model-format-normalizer"
|
||||
import { AGENT_MODEL_REQUIREMENTS } from "../../shared/model-requirements"
|
||||
import { normalizeFallbackModels } from "../../shared/model-resolver"
|
||||
import { buildFallbackChainFromModels } from "../../shared/fallback-chain-from-models"
|
||||
import { normalizeFallbackModels, flattenToFallbackModelStrings } from "../../shared/model-resolver"
|
||||
import { buildFallbackChainFromModels, findMostSpecificFallbackEntry } from "../../shared/fallback-chain-from-models"
|
||||
import { getAgentDisplayName, getAgentConfigKey } from "../../shared/agent-display-names"
|
||||
import { normalizeSDKResponse } from "../../shared"
|
||||
import { log } from "../../shared/logger"
|
||||
@@ -17,9 +18,8 @@ export async function resolveSubagentExecution(
|
||||
args: DelegateTaskArgs,
|
||||
executorCtx: ExecutorContext,
|
||||
parentAgent: string | undefined,
|
||||
categoryExamples: string,
|
||||
inheritedModel?: string
|
||||
): Promise<{ agentToUse: string; categoryModel: { providerID: string; modelID: string; variant?: string } | undefined; fallbackChain?: FallbackEntry[]; error?: string }> {
|
||||
categoryExamples: string
|
||||
): Promise<{ agentToUse: string; categoryModel: DelegatedModelConfig | undefined; fallbackChain?: FallbackEntry[]; error?: string }> {
|
||||
const { client, agentOverrides, userCategories } = executorCtx
|
||||
|
||||
if (!args.subagent_type?.trim()) {
|
||||
@@ -49,7 +49,7 @@ Create the work plan directly - that's your job as the planning agent.`,
|
||||
}
|
||||
|
||||
let agentToUse = agentName
|
||||
let categoryModel: { providerID: string; modelID: string; variant?: string } | undefined
|
||||
let categoryModel: DelegatedModelConfig | undefined
|
||||
let fallbackChain: FallbackEntry[] | undefined = undefined
|
||||
|
||||
try {
|
||||
@@ -117,8 +117,8 @@ Create the work plan directly - that's your job as the planning agent.`,
|
||||
: undefined
|
||||
|
||||
const resolution = resolveModelForDelegateTask({
|
||||
userModel: agentOverride?.model ?? inheritedModel,
|
||||
userFallbackModels: normalizedAgentFallbackModels,
|
||||
userModel: agentOverride?.model,
|
||||
userFallbackModels: flattenToFallbackModelStrings(normalizedAgentFallbackModels),
|
||||
categoryDefaultModel: matchedAgentModelStr,
|
||||
fallbackChain: agentRequirement?.fallbackChain,
|
||||
availableModels,
|
||||
@@ -141,6 +141,25 @@ Create the work plan directly - that's your job as the planning agent.`,
|
||||
defaultProviderID,
|
||||
)
|
||||
fallbackChain = configuredFallbackChain ?? agentRequirement?.fallbackChain
|
||||
|
||||
// Apply per-model settings: prefer resolver's exact entry, fall back to prefix match on user config
|
||||
const resolvedFallbackEntry = (resolution && !('skipped' in resolution)) ? resolution.fallbackEntry : undefined
|
||||
const effectiveEntry = resolvedFallbackEntry
|
||||
?? (categoryModel && fallbackChain
|
||||
? findMostSpecificFallbackEntry(categoryModel.providerID, categoryModel.modelID, fallbackChain)
|
||||
: undefined)
|
||||
|
||||
if (categoryModel && effectiveEntry) {
|
||||
categoryModel = {
|
||||
...categoryModel,
|
||||
variant: agentOverride?.variant ?? effectiveEntry.variant ?? categoryModel.variant,
|
||||
reasoningEffort: effectiveEntry.reasoningEffort,
|
||||
temperature: effectiveEntry.temperature,
|
||||
top_p: effectiveEntry.top_p,
|
||||
maxTokens: effectiveEntry.maxTokens,
|
||||
thinking: effectiveEntry.thinking,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!categoryModel && matchedAgent.model) {
|
||||
|
||||
Reference in New Issue
Block a user