tachibot-mcp 2.19.0 → 2.19.3

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to TachiBot MCP will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.19.3] - 2026-03-21
9
+
10
+ ### Fixed
11
+ - **Section header regex** — now matches mixed case + optional dashes (works across all providers, not just Gemini)
12
+ - **Planner 5/1 bug** — `parsePlanSteps` now matches `### Task [T-ID]:` format (was only matching `### Step N:`)
13
+ - **Planner mismatch warning** — surfaces parse failures instead of masking with `Math.max`
14
+
15
+ ## [2.19.2] - 2026-03-21
16
+
17
+ ### Added
18
+ - **Rotating pastel section headers** — 6 colors cycle per response: lavender, mauve, powder blue, sand, mint, peach
19
+ - **Indigo tool name badge** — replaces gray summary badge with soft indigo (61) + nerd font icon
20
+ - **Rounded corner tables** — markdown tables rendered as aligned ASCII with `╭─┬─╮ │ │ ╰─┴─╯` box-drawing
21
+ - **Color-coded verdicts** — pastel 256-color: sage green (151) pass, soft yellow (186) partial, rose (174) fail
22
+ - **Tables in FORMAT_INSTRUCTION** — models now allowed to use `| table |` format
23
+ - **Spacing** — blank line between badge bar and first section header
24
+
25
+ ### Changed
26
+ - **Emoji palette** — verdict 👩‍⚖️, sections use 🧠
27
+
8
28
  ## [2.19.0] - 2026-03-21
9
29
 
10
30
  ### Added
@@ -79,11 +79,11 @@ export const KIMI_MODELS = {
79
79
  K2_5: "moonshotai/kimi-k2.5", // Multimodal (vision/video), Agent Swarm, tops SWE-Bench
80
80
  };
81
81
  // MiniMax Models (MiniMax via OpenRouter)
82
- // M2.5 released Feb 2026 - Best agentic model, SWE-Bench 80.2%, VERY CHEAP
82
+ // M2.7 released Mar 18, 2026 - Self-evolving, #1 AI Intelligence Index, SWE-Pro 56.22%
83
83
  export const MINIMAX_MODELS = {
84
- M2_5: "minimax/minimax-m2.5", // SWE-Bench 80.2%, 37% faster than M2.1, open source
85
- M2_1: "minimax/minimax-m2.1", // 230B/10B MoE - SWE-Bench 72.5%, τ²-Bench 77.2% (legacy)
86
- M2: "minimax/minimax-m2", // Fallback model
84
+ M2_7: "minimax/minimax-m2.7", // 2300B/100B MoE, 200K ctx, SWE-Pro 56.22%, Multi-SWE #1, $0.30/$1.20
85
+ M2_5: "minimax/minimax-m2.5", // SWE-Bench 80.2%, 37% faster than M2.1 (legacy)
86
+ M2_1: "minimax/minimax-m2.1", // 230B/10B MoE - SWE-Bench 72.5% (legacy)
87
87
  };
88
88
  // Qwen Models (Alibaba via OpenRouter)
89
89
  // Qwen3 235B Thinking (July 2025) - Largest reasoning model available
@@ -171,7 +171,7 @@ export const CURRENT_MODELS = {
171
171
  kimi: KIMI_MODELS.K2_5, // K2.5 multimodal + agent swarm (thinking via reasoning param)
172
172
  qwen: QWEN_MODELS.CODER_NEXT, // Qwen3-Coder-Next: 80B/3B MoE, 262K ctx, SWE >70%
173
173
  qwen_reason: QWEN_MODELS.MAX_THINKING, // 235B MoE thinking mode (HMMT 98%)
174
- minimax: MINIMAX_MODELS.M2_5, // M2.5: SWE-Bench 80.2%, 37% faster, open source
174
+ minimax: MINIMAX_MODELS.M2_7, // M2.7: SWE-Pro 56.22%, Multi-SWE #1, self-evolving
175
175
  }
176
176
  };
177
177
  // Tool-specific defaults - References CURRENT_MODELS for easy bumping
@@ -292,12 +292,12 @@ export const TOOL_DEFAULTS = {
292
292
  },
293
293
  // MiniMax tools - VERY CHEAP, open source
