@pheem49/mint 1.2.4 → 1.3.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 -0
- package/index.html +16 -0
- package/main.js +36 -83
- package/mint-cli-logic.js +19 -0
- package/mint-cli.js +117 -15
- package/package.json +8 -2
- package/src/AI_Brain/Gemini_API.js +175 -9
- package/src/AI_Brain/knowledge_base.js +199 -125
- package/src/Automation_Layer/file_operations.js +41 -19
- package/src/CLI/chat_router.js +166 -0
- package/src/CLI/chat_ui.js +239 -110
- package/src/CLI/code_agent.js +443 -0
- package/src/CLI/code_session_memory.js +62 -0
- package/src/CLI/list_features.js +1 -0
- package/src/Plugins/mcp_manager.js +95 -0
- package/src/Plugins/plugin_manager.js +2 -2
- package/src/System/config_manager.js +27 -7
- package/src/System/granular_automation.js +88 -0
- package/src/UI/settings.html +24 -0
- package/src/UI/settings.js +98 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const { exec } = require('child_process');
|
|
2
|
+
const { screen } = require('electron');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GranularAutomation handles low-level OS input via xdotool.
|
|
6
|
+
* It uses a normalized coordinate system (0-1000).
|
|
7
|
+
*/
|
|
8
|
+
class GranularAutomation {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.screenWidth = 1920; // Default fallback
|
|
11
|
+
this.screenHeight = 1080;
|
|
12
|
+
this.updateScreenSize();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
updateScreenSize() {
|
|
16
|
+
try {
|
|
17
|
+
// In Electron main process, we can use the screen module
|
|
18
|
+
const primaryDisplay = screen.getPrimaryDisplay();
|
|
19
|
+
if (primaryDisplay && primaryDisplay.size) {
|
|
20
|
+
this.screenWidth = primaryDisplay.size.width;
|
|
21
|
+
this.screenHeight = primaryDisplay.size.height;
|
|
22
|
+
console.log(`[Automation] Screen detected: ${this.screenWidth}x${this.screenHeight}`);
|
|
23
|
+
}
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// Fallback for CLI or cases where screen module is unavailable
|
|
26
|
+
exec('xdpyinfo | grep dimensions', (err, stdout) => {
|
|
27
|
+
if (!err && stdout) {
|
|
28
|
+
const match = stdout.match(/(\d+)x(\d+) pixels/);
|
|
29
|
+
if (match) {
|
|
30
|
+
this.screenWidth = parseInt(match[1]);
|
|
31
|
+
this.screenHeight = parseInt(match[2]);
|
|
32
|
+
console.log(`[Automation] Screen detected via xdpyinfo: ${this.screenWidth}x${this.screenHeight}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
scaleX(x) {
|
|
40
|
+
return Math.round((x / 1000) * this.screenWidth);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
scaleY(y) {
|
|
44
|
+
return Math.round((y / 1000) * this.screenHeight);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
run(command) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
exec(command, (err, stdout, stderr) => {
|
|
50
|
+
if (err) {
|
|
51
|
+
console.error(`[Automation] xdotool error: ${stderr}`);
|
|
52
|
+
reject(err);
|
|
53
|
+
} else {
|
|
54
|
+
resolve(stdout);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async mouseMove(x, y) {
|
|
61
|
+
const sx = this.scaleX(x);
|
|
62
|
+
const sy = this.scaleY(y);
|
|
63
|
+
console.log(`[Automation] Moving mouse to ${sx}, ${sy}`);
|
|
64
|
+
return this.run(`xdotool mousemove ${sx} ${sy}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async mouseClick(x, y, button = 1) {
|
|
68
|
+
const sx = this.scaleX(x);
|
|
69
|
+
const sy = this.scaleY(y);
|
|
70
|
+
console.log(`[Automation] Clicking ${button} at ${sx}, ${sy}`);
|
|
71
|
+
// move first then click to be safe
|
|
72
|
+
return this.run(`xdotool mousemove ${sx} ${sy} click ${button}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async typeText(text) {
|
|
76
|
+
console.log(`[Automation] Typing: ${text}`);
|
|
77
|
+
// Escape double quotes for shell
|
|
78
|
+
const escaped = text.replace(/"/g, '\\"');
|
|
79
|
+
return this.run(`xdotool type "${escaped}"`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async keyTap(key) {
|
|
83
|
+
console.log(`[Automation] Key tap: ${key}`);
|
|
84
|
+
return this.run(`xdotool key "${key}"`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = new GranularAutomation();
|
package/src/UI/settings.html
CHANGED
|
@@ -352,6 +352,30 @@
|
|
|
352
352
|
</div>
|
|
353
353
|
</div>
|
|
354
354
|
</section>
|
|
355
|
+
|
|
356
|
+
<!-- MCP Servers Management -->
|
|
357
|
+
<section class="setting-section" style="margin-top: 30px;">
|
|
358
|
+
<h2 class="section-title">🌐 MCP Servers (Model Context Protocol)</h2>
|
|
359
|
+
<p class="hint" style="margin-bottom: 16px;">Connect Mint to external tools like Google Search, GitHub, or Filesystem.</p>
|
|
360
|
+
|
|
361
|
+
<div class="mcp-list" id="mcp-server-list" style="display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px;">
|
|
362
|
+
<!-- MCP items will be injected here -->
|
|
363
|
+
</div>
|
|
364
|
+
|
|
365
|
+
<div class="add-mcp-box" style="padding: 16px; background: rgba(255,255,255,0.05); border-radius: 12px; border: 1px dashed var(--border);">
|
|
366
|
+
<h3 style="font-size: 1rem; margin-bottom: 12px; color: var(--accent);">+ Add New MCP Server</h3>
|
|
367
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px;">
|
|
368
|
+
<input type="text" id="mcp-new-name" placeholder="Server Name (e.g. google-search)">
|
|
369
|
+
<input type="text" id="mcp-new-command" placeholder="Command (e.g. npx)">
|
|
370
|
+
</div>
|
|
371
|
+
<input type="text" id="mcp-new-args" placeholder="Arguments (e.g. -y @modelcontextprotocol/server-brave-search)" style="width: 100%; margin-bottom: 10px;">
|
|
372
|
+
<textarea id="mcp-new-env" placeholder='Env (JSON format, e.g. {"BRAVE_API_KEY": "..."})' style="width: 100%; min-height: 60px; background: var(--input-bg); color: var(--text-main); border: 1px solid var(--border); border-radius: 8px; padding: 10px; font-family: monospace; font-size: 0.8rem;"></textarea>
|
|
373
|
+
|
|
374
|
+
<button class="btn-primary" id="btn-add-mcp" style="margin-top: 10px; width: 100%;">Add MCP Server</button>
|
|
375
|
+
</div>
|
|
376
|
+
|
|
377
|
+
<p class="hint" style="margin-top: 12px;">Browse more servers at <a href="https://github.com/modelcontextprotocol/servers" target="_blank">MCP Servers Registry</a></p>
|
|
378
|
+
</section>
|
|
355
379
|
</div>
|
|
356
380
|
<div class="tab-pane" id="sect-shortcuts">
|
|
357
381
|
<!-- Keyboard Shortcuts -->
|
package/src/UI/settings.js
CHANGED
|
@@ -23,7 +23,8 @@ const DEFAULT_CONFIG = {
|
|
|
23
23
|
pluginSpotifyEnabled: true,
|
|
24
24
|
pluginCalendarEnabled: false,
|
|
25
25
|
pluginDiscordEnabled: false,
|
|
26
|
-
showDesktopWidget: true
|
|
26
|
+
showDesktopWidget: true,
|
|
27
|
+
mcpServers: {}
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
let currentConfig = { ...DEFAULT_CONFIG };
|
|
@@ -153,6 +154,9 @@ function applyConfig(config) {
|
|
|
153
154
|
document.getElementById('proactive-cooldown').value = cooldown;
|
|
154
155
|
updateIntervalDisplay(interval);
|
|
155
156
|
updateCooldownDisplay(cooldown);
|
|
157
|
+
|
|
158
|
+
// MCP Servers
|
|
159
|
+
renderMcpServers();
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
function lightenColor(hex, amount) {
|
|
@@ -433,12 +437,100 @@ document.getElementById('save-btn').addEventListener('click', async () => {
|
|
|
433
437
|
currentConfig.customBgEnd = document.getElementById('custom-bg-end').value;
|
|
434
438
|
currentConfig.customPanelBg = document.getElementById('custom-panel-bg').value;
|
|
435
439
|
|
|
440
|
+
// Ensure mcpServers is part of the saved config
|
|
441
|
+
if (!currentConfig.mcpServers) currentConfig.mcpServers = {};
|
|
442
|
+
|
|
443
|
+
console.log('[Settings] Saving config with MCP servers:', Object.keys(currentConfig.mcpServers).length);
|
|
436
444
|
await window.settingsApi.saveSettings(currentConfig);
|
|
437
445
|
const btn = document.getElementById('save-btn');
|
|
438
446
|
btn.textContent = '✅ Saved!';
|
|
439
447
|
setTimeout(() => { btn.textContent = 'Save Settings'; }, 1500);
|
|
440
448
|
});
|
|
441
449
|
|
|
450
|
+
// --- MCP Management Functions ---
|
|
451
|
+
function renderMcpServers() {
|
|
452
|
+
console.log('[Settings] Rendering MCP Servers UI...');
|
|
453
|
+
const list = document.getElementById('mcp-server-list');
|
|
454
|
+
if (!list) {
|
|
455
|
+
console.warn('[Settings] MCP list element not found in DOM.');
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
list.innerHTML = '';
|
|
459
|
+
|
|
460
|
+
const servers = currentConfig.mcpServers || {};
|
|
461
|
+
const entries = Object.entries(servers);
|
|
462
|
+
console.log(`[Settings] Found ${entries.length} servers in currentConfig.`);
|
|
463
|
+
|
|
464
|
+
if (entries.length === 0) {
|
|
465
|
+
list.innerHTML = '<p class="hint" style="text-align: center; padding: 10px;">No MCP servers connected.</p>';
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
for (const [name, cfg] of entries) {
|
|
470
|
+
const item = document.createElement('div');
|
|
471
|
+
item.style.cssText = 'display: flex; justify-content: space-between; align-items: center; padding: 12px; background: rgba(0,0,0,0.2); border-radius: 10px; border: 1px solid var(--border);';
|
|
472
|
+
|
|
473
|
+
item.innerHTML = `
|
|
474
|
+
<div style="display: flex; flex-direction: column; gap: 4px;">
|
|
475
|
+
<div style="font-weight: 600; color: var(--accent); display: flex; align-items: center; gap: 6px;">
|
|
476
|
+
<span>🌐 ${name}</span>
|
|
477
|
+
</div>
|
|
478
|
+
<div style="font-size: 0.75rem; opacity: 0.7; font-family: monospace;">${cfg.command} ${cfg.args.join(' ')}</div>
|
|
479
|
+
</div>
|
|
480
|
+
<button class="btn-danger" style="padding: 6px 12px; font-size: 0.8rem;" onclick="removeMcpServer('${name}')">Remove</button>
|
|
481
|
+
`;
|
|
482
|
+
list.appendChild(item);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
window.removeMcpServer = function(name) {
|
|
487
|
+
if (confirm(`Remove MCP server "${name}"?`)) {
|
|
488
|
+
delete currentConfig.mcpServers[name];
|
|
489
|
+
renderMcpServers();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
document.getElementById('btn-add-mcp').addEventListener('click', () => {
|
|
494
|
+
const nameInput = document.getElementById('mcp-new-name');
|
|
495
|
+
const cmdInput = document.getElementById('mcp-new-command');
|
|
496
|
+
const argsInput = document.getElementById('mcp-new-args');
|
|
497
|
+
const envInput = document.getElementById('mcp-new-env');
|
|
498
|
+
|
|
499
|
+
const name = nameInput.value.trim();
|
|
500
|
+
const command = cmdInput.value.trim();
|
|
501
|
+
const argsStr = argsInput.value.trim();
|
|
502
|
+
const envStr = envInput.value.trim();
|
|
503
|
+
|
|
504
|
+
if (!name || !command) {
|
|
505
|
+
alert('Name and Command are required!');
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Basic args split (by space, but respecting some quotes if possible - simple for now)
|
|
510
|
+
const args = argsStr ? argsStr.split(/\s+/) : [];
|
|
511
|
+
|
|
512
|
+
let env = {};
|
|
513
|
+
if (envStr) {
|
|
514
|
+
try {
|
|
515
|
+
env = JSON.parse(envStr);
|
|
516
|
+
} catch (e) {
|
|
517
|
+
alert('Invalid JSON in Environment Variables field!');
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (!currentConfig.mcpServers) currentConfig.mcpServers = {};
|
|
523
|
+
currentConfig.mcpServers[name] = { command, args, env };
|
|
524
|
+
|
|
525
|
+
// Clear inputs
|
|
526
|
+
nameInput.value = '';
|
|
527
|
+
cmdInput.value = '';
|
|
528
|
+
argsInput.value = '';
|
|
529
|
+
envInput.value = '';
|
|
530
|
+
|
|
531
|
+
renderMcpServers();
|
|
532
|
+
});
|
|
533
|
+
|
|
442
534
|
// Custom Workflows functionality
|
|
443
535
|
const openWorkflowsBtn = document.getElementById('open-workflows-btn');
|
|
444
536
|
const reloadWorkflowsBtn = document.getElementById('reload-workflows-btn');
|
|
@@ -508,6 +600,11 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
|
508
600
|
btn.classList.add('active');
|
|
509
601
|
const pane = document.getElementById(target);
|
|
510
602
|
if (pane) pane.classList.add('active');
|
|
603
|
+
|
|
604
|
+
// Re-render MCP list if switching to plugins tab
|
|
605
|
+
if (target === 'sect-plugins') {
|
|
606
|
+
renderMcpServers();
|
|
607
|
+
}
|
|
511
608
|
});
|
|
512
609
|
});
|
|
513
610
|
|