@brutalist/mcp 0.1.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,71 +0,0 @@
1
- import { logger } from './logger.js';
2
- import { MODEL_CACHE_DURATION_MS, OPENROUTER_MODELS_ENDPOINT } from './constants.js';
3
- export class ModelFetcher {
4
- static instance;
5
- cachedModels = null;
6
- cacheTimestamp = 0;
7
- // Minimal fallback if API fails
8
- FALLBACK_MODELS = [
9
- "anthropic/claude-3.5-sonnet",
10
- "openai/gpt-4o",
11
- "google/gemini-2.5-pro",
12
- "meta-llama/llama-3.1-8b-instruct",
13
- "mistralai/mixtral-8x7b-instruct"
14
- ];
15
- constructor() { }
16
- static getInstance() {
17
- if (!ModelFetcher.instance) {
18
- ModelFetcher.instance = new ModelFetcher();
19
- }
20
- return ModelFetcher.instance;
21
- }
22
- async getAvailableModels() {
23
- // Check cache
24
- if (this.cachedModels && (Date.now() - this.cacheTimestamp < MODEL_CACHE_DURATION_MS)) {
25
- logger.debug("Using cached models", { count: this.cachedModels.length });
26
- return this.cachedModels;
27
- }
28
- try {
29
- logger.info("Fetching available models from OpenRouter");
30
- const response = await fetch(OPENROUTER_MODELS_ENDPOINT);
31
- if (!response.ok) {
32
- throw new Error(`HTTP error! status: ${response.status}`);
33
- }
34
- const data = await response.json();
35
- if (!data.data || !Array.isArray(data.data)) {
36
- throw new Error("Invalid response format from OpenRouter API");
37
- }
38
- // Extract model IDs
39
- const models = data.data.map(model => model.id);
40
- if (models.length === 0) {
41
- throw new Error("No models returned from API");
42
- }
43
- // Update cache
44
- this.cachedModels = models;
45
- this.cacheTimestamp = Date.now();
46
- logger.info(`Successfully fetched ${models.length} available models from OpenRouter`);
47
- return models;
48
- }
49
- catch (error) {
50
- logger.error("Failed to fetch models from OpenRouter, using fallback", error);
51
- return this.FALLBACK_MODELS;
52
- }
53
- }
54
- async searchModels(query) {
55
- const allModels = await this.getAvailableModels();
56
- const lowerQuery = query.toLowerCase();
57
- return allModels.filter(model => model.toLowerCase().includes(lowerQuery));
58
- }
59
- async getModelsByProvider(provider) {
60
- const allModels = await this.getAvailableModels();
61
- const lowerProvider = provider.toLowerCase();
62
- return allModels.filter(model => model.toLowerCase().startsWith(lowerProvider + "/"));
63
- }
64
- clearCache() {
65
- this.cachedModels = null;
66
- this.cacheTimestamp = 0;
67
- logger.debug("Model cache cleared");
68
- }
69
- }
70
- export const modelFetcher = ModelFetcher.getInstance();
71
- //# sourceMappingURL=model-fetcher.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"model-fetcher.js","sourceRoot":"","sources":["../src/model-fetcher.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- import { ModelResponse } from './types/brutalist.js';
2
- export declare class OpenRouterClient {
3
- private client;
4
- private availableModels;
5
- constructor(apiKey: string);
6
- initialize(): Promise<void>;
7
- private getRandomModels;
8
- private getSpecificModels;
9
- executePrompt(prompt: string, model: string, contextData?: string): Promise<ModelResponse>;
10
- executeMultiModel(prompt: string, maxModels?: number, contextData?: string, specificModels?: string[]): Promise<ModelResponse[]>;
11
- getAvailableModels(): string[];
12
- synthesizeResponses(responses: ModelResponse[], originalPrompt: string): string;
13
- }
14
- //# sourceMappingURL=openrouter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAWrD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAgB;gBAE3B,MAAM,EAAE,MAAM;IAWpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,iBAAiB;IAoBnB,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC;IA+BnB,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAU,EACrB,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,aAAa,EAAE,CAAC;IA0B3B,kBAAkB,IAAI,MAAM,EAAE;IAK9B,mBAAmB,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM;CAqChF"}
@@ -1,123 +0,0 @@
1
- import OpenAI from 'openai';
2
- import { modelFetcher } from './model-fetcher.js';
3
- import { logger } from './logger.js';
4
- import { OPENROUTER_BASE_URL, GITHUB_REPO_URL, DEFAULT_TEMPERATURE, DEFAULT_MAX_TOKENS, SYNTHESIS_MAX_THEMES } from './constants.js';
5
- export class OpenRouterClient {
6
- client;
7
- availableModels = [];
8
- constructor(apiKey) {
9
- this.client = new OpenAI({
10
- baseURL: OPENROUTER_BASE_URL,
11
- apiKey: apiKey,
12
- defaultHeaders: {
13
- "HTTP-Referer": GITHUB_REPO_URL,
14
- "X-Title": "Brutalist MCP"
15
- }
16
- });
17
- }
18
- async initialize() {
19
- this.availableModels = await modelFetcher.getAvailableModels();
20
- logger.debug(`OpenRouter client initialized with ${this.availableModels.length} available models`);
21
- }
22
- getRandomModels(count) {
23
- if (this.availableModels.length === 0) {
24
- logger.warn("No models available, using empty array");
25
- return [];
26
- }
27
- const shuffled = [...this.availableModels].sort(() => 0.5 - Math.random());
28
- return shuffled.slice(0, Math.min(count, this.availableModels.length));
29
- }
30
- getSpecificModels(requestedModels) {
31
- // Validate requested models exist
32
- const validModels = requestedModels.filter(model => this.availableModels.includes(model));
33
- if (validModels.length === 0) {
34
- logger.warn(`None of the requested models are available: ${requestedModels.join(', ')}`);
35
- // Fall back to random selection
36
- return this.getRandomModels(Math.min(3, requestedModels.length));
37
- }
38
- if (validModels.length < requestedModels.length) {
39
- const invalid = requestedModels.filter(m => !this.availableModels.includes(m));
40
- logger.warn(`Some requested models not available: ${invalid.join(', ')}`);
41
- }
42
- return validModels;
43
- }
44
- async executePrompt(prompt, model, contextData) {
45
- const startTime = Date.now();
46
- // No system prompt - let the LLM using MCP generate its own based on tool descriptions
47
- const userPrompt = prompt + (contextData ? `\n\nContext: ${contextData}` : '');
48
- try {
49
- const completion = await this.client.chat.completions.create({
50
- model: model,
51
- messages: [
52
- { role: "user", content: userPrompt }
53
- ],
54
- temperature: DEFAULT_TEMPERATURE,
55
- max_tokens: DEFAULT_MAX_TOKENS
56
- });
57
- const responseTime = Date.now() - startTime;
58
- const content = completion.choices[0]?.message?.content || '';
59
- return {
60
- model: model,
61
- persona: `Brutal Critic (${model})`,
62
- content: content,
63
- tokensUsed: completion.usage?.total_tokens,
64
- responseTime: responseTime
65
- };
66
- }
67
- catch (error) {
68
- throw new Error(`OpenRouter API error for model ${model}: ${error instanceof Error ? error.message : String(error)}`);
69
- }
70
- }
71
- async executeMultiModel(prompt, maxModels = 3, contextData, specificModels) {
72
- const selectedModels = specificModels
73
- ? this.getSpecificModels(specificModels)
74
- : this.getRandomModels(maxModels);
75
- if (selectedModels.length === 0) {
76
- throw new Error("No valid models available for execution");
77
- }
78
- const promises = selectedModels.map(model => this.executePrompt(prompt, model, contextData));
79
- try {
80
- return await Promise.all(promises);
81
- }
82
- catch (error) {
83
- // If any model fails, still return partial results
84
- const results = await Promise.allSettled(promises);
85
- return results
86
- .filter((result) => result.status === 'fulfilled')
87
- .map(result => result.value);
88
- }
89
- }
90
- getAvailableModels() {
91
- return this.availableModels;
92
- }
93
- synthesizeResponses(responses, originalPrompt) {
94
- if (responses.length === 0) {
95
- return "No responses received from models.";
96
- }
97
- if (responses.length === 1) {
98
- return `**${responses[0].persona}** (${responses[0].model}):\n${responses[0].content}`;
99
- }
100
- let synthesis = `# Brutalist Analysis: ${responses.length} AI Critics\n\n`;
101
- // Group by persona for clarity
102
- responses.forEach((response, index) => {
103
- synthesis += `## ${response.persona} (${response.model})\n`;
104
- synthesis += `${response.content}\n\n`;
105
- if (response.responseTime) {
106
- synthesis += `*Response time: ${response.responseTime}ms*\n\n`;
107
- }
108
- });
109
- // Add summary if multiple perspectives
110
- if (responses.length > 1) {
111
- synthesis += `---\n\n**Key Themes Across Critics:**\n`;
112
- // Extract common themes (simple keyword analysis)
113
- const allContent = responses.map(r => r.content.toLowerCase()).join(' ');
114
- const criticalTerms = ['fail', 'problem', 'issue', 'vulnerable', 'slow', 'expensive', 'complex', 'difficult'];
115
- const foundTerms = criticalTerms.filter(term => allContent.includes(term));
116
- if (foundTerms.length > 0) {
117
- synthesis += `Multiple critics highlighted: ${foundTerms.slice(0, SYNTHESIS_MAX_THEMES).join(', ')}\n`;
118
- }
119
- }
120
- return synthesis;
121
- }
122
- }
123
- //# sourceMappingURL=openrouter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"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"}