@pheem49/mint 1.2.4 → 1.4.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.
package/README.md CHANGED
@@ -17,11 +17,18 @@
17
17
 
18
18
  ---
19
19
 
20
- **Mint** is a powerful AI Assistant built with **Electron**, **Node.js**, and **Google Gemini**. It bridges the gap between your Desktop and Terminal, featuring real-time screen vision, web automation, local knowledge search, and a professional CLI for developers who love the command line.
20
+ **Mint** is a powerful AI Assistant built with **Electron**, **Node.js**, and **Google Gemini** (with extended support for Hugging Face, Anthropic, OpenAI, and Local Models). It bridges the gap between your Desktop and Terminal, featuring real-time screen vision, web automation, local knowledge search, and a professional CLI for developers who love the command line.
21
21
 
22
- ## 🌟 Highlights
22
+ ## Highlights
23
23
 
24
24
  - **Dual-Mode AI**: Switch between a beautiful **Desktop GUI** and a professional **CLI**.
25
+ - **Code Agent Mode**: Use `mint code "<task>"` to inspect, edit, and verify a project directly from the current terminal workspace.
26
+ - **Chat-First Workflow**: Regular Mint chat can now auto-route coding requests into workspace Code Mode, so the main chat acts as the control surface.
27
+ - **Advanced Multi-Agent Hub**:
28
+ - **Smart Routing**: Intelligently routes coding/general tasks to the most capable configured provider (e.g., Claude, OpenAI, Gemini).
29
+ - **Agent Collaboration**: Enable Multi-Agent Review so that a primary AI writes the code while a secondary AI automatically reviews it in the same loop.
30
+ - **Resilient Fallback**: Automatically fallbacks to alternative AI providers (Gemini, Anthropic, OpenAI, Hugging Face, LM Studio, Ollama) if your active provider fails.
31
+ - **Visible Mode State**: The CLI status bar now shows whether Mint is currently in `Chat` or `Code` mode.
25
32
  - **Interactive Slash Commands**: Manage models and settings in the terminal with `/model`, `/config`, `/clear`, etc.
26
33
  - **Smart TUI Experience**: Professional message framing, character-wrapped Thai text support, and mouse scroll wheel navigation.
27
34
  - **System Information Action**: Retrieve OS, Kernel, and Architecture details via natural language.
@@ -33,7 +40,7 @@
33
40
 
34
41
  ---
35
42
 
36
- ## 📸 Screenshots
43
+ ## Screenshots
37
44
 
38
45
  <p align="center">
39
46
  <img src="assets/Agent_Mint.png" alt="Agent Mint UI" width="48%">
@@ -45,7 +52,7 @@
45
52
 
46
53
  ---
47
54
 
48
- ## ⌨️ CLI Usage (Power Users)
55
+ ## CLI Usage (Power Users)
49
56
 
50
57
  Mint CLI is built for speed and efficiency. Use the **`mint`** command from anywhere.
51
58
 
@@ -53,24 +60,49 @@ Mint CLI is built for speed and efficiency. Use the **`mint`** command from anyw
53
60
  <img src="assets/CLI_Screen.png" alt="Mint CLI Preview" width="100%">
54
61
  </p>
55
62
 
56
- ### 🚀 Professional Commands
63
+ ### Professional Commands
57
64
  - **`mint`** : Start interactive chat mode (Default).
65
+ - **`mint code "task"`** : Run Mint as a workspace-aware coding agent in the current project folder.
58
66
  - **`mint agent`** : Run Mint as a headless background agent (Monitoring mode).
59
- - **`mint agent "task"`** : **[NEW]** Start agent and execute an autonomous task immediately.
67
+ - **`mint agent "task"`** : Start agent and execute an autonomous task immediately.
60
68
  - **`mint task "task"`** : Delegate a multi-step task to an already running background agent.
61
69
  - **`mint onboard`** : Setup API Key, Model, and initialize global configuration in `~/.mint/`.
62
70
  - **`mint list`** : See full list of automation actions and plugins.
63
71
 
64
72
  ---
65
73
 
66
- ### 🤖 Autonomous Agent (Task Delegate)
74
+ ### Autonomous Agent (Task Delegate)
67
75
  Mint isn't just a chatbot—it's an autonomous worker. Assign complex tasks that require multiple steps of reasoning.