294
294
  minimax_code: {
295
- model: MINIMAX_MODELS.M2_5, // SWE-Bench 80.2%, 37% faster
295
+ model: MINIMAX_MODELS.M2_7, // SWE-Pro 56.22%, Multi-SWE #1
296
296
  maxTokens: 4000,
297
297
  temperature: 0.3, // Lower for precise code
298
298
  },
299
299
  minimax_agent: {
300
- model: MINIMAX_MODELS.M2_5, // SWE-Bench 80.2%, best agentic, open source
300
+ model: MINIMAX_MODELS.M2_7, // SWE-Pro 56.22%, self-evolving, #1 AI Intelligence Index
301
301
  maxTokens: 4000,
302
302
  temperature: 0.5, // Balanced for agentic tasks
303
303
  },
@@ -352,9 +352,9 @@ export const MODEL_DISPLAY_NAMES = {
352
352
  "qwen/qwq-32b": "qwq-32b",
353
353
  "qwen/qwen3-max-thinking": "qwen-max",
354
354
  // MiniMax
355
+ "minimax/minimax-m2.7": "minimax-m2.7",
355
356
  "minimax/minimax-m2.5": "minimax-m2.5",
356
357
  "minimax/minimax-m2.1": "minimax-m2.1",
357
- "minimax/minimax-m2": "minimax-m2",
358
358
  };
359
359
  // Helper to get display name (falls back to model ID if not mapped)
