feat: add models scan and fallbacks

This commit is contained in:
Peter Steinberger
2026-01-04 17:50:55 +01:00
parent a2ba7ddf90
commit 734bb6b4fd
22 changed files with 2058 additions and 187 deletions

View File

@@ -88,6 +88,7 @@ const FIELD_LABELS: Record<string, string> = {
"gateway.reload.debounceMs": "Config Reload Debounce (ms)",
"agent.workspace": "Workspace",
"agent.model": "Default Model",
"agent.modelFallbacks": "Model Fallbacks",
"ui.seamColor": "Accent Color",
"browser.controlUrl": "Browser Control URL",
"session.agentToAgent.maxPingPongTurns": "Agent-to-Agent Ping-Pong Turns",
@@ -111,6 +112,8 @@ const FIELD_HELP: Record<string, string> = {
'Hot reload strategy for config changes ("hybrid" recommended).',
"gateway.reload.debounceMs":
"Debounce window (ms) before applying config changes.",
"agent.modelFallbacks":
"Ordered fallback models (provider/model). Used when the primary model fails.",
"session.agentToAgent.maxPingPongTurns":
"Max reply-back turns between requester and target (05).",
};

View File

@@ -50,6 +50,7 @@ export type SessionEntry = {
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
modelProvider?: string;
model?: string;
contextTokens?: number;
displayName?: string;
@@ -335,6 +336,7 @@ export async function updateLastRoute(params: {
inputTokens: existing?.inputTokens,
outputTokens: existing?.outputTokens,
totalTokens: existing?.totalTokens,
modelProvider: existing?.modelProvider,
model: existing?.model,
contextTokens: existing?.contextTokens,
displayName: existing?.displayName,

View File

@@ -666,6 +666,8 @@ export type ClawdbotConfig = {
allowedModels?: string[];
/** Optional model aliases for /model (alias -> provider/model). */
modelAliases?: Record<string, string>;
/** Ordered fallback models (provider/model). */
modelFallbacks?: string[];
/** Optional display-only context window override (used for % in status UIs). */
contextTokens?: number;
/** Default thinking level when no /think directive is present. */

View File

@@ -366,6 +366,7 @@ export const ClawdbotSchema = z.object({
workspace: z.string().optional(),
allowedModels: z.array(z.string()).optional(),
modelAliases: z.record(z.string(), z.string()).optional(),
modelFallbacks: z.array(z.string()).optional(),
contextTokens: z.number().int().positive().optional(),
thinkingDefault: z
.union([