68
76
 
77
+ ### Code Agent Mode
78
+ Mint now includes a dedicated coding workflow as the first step toward a Claude-Code-like experience in the terminal.
79
+
80
+ **What it can do now:**
81
+ - Inspect the current workspace before editing
82
+ - Search code across the repo
83
+ - Read targeted file ranges
84
+ - Run non-destructive shell commands in the project with interactive approval
85
+ - Apply patch-based file edits with approval before changes are written
86
+ - Reuse lightweight session memory and git/test context per project
87
+
88
+ **Usage Example:**
89
+ ```bash
90
+ mint code "fix the failing CLI command and verify it"
91
+ ```
92
+
93
+ **Chat-first Example:**
94
+ ```bash
95
+ mint
96
+ > สำรวจโปรเจคนี้ให้หน่อย
97
+ ```
98
+
99
+ Mint will classify the request, switch the status bar to `Code`, and return to `Chat` mode after the coding flow finishes.
100
+
69
101
  **Supported Autonomous Tools:**
70
- - 🌐 **Web Automation**: Full Puppeteer-based browsing, info extraction, and research.
71
- - 📁 **File System**: Create, Write, Delete, and Manage folders using `~/` path expansion.
72
- - 🔍 **Knowledge Search**: Query local files and documentation (RAG).
73
- - 🛡️ **Safety Mode (Bash)**: Mint proposes commands via notifications; you choose whether to run them.
102
+ - **Web Automation**: Full Puppeteer-based browsing, info extraction, and research.
103
+ - **File System**: Create, Write, Delete, and Manage folders using `~/` path expansion.
104
+ - **Knowledge Search**: Query local files and documentation (RAG).
105
+ - **Safety Mode (Bash)**: Mint proposes commands via notifications; you choose whether to run them.
74
106
 
75
107
  **Usage Examples:**
76
108
  ```bash
@@ -83,28 +115,28 @@ mint task 'Process these 5 files and move them to ~/Documents/Archive'
83
115
 
84
116
  ---
85
117
 
86
- ### Slash Commands (Interactive Chat)
118
+ ### Slash Commands (Interactive Chat)
87
119
  While in terminal chat, type **`/`** to access advanced tools with the new visual autocomplete system.
88
120
  > [!TIP]
89
121
  > Use **Up/Down arrow keys** to navigate the suggestion list and press **Enter** to select!
90
122
 
91
123
  - `/help` : View all commands and descriptions.
92
- - `/models` : List and switch between Gemini/Ollama models.
124
+ - `/models` : List and switch between Gemini, Ollama, Hugging Face, Anthropic, OpenAI, and Local models.
93
125
  - `/config` : Check your active API keys and preferences.
94
126
  - `/clear` / `/reset` : Clean terminal or reset AI context.
95
127
 
96
128
  ---
97
129
 
98
- ### 🕒 Proactive Monitoring
130
+ ### Proactive Monitoring
99
131
  When running in `agent` mode, Mint monitors your system in the background:
100
- - 🔋 **Battery Alerts**: Notifies you when power is low or charging status changes.
101
- - 🌐 **Network Status**: Alerts you when connection status changes.
102
- - 📊 **Resource Usage**: Proactive tips if system load is too high (System Metrics).
132
+ - **Battery Alerts**: Notifies you when power is low or charging status changes.
133
+ - **Network Status**: Alerts you when connection status changes.
134
+ - **Resource Usage**: Proactive tips if system load is too high (System Metrics).
103
135
 
104
136
 
105
137
  ---
106
138
 
107
- ## 🎨 Desktop GUI Features
139
+ ## Desktop GUI Features
108
140
 
109
141
  - **Floating Widget**: A persistent AI character on your desktop.
110
142
  - **Animated Aura**: The widget breathes and glows when Mint is thinking or proactive.
@@ -114,15 +146,15 @@ When running in `agent` mode, Mint monitors your system in the background:
114
146
 
115
147
  ---
116
148
 
117
- ## 🛡️ Security & Privacy
149
+ ## Security & Privacy
118
150
 
119
151
  - **Push Protection**: Automated `.gitignore` patterns for `mint-config.json` and `.env` files.
120
152
  - **History Scrubbing**: Integrated tools to ensure API keys are never leaked to Git history.
121
- - **Local First**: Built-in **Ollama** support for 100% private, offline AI processing.
153
+ - **Local First**: Built-in **Ollama** and **LM Studio (OpenAI Compatible)** support for 100% private, offline AI processing.
122
154
 
123
155
  ---
124
156
 
125
- ## 🛠️ Getting Started
157
+ ## Getting Started
126
158
 
127
159
  ### Prerequisites
128
160
  - [Node.js](https://nodejs.org/) (LTS)
@@ -145,7 +177,7 @@ When running in `agent` mode, Mint monitors your system in the background:
145
177
 
146
178
  ---
147
179
 
148
- ## 📂 Project Structure
180
+ ## Project Structure
149
181
 
150
182
  ```text
