feat(models): implement custom model support for ollama/openrouter

Adds the ability for users to specify custom model IDs for Ollama and OpenRouter providers, bypassing the internal supported model list.

    - Introduces --ollama and --openrouter flags for the 'task-master models --set-<role>' command.
    - Updates the interactive 'task-master models --setup' to include options for entering custom Ollama/OpenRouter IDs.
    - Implements live validation against the OpenRouter API when a custom OpenRouter ID is provided.
    - Refines the model setting logic to prioritize explicit provider flags/choices.
    - Adds warnings when custom models are set.
    - Updates the changeset file.
This commit is contained in:
Eyal Toledano
2025-04-27 17:25:54 -04:00
parent ed79d4f473
commit c8722b0a7a
12 changed files with 10157 additions and 201 deletions

View File

@@ -37,6 +37,20 @@ export async function modelsDirect(args, log, context = {}) {
log.info(`Executing models_direct with args: ${JSON.stringify(args)}`);
log.info(`Using project root: ${projectRoot}`);
// Validate flags: cannot use both openrouter and ollama simultaneously
if (args.openrouter && args.ollama) {
log.error(
'Error: Cannot use both openrouter and ollama flags simultaneously.'
);
return {
success: false,
error: {
code: 'INVALID_ARGS',
message: 'Cannot use both openrouter and ollama flags simultaneously.'
}
};
}
try {
enableSilentMode();
@@ -55,7 +69,12 @@ export async function modelsDirect(args, log, context = {}) {
return await setModel('main', args.setMain, {
session,
mcpLog: logWrapper,
projectRoot // Pass projectRoot to function
projectRoot, // Pass projectRoot to function
providerHint: args.openrouter
? 'openrouter'
: args.ollama
? 'ollama'
: undefined // Pass hint
});
}
@@ -63,7 +82,12 @@ export async function modelsDirect(args, log, context = {}) {
return await setModel('research', args.setResearch, {
session,
mcpLog: logWrapper,
projectRoot // Pass projectRoot to function
projectRoot, // Pass projectRoot to function
providerHint: args.openrouter
? 'openrouter'
: args.ollama
? 'ollama'
: undefined // Pass hint
});
}
@@ -71,7 +95,12 @@ export async function modelsDirect(args, log, context = {}) {
return await setModel('fallback', args.setFallback, {
session,
mcpLog: logWrapper,
projectRoot // Pass projectRoot to function
projectRoot, // Pass projectRoot to function
providerHint: args.openrouter
? 'openrouter'
: args.ollama
? 'ollama'
: undefined // Pass hint
});
}

View File

@@ -46,7 +46,15 @@ export function registerModelsTool(server) {
projectRoot: z
.string()
.optional()
.describe('The directory of the project. Must be an absolute path.')
.describe('The directory of the project. Must be an absolute path.'),
openrouter: z
.boolean()
.optional()
.describe('Indicates the set model ID is a custom OpenRouter model.'),
ollama: z
.boolean()
.optional()
.describe('Indicates the set model ID is a custom Ollama model.')
}),
execute: async (args, { log, session }) => {
try {