@pheem49/mint 1.3.0 β 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 +28 -24
- package/mint-cli.js +201 -26
- package/package.json +13 -2
- package/src/AI_Brain/Gemini_API.js +299 -46
- package/src/AI_Brain/agent_orchestrator.js +73 -0
- package/src/AI_Brain/autonomous_brain.js +2 -0
- package/src/AI_Brain/memory_store.js +318 -0
- package/src/CLI/chat_router.js +17 -2
- package/src/CLI/chat_ui.js +83 -1
- package/src/CLI/code_agent.js +143 -30
- package/src/CLI/onboarding.js +53 -6
- package/src/CLI/workspace_manager.js +81 -0
- package/src/Plugins/spotify.js +168 -40
- package/src/Plugins/system_monitor.js +72 -0
- package/src/System/config_manager.js +35 -2
- package/src/System/notifications.js +23 -0
- package/src/UI/settings.html +143 -65
- package/src/UI/settings.js +155 -41
- package/tests/agent_orchestrator.test.js +41 -0
- package/tests/config_manager.test.js +141 -0
- package/tests/memory_store.test.js +185 -0
- package/tests/spotify.test.js +201 -0
- package/tests/system_monitor.test.js +37 -0
- package/tests/workspace_manager.test.js +41 -0
package/README.md
CHANGED
|
@@ -17,13 +17,17 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
**Mint** is a powerful AI Assistant built with **Electron**, **Node.js**, and **Google Gemini
|
|
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
|
-
##
|
|
22
|
+
## Highlights
|
|
23
23
|
|
|
24
24
|
- **Dual-Mode AI**: Switch between a beautiful **Desktop GUI** and a professional **CLI**.
|
|
25
25
|
- **Code Agent Mode**: Use `mint code "<task>"` to inspect, edit, and verify a project directly from the current terminal workspace.
|
|
26
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.
|
|
27
31
|
- **Visible Mode State**: The CLI status bar now shows whether Mint is currently in `Chat` or `Code` mode.
|
|
28
32
|
- **Interactive Slash Commands**: Manage models and settings in the terminal with `/model`, `/config`, `/clear`, etc.
|
|
29
33
|
- **Smart TUI Experience**: Professional message framing, character-wrapped Thai text support, and mouse scroll wheel navigation.
|
|
@@ -36,7 +40,7 @@
|
|
|
36
40
|
|
|
37
41
|
---
|
|
38
42
|
|
|
39
|
-
##
|
|
43
|
+
## Screenshots
|
|
40
44
|
|
|
41
45
|
<p align="center">
|
|
42
46
|
<img src="assets/Agent_Mint.png" alt="Agent Mint UI" width="48%">
|
|
@@ -48,7 +52,7 @@
|
|
|
48
52
|
|
|
49
53
|
---
|
|
50
54
|
|
|
51
|
-
##
|
|
55
|
+
## CLI Usage (Power Users)
|
|
52
56
|
|
|
53
57
|
Mint CLI is built for speed and efficiency. Use the **`mint`** command from anywhere.
|
|
54
58
|
|
|
@@ -56,21 +60,21 @@ Mint CLI is built for speed and efficiency. Use the **`mint`** command from anyw
|
|
|
56
60
|
<img src="assets/CLI_Screen.png" alt="Mint CLI Preview" width="100%">
|
|
57
61
|
</p>
|
|
58
62
|
|
|
59
|
-
###
|
|
63
|
+
### Professional Commands
|
|
60
64
|
- **`mint`** : Start interactive chat mode (Default).
|
|
61
65
|
- **`mint code "task"`** : Run Mint as a workspace-aware coding agent in the current project folder.
|
|
62
66
|
- **`mint agent`** : Run Mint as a headless background agent (Monitoring mode).
|
|
63
|
-
- **`mint agent "task"`** :
|
|
67
|
+
- **`mint agent "task"`** : Start agent and execute an autonomous task immediately.
|
|
64
68
|
- **`mint task "task"`** : Delegate a multi-step task to an already running background agent.
|
|
65
69
|
- **`mint onboard`** : Setup API Key, Model, and initialize global configuration in `~/.mint/`.
|
|
66
70
|
- **`mint list`** : See full list of automation actions and plugins.
|
|
67
71
|
|
|
68
72
|
---
|
|
69
73
|
|
|
70
|
-
###
|
|
74
|
+
### Autonomous Agent (Task Delegate)
|
|
71
75
|
Mint isn't just a chatbotβit's an autonomous worker. Assign complex tasks that require multiple steps of reasoning.
|
|
72
76
|
|
|
73
|
-
###
|
|
77
|
+
### Code Agent Mode
|
|
74
78
|
Mint now includes a dedicated coding workflow as the first step toward a Claude-Code-like experience in the terminal.
|
|
75
79
|
|
|
76
80
|
**What it can do now:**
|
|
@@ -95,10 +99,10 @@ mint
|
|
|
95
99
|
Mint will classify the request, switch the status bar to `Code`, and return to `Chat` mode after the coding flow finishes.
|
|
96
100
|
|
|
97
101
|
**Supported Autonomous Tools:**
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
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.
|
|
102
106
|
|
|
103
107
|
**Usage Examples:**
|
|
104
108
|
```bash
|
|
@@ -111,28 +115,28 @@ mint task 'Process these 5 files and move them to ~/Documents/Archive'
|
|
|
111
115
|
|
|
112
116
|
---
|
|
113
117
|
|
|
114
|
-
###
|
|
118
|
+
### Slash Commands (Interactive Chat)
|
|
115
119
|
While in terminal chat, type **`/`** to access advanced tools with the new visual autocomplete system.
|
|
116
120
|
> [!TIP]
|
|
117
121
|
> Use **Up/Down arrow keys** to navigate the suggestion list and press **Enter** to select!
|
|
118
122
|
|
|
119
123
|
- `/help` : View all commands and descriptions.
|
|
120
|
-
- `/models` : List and switch between Gemini
|
|
124
|
+
- `/models` : List and switch between Gemini, Ollama, Hugging Face, Anthropic, OpenAI, and Local models.
|
|
121
125
|
- `/config` : Check your active API keys and preferences.
|
|
122
126
|
- `/clear` / `/reset` : Clean terminal or reset AI context.
|
|
123
127
|
|
|
124
128
|
---
|
|
125
129
|
|
|
126
|
-
###
|
|
130
|
+
### Proactive Monitoring
|
|
127
131
|
When running in `agent` mode, Mint monitors your system in the background:
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
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).
|
|
131
135
|
|
|
132
136
|
|
|
133
137
|
---
|
|
134
138
|
|
|
135
|
-
##
|
|
139
|
+
## Desktop GUI Features
|
|
136
140
|
|
|
137
141
|
- **Floating Widget**: A persistent AI character on your desktop.
|
|
138
142
|
- **Animated Aura**: The widget breathes and glows when Mint is thinking or proactive.
|
|
@@ -142,15 +146,15 @@ When running in `agent` mode, Mint monitors your system in the background:
|
|
|
142
146
|
|
|
143
147
|
---
|
|
144
148
|
|
|
145
|
-
##
|
|
149
|
+
## Security & Privacy
|
|
146
150
|
|
|
147
151
|
- **Push Protection**: Automated `.gitignore` patterns for `mint-config.json` and `.env` files.
|
|
148
152
|
- **History Scrubbing**: Integrated tools to ensure API keys are never leaked to Git history.
|
|
149
|
-
- **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.
|
|
150
154
|
|
|
151
155
|
---
|
|
152
156
|
|
|
153
|
-
##
|
|
157
|
+
## Getting Started
|
|
154
158
|
|
|
155
159
|
### Prerequisites
|
|
156
160
|
- [Node.js](https://nodejs.org/) (LTS)
|
|
@@ -173,7 +177,7 @@ When running in `agent` mode, Mint monitors your system in the background:
|
|
|
173
177
|
|
|
174
178
|
---
|
|
175
179
|
|
|
176
|
-
##
|
|
180
|
+
## Project Structure
|
|
177
181
|
|
|
178
182
|
```text
|
|
179
183
|
Mint/
|
|
@@ -191,6 +195,6 @@ Mint/
|
|
|
191
195
|
|
|
192
196
|
---
|
|
193
197
|
|
|
194
|
-
##
|
|
198
|
+
## License
|
|
195
199
|
|
|
196
200
|
Distributed under the **GNU Affero General Public License v3.0**. See `LICENSE` for details.
|
package/mint-cli.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
require('dotenv').config({ quiet: true });
|
|
3
3
|
const { Command } = require('commander');
|
|
4
|
-
const { handleChat, resetChat } = require('./src/AI_Brain/Gemini_API');
|
|
4
|
+
const { handleChat, handleGeminiChatStream, resetChat, refreshApiKeyFromConfig } = require('./src/AI_Brain/Gemini_API');
|
|
5
|
+
const agentOrchestrator = require('./src/AI_Brain/agent_orchestrator');
|
|
6
|
+
const workspaceManager = require('./src/CLI/workspace_manager');
|
|
7
|
+
const systemMonitor = require('./src/Plugins/system_monitor');
|
|
8
|
+
const { sendNotification } = require('./src/System/notifications');
|
|
5
9
|
const pkg = require('./package.json');
|
|
6
10
|
const { runOnboarding } = require('./src/CLI/onboarding');
|
|
7
11
|
const { startAgent } = require('./src/AI_Brain/headless_agent');
|
|
@@ -128,14 +132,88 @@ program.parse(process.argv);
|
|
|
128
132
|
* The Interactive Chat Loop β Gemini-style TUI
|
|
129
133
|
*/
|
|
130
134
|
async function startInteractiveChat(initialMessage = null) {
|
|
131
|
-
|
|
135
|
+
let lastResponseText = "";
|
|
136
|
+
const { screen, appendMessage, streamMessage, setThinking, updateStatusModel, copyLastResponse, requestApproval, setMode } = createChatUI({
|
|
132
137
|
onSubmit: async (text) => {
|
|
133
138
|
if (text.startsWith('/')) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
if (text.startsWith('/agent')) {
|
|
140
|
+
const args = text.split(' ');
|
|
141
|
+
if (args[1] === 'list') {
|
|
142
|
+
appendMessage('system', `Available Agents: ${agentOrchestrator.listAgents().join(', ')}`);
|
|
143
|
+
} else if (args[1]) {
|
|
144
|
+
const success = agentOrchestrator.setAgent(args[1]);
|
|
145
|
+
if (success) {
|
|
146
|
+
const agent = agentOrchestrator.getCurrentAgent();
|
|
147
|
+
appendMessage('system', `Switched to Agent: ${agent.icon} ${agent.name}`);
|
|
148
|
+
updateStatusModel(null, agent.name); // Pass name to status bar
|
|
149
|
+
resetChat(); // Reset to apply new system prompt
|
|
150
|
+
} else {
|
|
151
|
+
appendMessage('error', `Agent "${args[1]}" not found. Try /agent list`);
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
const agent = agentOrchestrator.getCurrentAgent();
|
|
155
|
+
appendMessage('system', `Current Agent: ${agent.icon} ${agent.name}\nUsage: /agent <type> or /agent list`);
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (text.startsWith('/stats')) {
|
|
161
|
+
appendMessage('system', 'π Fetching system statistics...');
|
|
162
|
+
const stats = await systemMonitor.execute('stats');
|
|
163
|
+
appendMessage('system', stats);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (text.startsWith('/workspace')) {
|
|
168
|
+
const args = text.split(' ');
|
|
169
|
+
const subCmd = args[1];
|
|
170
|
+
|
|
171
|
+
if (subCmd === 'add') {
|
|
172
|
+
const name = args[2];
|
|
173
|
+
const wsPath = args[3] || '.';
|
|
174
|
+
const instructions = args.slice(4).join(' ');
|
|
175
|
+
if (!name) {
|
|
176
|
+
appendMessage('error', 'Usage: /workspace add <name> [path] [instructions]');
|
|
177
|
+
} else {
|
|
178
|
+
workspaceManager.addWorkspace(name, wsPath, instructions);
|
|
179
|
+
appendMessage('system', `Workspace "${name}" registered at ${path.resolve(wsPath)}`);
|
|
180
|
+
resetChat();
|
|
181
|
+
}
|
|
182
|
+
} else if (subCmd === 'list') {
|
|
183
|
+
const all = workspaceManager.listWorkspaces();
|
|
184
|
+
let listMsg = "Registered Workspaces:\n";
|
|
185
|
+
for (const n in all) listMsg += `- ${n}: ${all[n].path}\n`;
|
|
186
|
+
appendMessage('system', Object.keys(all).length ? listMsg : "No workspaces registered.");
|
|
187
|
+
} else if (subCmd === 'remove') {
|
|
188
|
+
const name = args[2];
|
|
189
|
+
if (workspaceManager.removeWorkspace(name)) {
|
|
190
|
+
appendMessage('system', `Removed workspace "${name}"`);
|
|
191
|
+
resetChat();
|
|
192
|
+
} else {
|
|
193
|
+
appendMessage('error', `Workspace "${name}" not found.`);
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
const ws = workspaceManager.getWorkspaceByPath(process.cwd());
|
|
197
|
+
appendMessage('system', ws ? `Current Workspace: ${ws.name}\nPath: ${ws.path}` : "Not currently in a registered workspace.\nUsage: /workspace <add|list|remove>");
|
|
198
|
+
}
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (text.startsWith('/review')) {
|
|
203
|
+
if (!lastResponseText) {
|
|
204
|
+
appendMessage('error', 'Nothing to review yet. Get a response first.');
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
agentOrchestrator.setAgent('reviewer');
|
|
208
|
+
appendMessage('system', 'βοΈ Requesting second-pass review from Mint Reviewer...');
|
|
209
|
+
text = `Please review this previous response and provide a critique:\n\n${lastResponseText}`;
|
|
210
|
+
} else {
|
|
211
|
+
// Other slash commands
|
|
212
|
+
const fakeRl = { close: () => { } };
|
|
213
|
+
appendMessage('user', text);
|
|
214
|
+
await handleSlashCommandUI(text, appendMessage, updateStatusModel, copyLastResponse, setThinking, requestApproval, setMode);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
139
217
|
}
|
|
140
218
|
appendMessage('user', text);
|
|
141
219
|
|
|
@@ -162,16 +240,92 @@ async function startInteractiveChat(initialMessage = null) {
|
|
|
162
240
|
}, 1000);
|
|
163
241
|
|
|
164
242
|
try {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
243
|
+
const config = require('./src/System/config_manager').readConfig();
|
|
244
|
+
const provider = config.aiProvider || 'gemini';
|
|
245
|
+
const currentAgent = agentOrchestrator.getCurrentAgent();
|
|
246
|
+
updateStatusModel(null, currentAgent.name);
|
|
247
|
+
if (provider === 'gemini') {
|
|
248
|
+
// ββ Streaming path (Gemini only) ββββββββββββββββββββββββββββββββββ
|
|
249
|
+
// Gemini returns JSON so we buffer all chunks and progressively
|
|
250
|
+
// extract the "response" field as more of the JSON arrives.
|
|
251
|
+
clearInterval(timer);
|
|
252
|
+
|
|
253
|
+
let jsonBuffer = '';
|
|
254
|
+
let finalParsed = null;
|
|
255
|
+
let streamer = null;
|
|
256
|
+
let displayedChars = 0; // chars of response text already sent to TUI
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
for await (const event of handleGeminiChatStream(text)) {
|
|
260
|
+
if (event.chunk) {
|
|
261
|
+
jsonBuffer += event.chunk;
|
|
262
|
+
|
|
263
|
+
// Progressively extract readable text from the growing JSON buffer
|
|
264
|
+
const match = jsonBuffer.match(/"response"\s*:\s*"((?:[^"\\]|\\.)*)"/s);
|
|
265
|
+
if (match) {
|
|
266
|
+
const fullText = match[1]
|
|
267
|
+
.replace(/\\n/g, '\n')
|
|
268
|
+
.replace(/\\"/g, '"')
|
|
269
|
+
.replace(/\\\\/g, '\\');
|
|
270
|
+
const newChars = fullText.slice(displayedChars);
|
|
271
|
+
if (newChars.length > 0) {
|
|
272
|
+
if (!streamer) {
|
|
273
|
+
setThinking(false);
|
|
274
|
+
streamer = streamMessage('assistant');
|
|
275
|
+
}
|
|
276
|
+
streamer.appendChunk(newChars);
|
|
277
|
+
displayedChars = fullText.length;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} else if (event.done) {
|
|
281
|
+
finalParsed = event.parsed;
|
|
282
|
+
// Flush any remaining response text not yet displayed
|
|
283
|
+
if (finalParsed && finalParsed.response) {
|
|
284
|
+
const remaining = finalParsed.response.slice(displayedChars);
|
|
285
|
+
if (!streamer) {
|
|
286
|
+
setThinking(false);
|
|
287
|
+
streamer = streamMessage('assistant');
|
|
288
|
+
}
|
|
289
|
+
if (remaining) streamer.appendChunk(remaining);
|
|
290
|
+
}
|
|
291
|
+
if (streamer) {
|
|
292
|
+
streamer.finalize(event.timestamp);
|
|
293
|
+
} else {
|
|
294
|
+
setThinking(false);
|
|
295
|
+
appendMessage('assistant',
|
|
296
|
+
finalParsed ? finalParsed.response : '',
|
|
297
|
+
event.timestamp);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
} catch (streamErr) {
|
|
302
|
+
setThinking(false);
|
|
303
|
+
appendMessage('error', streamErr.message);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Execute Actions from the final parsed response
|
|
308
|
+
if (finalParsed) {
|
|
309
|
+
const { executeAction } = require('./mint-cli-logic');
|
|
310
|
+
if (finalParsed.action && finalParsed.action.type !== 'none') {
|
|
311
|
+
const result = await executeAction(finalParsed.action);
|
|
312
|
+
if (result) appendMessage('system', `Action: ${result}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
169
315
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
316
|
+
} else {
|
|
317
|
+
// ββ Non-streaming fallback (Ollama, Anthropic, OpenAI, etc.) ββ
|
|
318
|
+
const response = await handleChat(text);
|
|
319
|
+
clearInterval(timer);
|
|
320
|
+
setThinking(false);
|
|
321
|
+
lastResponseText = response.response;
|
|
322
|
+
appendMessage('assistant', response.response, response.timestamp);
|
|
323
|
+
|
|
324
|
+
const { executeAction } = require('./mint-cli-logic');
|
|
325
|
+
if (response.action && response.action.type !== 'none') {
|
|
326
|
+
const result = await executeAction(response.action);
|
|
327
|
+
if (result) appendMessage('system', `Action: ${result}`);
|
|
328
|
+
}
|
|
175
329
|
}
|
|
176
330
|
} catch (err) {
|
|
177
331
|
clearInterval(timer);
|
|
@@ -248,26 +402,47 @@ async function handleSlashCommandUI(input, appendMessage, updateStatusModel, cop
|
|
|
248
402
|
const config = readConfig();
|
|
249
403
|
if (args.length === 0) {
|
|
250
404
|
appendMessage('system', [
|
|
251
|
-
`Current
|
|
252
|
-
|
|
253
|
-
'
|
|
254
|
-
' - gemini-
|
|
255
|
-
' -
|
|
256
|
-
' -
|
|
405
|
+
`Current Provider: ${config.aiProvider}`,
|
|
406
|
+
`Current Gemini Model: ${config.geminiModel}`,
|
|
407
|
+
'Available Providers/Presets:',
|
|
408
|
+
' - gemini-2.5-flash (Default Gemini)',
|
|
409
|
+
' - ollama (Local provider)',
|
|
410
|
+
' - anthropic (Claude)',
|
|
411
|
+
' - openai (GPT)',
|
|
412
|
+
' - huggingface (Inference API)',
|
|
413
|
+
' - local (LM Studio / OpenAI Compatible)',
|
|
257
414
|
'Usage: /models <name> to switch'
|
|
258
415
|
].join('\n'));
|
|
259
416
|
} else {
|
|
260
417
|
const { writeConfig } = require('./src/System/config_manager');
|
|
261
418
|
const newModel = args[0];
|
|
419
|
+
let newProvider = 'gemini';
|
|
420
|
+
|
|
262
421
|
if (newModel === 'ollama') {
|
|
263
|
-
|
|
422
|
+
newProvider = 'ollama';
|
|
423
|
+
} else if (newModel === 'anthropic') {
|
|
424
|
+
newProvider = 'anthropic';
|
|
425
|
+
} else if (newModel === 'openai') {
|
|
426
|
+
newProvider = 'openai';
|
|
427
|
+
} else if (newModel === 'huggingface') {
|
|
428
|
+
newProvider = 'huggingface';
|
|
429
|
+
} else if (newModel === 'local' || newModel === 'local_openai') {
|
|
430
|
+
newProvider = 'local_openai';
|
|
431
|
+
} else if (newModel.startsWith('gpt-')) {
|
|
432
|
+
newProvider = 'openai';
|
|
433
|
+
config.openaiModel = newModel;
|
|
434
|
+
} else if (newModel.startsWith('claude-')) {
|
|
435
|
+
newProvider = 'anthropic';
|
|
436
|
+
config.anthropicModel = newModel;
|
|
264
437
|
} else {
|
|
265
|
-
|
|
438
|
+
newProvider = 'gemini';
|
|
266
439
|
config.geminiModel = newModel;
|
|
267
440
|
}
|
|
441
|
+
|
|
442
|
+
config.aiProvider = newProvider;
|
|
268
443
|
writeConfig(config);
|
|
269
|
-
appendMessage('system', `β
Switched to: ${newModel}`);
|
|
270
|
-
if (updateStatusModel) updateStatusModel(newModel);
|
|
444
|
+
appendMessage('system', `β
Switched to: ${newProvider} ${newProvider === 'gemini' ? `(${newModel})` : ''}`);
|
|
445
|
+
if (updateStatusModel) updateStatusModel(newProvider === 'gemini' ? newModel : newProvider);
|
|
271
446
|
}
|
|
272
447
|
break;
|
|
273
448
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pheem49/mint",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A powerful Electron-based AI desktop assistant powered by Google Gemini, featuring screen vision, web automation, and proactive suggestions.",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "electron .",
|
|
8
|
-
"test": "
|
|
8
|
+
"test": "jest --testPathPatterns=tests/",
|
|
9
|
+
"test:watch": "jest --testPathPatterns=tests/ --watch",
|
|
9
10
|
"build:linux": "electron-builder --linux",
|
|
10
11
|
"cli": "node mint-cli.js"
|
|
11
12
|
},
|
|
13
|
+
"jest": {
|
|
14
|
+
"testEnvironment": "node",
|
|
15
|
+
"testMatch": ["**/tests/**/*.test.js"],
|
|
16
|
+
"collectCoverageFrom": [
|
|
17
|
+
"src/AI_Brain/memory_store.js",
|
|
18
|
+
"src/AI_Brain/knowledge_base.js",
|
|
19
|
+
"src/System/config_manager.js"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
12
22
|
"bin": {
|
|
13
23
|
"mint": "mint-cli.js"
|
|
14
24
|
},
|
|
@@ -45,6 +55,7 @@
|
|
|
45
55
|
"@vitejs/plugin-react": "^6.0.1",
|
|
46
56
|
"electron": "^40.7.0",
|
|
47
57
|
"electron-builder": "^26.8.1",
|
|
58
|
+
"jest": "^30.4.0",
|
|
48
59
|
"vite": "^8.0.10"
|
|
49
60
|
},
|
|
50
61
|
"build": {
|