151
183
  Mint/
@@ -163,6 +195,6 @@ Mint/
163
195
 
164
196
  ---
165
197
 
166
- ## 🏛️ License
198
+ ## License
167
199
 
168
200
  Distributed under the **GNU Affero General Public License v3.0**. See `LICENSE` for details.
package/index.html ADDED
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Mint AI</title>
7
+ <!-- We can add Google Fonts here -->
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
11
+ </head>
12
+ <body>
13
+ <div id="root"></div>
14
+ <script type="module" src="/ui/src/main.jsx"></script>
15
+ </body>
16
+ </html>
package/main.js CHANGED
@@ -13,21 +13,22 @@ const { parseCommand } = require('./src/Command_Parser/parser');
13
13
  const pluginManager = require('./src/Plugins/plugin_manager');
14
14
  const { analyzeAndSuggest } = require('./src/AI_Brain/proactive_engine');
15
15
  const { recordBehavior, getBehaviorSummary } = require('./src/AI_Brain/behavior_memory');
16
- const { indexFile } = require('./src/AI_Brain/knowledge_base');
16
+ const { indexFile, indexFolder } = require('./src/AI_Brain/knowledge_base');
17
+
17
18
  const SystemAutomation = require('./src/System/system_automation');
18
19
  const systemEvents = require('./src/System/system_events');
19
20
  const customWorkflows = require('./src/System/custom_workflows');
21
+ const mcpManager = require('./src/Plugins/mcp_manager');
22
+ const granularAutomation = require('./src/System/granular_automation');
20
23
  const googleTTS = require('google-tts-api');
21
24
 
22
25
  let mainWindow;
23
26
  let settingsWindow = null;
24
27
  let screenPickerWindow = null;
25
28
  let spotlightWindow = null;
26
- let floatingWindow = null;
27
29
  let widgetWindow = null;
28
30
  let proactiveGlowWindow = null;
29
31
  let tray = null;
30
- let floatingUnreadCount = 0;
31
32
 
32
33
  // =====================
33
34
  // Proactive Loop
@@ -192,7 +193,7 @@ function createWindow() {
192
193
  });
193
194
 
194
195
  mainWindow.on('focus', () => {
195
- clearFloatingUnread();
196
+ // clearFloatingUnread(); // Disabled
196
197
  });
197
198
  }
198
199
 
@@ -291,41 +292,7 @@ function createSpotlightWindow() {
291
292
  });
292
293
  }
293
294
 
294
- function createFloatingWindow() {
295
- if (floatingWindow) return;
296
- const display = screen.getPrimaryDisplay();
297
- const { x, y, width, height } = display.workArea;
298
- const size = 72;
299
- const margin = 20;
300
- const posX = x + width - size - margin;
301
- const posY = y + height - size - margin - 40;
302
-
303
- floatingWindow = new BrowserWindow({
304
- width: size,
305
- height: size,
306
- x: posX,
307
- y: posY,
308
- frame: false,
309
- transparent: true,
310
- resizable: false,
311
- alwaysOnTop: true,
312
- skipTaskbar: true,
313
- show: true,
314
- webPreferences: {
315
- preload: path.join(__dirname, 'src/UI/preload-floating.js'),
316
- nodeIntegration: false,
317
- contextIsolation: true
318
- }
319
- });
320
-
321
- floatingWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
322
- floatingWindow.setAlwaysOnTop(true, 'floating');
323
- floatingWindow.loadFile('src/UI/floating.html');
324
-
325
- floatingWindow.on('closed', () => {
326
- floatingWindow = null;
327
- });
328
- }
295
+ // Floating window logic removed
329
296
 
