tachibot-mcp 2.0.5 → 2.0.7

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.
Files changed (53) hide show
  1. package/.env.example +5 -2
  2. package/dist/src/config/model-constants.js +85 -72
  3. package/dist/src/config/model-preferences.js +5 -4
  4. package/dist/src/config.js +2 -1
  5. package/dist/src/mcp-client.js +3 -3
  6. package/dist/src/modes/scout.js +2 -1
  7. package/dist/src/optimization/model-router.js +19 -16
  8. package/dist/src/orchestrator-instructions.js +1 -1
  9. package/dist/src/orchestrator-lite.js +1 -1
  10. package/dist/src/orchestrator.js +1 -1
  11. package/dist/src/profiles/balanced.js +1 -2
  12. package/dist/src/profiles/code_focus.js +1 -2
  13. package/dist/src/profiles/full.js +1 -2
  14. package/dist/src/profiles/minimal.js +1 -2
  15. package/dist/src/profiles/research_power.js +1 -2
  16. package/dist/src/server.js +13 -12
  17. package/dist/src/tools/gemini-tools.js +15 -16
  18. package/dist/src/tools/grok-enhanced.js +21 -17
  19. package/dist/src/tools/grok-tools.js +26 -20
  20. package/dist/src/tools/openai-tools.js +28 -61
  21. package/dist/src/tools/tool-router.js +53 -52
  22. package/dist/src/tools/unified-ai-provider.js +1 -1
  23. package/dist/src/tools/workflow-runner.js +16 -0
  24. package/dist/src/tools/workflow-validator-tool.js +1 -1
  25. package/dist/src/utils/api-keys.js +20 -0
  26. package/dist/src/validators/interpolation-validator.js +4 -0
  27. package/dist/src/validators/tool-registry-validator.js +1 -1
  28. package/dist/src/validators/tool-types.js +0 -1
  29. package/dist/src/workflows/custom-workflows.js +4 -3
  30. package/dist/src/workflows/engine/VariableInterpolator.js +30 -3
  31. package/dist/src/workflows/engine/WorkflowExecutionEngine.js +2 -2
  32. package/dist/src/workflows/engine/WorkflowOutputFormatter.js +27 -4
  33. package/dist/src/workflows/fallback-strategies.js +2 -2
  34. package/dist/src/workflows/model-router.js +30 -5
  35. package/dist/src/workflows/tool-mapper.js +41 -14
  36. package/docs/API_KEYS.md +10 -6
  37. package/docs/TOOLS_REFERENCE.md +7 -43
  38. package/package.json +1 -1
  39. package/profiles/balanced.json +1 -2
  40. package/profiles/code_focus.json +1 -2
  41. package/profiles/debug_intensive.json +0 -1
  42. package/profiles/full.json +2 -3
  43. package/profiles/minimal.json +1 -2
  44. package/profiles/research_power.json +1 -2
  45. package/profiles/workflow_builder.json +1 -2
  46. package/smithery.yaml +2 -2
  47. package/tools.config.json +15 -3
  48. package/workflows/code-architecture-review.yaml +5 -3
  49. package/workflows/creative-brainstorm-yaml.yaml +1 -1
  50. package/workflows/pingpong.yaml +5 -3
  51. package/workflows/system/README.md +1 -1
  52. package/workflows/system/verifier.yaml +8 -5
  53. package/workflows/ultra-creative-brainstorm.yaml +3 -3
@@ -5,23 +5,16 @@
5
5
  */
6
6
  import { z } from "zod";
7
7
  import { validateToolInput } from "../utils/input-validator.js";
8
+ import { GEMINI_MODELS } from "../config/model-constants.js";
8
9
  // NOTE: dotenv is loaded in server.ts before any imports
9
10
  // No need to reload here - just read from process.env
10
11
  // Gemini API configuration
11
12
  const GEMINI_API_KEY = process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
12
13
  const GEMINI_API_URL = "https://generativelanguage.googleapis.com/v1beta";
13
- // Available Gemini models (2025 - Latest)
14
- export var GeminiModel;
15
- (function (GeminiModel) {
16
- // Primary models (Gemini 2.5 - preferred)
17
- GeminiModel["FLASH"] = "gemini-2.5-flash";
18
- GeminiModel["PRO"] = "gemini-2.5-pro";
19
- GeminiModel["FLASH_LITE"] = "gemini-2.5-flash-lite";
20
- })(GeminiModel || (GeminiModel = {}));
21
14
  /**
22
15
  * Call Gemini API directly
23
16
  */
