Files
devclaw-gitea/lib/tools/autoconfigure-models.ts

137 lines
4.6 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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<Array<{ model: string; provider: string; authenticated: boolean }>> {
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<string, unknown>) {
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: <this-configuration> })\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}`,
});
}
},
});
}