330
297
  function createWidgetWindow() {
331
298
  if (widgetWindow) return;
@@ -363,28 +330,21 @@ function createWidgetWindow() {
363
330
  });
364
331
  }
365
332
 
366
- function updateFloatingUnread() {
367
- if (floatingWindow && !floatingWindow.isDestroyed()) {
368
- floatingWindow.webContents.send('floating-notify', floatingUnreadCount);
369
- }
370
- }
371
-
372
- function clearFloatingUnread() {
373
- if (floatingUnreadCount === 0) return;
374
- floatingUnreadCount = 0;
375
- updateFloatingUnread();
376
- }
333
+ // Floating unread logic removed
377
334
 
378
335
  app.whenReady().then(() => {
379
336
  const config = readConfig();
380
337
  createWindow();
381
338
  createTray();
382
- createFloatingWindow();
339
+ // createFloatingWindow(); // Removed
383
340
 
384
341
  // Only show AI widget if enabled in settings
385
342
  if (config.showDesktopWidget !== false) {
386
343
  createWidgetWindow();
387
344
  }
345
+
346
+ // Initialize MCP Servers
347
+ mcpManager.init().catch(err => console.error('[MCP] Init Error:', err));
388
348
 
389
349
  // Start monitoring system events (battery, wifi, etc.)
390
350
  systemEvents.startMonitoring();
@@ -395,7 +355,7 @@ app.whenReady().then(() => {
395
355
  systemEvents.on('low-battery', (level) => {
396
356
  if (mainWindow && !mainWindow.isDestroyed()) {
397
357
  mainWindow.webContents.send('proactive-notification', {
398
- message: `⚠️ แบตเตอรี่เหลือน้อยแล้วนะคะ (${level}%) อย่าลืมเสียบสายชาร์จนะค๊า ✨`,
358
+ message: `⚠️ Battery is low (${level}%). Please plug in your charger. ✨`,
399
359
  type: 'warning'
400
360
  });
401
361
  }
@@ -403,7 +363,7 @@ app.whenReady().then(() => {
403
363
 
404
364
  systemEvents.on('connection-change', (isOnline) => {
405
365
  if (mainWindow && !mainWindow.isDestroyed()) {
406
- const msg = isOnline ? '✅ เชื่อมต่ออินเทอร์เน็ตได้แล้วค่ะ ✨' : '❌ การเชื่อมต่ออินเทอร์เน็ตขาดหายไปนะคะ';
366
+ const msg = isOnline ? '✅ Internet connection restored. ✨' : '❌ Internet connection lost.';
407
367
  mainWindow.webContents.send('proactive-notification', { message: msg, type: 'info' });
408
368
  }
409
369
  });
@@ -438,6 +398,7 @@ app.on('window-all-closed', (e) => {
438
398
 
439
399
  app.on('will-quit', () => {
440
400
  globalShortcut.unregisterAll();
401
+ mcpManager.shutdown();
441
402
  });
442
403
 
443
404
  // =====================
@@ -473,7 +434,7 @@ ipcMain.on('close-window', (event) => {
473
434
  });
474
435
 
475
436
  ipcMain.on('minimize-window', (event) => {
476
- if (mainWindow) mainWindow.hide();
437
+ if (mainWindow) mainWindow.minimize();
477
438
  });
478
439
 
479
440
  ipcMain.on('quit-app', (event) => {
@@ -512,6 +473,7 @@ ipcMain.handle('get-settings', () => {
512
473
  });
513
474
 
514
475
  ipcMain.handle('save-settings', (event, config) => {
476
+ console.log('[Settings] Saving new config. MCP Servers count:', Object.keys(config.mcpServers || {}).length);
515
477
  const result = writeConfig(config);
516
478
  // Refresh API key if user updated it in settings
517
479
  refreshApiKeyFromConfig();
@@ -597,33 +559,7 @@ ipcMain.on('spotlight-resize', (event, width, height) => {
597
559
  }
598
560
  });
599
561
 
600
- // =====================
601
- // IPC — Floating Icon
602
- // =====================
603
- ipcMain.on('floating-click', () => {
604
- if (mainWindow) {
605
- mainWindow.show();
606
- mainWindow.focus();
607
- }
608
- clearFloatingUnread();
609
- });
610
-
611
- ipcMain.on('ai-notify', () => {
612
- floatingUnreadCount += 1;
613
- updateFloatingUnread();
614
- });
615
-
616
- ipcMain.on('ai-notify-clear', () => {
617
- clearFloatingUnread();
618
- });
619
-
620
- ipcMain.on('floating-drag-move', (_event, x, y) => {
621
- if (!floatingWindow || floatingWindow.isDestroyed()) return;
622
- const [width, height] = floatingWindow.getSize();
623
- const posX = Math.round(x - width / 2);
624
- const posY = Math.round(y - height / 2);
625
- floatingWindow.setBounds({ x: posX, y: posY, width, height });
626
- });
562
+ // Floating IPC removed
627
563
 
628
564
  ipcMain.handle('open-external', (event, url) => {
629
565
  shell.openExternal(url);
@@ -924,8 +860,11 @@ async function executeAction(action) {
924
860
  createFolder(action.target);
925
861
  break;
926
862
  case 'open_file':
927
- await openFile(action.target);
928
- break;
863
+ const fileRes = await openFile(action.target);
864
+ return fileRes || `Successfully opened file: ${action.target} ✅`;
865
+ case 'open_folder':
866
+ const folderRes = await openFile(action.target);
867
+ return folderRes || `Successfully opened folder: ${action.target} ✅`;
929
868
  case 'delete_file':
930
869
  await deleteFile(action.target);
931
870
  break;
@@ -934,6 +873,20 @@ async function executeAction(action) {
934
873
  break;
935
874
  case 'learn_file':
936
875
  return await indexFile(action.target);
876
+ case 'learn_folder':
877
+ const { indexFolder } = require('./src/AI_Brain/knowledge_base');
878
+ return await indexFolder(action.target);
879
+ case 'mcp_tool':
880
+ const mcpResult = await mcpManager.callTool(action.server, action.target, action.args);
881
+ return JSON.stringify(mcpResult.content);
882
+ case 'mouse_move':
883
+ return await granularAutomation.mouseMove(action.x, action.y);
884
+ case 'mouse_click':
885
+ return await granularAutomation.mouseClick(action.x, action.y, action.button || 1);
886
+ case 'type_text':
887
+ return await granularAutomation.typeText(action.target);
888
+ case 'key_tap':
889
+ return await granularAutomation.keyTap(action.target);
937
890
  case 'plugin':
938
891
  return await pluginManager.executePlugin(action.pluginName, action.target);
939
892
  case 'system_automation':
package/mint-cli-logic.js CHANGED
@@ -26,11 +26,30 @@ async function executeAction(action) {
26
26
  case 'open_file':
27
27
  await openFile(action.target);
28
28
  return `Opening: ${action.target}`;
29
+ case 'open_folder':
30
+ await openFile(action.target);
31
+ return `Opening folder: ${action.target}`;
29
32
  case 'delete_file':
30
33
  await deleteFile(action.target);
31
34
  return `Deleted: ${action.target}`;
32
35
  case 'learn_file':
33
36
  return await indexFile(action.target);
37
+ case 'mcp_tool':
38
+ const mcpManager = require('./src/Plugins/mcp_manager');
39
+ const mcpResult = await mcpManager.callTool(action.server, action.target, action.args);
40
+ return JSON.stringify(mcpResult.content);
41
+ case 'mouse_move':
42
+ const granularAutomation = require('./src/System/granular_automation');
43
+ return await granularAutomation.mouseMove(action.x, action.y);
44
+ case 'mouse_click':
45
+ const granularAutomationClick = require('./src/System/granular_automation');
46
+ return await granularAutomationClick.mouseClick(action.x, action.y, action.button || 1);
47
+ case 'type_text':
48
+ const granularAutomationType = require('./src/System/granular_automation');
49
+ return await granularAutomationType.typeText(action.target);
50
+ case 'key_tap':
51
+ const granularAutomationKey = require('./src/System/granular_automation');
52
+ return await granularAutomationKey.keyTap(action.target);
34
53
  case 'plugin':
35
54
  return await pluginManager.executePlugin(action.pluginName, action.target);
36
55
  case 'system_automation':