2025-03-17 20:17:28 +00:00
|
|
|
import options from "../../services/options.js";
|
|
|
|
|
import log from "../../services/log.js";
|
|
|
|
|
import type { Request, Response } from "express";
|
2025-03-26 17:56:37 +00:00
|
|
|
import { PROVIDER_CONSTANTS } from '../../services/llm/constants/provider_constants.js';
|
2025-04-09 21:08:30 +00:00
|
|
|
import Anthropic from '@anthropic-ai/sdk';
|
2025-03-17 20:17:28 +00:00
|
|
|
|
2025-03-26 04:13:04 +00:00
|
|
|
// Interface for Anthropic model entries
|
|
|
|
|
interface AnthropicModel {
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
type: string;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-17 20:17:28 +00:00
|
|
|
/**
|
2025-03-26 19:19:19 +00:00
|
|
|
* @swagger
|
|
|
|
|
* /api/anthropic/models:
|
|
|
|
|
* post:
|
|
|
|
|
* summary: List available models from Anthropic
|
|
|
|
|
* operationId: anthropic-list-models
|
|
|
|
|
* requestBody:
|
|
|
|
|
* required: false
|
|
|
|
|
* content:
|
|
|
|
|
* application/json:
|
|
|
|
|
* schema:
|
|
|
|
|
* type: object
|
|
|
|
|
* properties:
|
|
|
|
|
* baseUrl:
|
|
|
|
|
* type: string
|
|
|
|
|
* description: Optional custom Anthropic API base URL
|
|
|
|
|
* responses:
|
|
|
|
|
* '200':
|
|
|
|
|
* description: List of available Anthropic models
|
|
|
|
|
* content:
|
|
|
|
|
* application/json:
|
|
|
|
|
* schema:
|
|
|
|
|
* type: object
|
|
|
|
|
* properties:
|
|
|
|
|
* success:
|
|
|
|
|
* type: boolean
|
|
|
|
|
* chatModels:
|
|
|
|
|
* type: array
|
|
|
|
|
* items:
|
|
|
|
|
* type: object
|
|
|
|
|
* properties:
|
|
|
|
|
* id:
|
|
|
|
|
* type: string
|
|
|
|
|
* name:
|
|
|
|
|
* type: string
|
|
|
|
|
* type:
|
|
|
|
|
* type: string
|
|
|
|
|
* embeddingModels:
|
|
|
|
|
* type: array
|
|
|
|
|
* items:
|
|
|
|
|
* type: object
|
|
|
|
|
* properties:
|
|
|
|
|
* id:
|
|
|
|
|
* type: string
|
|
|
|
|
* name:
|
|
|
|
|
* type: string
|
|
|
|
|
* type:
|
|
|
|
|
* type: string
|
|
|
|
|
* '500':
|
|
|
|
|
* description: Error listing models
|
|
|
|
|
* security:
|
|
|
|
|
* - session: []
|
|
|
|
|
* tags: ["llm"]
|
2025-03-17 20:17:28 +00:00
|
|
|
*/
|
|
|
|
|
async function listModels(req: Request, res: Response) {
|
|
|
|
|
try {
|
|
|
|
|
const { baseUrl } = req.body;
|
|
|
|
|
|
2025-04-09 21:08:30 +00:00
|
|
|
// Use provided base URL or default from options
|
|
|
|
|
const anthropicBaseUrl = baseUrl ||
|
|
|
|
|
await options.getOption('anthropicBaseUrl') ||
|
|
|
|
|
PROVIDER_CONSTANTS.ANTHROPIC.BASE_URL;
|
2025-03-26 04:13:04 +00:00
|
|
|
|
2025-03-17 20:17:28 +00:00
|
|
|
const apiKey = await options.getOption('anthropicApiKey');
|
|
|
|
|
|
|
|
|
|
if (!apiKey) {
|
|
|
|
|
throw new Error('Anthropic API key is not configured');
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-09 21:08:30 +00:00
|
|
|
log.info(`Listing models from Anthropic API using the SDK`);
|
2025-03-26 04:13:04 +00:00
|
|
|
|
2025-04-09 21:08:30 +00:00
|
|
|
// Initialize the Anthropic client with the SDK
|
|
|
|
|
const client = new Anthropic({
|
|
|
|
|
apiKey,
|
|
|
|
|
baseURL: anthropicBaseUrl,
|
|
|
|
|
defaultHeaders: {
|
2025-03-26 17:56:37 +00:00
|
|
|
'anthropic-version': PROVIDER_CONSTANTS.ANTHROPIC.API_VERSION,
|
|
|
|
|
'anthropic-beta': PROVIDER_CONSTANTS.ANTHROPIC.BETA_VERSION
|
2025-04-09 21:08:30 +00:00
|
|
|
}
|
2025-03-17 20:17:28 +00:00
|
|
|
});
|
|
|
|
|
|
2025-04-09 21:08:30 +00:00
|
|
|
// Use the SDK's built-in models listing
|
|
|
|
|
const response = await client.models.list();
|
|
|
|
|
|
2025-03-17 20:17:28 +00:00
|
|
|
// Process the models
|
2025-04-09 21:08:30 +00:00
|
|
|
const allModels = response.data || [];
|
2025-03-17 20:17:28 +00:00
|
|
|
|
2025-03-26 04:13:04 +00:00
|
|
|
// Log available models
|
2025-04-09 21:08:30 +00:00
|
|
|
log.info(`Found ${allModels.length} models from Anthropic: ${allModels.map(m => m.id).join(', ')}`);
|
2025-03-26 04:13:04 +00:00
|
|
|
|
2025-03-17 20:17:28 +00:00
|
|
|
// Separate models into chat models and embedding models
|
|
|
|
|
const chatModels = allModels
|
2025-04-09 21:08:30 +00:00
|
|
|
.filter(model =>
|
2025-03-17 20:17:28 +00:00
|
|
|
// Claude models are for chat
|
|
|
|
|
model.id.includes('claude')
|
|
|
|
|
)
|
2025-04-09 21:08:30 +00:00
|
|
|
.map(model => {
|
2025-03-26 04:13:04 +00:00
|
|
|
// Get a simplified name for display purposes
|
|
|
|
|
let displayName = model.id;
|
|
|
|
|
// Try to simplify the model name by removing version suffixes
|
|
|
|
|
if (model.id.match(/claude-\d+-\w+-\d+/)) {
|
|
|
|
|
displayName = model.id.replace(/-\d+$/, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: model.id, // Keep full ID for API calls
|
|
|
|
|
name: displayName, // Use simplified name for display
|
|
|
|
|
type: 'chat'
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Also include known models that might not be returned by the API
|
2025-03-26 17:56:37 +00:00
|
|
|
for (const model of PROVIDER_CONSTANTS.ANTHROPIC.AVAILABLE_MODELS) {
|
2025-03-26 04:13:04 +00:00
|
|
|
// Check if this model is already in our list
|
2025-03-26 17:56:37 +00:00
|
|
|
if (!chatModels.some((m: AnthropicModel) => m.id === model.id)) {
|
2025-03-26 04:13:04 +00:00
|
|
|
chatModels.push({
|
2025-03-26 17:56:37 +00:00
|
|
|
id: model.id,
|
|
|
|
|
name: model.name,
|
2025-03-26 04:13:04 +00:00
|
|
|
type: 'chat'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-17 20:17:28 +00:00
|
|
|
|
|
|
|
|
// Note: Anthropic might not have embedding models yet, but we'll include this for future compatibility
|
|
|
|
|
const embeddingModels = allModels
|
2025-04-09 21:08:30 +00:00
|
|
|
.filter(model =>
|
2025-03-17 20:17:28 +00:00
|
|
|
// If Anthropic releases embedding models, they'd likely include 'embed' in the name
|
|
|
|
|
model.id.includes('embed')
|
|
|
|
|
)
|
2025-04-09 21:08:30 +00:00
|
|
|
.map(model => ({
|
2025-03-17 20:17:28 +00:00
|
|
|
id: model.id,
|
|
|
|
|
name: model.id,
|
|
|
|
|
type: 'embedding'
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Return the models list
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
chatModels,
|
|
|
|
|
embeddingModels
|
|
|
|
|
};
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
log.error(`Error listing Anthropic models: ${error.message || 'Unknown error'}`);
|
|
|
|
|
|
|
|
|
|
// Properly throw the error to be handled by the global error handler
|
|
|
|
|
throw new Error(`Failed to list Anthropic models: ${error.message || 'Unknown error'}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
listModels
|
2025-04-09 21:08:30 +00:00
|
|
|
};
|