24
- export async function callGemini(prompt, model = GeminiModel.PRO, systemPrompt, temperature = 0.7, skipValidation = false) {
17
+ export async function callGemini(prompt, model = GEMINI_MODELS.GEMINI_3_PRO, systemPrompt, temperature = 0.7, skipValidation = false) {
25
18
  if (!GEMINI_API_KEY) {
26
19
  return `[Gemini API key not configured. Add GOOGLE_API_KEY to .env file]`;
27
20
  }
@@ -144,10 +137,16 @@ export const geminiQueryTool = {
144
137
  description: "Query Gemini",
145
138
  parameters: z.object({
146
139
  prompt: z.string(),
147
- model: z.enum(["pro", "flash"]).optional().default("pro")
140
+ model: z.enum(["gemini-3", "pro", "flash"]).optional().default("gemini-3")
148
141
  }),
149
142
  execute: async (args, { log }) => {
150
- const model = args.model === "flash" ? GeminiModel.FLASH : GeminiModel.PRO;
143
+ let model = GEMINI_MODELS.GEMINI_3_PRO; // Default to Gemini 3
144
+ if (args.model === "flash") {
145
+ model = GEMINI_MODELS.FLASH;
146
+ }
147
+ else if (args.model === "pro") {
148
+ model = GEMINI_MODELS.PRO;
149
+ }
151
150
  return await callGemini(args.prompt, model);
152
151
  }
153
152
  };
@@ -174,7 +173,7 @@ IMPORTANT: Output a detailed written response with:
174
173
  4. Quick feasibility assessment
175
174
 
176
175
  Provide your complete analysis as visible text output.`;
177
- const response = await callGemini(args.prompt, GeminiModel.PRO, systemPrompt, 0.9);
176
+ const response = await callGemini(args.prompt, GEMINI_MODELS.GEMINI_3_PRO, systemPrompt, 0.9);
178
177
  // If multiple rounds requested, we could iterate here
179
178
  // For now, return the single response
180
179
  return response;
@@ -208,7 +207,7 @@ Provide:
208
207
  2. ${args.focus === 'security' ? 'Security vulnerabilities' : 'Issues found'}
209
208
  3. Specific recommendations for improvement
210
209
  4. Code quality score (1-10) with justification`;
211
- return await callGemini(`Analyze this code:\n\n\`\`\`${args.language || ''}\n${args.code}\n\`\`\``, GeminiModel.PRO, systemPrompt, 0.3);
210
+ return await callGemini(`Analyze this code:\n\n\`\`\`${args.language || ''}\n${args.code}\n\`\`\``, GEMINI_MODELS.GEMINI_3_PRO, systemPrompt, 0.3);
212
211
  }
213
212
  };