360
360
  export function getModelDisplayName(modelId) {
@@ -393,7 +393,7 @@ export const MODEL_PRICING = {
393
393
  "qwen/qwq-32b": 0.001,
394
394
  "qwen/qwen3-max-thinking": 0.005,
395
395
  // OpenRouter models - MiniMax (VERY CHEAP!)
396
- "minimax/minimax-m2.5": 0.000685, // ~same pricing tier as M2.1, 37% faster
397
- "minimax/minimax-m2.1": 0.000685, // ($0.27 + $1.10) / 2 / 1000 - legacy
398
- "minimax/minimax-m2": 0.0005,
396
+ "minimax/minimax-m2.7": 0.00075, // ($0.30 + $1.20) / 2 / 1000 - flagship
397
+ "minimax/minimax-m2.5": 0.000685, // legacy
398
+ "minimax/minimax-m2.1": 0.000685, // legacy
399
399
  };
@@ -29,7 +29,7 @@ const MODELS = {
29
29
  QWEN: QWEN_MODELS.CODER_NEXT, // qwen/qwen3-coder-next (80B/3B MoE, 262K ctx)
30
30
  QWEN_REASON: QWEN_MODELS.MAX_THINKING, // qwen/qwen3-235b-a22b-thinking (235B MoE)
31
31
  KIMI: KIMI_MODELS.K2_5, // moonshotai/kimi-k2.5 (thinking via reasoning param)
32
- MINIMAX: MINIMAX_MODELS.M2_5, // minimax/minimax-m2.5 (SWE 80.2%, open source)
32
+ MINIMAX: MINIMAX_MODELS.M2_7, // minimax/minimax-m2.7 (SWE-Pro 56.22%, #1 AI Intelligence Index)
33
33
  };
34
34
  /**
35
35
  * Get Scout model configuration
@@ -101,7 +101,7 @@ modelProviderRegistry.registerMany([
101
101
  // Qwen reason (heavy math/reasoning)
102
102
  { modelName: "qwen-reason", toolName: "qwen_reason", provider: "openrouter", aliases: ["qwen_reason", "qwen-max", "qwen-thinking"] },
103
103
  // MiniMax models (cheap agentic)
104
- { modelName: "minimax", toolName: "minimax_agent", provider: "openrouter", aliases: ["minimax-agent", "minimax-m2.5", "minimax-m2.1"] },
104
+ { modelName: "minimax", toolName: "minimax_agent", provider: "openrouter", aliases: ["minimax-agent", "minimax-m2.7", "minimax-m2.5"] },
105
105
  { modelName: "minimax-code", toolName: "minimax_code", provider: "openrouter", aliases: ["minimax_code"] },
106
106
  // Think tool
107
107
  { modelName: "think", toolName: "think", provider: "anthropic" },
@@ -608,8 +608,8 @@ async function initializeServer() {
608
608
  safeAddTool(kimiDecomposeTool); // Task decomposition (Kimi K2.5 Agent Swarm)
609
609
  safeAddTool(kimiLongContextTool); // Long-context analysis (Kimi K2.5 - 256K)
610
610
  safeAddTool(qwenReasonTool); // Heavy reasoning (Qwen3-Max-Thinking >1T params)
611
- safeAddTool(minimaxCodeTool); // MiniMax M2.5 - SWE-Bench 80.2%, open source
612
- safeAddTool(minimaxAgentTool); // MiniMax M2.5 - agentic workflows, open source
611
+ safeAddTool(minimaxCodeTool); // MiniMax M2.7 - SWE-Pro 56.22%, #1 AI Intelligence Index
612
+ safeAddTool(minimaxAgentTool); // MiniMax M2.7 - agentic workflows, self-evolving
613
613
  console.error(`✅ Registered OpenRouter tools (Qwen, QwQ, Kimi x4, MiniMax)`);
614
614
  // Register planner tools (multi-model council for plan creation/execution)
615
615
  const { plannerMakerTool, plannerRunnerTool, listPlansTool } = await import("./tools/planner-tools.js");
@@ -71,9 +71,9 @@ const JUROR_REGISTRY = {
71
71
  label: "MiniMax (Agentic)",
72
72
  role: "Focus on practical execution steps and agentic task planning.",
73
73
  call: async (q) => callOpenRouter([
74
- { role: "system", content: `You are MiniMax M2.5, an agentic model (SWE-Bench 80.2%). Focus on practical execution and step-by-step plans. ${FORMAT_INSTRUCTION}` },
74
+ { role: "system", content: `You are MiniMax M2.7, a self-evolving agentic model (SWE-Pro 56.22%, #1 AI Intelligence Index). Focus on practical execution and step-by-step plans. ${FORMAT_INSTRUCTION}` },
75
75
  { role: "user", content: q }
76
- ], OpenRouterModel.MINIMAX_M2_5, 0.5, 3000),
76
+ ], OpenRouterModel.MINIMAX_M2_7, 0.5, 3000),
77
77
  },
78
78
  };
79
79
  const DEFAULT_JURORS = ["grok", "kimi", "qwen", "openai"];
@@ -28,10 +28,10 @@ export var OpenRouterModel;
28
28
  // Moonshot AI models (Kimi)
29
29
  OpenRouterModel["KIMI_K2_THINKING"] = "moonshotai/kimi-k2-thinking";
30
30
  OpenRouterModel["KIMI_K2_5"] = "moonshotai/kimi-k2.5";
31
- // MiniMax models - VERY CHEAP, best agentic, open source
31
+ // MiniMax models - VERY CHEAP, #1 AI Intelligence Index
32
+ OpenRouterModel["MINIMAX_M2_7"] = "minimax/minimax-m2.7";
32
33
  OpenRouterModel["MINIMAX_M2_5"] = "minimax/minimax-m2.5";
33
34
  OpenRouterModel["MINIMAX_M2_1"] = "minimax/minimax-m2.1";
34
- OpenRouterModel["MINIMAX_M2"] = "minimax/minimax-m2";
35
35
  })(OpenRouterModel || (OpenRouterModel = {}));
36
36
  // Fallback map for when providers hit quota limits
37
37
  const MODEL_FALLBACKS = {
@@ -881,12 +881,12 @@ ${FORMAT_INSTRUCTION}`
881
881
  };
882
882
  /**
883
883
  * MiniMax Code Tool
884
- * Single-pass code operations with MiniMax M2.5 (SWE-Bench 80.2%)
884
+ * Single-pass code operations with MiniMax M2.7 (SWE-Pro 56.22%, #1 AI Intelligence Index)
885
885
  * Best for: atomic code tasks — one input, one output, no planning needed
886
886
  */
887
887
  export const minimaxCodeTool = {
888
888
  name: "minimax_code",
889
- description: "Single-pass code operations with MiniMax M2.5 (SWE-Bench 80.2%). Put your REQUEST in the 'query' parameter. For multi-step tasks, use minimax_agent instead.",
889
+ description: "Single-pass code operations with MiniMax M2.7 (SWE-Pro 56.22%, #1 AI Intelligence Index). Put your REQUEST in the 'query' parameter. For multi-step tasks, use minimax_agent instead.",
890
890
  parameters: z.object({
891
891
  query: z.string().describe("Your request or question (REQUIRED - put your main request here)"),
892
892
  task: z.enum(["generate", "fix", "review", "optimize", "debug", "refactor"])
@@ -955,17 +955,17 @@ ${FORMAT_INSTRUCTION}`;
955
955
  ];
956
956
  const temp = taskTemperatures[args.task || "review"] ?? 0.3;
957
957
  const reportFn = reportProgress ?? (async () => { });
958
- return await withHeartbeat(() => callOpenRouter(messages, OpenRouterModel.MINIMAX_M2_5, temp, 4000), reportFn);
958
+ return await withHeartbeat(() => callOpenRouter(messages, OpenRouterModel.MINIMAX_M2_7, temp, 4000), reportFn);
959
959
  }
960
960
  };
961
961
  /**
962
962
  * MiniMax Agent Tool
963
- * Multi-step task decomposition and execution with MiniMax M2.5
963
+ * Multi-step task decomposition and execution with MiniMax M2.7
964
964
  * Best for: tasks requiring planning, analysis, research synthesis, decision-making
965
965
  */
966
966
  export const minimaxAgentTool = {
967
967
  name: "minimax_agent",
968
- description: "Multi-step task decomposition and execution with MiniMax M2.5: plan, analyze, research, decide. Use when a task needs breakdown into steps before execution. For single-pass code tasks, use minimax_code instead. Put TASK in 'task' parameter.",
968
+ description: "Multi-step task decomposition and execution with MiniMax M2.7: plan, analyze, research, decide. Use when a task needs breakdown into steps before execution. For single-pass code tasks, use minimax_code instead. Put TASK in 'task' parameter.",
969
969
  parameters: z.object({
970
970
  task: z.string().describe("The task to execute (REQUIRED - describe what needs to be done)"),
971
971
  context: z.string().optional().describe("Additional context about the environment or constraints"),
@@ -1021,7 +1021,7 @@ ${FORMAT_INSTRUCTION}`
1021
1021
  }
1022
1022
  ];
1023
1023
  const reportFn = reportProgress ?? (async () => { });
1024
- return await withHeartbeat(() => callOpenRouter(messages, OpenRouterModel.MINIMAX_M2_5, 0.3, 4000), reportFn);
1024
+ return await withHeartbeat(() => callOpenRouter(messages, OpenRouterModel.MINIMAX_M2_7, 0.3, 4000), reportFn);
1025
1025
  }
1026
1026
  };
