UNPKG

n8n

Version:

n8n Workflow Automation Tool

136 lines 6.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildResolveLlmTool = buildResolveLlmTool; const agents_1 = require("@n8n/agents"); const zod_1 = require("zod"); const builder_tool_names_1 = require("../builder-tool-names"); const llm_provider_defaults_1 = require("./llm-provider-defaults"); function findProviderDefault(provider) { const requestedProvider = provider.trim(); return Object.entries(llm_provider_defaults_1.LLM_PROVIDER_DEFAULTS).find(([, defaults]) => defaults.provider === requestedProvider); } function toLlmResolution(credential, defaults, model) { return { ok: true, provider: defaults.provider, model: model?.trim() || defaults.defaultModel, credentialId: credential.id, credentialName: credential.name, }; } async function resolveModelAgainstLookup(credential, defaults, requestedModel, modelLookup) { const trimmedModel = requestedModel.trim(); if (!defaults.modelLookup || !trimmedModel) { return toLlmResolution(credential, defaults, requestedModel); } let availableModels; try { availableModels = await modelLookup.list(credential.id, credential.type, defaults.modelLookup); } catch (error) { return { ok: false, reason: 'model_lookup_failed', provider: defaults.provider, requestedModel: trimmedModel, error: error instanceof Error ? error.message : String(error), }; } const lowerHint = trimmedModel.toLowerCase(); const exactMatch = availableModels.find((m) => m.value.toLowerCase() === lowerHint); if (exactMatch) { return toLlmResolution(credential, defaults, exactMatch.value); } const candidates = availableModels.filter((m) => m.value.toLowerCase().includes(lowerHint) || m.name.toLowerCase().includes(lowerHint)); if (candidates.length === 1) { return toLlmResolution(credential, defaults, candidates[0].value); } return { ok: false, reason: 'unknown_model', provider: defaults.provider, requestedModel: trimmedModel, availableModels: candidates.length > 0 ? candidates : availableModels, }; } function buildResolveLlmTool(deps) { return new agents_1.Tool(builder_tool_names_1.BUILDER_TOOLS.RESOLVE_LLM) .description('Resolve the agent main LLM without showing a picker. Use this when the user ' + 'explicitly requests a provider/model, or when a fresh agent needs a default LLM. ' + 'If provider is given, resolves only that provider; if model is omitted, uses the ' + 'provider default model. For "Anthropic via OpenRouter", pass provider="openrouter" ' + 'and omit model unless the user named a concrete OpenRouter model id. Returns ok=false ' + 'when credentials are missing, unsupported, or ambiguous; use ask_llm only when the ' + 'user must choose.') .input(zod_1.z.object({ provider: zod_1.z .string() .optional() .describe('Requested provider, e.g. "anthropic", "openai", or "openrouter".'), model: zod_1.z .string() .optional() .describe('Requested model without the selected provider prefix. For OpenRouter use the routed id, e.g. "anthropic/claude-sonnet-4.6".'), })) .handler(async ({ provider, model }) => { const all = await deps.credentialProvider.list(); const llmCredentials = all.filter((credential) => llm_provider_defaults_1.LLM_PROVIDER_DEFAULTS[credential.type]); if (provider) { const providerEntry = findProviderDefault(provider); if (!providerEntry) { return { ok: false, reason: 'unsupported_provider', provider, supportedProviders: Object.values(llm_provider_defaults_1.LLM_PROVIDER_DEFAULTS).map((defaults) => defaults.provider), }; } const [credentialType, defaults] = providerEntry; const matchingCredentials = llmCredentials.filter((credential) => credential.type === credentialType); if (matchingCredentials.length === 1) { const credential = matchingCredentials[0]; if (model?.trim()) { return await resolveModelAgainstLookup(credential, defaults, model, deps.modelLookup); } return toLlmResolution(credential, defaults); } return { ok: false, reason: matchingCredentials.length === 0 ? 'missing_credential' : 'ambiguous_credential', provider: defaults.provider, credentialType, credentials: matchingCredentials.map((credential) => ({ id: credential.id, name: credential.name, })), }; } if (llmCredentials.length === 1) { const credential = llmCredentials[0]; const defaults = llm_provider_defaults_1.LLM_PROVIDER_DEFAULTS[credential.type]; if (model?.trim()) { return await resolveModelAgainstLookup(credential, defaults, model, deps.modelLookup); } return toLlmResolution(credential, defaults); } return { ok: false, reason: llmCredentials.length === 0 ? 'missing_credential' : 'ambiguous_provider_or_credential', credentials: llmCredentials.map((credential) => { const defaults = llm_provider_defaults_1.LLM_PROVIDER_DEFAULTS[credential.type]; return { id: credential.id, name: credential.name, type: credential.type, provider: defaults.provider, }; }), }; }) .build(); } //# sourceMappingURL=resolve-llm.tool.js.map