214
213
  /**
@@ -236,7 +235,7 @@ Format your response clearly with:
236
235
  ${args.type === 'sentiment' ? '- Overall sentiment\n- Confidence score\n- Emotional indicators' : ''}
237
236
  ${args.type === 'entities' ? '- People\n- Organizations\n- Locations\n- Other entities' : ''}
238
237
  ${args.type === 'key-points' ? '- Main arguments\n- Supporting points\n- Conclusions' : ''}`;
239
- return await callGemini(`Analyze this text:\n\n${args.text}`, GeminiModel.PRO, systemPrompt, 0.3);
238
+ return await callGemini(`Analyze this text:\n\n${args.text}`, GEMINI_MODELS.GEMINI_3_PRO, systemPrompt, 0.3);
240
239
  }
241
240
  };
242
241
  /**
@@ -269,7 +268,7 @@ Focus on:
269
268
  - Main ideas and key arguments
270
269
  - Important facts and figures
271
270
  - Conclusions and implications`;
272
- return await callGemini(`Summarize this content:\n\n${args.content}`, GeminiModel.PRO, systemPrompt, 0.3);
271
+ return await callGemini(`Summarize this content:\n\n${args.content}`, GEMINI_MODELS.GEMINI_3_PRO, systemPrompt, 0.3);
273
272
  }
274
273
  };
275
274
  /**
@@ -302,7 +301,7 @@ Make it specific and visually descriptive.`;
302
301
  ${args.style ? `Style: ${args.style}` : ''}
303
302
  ${args.mood ? `Mood: ${args.mood}` : ''}
304
303
  ${args.details ? `Additional details: ${args.details}` : ''}`;
305
- return await callGemini(userPrompt, GeminiModel.PRO, systemPrompt, 0.7);
304
+ return await callGemini(userPrompt, GEMINI_MODELS.GEMINI_3_PRO, systemPrompt, 0.7);
306
305
  }
307
306
  };
308
307
  /**
@@ -6,16 +6,20 @@ import { z } from "zod";
6
6
  import { config } from "dotenv";
7
7
  import * as path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
+ import { getGrokApiKey, hasGrokApiKey } from "../utils/api-keys.js";
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = path.dirname(__filename);
11
12
  config({ path: path.resolve(__dirname, '../../../.env') });
12
13
  // Grok API configuration
13
- const GROK_API_KEY = process.env.GROK_API_KEY || process.env.XAI_API_KEY;
14
+ const GROK_API_KEY = getGrokApiKey();
14
15
  const GROK_API_URL = "https://api.x.ai/v1/chat/completions";
15
- // Grok models - Updated 2025-11-07 with new fast models
16
+ // Grok models - Updated 2025-11-22 with correct API model names
16
17
  export var GrokModel;
17
18
  (function (GrokModel) {
18
- // New fast models (2025) - PRIMARY USE
19
+ // Grok 4.1 models (Nov 2025) - LATEST & BEST (verified working)
20
+ GrokModel["GROK_4_1_FAST_REASONING"] = "grok-4-1-fast-reasoning";
21
+ GrokModel["GROK_4_1_FAST"] = "grok-4-1-fast-non-reasoning";
22
+ // Grok 4 fast models (2025) - Still good
19
23
  GrokModel["CODE_FAST"] = "grok-code-fast-1";
20
24
  GrokModel["GROK_4_FAST_REASONING"] = "grok-4-fast-reasoning";
21
25
  GrokModel["GROK_4_FAST"] = "grok-4-fast-non-reasoning";
@@ -35,7 +39,7 @@ export async function callGrokEnhanced(messages, options = {}) {
35
39
  content: `[Grok API key not configured. Add GROK_API_KEY or XAI_API_KEY to .env file]`
36
40
  };
37
41
  }
38
- const { model = GrokModel.GROK_4_FAST_REASONING, // Changed: Use cheap fast reasoning by default
42
+ const { model = GrokModel.GROK_4_1_FAST_REASONING, // Updated 2025-11-22: Use latest Grok 4.1 by default
39
43
  temperature = 0.7, maxTokens = options.useHeavy ? 100000 : 4000, enableLiveSearch = false, searchSources = 100, // Default to 100 sources for cost control
40
44
  searchDomains = [], structuredOutput = false } = options;
41
45
  try {
@@ -140,9 +144,9 @@ Cite your sources when using web data.`
140
144
  content: query
141
145
  }
142
146
  ];
143
- log?.info(`Grok Scout: ${variant} research with ${enableLiveSearch ? 'live search' : 'knowledge base'} (using ${enableLiveSearch ? 'grok-4-fast-reasoning with search' : 'grok-4-fast-reasoning'})`);
147
+ log?.info(`Grok Scout: ${variant} research with ${enableLiveSearch ? 'live search' : 'knowledge base'} (using grok-4-1-fast-reasoning with enhanced reasoning)`);
144
148
  const result = await callGrokEnhanced(messages, {
145
- model: GrokModel.GROK_4_FAST_REASONING, // Changed: Use fast reasoning (works with search)
149
+ model: GrokModel.GROK_4_1_FAST_REASONING, // Updated 2025-11-21: Use latest Grok 4.1
146
150
  enableLiveSearch,
147
151
  searchSources,
148
152
  searchDomains,
@@ -197,11 +201,11 @@ ${enableLiveSearch ? 'Use live search for current information when needed.' : ''
197
201
  content: problem
198
202
  }
199
203
  ];
200
- const modelName = useHeavy ? 'Grok-4-Heavy' : 'Grok-4-Fast-Reasoning';
201
- const costInfo = useHeavy ? '$3/$15 (expensive!)' : '$0.20/$0.50 (cheap!)';
204
+ const modelName = useHeavy ? 'Grok-4-Heavy' : 'Grok-4.1';
205
+ const costInfo = useHeavy ? '$3/$15 (expensive!)' : '$0.20/$0.50 (latest!)';
202
206
  log?.info(`Using ${modelName} (${approach}) with ${enableLiveSearch ? 'live search' : 'knowledge base'} - Cost: ${costInfo}`);
203
207
  const result = await callGrokEnhanced(messages, {
204
- model: useHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_FAST_REASONING, // Changed: Use fast reasoning unless heavy requested
208
+ model: useHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_1_FAST_REASONING, // Updated 2025-11-21: Use latest Grok 4.1
205
209
  useHeavy,
206
210
  enableLiveSearch,
207
211
  searchSources: 50,
@@ -253,14 +257,14 @@ export const grokFunctionTool = {
253
257
  ];
254
258
  // Make request with tools
255
259
  const requestBody = {
256
- model: args.useHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_FAST_REASONING, // Changed: Use fast reasoning unless heavy requested
260
+ model: args.useHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_1_FAST, // Updated 2025-11-22: Use tool-calling optimized Grok 4.1 Fast Non-Reasoning
257
261
  messages,
258
262
  tools,
259
263
  tool_choice: "auto", // Let Grok decide when to call functions
260
264
  max_tokens: args.useHeavy ? 50000 : 5000,
261
265
  temperature: 0.3 // Lower for function calling
262
266
  };
263
- log?.info(`Function calling with ${args.useHeavy ? 'Grok-4-Heavy ($3/$15)' : 'Grok-4-Fast-Reasoning ($0.20/$0.50)'}`);
267
+ log?.info(`Function calling with ${args.useHeavy ? 'Grok-4-Heavy ($3/$15)' : 'Grok-4.1-Fast ($0.20/$0.50, tool-calling optimized)'}`);
264
268
  try {
265
269
  const response = await fetch(GROK_API_URL, {
266
270
  method: "POST",
@@ -318,13 +322,13 @@ Limit search to ${max_search_results} sources for cost control.`
318
322
  content: `Search for: ${query}`
319
323
  }
320
324
  ];
321
- log?.info(`Grok Search: ${max_search_results} sources, recency: ${recency} (using grok-4-fast-reasoning with search)`);
325
+ log?.info(`Grok Search: ${max_search_results} sources, recency: ${recency} (using grok-4-1-fast-reasoning with enhanced reasoning)`);
322
326
  // Extract domains from sources if specified
323
327
  const domains = sources
324
328
  ?.filter((s) => s.allowed_websites)
325
329
  ?.flatMap((s) => s.allowed_websites) || [];
326
330
  const result = await callGrokEnhanced(messages, {
327
- model: GrokModel.GROK_4_FAST_REASONING, // Changed: Use fast reasoning with search
331
+ model: GrokModel.GROK_4_1_FAST_REASONING, // Updated 2025-11-21: Use latest Grok 4.1 with search
328
332
  enableLiveSearch: true,
329
333
  searchSources: max_search_results,
330
334
  searchDomains: domains,
@@ -340,7 +344,7 @@ Limit search to ${max_search_results} sources for cost control.`
340
344
  * Check if Grok is available
341
345
  */