1027
1027
  /**
@@ -1050,7 +1050,7 @@ export function getAllOpenRouterTools() {
1050
1050
  kimiLongContextTool, // Kimi K2.5 - long-context analysis (256K)
1051
1051
  // NEW tools (Jan 2026)
1052
1052
  qwenReasonTool, // Qwen3-Max-Thinking - heavy reasoning
1053
- minimaxCodeTool, // MiniMax M2.5 - SWE tasks (80.2%, cheap, open source)
1054
- minimaxAgentTool, // MiniMax M2.5 - agentic workflows (cheap, open source)
1053
+ minimaxCodeTool, // MiniMax M2.7 - SWE-Pro 56.22%, #1 AI Intelligence Index
1054
+ minimaxAgentTool, // MiniMax M2.7 - agentic workflows, self-evolving
1055
1055
  ];
1056
1056
  }
@@ -1136,11 +1136,13 @@ function generateProgressBar(current, total) {
1136
1136
  */
1137
1137
  function parsePlanSteps(plan) {
1138
1138
  const steps = [];
1139
- // Try numbered steps first (### Step 1: or 1. or Step 1:)
1139
+ // Try structured step/task headers (### Step 1:, ### Task T1:, 1., Step 1:)
1140
1140
  const stepPatterns = [
1141
1141
  /###\s*Step\s*\d+[:\s]+([^\n]+)([\s\S]*?)(?=###\s*Step|\n##[^#]|$)/gi,
1142
+ /###\s*Task\s*[^\n:]+:\s*([^\n]+)([\s\S]*?)(?=###\s*Task|\n##[^#]|$)/gi,
1142
1143
  /^\s*(\d+)\.\s*([^\n]+)([\s\S]*?)(?=^\s*\d+\.|$)/gm,
1143
1144
  /^Step\s*\d+[:\s]+([^\n]+)([\s\S]*?)(?=^Step\s*\d+|$)/gim,
1145
+ /^Task\s*[^\n:]+:\s*([^\n]+)([\s\S]*?)(?=^Task\s*\S+|$)/gim,
1144
1146
  ];
1145
1147
  for (const pattern of stepPatterns) {
1146
1148
  const matches = [...plan.matchAll(pattern)];
@@ -1253,6 +1255,10 @@ Evidence params (unblind the checkpoints):
1253
1255
  // Parse plan into steps
1254
1256
  const steps = parsePlanSteps(plan);
1255
1257
  const totalSteps = steps.length;
1258
+ if (completed.length > totalSteps) {
1259
+ lines.push(`⚠️ Plan parse mismatch: ${completed.length} steps completed but only ${totalSteps} parsed. Plan format may have degraded.`);
1260
+ lines.push("");
1261
+ }
1256
1262
  if (mode === "start") {
1257
1263
  // ═══════════════════════════════════════════════════════════════
1258
1264
  // START: Show parsed plan and devlog hint
@@ -185,7 +185,7 @@ export function renderOutput(content, modelOrOptions) {
185
185
  if (options.summary)
186
186
  parts.push(renderSummaryBadge(options.summary));
187
187
  if (parts.length)
188
- output += parts.join('') + '\n';
188
+ output += parts.join('') + '\n\n';
189
189
  output += stripMarkdown(content, { boldHeaders: true });
190
190
  break;
191
191
  }
@@ -435,9 +435,11 @@ function renderAnsi(md) {
435
435
  return md;
436
436
  }
437
437
  }
438
+ let sectionColorIdx = 0;
438
439
  export function stripMarkdown(md, options) {
439
440
  if (!md || !md.trim())
440
441
  return '';
442
+ sectionColorIdx = 0; // reset per call so colors cycle consistently
441
443
  const { boldHeaders = false } = options || {};
442
444
  // 1. Extract code blocks to placeholders (protect from stripping)
443
445
  const codeBlocks = [];
@@ -450,8 +452,14 @@ export function stripMarkdown(md, options) {
450
452
  text = text
451
453
  // Markdown headers — strip # prefix (or bold if boldHeaders)
452
454
  .replace(/^#{1,6}\s+(.+)$/gm, boldHeaders ? '\x1b[1m$1\x1b[0m' : '$1')
453
- // Emoji section headers — e.g. "🔍 TYPE SAFETY ───" soft teal bg, dark bold text
454
- .replace(/^(.{1,2})\s+([A-Z][A-Z\s&]+?)\s*─+$/gm, boldHeaders ? '\x1b[48;5;73m\x1b[30m\x1b[1m $1 $2 \x1b[0m' : '$1 $2')
455
+ // Emoji section headers — e.g. "🧠 TYPE SAFETY ───" or "🧠 Key Activities" rotating pastel bg
456
+ .replace(/^(.{1,2})\s+([A-Z][\w\s&,()/-]{2,50}?)\s*─*$/gm, (_match, emoji, header) => {
457
+ if (!boldHeaders)
458
+ return `${emoji} ${header}`;
459
+ const pastels = [146, 182, 152, 187, 116, 180]; // lavender, mauve, powder blue, sand, mint, peach
460
+ const bg = `\x1b[48;5;${pastels[sectionColorIdx++ % pastels.length]}m`;
461
+ return `${bg}\x1b[30m\x1b[1m ${emoji} ${header} \x1b[0m`;
462
+ })
455
463
  // Verdict lines — color-coded: green=pass, yellow=partial, red=fail
456
464
  .replace(/^(✅|🫠|💀|🟢|🟡|🔴)\s*(pass|partial|fail)\b(.*)$/gmi, (_match, emoji, status, rest) => {
457
465
  if (!boldHeaders)
@@ -482,7 +490,38 @@ export function stripMarkdown(md, options) {
482
490
  // Clean up extra whitespace
483
491
  .replace(/\n{3,}/g, '\n\n')
484
492
  .trim();
485
- // 3. Restore code blocks
493
+ // 3. Format markdown tables into aligned ASCII tables
494
+ text = text.replace(/(?:^\|.+\|$\n?){2,}/gm, (tableBlock) => {
495
+ const rows = tableBlock.trim().split('\n')
496
+ .filter(r => !/^\|[\s:|-]+\|$/.test(r)); // strip separator row (|:---|:---|)
497
+ if (rows.length === 0)
498
+ return tableBlock;
499
+ // Parse cells
500
+ const parsed = rows.map(r => r.split('|').slice(1, -1).map(c => c.trim()));
501
+ // Calculate column widths
502
+ const colCount = Math.max(...parsed.map(r => r.length));
503
+ const widths = Array(colCount).fill(0);
504
+ for (const row of parsed) {
505
+ for (let i = 0; i < row.length; i++) {
506
+ widths[i] = Math.max(widths[i], row[i].length);
507
+ }
508
+ }
509
+ // Build aligned table with rounded corners
510
+ const topBorder = '╭' + widths.map(w => '─'.repeat(w + 2)).join('┬') + '╮';
511
+ const midBorder = '├' + widths.map(w => '─'.repeat(w + 2)).join('┼') + '┤';
512
+ const botBorder = '╰' + widths.map(w => '─'.repeat(w + 2)).join('┴') + '╯';
513
+ const formatRow = (cells) => '│' + cells.map((c, i) => ` ${c.padEnd(widths[i])} `).join('│') + '│';
514
+ const lines = [];
515
+ lines.push(topBorder);
516
+ lines.push(formatRow(parsed[0])); // header
517
+ lines.push(midBorder);
518
+ for (let i = 1; i < parsed.length; i++) {
519
+ lines.push(formatRow(parsed[i]));
520
+ }
521
+ lines.push(botBorder);
522
+ return lines.join('\n');
523
+ });
524
+ // 4. Restore code blocks
486
525
  text = text.replace(/@@CODE(\d+)@@/g, (_, n) => codeBlocks[+n]);
487
526
  return text;
488
527
  }
@@ -452,10 +452,10 @@ export function renderModelBadge(model, theme) {
452
452
  * e.g. model badge: [bright magenta] grok [reset] + summary: [dim gray] search query [reset]
453
453
  */
454
454
  export function renderSummaryBadge(summary) {
455
- // Dimmed bg + bold sits next to the bright model badge
456
- const bg = '\x1b[48;5;238m'; // dark gray bg (ansi256 color 238)
455
+ // Soft indigo bg + white bold pairs with bright model badge
456
+ const bg = '\x1b[48;5;61m'; // soft indigo bg (ansi256 color 61)
457
457
  const fg = '\x1b[97m'; // bright white text
458
- return `${bg}${fg}${ANSI.bold} ${summary} ${ANSI.reset}`;
458
+ return `${bg}${fg}${ANSI.bold} ${summary} ${ANSI.reset}`;
459
459
  }
460
460
  /**
461
461
  * Get model badge (alias for backward compatibility)
@@ -5,7 +5,7 @@
5
5
  export const FORMAT_INSTRUCTION = `
6
6
  OUTPUT RULES:
7
7
  • No **bold** or __underline__ (CLI shows raw asterisks).
8
- • Allowed: \`code\`, \`\`\`blocks\`\`\`, lists, headers, emojis.
8
+ • Allowed: \`code\`, \`\`\`blocks\`\`\`, lists, headers, emojis, | tables |.
9
9
  • Lines under 80 chars. Paragraphs ≤4 lines.
10
10
  • Blank line between sections.
11
11
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "tachibot-mcp",
3
3
  "mcpName": "io.github.byPawel/tachibot-mcp",
4
4
  "displayName": "TachiBot MCP - Universal AI Orchestrator",
5
- "version": "2.19.0",
5
+ "version": "2.19.3",
6
6
  "type": "module",
7
7
  "main": "dist/src/server.js",
8
8
  "bin": {