@pheem49/mint 1.5.1 → 1.5.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/GUIDE_TH.md +7 -7
- package/README.md +140 -66
- package/assets/Agent_Mint.png +0 -0
- package/assets/Settings.png +0 -0
- package/main.js +12 -0
- package/mint-cli.js +148 -921
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json +31 -1
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json +6 -1
- package/package.json +20 -21
- package/preload.js +2 -0
- package/scripts/install_linux_desktop_entry.js +48 -0
- package/src/AI_Brain/Gemini_API.js +194 -491
- package/src/AI_Brain/autonomous_brain.js +46 -19
- package/src/AI_Brain/headless_agent.js +21 -2
- package/src/AI_Brain/proactive_engine.js +12 -2
- package/src/AI_Brain/provider_adapter.js +358 -0
- package/src/Automation_Layer/browser_automation.js +26 -24
- package/src/CLI/approval_handler.js +47 -0
- package/src/CLI/chat_router.js +7 -0
- package/src/CLI/chat_ui.js +586 -80
- package/src/CLI/cli_colors.js +115 -0
- package/src/CLI/cli_formatters.js +94 -0
- package/src/CLI/code_agent.js +825 -283
- package/src/CLI/intent_detectors.js +181 -0
- package/src/CLI/interactive_chat.js +641 -0
- package/src/CLI/list_features.js +3 -0
- package/src/CLI/repo_summarizer.js +282 -0
- package/src/CLI/semantic_code_search.js +312 -0
- package/src/CLI/skill_manager.js +41 -0
- package/src/CLI/slash_command_handler.js +418 -0
- package/src/CLI/symbol_indexer.js +231 -0
- package/src/CLI/updater.js +21 -1
- package/src/Channels/discord_bridge.js +11 -13
- package/src/Channels/line_bridge.js +10 -10
- package/src/Channels/slack_bridge.js +7 -12
- package/src/Channels/telegram_bridge.js +6 -14
- package/src/Channels/whatsapp_bridge.js +11 -9
- package/src/System/chat_history_manager.js +20 -12
- package/src/System/config_manager.js +4 -1
- package/src/System/ipc_handlers.js +10 -0
- package/src/System/optional_require.js +23 -0
- package/src/System/picture_store.js +109 -0
- package/src/System/task_manager.js +127 -0
- package/src/System/tool_registry.js +13 -0
- package/src/System/window_manager.js +16 -8
- package/src/UI/live2d_manager.js +246 -14
- package/src/UI/renderer.js +620 -45
- package/src/UI/settings.css +738 -439
- package/src/UI/settings.html +487 -432
- package/src/UI/settings.js +44 -10
- package/src/UI/styles.css +1403 -106
- package/privacy.txt +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ANSI color constants for Mint CLI output.
|
|
5
|
+
*/
|
|
6
|
+
const colors = {
|
|
7
|
+
reset: '\x1b[0m',
|
|
8
|
+
bright: '\x1b[1m',
|
|
9
|
+
mint: '\x1b[38;5;121m',
|
|
10
|
+
pink: '\x1b[38;5;213m',
|
|
11
|
+
gray: '\x1b[90m',
|
|
12
|
+
cyan: '\x1b[36m',
|
|
13
|
+
yellow: '\x1b[33m'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let isExiting = false;
|
|
17
|
+
|
|
18
|
+
function formatCount(value) {
|
|
19
|
+
const number = Number(value) || 0;
|
|
20
|
+
return number.toLocaleString('en-US');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function formatDurationMs(value) {
|
|
24
|
+
const ms = Math.max(0, Number(value) || 0);
|
|
25
|
+
const seconds = ms / 1000;
|
|
26
|
+
if (seconds < 10) return `${seconds.toFixed(1)}s`;
|
|
27
|
+
if (seconds < 60) return `${Math.round(seconds)}s`;
|
|
28
|
+
const minutes = Math.floor(seconds / 60);
|
|
29
|
+
const remaining = Math.round(seconds % 60);
|
|
30
|
+
return `${minutes}m ${remaining}s`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function fitText(value, width) {
|
|
34
|
+
const text = String(value || '');
|
|
35
|
+
if (text.length <= width) return text;
|
|
36
|
+
if (width <= 3) return text.slice(0, width);
|
|
37
|
+
return `${text.slice(0, width - 3)}...`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function line(label, value, width) {
|
|
41
|
+
const text = fitText(` ${label.padEnd(28)}${String(value || '')}`, width - 2);
|
|
42
|
+
return `│${text.padEnd(width - 2)}│`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function divider(width) {
|
|
46
|
+
return `│ ${'─'.repeat(Math.max(0, width - 4))}│`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function formatExitSummary(summary = {}) {
|
|
50
|
+
const width = Math.max(76, Math.min(135, process.stdout.columns || 100));
|
|
51
|
+
const top = `╭${'─'.repeat(width - 2)}╮`;
|
|
52
|
+
const bottom = `╰${'─'.repeat(width - 2)}╯`;
|
|
53
|
+
const empty = `│${''.padEnd(width - 2)}│`;
|
|
54
|
+
const message = summary.message || 'Agent powering down. Goodbye!';
|
|
55
|
+
const toolCalls = summary.toolCalls || {};
|
|
56
|
+
const modelUsage = Array.isArray(summary.modelUsage) ? summary.modelUsage : [];
|
|
57
|
+
const primaryModel = modelUsage[0]
|
|
58
|
+
? `${modelUsage[0].provider || 'provider'}:${modelUsage[0].model || 'model'}`
|
|
59
|
+
: '';
|
|
60
|
+
const totals = modelUsage.reduce((acc, item) => {
|
|
61
|
+
acc.input += Number(item.inputTokens) || 0;
|
|
62
|
+
acc.cache += Number(item.cacheReads) || 0;
|
|
63
|
+
acc.output += Number(item.outputTokens) || 0;
|
|
64
|
+
acc.reasoning += Number(item.reasoningTokens) || 0;
|
|
65
|
+
acc.total += Number(item.totalTokens) || 0;
|
|
66
|
+
return acc;
|
|
67
|
+
}, { input: 0, cache: 0, output: 0, reasoning: 0, total: 0 });
|
|
68
|
+
if (!totals.total) totals.total = totals.input + totals.output;
|
|
69
|
+
|
|
70
|
+
const lines = [
|
|
71
|
+
top,
|
|
72
|
+
line(message, '', width),
|
|
73
|
+
empty,
|
|
74
|
+
line('Performance', '', width),
|
|
75
|
+
line('Wall Time:', formatDurationMs(summary.wallMs), width),
|
|
76
|
+
line('Agent Active:', formatDurationMs(summary.agentActiveMs), width)
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
if (Number(toolCalls.total) > 0) {
|
|
80
|
+
lines.push(
|
|
81
|
+
line('Tool Calls:', `${formatCount(toolCalls.total)} ( ✓ ${formatCount(toolCalls.success)} x ${formatCount(toolCalls.failed)} )`, width),
|
|
82
|
+
line('Success Rate:', `${Number(toolCalls.successRate || 0).toFixed(1)}%`, width)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
lines.push(
|
|
87
|
+
empty,
|
|
88
|
+
line('Model:', primaryModel || 'No model calls recorded.', width),
|
|
89
|
+
divider(width),
|
|
90
|
+
line('Token usage:', `total=${formatCount(totals.total)} input=${formatCount(totals.input)} (+ ${formatCount(totals.cache)} cached) output=${formatCount(totals.output)}${totals.reasoning ? ` (reasoning ${formatCount(totals.reasoning)})` : ''}`, width)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
lines.push(bottom);
|
|
94
|
+
return lines.join('\n');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Restore terminal state, print goodbye, and exit.
|
|
99
|
+
* @param {number} [code=0]
|
|
100
|
+
*/
|
|
101
|
+
function exitWithGoodbye(code = 0, summary = null) {
|
|
102
|
+
if (isExiting) return;
|
|
103
|
+
isExiting = true;
|
|
104
|
+
|
|
105
|
+
process.stdout.write('\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l');
|
|
106
|
+
process.stdout.write('\x1b[?25h');
|
|
107
|
+
if (summary) {
|
|
108
|
+
console.log(`\n${colors.pink}${formatExitSummary(summary)}${colors.reset}\n`);
|
|
109
|
+
} else {
|
|
110
|
+
console.log(`\n${colors.pink}Goodbye! See you again soon!${colors.reset}\n`);
|
|
111
|
+
}
|
|
112
|
+
process.exit(code);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = { colors, exitWithGoodbye, _helpers: { formatExitSummary, formatDurationMs } };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { colors } = require('./cli_colors');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Formats a code-agent progress event into a console-friendly string.
|
|
7
|
+
* @param {string|object} info
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
function formatProgress(info) {
|
|
11
|
+
if (typeof info === 'string') return `${colors.gray}[Mint Code] ${info}${colors.reset}`;
|
|
12
|
+
|
|
13
|
+
const { action, target, message, thought } = info;
|
|
14
|
+
|
|
15
|
+
if (thought && process.env.MINT_HIDE_AGENT_NOTES !== '1') {
|
|
16
|
+
return `\n${colors.gray}${colors.bright}•${colors.reset} ${colors.gray}${thought}${colors.reset}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (action === 'ask_user') {
|
|
20
|
+
return `\n${colors.mint}✓${colors.reset} ${colors.bright}Ask User${colors.reset}\n${colors.gray} ${target || message || ''}${colors.reset}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let icon = `${colors.mint}✓${colors.reset}`;
|
|
24
|
+
let label = action || info.phase;
|
|
25
|
+
let color = colors.reset;
|
|
26
|
+
|
|
27
|
+
switch (action) {
|
|
28
|
+
case 'thinking':
|
|
29
|
+
return `\n${colors.yellow}* ${colors.bright}Thinking${colors.reset}`;
|
|
30
|
+
case 'web_search': label = 'WebSearch'; break;
|
|
31
|
+
case 'list_files':
|
|
32
|
+
case 'find_path': label = 'Explored'; break;
|
|
33
|
+
case 'read_file': label = 'ReadFile'; break;
|
|
34
|
+
case 'search_code': label = 'SearchText'; break;
|
|
35
|
+
case 'plan': label = 'Plan'; break;
|
|
36
|
+
case 'apply_patch':
|
|
37
|
+
case 'write_file': label = 'Edited'; break;
|
|
38
|
+
case 'run_shell': label = 'Ran command'; break;
|
|
39
|
+
case 'json_repair':
|
|
40
|
+
icon = '*';
|
|
41
|
+
label = 'Repairing JSON';
|
|
42
|
+
break;
|
|
43
|
+
case 'reviewer_start': label = 'Reviewing'; break;
|
|
44
|
+
default: break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const content = target || message || '';
|
|
48
|
+
return ` ${icon} ${colors.bright}${label}${colors.reset} ${color}${content}${colors.reset}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Formats a list of memory interactions for display.
|
|
53
|
+
* @param {Array} interactions
|
|
54
|
+
* @param {string} [title]
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
function formatMemoryInteractions(interactions, title = 'Remembered interactions') {
|
|
58
|
+
if (!Array.isArray(interactions) || interactions.length === 0) {
|
|
59
|
+
return `${title}:\n(no memories found)`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const lines = [`${title}:`];
|
|
63
|
+
interactions.forEach((item, index) => {
|
|
64
|
+
const when = item.created_at ? ` (${item.created_at})` : '';
|
|
65
|
+
const id = item.id ? `#${item.id} ` : '';
|
|
66
|
+
lines.push(`${index + 1}. ${id}User${when}: ${item.user_text}`);
|
|
67
|
+
lines.push(` Mint: ${item.ai_text}`);
|
|
68
|
+
});
|
|
69
|
+
return lines.join('\n');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Splits a response text into sentence-level chunks for streaming.
|
|
74
|
+
* @param {string} text
|
|
75
|
+
* @returns {string[]}
|
|
76
|
+
*/
|
|
77
|
+
function splitResponseSentences(text) {
|
|
78
|
+
const normalized = String(text || '').replace(/\r\n/g, '\n');
|
|
79
|
+
if (!normalized) return [];
|
|
80
|
+
|
|
81
|
+
const chunks = [];
|
|
82
|
+
let buffer = '';
|
|
83
|
+
for (const char of normalized) {
|
|
84
|
+
buffer += char;
|
|
85
|
+
if (char === '\n' || /[.!?。!?…]/u.test(char)) {
|
|
86
|
+
if (buffer.trim()) chunks.push(buffer);
|
|
87
|
+
buffer = '';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (buffer.trim()) chunks.push(buffer);
|
|
91
|
+
return chunks.length > 0 ? chunks : [normalized];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { formatProgress, formatMemoryInteractions, splitResponseSentences };
|