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 +20 -0
- package/dist/src/config/model-constants.js +11 -11
- package/dist/src/config/model-defaults.js +1 -1
- package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/tools/jury-tool.js +2 -2
- package/dist/src/tools/openrouter-tools.js +10 -10
- package/dist/src/tools/planner-tools.js +7 -1
- package/dist/src/utils/ansi-renderer.js +43 -4
- package/dist/src/utils/ansi-styles.js +3 -3
- package/dist/src/utils/format-constants.js +1 -1
- package/package.json +1 -1
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.
|
|
82
|
+
// M2.7 released Mar 18, 2026 - Self-evolving, #1 AI Intelligence Index, SWE-Pro 56.22%
|
|
83
83
|
export const MINIMAX_MODELS = {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
397
|
-
"minimax/minimax-m2.
|
|
398
|
-
"minimax/minimax-m2": 0.
|
|
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.
|
|
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.
|
|
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" },
|
package/dist/src/server.js
CHANGED
|
@@ -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.
|
|
612
|
-
safeAddTool(minimaxAgentTool); // MiniMax M2.
|
|
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.
|
|
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.
|
|
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,
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
1054
|
-
minimaxAgentTool, // MiniMax M2.
|
|
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
|
|
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. "
|
|
454
|
-
.replace(/^(.{1,2})\s+([A-Z][
|
|
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.
|
|
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
|
-
//
|
|
456
|
-
const bg = '\x1b[48;5;
|
|
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}
|
|
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