/** * autoconfigure-models.ts — Tool for automatically configuring model assignments. * * Queries available authenticated models and intelligently assigns them to DevClaw roles. */ import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../types.js"; import { assignModels, formatAssignment, generateSetupInstructions, type ModelAssignment, } from "../setup/smart-model-selector.js"; import { fetchAuthenticatedModels } from "../setup/model-fetcher.js"; /** * Get available authenticated models from OpenClaw. */ async function getAuthenticatedModels( api: OpenClawPluginApi, ): Promise> { try { const models = await fetchAuthenticatedModels(); // Map to the format expected by assignModels() return models.map((m) => { // Extract provider from key (format: provider/model-name) const provider = m.key.split("/")[0] || "unknown"; return { model: m.key, provider, authenticated: true, }; }); } catch (err) { throw new Error(`Failed to get authenticated models: ${(err as Error).message}`); } } /** * Create the autoconfigure_models tool. */ export function createAutoConfigureModelsTool(api: OpenClawPluginApi) { return (ctx: ToolContext) => ({ name: "autoconfigure_models", label: "Auto-Configure Models", description: "Automatically discover authenticated models and intelligently assign them to DevClaw roles based on capability tiers", parameters: { type: "object", properties: { preferProvider: { type: "string", description: "Optional: Prefer models from this provider (e.g., 'anthropic', 'openai')", }, }, }, async execute(_id: string, params: Record) { try { // Get all authenticated models let authenticatedModels = await getAuthenticatedModels(api); // Filter by preferred provider if specified const preferProvider = params?.preferProvider as string | undefined; if (preferProvider) { const filtered = authenticatedModels.filter( (m) => m.provider.toLowerCase() === preferProvider.toLowerCase(), ); if (filtered.length === 0) { return jsonResult({ success: false, error: `No authenticated models found for provider: ${preferProvider}`, message: `❌ No authenticated models found for provider "${preferProvider}".\n\nAvailable providers: ${[...new Set(authenticatedModels.map((m) => m.provider))].join(", ")}`, }); } authenticatedModels = filtered; } // Intelligently assign models using current session context const assignment = await assignModels(authenticatedModels, ctx.sessionKey); if (!assignment) { // No models available const instructions = generateSetupInstructions(); return jsonResult({ success: false, modelCount: 0, message: instructions, }); } // Format the assignment const table = formatAssignment(assignment); const modelCount = authenticatedModels.length; let message = `✅ Auto-configured models based on ${modelCount} authenticated model${modelCount === 1 ? "" : "s"}:\n\n`; message += table; message += "\n\n"; if (modelCount === 1) { message += "ℹ️ Only one authenticated model found — assigned to all roles."; } else { message += "ℹ️ Models assigned by capability tier (Tier 1 → senior, Tier 2 → medior/reviewer, Tier 3 → junior/tester)."; } if (preferProvider) { message += `\n📌 Filtered to provider: ${preferProvider}`; } message += "\n\n**Next step:** Pass this configuration to `setup` tool:\n"; message += "```javascript\n"; message += "setup({ models: })\n"; message += "```"; return jsonResult({ success: true, modelCount, assignment, models: assignment, provider: preferProvider || "auto", message, }); } catch (err) { const errorMsg = (err as Error).message; api.logger.error(`Auto-configure models error: ${errorMsg}`); return jsonResult({ success: false, error: errorMsg, message: `❌ Failed to auto-configure models: ${errorMsg}`, }); } }, }); }