342
346
  export function isGrokAvailable() {
343
- return !!(GROK_API_KEY);
347
+ return hasGrokApiKey();
344
348
  }
345
349
  /**
346
350
  * Get Grok configuration status
@@ -348,10 +352,10 @@ export function isGrokAvailable() {
348
352
  export function getGrokStatus() {
349
353
  return {
350
354
  available: isGrokAvailable(),
351
- model: GrokModel.GROK_4_FAST_REASONING,
355
+ model: GrokModel.GROK_4_1_FAST_REASONING,
352
356
  features: [
353
- 'Fast reasoning (grok-4-fast-reasoning: $0.20/$0.50, 2M→4M context)',
354
- 'Code specialist (grok-code-fast-1: 92 tok/sec)',
357
+ 'Grok 4.1 Fast Reasoning (Nov 2025): Enhanced reasoning, creativity & emotional intelligence ($0.20/$0.50, 2M context)',
358
+ 'Grok 4.1 Fast Non-Reasoning: Tool-calling optimized, agentic workflows ($0.20/$0.50, 2M context)',
355
359
  'Heavy mode available (grok-4-0709: $3/$15, use sparingly)',
356
360
  'Live web search with citations',
357
361
  'Function calling',
@@ -8,16 +8,20 @@ import * as path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
9
  import { grokSearchTool } from './grok-enhanced.js';
10
10
  import { validateToolInput } from "../utils/input-validator.js";
11
+ import { getGrokApiKey, hasGrokApiKey } from "../utils/api-keys.js";
11
12
  const __filename = fileURLToPath(import.meta.url);
12
13
  const __dirname = path.dirname(__filename);
13
14
  config({ path: path.resolve(__dirname, '../../../.env') });
14
15
  // Grok API configuration
15
- const GROK_API_KEY = process.env.GROK_API_KEY;
16
+ const GROK_API_KEY = getGrokApiKey();
16
17
  const GROK_API_URL = "https://api.x.ai/v1/chat/completions";
17
- // Available Grok models - Updated 2025-11-07 with new fast models
18
+ // Available Grok models - Updated 2025-11-22 with correct API model names
18
19
  export var GrokModel;
19
20
  (function (GrokModel) {
20
- // New fast models (2025) - PRIMARY USE
21
+ // Grok 4.1 models (Nov 2025) - LATEST & BEST (verified working)
22
+ GrokModel["GROK_4_1_FAST_REASONING"] = "grok-4-1-fast-reasoning";
23
+ GrokModel["GROK_4_1_FAST"] = "grok-4-1-fast-non-reasoning";
24
+ // Grok 4 fast models (2025) - Still good
21
25
  GrokModel["CODE_FAST"] = "grok-code-fast-1";
22
26
  GrokModel["GROK_4_FAST_REASONING"] = "grok-4-fast-reasoning";
23
27
  GrokModel["GROK_4_FAST"] = "grok-4-fast-non-reasoning";
@@ -28,11 +32,11 @@ export var GrokModel;
28
32
  /**
29
33
  * Call Grok API
30
34
  */
31
- export async function callGrok(messages, model = GrokModel.GROK_4_FAST_REASONING, // Changed: Use cheap fast reasoning by default
35
+ export async function callGrok(messages, model = GrokModel.GROK_4_1_FAST_REASONING, // Updated 2025-11-22: Use latest Grok 4.1 by default
32
36
  temperature = 0.7, maxTokens = 16384, // Increased default for comprehensive responses
33
37
  forceVisibleOutput = true) {
34
38
  if (!GROK_API_KEY) {
35
- return `[Grok API key not configured. Add GROK_API_KEY to .env file]`;
39
+ return `[Grok API key not configured. Add XAI_API_KEY to .env file]`;
36
40
  }
37
41
  // Validate and sanitize message content
38
42
  const validatedMessages = messages.map((msg) => {
@@ -44,7 +48,9 @@ forceVisibleOutput = true) {
44
48
  });
45
49
  try {
46
50
  // For Grok 4 models, we need to handle reasoning tokens specially
47
- const isGrok4 = model === GrokModel.GROK_4_FAST_REASONING ||
51
+ const isGrok4 = model === GrokModel.GROK_4_1_FAST_REASONING ||
52
+ model === GrokModel.GROK_4_1_FAST ||
53
+ model === GrokModel.GROK_4_FAST_REASONING ||
48
54
  model === GrokModel.GROK_4_FAST ||
49
55
  model === GrokModel.GROK_4_HEAVY;
50
56
  // Adjust prompt for Grok 4 to ensure visible output
@@ -113,7 +119,7 @@ export const grokReasonTool = {
113
119
  const messages = [
114
120
  {
115
121
  role: "system",
116
- content: `You are Grok, an expert at logical reasoning and problem-solving.
122
+ content: `You are Grok 4.1, an expert at logical reasoning and problem-solving with enhanced emotional intelligence.
117
123
  ${approachPrompts[approach]}.
118
124
  ${context ? `Context: ${context}` : ''}`
119
125
  },
@@ -122,8 +128,8 @@ ${context ? `Context: ${context}` : ''}`
122
128
  content: problem
123
129
  }
124
130
  ];
125
- // Use GROK_4_FAST_REASONING by default (3x cheaper!), GROK_4_HEAVY only if explicitly requested
126
- const model = useHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_FAST_REASONING;
131
+ // Use GROK_4_1_FAST_REASONING by default (latest with enhanced reasoning!), GROK_4_HEAVY only if explicitly requested
132
+ const model = useHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_1_FAST_REASONING;
127
133
  const maxTokens = useHeavy ? 100000 : 16384; // 100k for heavy, 16k for normal reasoning
128
134
  log?.info(`Using Grok model: ${model} for deep reasoning (max tokens: ${maxTokens}, cost: ${useHeavy ? 'expensive $3/$15' : 'cheap $0.20/$0.50'})`);
129
135
  return await callGrok(messages, model, 0.7, maxTokens, true);
@@ -154,7 +160,7 @@ export const grokCodeTool = {
154
160
  const messages = [
155
161
  {
156
162
  role: "system",
157
- content: `You are Grok Code Fast, an expert programmer and code analyst.
163
+ content: `You are Grok 4.1 Fast, an expert programmer and code analyst with advanced tool-calling capabilities.
158
164
  Task: ${taskPrompts[task]}
159
165
  ${language ? `Language: ${language}` : ''}
160
166
  ${requirements ? `Requirements: ${requirements}` : ''}`
@@ -164,8 +170,8 @@ ${requirements ? `Requirements: ${requirements}` : ''}`
164
170
  content: `Code:\n\`\`\`${language || ''}\n${code}\n\`\`\``
165
171
  }
166
172
  ];
167
- log?.info(`Using Grok Code Fast (92 tok/sec coding specialist)`);
168
- return await callGrok(messages, GrokModel.CODE_FAST, 0.2, 4000, true);
173
+ log?.info(`Using Grok 4.1 Fast Non-Reasoning (2M context, tool-calling optimized, $0.20/$0.50)`);
174
+ return await callGrok(messages, GrokModel.GROK_4_1_FAST, 0.2, 4000, true);
169
175
  }
170
176
  };
171
177
  /**
@@ -208,8 +214,8 @@ Analyze the issue systematically:
208
214
  content: prompt
209
215
  }
210
216
  ];
211
- log?.info(`Using Grok Code Fast for debugging (specialized code model)`);
212
- return await callGrok(messages, GrokModel.CODE_FAST, 0.3, 3000, true);
217
+ log?.info(`Using Grok 4.1 Fast Non-Reasoning for debugging (tool-calling optimized, $0.20/$0.50)`);
218
+ return await callGrok(messages, GrokModel.GROK_4_1_FAST, 0.3, 3000, true);
213
219
  }
214
220
  };
215
221
  /**
@@ -240,8 +246,8 @@ ${constraints ? `Constraints: ${constraints}` : ''}`
240
246
  content: requirements
241
247
  }
242
248
  ];
243
- log?.info(`Using Grok 4 Fast Reasoning for architecture (cheap reasoning model)`);
244
- return await callGrok(messages, GrokModel.GROK_4_FAST_REASONING, 0.6, 4000, true);
249
+ log?.info(`Using Grok 4.1 Fast Reasoning for architecture (latest model, $0.20/$0.50)`);
250
+ return await callGrok(messages, GrokModel.GROK_4_1_FAST_REASONING, 0.6, 4000, true);
245
251
  }
246
252
  };
247
253
  /**
@@ -271,9 +277,9 @@ ${constraints ? `Constraints: ${constraints}` : 'No constraints - think freely!'
271
277
  content: `Brainstorm creative solutions for: ${topic}`
272
278
  }
273
279
  ];
274
- // Use GROK_4_FAST for creative brainstorming (cheap, fast), GROK_4_HEAVY only if explicitly requested
275
- const model = forceHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_FAST;
276
- log?.info(`Brainstorming with Grok model: ${model} (Heavy: ${forceHeavy}, cost: ${forceHeavy ? 'expensive $3/$15' : 'cheap $0.20/$0.50'})`);
280
+ // Use GROK_4_1_FAST_REASONING for creative brainstorming (needs reasoning for creativity), GROK_4_HEAVY only if explicitly requested
281
+ const model = forceHeavy ? GrokModel.GROK_4_HEAVY : GrokModel.GROK_4_1_FAST_REASONING;
282
+ log?.info(`Brainstorming with Grok model: ${model} (Heavy: ${forceHeavy}, cost: ${forceHeavy ? 'expensive $3/$15' : 'cheap $0.20/$0.50 - latest 4.1'})`);
277
283
  return await callGrok(messages, model, 0.95, 4000); // High temperature for creativity
278
284
  }
279
285
  };
@@ -281,7 +287,7 @@ ${constraints ? `Constraints: ${constraints}` : 'No constraints - think freely!'
281
287
  * Check if Grok is available
282
288
  */
283
289
  export function isGrokAvailable() {
284
- return !!GROK_API_KEY;
290
+ return hasGrokApiKey();
285
291
  }
286
292
  export function getAllGrokTools() {
287
293
  if (!isGrokAvailable()) {
@@ -70,12 +70,14 @@ const ResponsesAPISchema = z.object({
70
70
  total_tokens: z.number().optional()
71
71
  }).optional()
72
72
  });
73
- // Available OpenAI models (GPT-5.1 family)
73
+ // Available OpenAI GPT-5 models (optimized for Claude Code)
74
74
  export var OpenAI51Model;
75
75
  (function (OpenAI51Model) {
76
76
  OpenAI51Model["FULL"] = "gpt-5.1";
77
+ OpenAI51Model["PRO"] = "gpt-5-pro";
77
78
  OpenAI51Model["CODEX_MINI"] = "gpt-5.1-codex-mini";
78
79
  OpenAI51Model["CODEX"] = "gpt-5.1-codex";
80
+ OpenAI51Model["CODEX_MAX"] = "gpt-5.1-codex-max";
79
81
  })(OpenAI51Model || (OpenAI51Model = {}));
80
82
  /**
81
83
  * Call OpenAI API with model fallback support
@@ -111,34 +113,33 @@ reasoningEffort = "low", requireConfirmation = false, skipValidation = false) {
111
113
  for (const currentModel of modelsToTry) {
112
114
  console.error(`🔍 TRACE: Trying model: ${currentModel}`);
113
115
  try {
114
- // GPT-5.1 models use /v1/responses, others use /v1/chat/completions
115
- const isGPT51 = currentModel.startsWith('gpt-5.1');
116
- const endpoint = isGPT51 ? OPENAI_RESPONSES_URL : OPENAI_CHAT_URL;
116
+ // Codex models use /v1/responses, non-codex use /v1/chat/completions
117
+ const isCodex = currentModel.includes('codex');
118
+ const endpoint = isCodex ? OPENAI_RESPONSES_URL : OPENAI_CHAT_URL;
117
119
  let requestBody;
118
- // GPT-5.1 uses Responses API format, others use Chat Completions format
119
- if (isGPT51) {
120
- // Responses API format - NO temperature, use reasoning.effort instead
120
+ if (isCodex) {
121
+ // Responses API format for codex models
121
122
  requestBody = {
122
123
  model: currentModel,
123
124
  input: validatedMessages,
124
125
  max_output_tokens: maxTokens,
125
126
  stream: false,
126
127
  reasoning: {
127
- effort: reasoningEffort // "none", "low", "medium", "high"
128
+ effort: reasoningEffort
128
129
  }
129
130
  };
130
131
  }
131
132
  else {
132
- // Chat Completions format
133
+ // Chat Completions format for non-codex GPT-5 models (gpt-5.1, gpt-5-pro)
133
134
  requestBody = {
134
135
  model: currentModel,
135
136
  messages: validatedMessages,
136
137
  temperature,
137
- max_tokens: maxTokens,
138
+ max_completion_tokens: maxTokens, // GPT-5 requires max_completion_tokens (not max_tokens)
138
139
  stream: false
139
140
  };
140
141
  }
141
- console.error(`🔍 TRACE: Using ${isGPT51 ? '/v1/responses' : '/v1/chat/completions'} endpoint`);
142
+ console.error(`🔍 TRACE: Using ${isCodex ? '/v1/responses' : '/v1/chat/completions'} endpoint`);
142
143
  const response = await fetch(endpoint, {
143
144
  method: "POST",
144
145
  headers: {
@@ -159,16 +160,15 @@ reasoningEffort = "low", requireConfirmation = false, skipValidation = false) {
159
160
  throw new Error(lastError);
160
161
  }
161
162
  const rawData = await response.json();
162
- // Parse based on API type - they have DIFFERENT response formats!
163
+ // Parse based on API type
163
164
  let rawContent;
164
- if (isGPT51) {
165
- // Validate and parse Responses API format
165
+ if (isCodex) {
166
+ // Responses API format
166
167
  const parseResult = ResponsesAPISchema.safeParse(rawData);
167
168
  if (parseResult.success) {
168
169
  const data = parseResult.data;
169
170
  const messageOutput = data.output.find(item => item.type === 'message');
170
171
  rawContent = messageOutput?.content?.[0]?.text;
171
- // Capture reasoning info
172
172
  if (data.reasoning) {
173
173
  console.error(`🔍 TRACE: Reasoning effort: ${data.reasoning.effort}`);
174
174
  }
@@ -178,7 +178,7 @@ reasoningEffort = "low", requireConfirmation = false, skipValidation = false) {
178
178
  }
179
179
  }
180
180
  else {
181
- // Validate and parse Chat Completions API format
181
+ // Chat Completions format
182
182
  const parseResult = ChatCompletionResponseSchema.safeParse(rawData);
183
183
  if (parseResult.success) {
184
184
  const chatData = parseResult.data;
@@ -225,17 +225,16 @@ reasoningEffort = "low", skipValidation = false) {
225
225
  return { ...msg, content: validation.sanitized };
226
226
  });
227
227
  try {
228
- // GPT-5.1 models use /v1/responses, others use /v1/chat/completions
229
- const isGPT51 = model.startsWith('gpt-5.1');
230
- const endpoint = isGPT51 ? OPENAI_RESPONSES_URL : OPENAI_CHAT_URL;
228
+ // Codex models use /v1/responses, non-codex use /v1/chat/completions
229
+ const isCodex = model.includes('codex');
230
+ const endpoint = isCodex ? OPENAI_RESPONSES_URL : OPENAI_CHAT_URL;
231
231
  let requestBody;
232
- // GPT-5.1 uses Responses API format, others use Chat Completions format
233
- if (isGPT51) {
234
- // Responses API format - NO temperature, use reasoning.effort instead
232
+ if (isCodex) {
233
+ // Responses API format for codex models
235
234
  requestBody = {
236
235
  model: model,
237
236
  input: validatedMessages,
238
- max_output_tokens: maxTokens,
237
+ max_output_tokens: maxTokens, // NOT max_completion_tokens or max_tokens!
239
238
  stream: false,
240
239
  reasoning: {
241
240
  effort: reasoningEffort // "none", "low", "medium", "high"
@@ -243,17 +242,17 @@ reasoningEffort = "low", skipValidation = false) {
243
242
  };
244
243
  }
245
244
  else {
246
- // Chat Completions format
245
+ // Chat Completions format for non-codex GPT-5 models (gpt-5.1, gpt-5-pro)
247
246
  requestBody = {
248
247
  model: model,
249
248
  messages: validatedMessages,
250
249
  temperature,
251
- max_tokens: maxTokens,
250
+ max_completion_tokens: maxTokens, // GPT-5 requires max_completion_tokens (not max_tokens)
252
251
  stream: false
253
252
  };
254
253
  }
255
- console.error(`🔍 TRACE: Using ${isGPT51 ? '/v1/responses' : '/v1/chat/completions'} endpoint`);
256
- console.error(`🔍 TRACE: Model params: max_tokens=${maxTokens}, temperature=${temperature}${isGPT51 ? `, reasoning_effort=${reasoningEffort}` : ''}`);
254
+ console.error(`🔍 TRACE: Using ${isCodex ? '/v1/responses' : '/v1/chat/completions'} endpoint`);
255
+ console.error(`🔍 TRACE: Model params: ${isCodex ? `max_output_tokens=${maxTokens}, reasoning_effort=${reasoningEffort}` : `max_completion_tokens=${maxTokens}, temperature=${temperature}`}`);
257
256
  const response = await fetch(endpoint, {
258
257
  method: "POST",
259
258
  headers: {
@@ -270,7 +269,7 @@ reasoningEffort = "low", skipValidation = false) {
270
269
  const rawData = await response.json();
271
270
  // Parse based on API type - they have DIFFERENT response formats!
272
271
  let rawContent;
273
- if (isGPT51) {
272
+ if (isCodex) {
274
273
  // Validate and parse Responses API format
275
274
  const parseResult = ResponsesAPISchema.safeParse(rawData);
276
275
  if (parseResult.success) {
@@ -378,7 +377,7 @@ export const gpt5MiniReasonTool = {
378
377
  }
379
378
  };
380
379
  export const openaiGpt5ReasonTool = {
381
- name: "openai_gpt5_reason",
380
+ name: "openai_reason",
382
381
  description: "Mathematical reasoning using GPT-5.1 with high reasoning effort",
383
382
  parameters: z.object({
384
383
  query: z.string(),
@@ -409,37 +408,6 @@ ${args.context ? `Context: ${args.context}` : ''}`
409
408
  return await callOpenAI(messages, OpenAI51Model.FULL, 0.7, 4000, "high");
410
409
  }
411
410
  };
412
- /**
413
- * OpenAI Compare Tool
414
- * Multi-option comparison and consensus building using GPT-5.1-codex-mini
415
- */
416
- export const openaiCompareTool = {
417
- name: "openai_compare",
418
- description: "Multi-model consensus",
419
- parameters: z.object({
420
- topic: z.string(),
421
- options: z.array(z.string()),
422
- criteria: z.string().optional(),
423
- includeRecommendation: z.boolean().optional().default(true)
424
- }),
425
- execute: async (args, { log }) => {
426
- const optionsList = args.options.map((opt, i) => `${i + 1}. ${opt}`).join('\n');
427
- const messages = [
428
- {
429
- role: "system",
430
- content: `You are an expert at comparative analysis and decision-making.
431
- Compare the given options systematically.
432
- ${args.criteria ? `Criteria: ${args.criteria}` : 'Consider: pros, cons, trade-offs, and suitability'}
433
- ${args.includeRecommendation ? 'Provide a clear recommendation with justification.' : ''}`
434
- },
435
- {
436
- role: "user",
437
- content: `Topic: ${args.topic}\n\nOptions:\n${optionsList}`
438
- }
439
- ];
440
- return await callOpenAI(messages, OpenAI51Model.CODEX_MINI, 0.7, 3000, "low");
441
- }
442
- };
443
411
  /**
444
412
  * OpenAI Brainstorm Tool
445
413
  * Creative ideation and brainstorming
@@ -582,7 +550,6 @@ export function getAllOpenAITools() {
582
550
  }
583
551
  return [
584
552
  openaiGpt5ReasonTool, // GPT-5.1 reasoning (high effort)
585
- openaiCompareTool, // GPT-5.1-codex-mini comparison (low effort)
586
553
  openAIBrainstormTool, // GPT-5.1-codex-mini brainstorming (medium effort)
587
554
  openaiCodeReviewTool, // GPT-5.1-codex-mini code review (medium effort)
588
555
  openaiExplainTool // GPT-5.1-codex-mini explanations (low effort)