@pheem49/mint 1.5.0 → 1.5.2
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 +35 -1
- package/main.js +28 -14
- package/mint-cli-logic.js +3 -119
- package/mint-cli.js +201 -500
- package/models/Shiroko_Model/Shiroko/Shiroko_Core/72d86db84cfa9730b894c241fd24c0db.png +0 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core/items_pinned_to_model.json +14 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json +40 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253/347/234/274/347/217/240/346/221/207/346/231/203.exp3.json +15 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//345/233/264/350/243/231.exp3.json +10 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/215/347/205/247.exp3.json +50 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/277/347/254/224.exp3.json +10 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json +15 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//347/214/253/345/222/252/346/273/244/351/225/234.exp3.json +10 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//347/234/274/351/225/234.exp3.json +10 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_00.png +0 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_01.png +0 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_02.png +0 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_03.png +0 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.cdi3.json +1498 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.moc3 +0 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.model3.json +47 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.physics3.json +6658 -0
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.vtube.json +1299 -0
- package/models/Shiroko_Model/Shiroko//342/232/241/351/253/230/344/272/256/342/232/241/344/275/277/347/224/250/346/225/231/347/250/213/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.txt +23 -0
- package/package.json +40 -17
- package/src/AI_Brain/Gemini_API.js +147 -46
- package/src/AI_Brain/autonomous_brain.js +2 -1
- package/src/AI_Brain/memory_store.js +299 -3
- package/src/AI_Brain/proactive_engine.js +12 -2
- package/src/Automation_Layer/browser_automation.js +26 -24
- package/src/CLI/approval_handler.js +42 -0
- package/src/CLI/chat_router.js +18 -6
- package/src/CLI/chat_ui.js +583 -52
- package/src/CLI/cli_colors.js +32 -0
- package/src/CLI/cli_formatters.js +89 -0
- package/src/CLI/code_agent.js +369 -71
- package/src/CLI/image_input.js +90 -0
- package/src/CLI/intent_detectors.js +181 -0
- package/src/CLI/interactive_chat.js +479 -0
- package/src/CLI/list_features.js +3 -0
- package/src/CLI/onboarding.js +72 -15
- 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 +6 -4
- 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/action_executor.js +59 -10
- package/src/System/chat_history_manager.js +20 -12
- package/src/System/config_manager.js +31 -1
- package/src/System/granular_automation.js +122 -53
- package/src/System/optional_require.js +23 -0
- package/src/System/proactive_loop.js +19 -3
- package/src/System/safety_manager.js +108 -0
- package/src/System/sandbox_runner.js +182 -0
- package/src/System/system_automation.js +127 -81
- package/src/System/system_info.js +70 -0
- package/src/System/tool_registry.js +280 -0
- package/src/System/window_manager.js +4 -2
- package/src/UI/live2d_manager.js +566 -0
- package/src/UI/renderer.js +339 -21
- package/src/UI/settings.css +655 -420
- package/src/UI/settings.html +478 -432
- package/src/UI/settings.js +10 -8
- package/src/UI/styles.css +516 -31
- package/.codex +0 -0
- package/docs/assets/Agent_Mint.png +0 -0
- package/docs/assets/CLI_Screen.png +0 -0
- package/docs/assets/Settings.png +0 -0
- package/docs/assets/icon.png +0 -0
- package/docs/guide.html +0 -632
- package/docs/index.html +0 -133
- package/docs/style.css +0 -579
- package/index.html +0 -16
- package/src/UI/index.html +0 -126
- package/tech_news.txt +0 -3
- package/test_knowledge.txt +0 -3
- package/tests/action_executor_safety.test.js +0 -67
- package/tests/agent_orchestrator.test.js +0 -41
- package/tests/chat_router.test.js +0 -42
- package/tests/code_agent.test.js +0 -69
- package/tests/config_manager.test.js +0 -141
- package/tests/docker.test.js +0 -46
- package/tests/file_operations.test.js +0 -57
- package/tests/gmail.test.js +0 -135
- package/tests/gmail_auth.test.js +0 -129
- package/tests/google_calendar.test.js +0 -113
- package/tests/google_tts_urls.test.js +0 -24
- package/tests/memory_store.test.js +0 -185
- package/tests/notion.test.js +0 -121
- package/tests/provider_routing.test.js +0 -83
- package/tests/safety_manager.test.js +0 -40
- package/tests/spotify.test.js +0 -201
- package/tests/system_monitor.test.js +0 -37
- package/tests/updater.test.js +0 -32
- package/tests/workspace_manager.test.js +0 -56
|
@@ -1,115 +1,161 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { execFile } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
* Executes a shell command and returns a promise.
|
|
5
|
-
*/
|
|
6
|
-
function execPromise(command) {
|
|
4
|
+
function execPromise(command, args = []) {
|
|
7
5
|
return new Promise((resolve, reject) => {
|
|
8
|
-
|
|
6
|
+
execFile(command, args, (error, stdout, stderr) => {
|
|
9
7
|
if (error) {
|
|
8
|
+
error.stderr = stderr;
|
|
10
9
|
reject(error);
|
|
11
10
|
return;
|
|
12
11
|
}
|
|
13
|
-
resolve(stdout.trim());
|
|
12
|
+
resolve(String(stdout || '').trim());
|
|
14
13
|
});
|
|
15
14
|
});
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
function unsupported(feature) {
|
|
18
|
+
throw new Error(`${feature} is not supported on ${process.platform} by the current automation provider.`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function clampPercent(percent) {
|
|
22
|
+
const value = Number(percent);
|
|
23
|
+
if (!Number.isFinite(value)) return 50;
|
|
24
|
+
return Math.max(0, Math.min(100, Math.round(value)));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const linuxProvider = {
|
|
23
28
|
async setVolume(percent) {
|
|
24
|
-
|
|
29
|
+
const value = clampPercent(percent);
|
|
25
30
|
try {
|
|
26
|
-
await execPromise(
|
|
27
|
-
return `Volume set to ${
|
|
28
|
-
} catch (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return `Volume set to ${percent}%`;
|
|
32
|
-
} catch (err) {
|
|
33
|
-
throw new Error("Failed to set volume. amixer or pactl not found.");
|
|
34
|
-
}
|
|
31
|
+
await execPromise('amixer', ['-D', 'pulse', 'sset', 'Master', `${value}%`]);
|
|
32
|
+
return `Volume set to ${value}%`;
|
|
33
|
+
} catch (_) {
|
|
34
|
+
await execPromise('pactl', ['set-sink-volume', '@DEFAULT_SINK@', `${value}%`]);
|
|
35
|
+
return `Volume set to ${value}%`;
|
|
35
36
|
}
|
|
36
37
|
},
|
|
37
|
-
|
|
38
38
|
async mute() {
|
|
39
39
|
try {
|
|
40
|
-
await execPromise(
|
|
41
|
-
return
|
|
42
|
-
} catch (
|
|
43
|
-
await execPromise(
|
|
44
|
-
return
|
|
40
|
+
await execPromise('amixer', ['-D', 'pulse', 'sset', 'Master', 'toggle']);
|
|
41
|
+
return 'Volume toggled (mute/unmute)';
|
|
42
|
+
} catch (_) {
|
|
43
|
+
await execPromise('pactl', ['set-sink-mute', '@DEFAULT_SINK@', 'toggle']);
|
|
44
|
+
return 'Volume toggled (mute/unmute)';
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
|
-
|
|
48
|
-
// Brightness Control (Using brightnessctl or xbacklight)
|
|
49
47
|
async setBrightness(percent) {
|
|
48
|
+
const value = clampPercent(percent);
|
|
50
49
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
await execPromise(`xbacklight -set ${percent}`);
|
|
57
|
-
return `Brightness set to ${percent}%`;
|
|
58
|
-
} catch (err) {
|
|
59
|
-
throw new Error("Failed to set brightness. brightnessctl or xbacklight not found.");
|
|
60
|
-
}
|
|
50
|
+
await execPromise('brightnessctl', ['set', `${value}%`]);
|
|
51
|
+
return `Brightness set to ${value}%`;
|
|
52
|
+
} catch (_) {
|
|
53
|
+
await execPromise('xbacklight', ['-set', String(value)]);
|
|
54
|
+
return `Brightness set to ${value}%`;
|
|
61
55
|
}
|
|
62
56
|
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
sleep: () => execPromise('systemctl', ['suspend']),
|
|
58
|
+
restart: () => execPromise('systemctl', ['reboot']),
|
|
59
|
+
shutdown: () => execPromise('systemctl', ['poweroff']),
|
|
60
|
+
async minimizeAll() {
|
|
61
|
+
await execPromise('xdotool', ['key', 'Super+d']);
|
|
62
|
+
return 'Minimized all windows';
|
|
67
63
|
},
|
|
64
|
+
async getSystemInfo() {
|
|
65
|
+
try {
|
|
66
|
+
const osInfo = await execPromise('lsb_release', ['-ds']);
|
|
67
|
+
const kernel = await execPromise('uname', ['-r']);
|
|
68
|
+
const arch = await execPromise('uname', ['-m']);
|
|
69
|
+
return `Operating System: ${osInfo}\nKernel: ${kernel}\nArchitecture: ${arch}`;
|
|
70
|
+
} catch (_) {
|
|
71
|
+
const osRelease = fs.existsSync('/etc/os-release') ? fs.readFileSync('/etc/os-release', 'utf8') : '';
|
|
72
|
+
const prettyName = (osRelease.match(/^PRETTY_NAME="?([^"\n]+)"?/m) || [])[1] || 'Linux';
|
|
73
|
+
const kernel = await execPromise('uname', ['-r']);
|
|
74
|
+
const arch = await execPromise('uname', ['-m']);
|
|
75
|
+
return `Operating System: ${prettyName}\nKernel: ${kernel}\nArchitecture: ${arch}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
const macProvider = {
|
|
81
|
+
async setVolume(percent) {
|
|
82
|
+
const value = clampPercent(percent);
|
|
83
|
+
await execPromise('osascript', ['-e', `set volume output volume ${value}`]);
|
|
84
|
+
return `Volume set to ${value}%`;
|
|
71
85
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return
|
|
86
|
+
async mute() {
|
|
87
|
+
await execPromise('osascript', ['-e', 'set volume output muted not (output muted of (get volume settings))']);
|
|
88
|
+
return 'Volume toggled (mute/unmute)';
|
|
89
|
+
},
|
|
90
|
+
setBrightness: () => unsupported('Brightness control'),
|
|
91
|
+
sleep: () => execPromise('osascript', ['-e', 'tell application "System Events" to sleep']),
|
|
92
|
+
restart: () => execPromise('osascript', ['-e', 'tell application "System Events" to restart']),
|
|
93
|
+
shutdown: () => execPromise('osascript', ['-e', 'tell application "System Events" to shut down']),
|
|
94
|
+
async minimizeAll() {
|
|
95
|
+
await execPromise('osascript', ['-e', 'tell application "System Events" to keystroke "h" using {command down, option down}']);
|
|
96
|
+
return 'Hid visible applications';
|
|
75
97
|
},
|
|
98
|
+
async getSystemInfo() {
|
|
99
|
+
const product = await execPromise('sw_vers', ['-productName']);
|
|
100
|
+
const version = await execPromise('sw_vers', ['-productVersion']);
|
|
101
|
+
const build = await execPromise('sw_vers', ['-buildVersion']);
|
|
102
|
+
const arch = await execPromise('uname', ['-m']);
|
|
103
|
+
return `Operating System: ${product} ${version} (${build})\nArchitecture: ${arch}`;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
76
106
|
|
|
77
|
-
|
|
107
|
+
const windowsProvider = {
|
|
108
|
+
setVolume: () => unsupported('Volume control'),
|
|
109
|
+
mute: () => unsupported('Mute control'),
|
|
110
|
+
setBrightness: () => unsupported('Brightness control'),
|
|
111
|
+
sleep: () => execPromise('rundll32.exe', ['powrprof.dll,SetSuspendState', '0,1,0']),
|
|
112
|
+
restart: () => execPromise('shutdown.exe', ['/r', '/t', '0']),
|
|
113
|
+
shutdown: () => execPromise('shutdown.exe', ['/s', '/t', '0']),
|
|
78
114
|
async minimizeAll() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
115
|
+
await execPromise('powershell.exe', [
|
|
116
|
+
'-NoProfile',
|
|
117
|
+
'-NonInteractive',
|
|
118
|
+
'-Command',
|
|
119
|
+
'$shell = New-Object -ComObject Shell.Application; $shell.MinimizeAll()'
|
|
120
|
+
]);
|
|
121
|
+
return 'Minimized all windows';
|
|
85
122
|
},
|
|
123
|
+
async getSystemInfo() {
|
|
124
|
+
const caption = await execPromise('powershell.exe', [
|
|
125
|
+
'-NoProfile',
|
|
126
|
+
'-NonInteractive',
|
|
127
|
+
'-Command',
|
|
128
|
+
'(Get-CimInstance Win32_OperatingSystem).Caption'
|
|
129
|
+
]);
|
|
130
|
+
const version = await execPromise('cmd.exe', ['/c', 'ver']);
|
|
131
|
+
const arch = process.arch;
|
|
132
|
+
return `Operating System: ${caption}\nVersion: ${version}\nArchitecture: ${arch}`;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
86
135
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return `Operating System: ${osInfo}\nKernel: ${kernel}\nArchitecture: ${arch}`;
|
|
104
|
-
} catch (err) {
|
|
105
|
-
return "Could not retrieve OS information.";
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Handle weather or other info if target is provided
|
|
111
|
-
// For now, let's just return a placeholder or handle it if needed
|
|
136
|
+
function getProvider(platform = process.platform) {
|
|
137
|
+
if (platform === 'darwin') return macProvider;
|
|
138
|
+
if (platform === 'win32') return windowsProvider;
|
|
139
|
+
return linuxProvider;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const SystemAutomation = {
|
|
143
|
+
setVolume: (percent) => getProvider().setVolume(percent),
|
|
144
|
+
mute: () => getProvider().mute(),
|
|
145
|
+
setBrightness: (percent) => getProvider().setBrightness(percent),
|
|
146
|
+
sleep: () => getProvider().sleep(),
|
|
147
|
+
restart: () => getProvider().restart(),
|
|
148
|
+
shutdown: () => getProvider().shutdown(),
|
|
149
|
+
minimizeAll: () => getProvider().minimizeAll(),
|
|
150
|
+
async getSystemInfo(target = '') {
|
|
151
|
+
if (!target) return getProvider().getSystemInfo();
|
|
112
152
|
return `System info for ${target} is not yet implemented.`;
|
|
153
|
+
},
|
|
154
|
+
_providers: {
|
|
155
|
+
linux: linuxProvider,
|
|
156
|
+
darwin: macProvider,
|
|
157
|
+
win32: windowsProvider,
|
|
158
|
+
getProvider
|
|
113
159
|
}
|
|
114
160
|
};
|
|
115
161
|
|
|
@@ -1,4 +1,70 @@
|
|
|
1
1
|
const os = require('os');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
|
|
4
|
+
function readFirstExisting(paths) {
|
|
5
|
+
for (const filePath of paths) {
|
|
6
|
+
try {
|
|
7
|
+
const value = fs.readFileSync(filePath, 'utf8').trim();
|
|
8
|
+
if (value && value !== 'None' && value !== 'To be filled by O.E.M.') {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
} catch (_) {}
|
|
12
|
+
}
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getLinuxDistro() {
|
|
17
|
+
try {
|
|
18
|
+
const content = fs.readFileSync('/etc/os-release', 'utf8');
|
|
19
|
+
const values = {};
|
|
20
|
+
content.split('\n').forEach(line => {
|
|
21
|
+
const match = line.match(/^([A-Z_]+)=(.*)$/);
|
|
22
|
+
if (match) {
|
|
23
|
+
values[match[1]] = match[2].replace(/^"|"$/g, '');
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return values.PRETTY_NAME || values.NAME || '';
|
|
27
|
+
} catch (_) {
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getMachineModel() {
|
|
33
|
+
if (os.platform() !== 'linux') {
|
|
34
|
+
return {
|
|
35
|
+
vendor: '',
|
|
36
|
+
product: os.hostname(),
|
|
37
|
+
version: '',
|
|
38
|
+
board: '',
|
|
39
|
+
display: os.hostname()
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const vendor = readFirstExisting([
|
|
44
|
+
'/sys/devices/virtual/dmi/id/sys_vendor',
|
|
45
|
+
'/sys/class/dmi/id/sys_vendor'
|
|
46
|
+
]);
|
|
47
|
+
const product = readFirstExisting([
|
|
48
|
+
'/sys/devices/virtual/dmi/id/product_name',
|
|
49
|
+
'/sys/class/dmi/id/product_name'
|
|
50
|
+
]);
|
|
51
|
+
const version = readFirstExisting([
|
|
52
|
+
'/sys/devices/virtual/dmi/id/product_version',
|
|
53
|
+
'/sys/class/dmi/id/product_version'
|
|
54
|
+
]);
|
|
55
|
+
const board = readFirstExisting([
|
|
56
|
+
'/sys/devices/virtual/dmi/id/board_name',
|
|
57
|
+
'/sys/class/dmi/id/board_name'
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
vendor,
|
|
62
|
+
product,
|
|
63
|
+
version,
|
|
64
|
+
board,
|
|
65
|
+
display: [vendor, product, version].filter(Boolean).join(' ') || board || os.hostname()
|
|
66
|
+
};
|
|
67
|
+
}
|
|
2
68
|
|
|
3
69
|
/**
|
|
4
70
|
* ดึงข้อมูล RAM, CPU, เวลาปัจจุบัน
|
|
@@ -16,9 +82,12 @@ function getSystemInfo() {
|
|
|
16
82
|
const cpuModel = os.cpus()[0]?.model || 'Unknown CPU';
|
|
17
83
|
const cpuCores = os.cpus().length;
|
|
18
84
|
const platform = os.platform();
|
|
85
|
+
const distro = platform === 'linux' ? getLinuxDistro() : '';
|
|
19
86
|
const hostname = os.hostname();
|
|
87
|
+
const machine = getMachineModel();
|
|
20
88
|
|
|
21
89
|
return {
|
|
90
|
+
machine,
|
|
22
91
|
ram: {
|
|
23
92
|
total: (totalRAM / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
24
93
|
used: (usedRAM / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
@@ -32,6 +101,7 @@ function getSystemInfo() {
|
|
|
32
101
|
time: timeStr,
|
|
33
102
|
date: dateStr,
|
|
34
103
|
platform,
|
|
104
|
+
distro,
|
|
35
105
|
hostname
|
|
36
106
|
};
|
|
37
107
|
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
const TOOL_REGISTRY = Object.freeze({
|
|
2
|
+
none: {
|
|
3
|
+
permission: 'safe',
|
|
4
|
+
required: [],
|
|
5
|
+
description: 'No action.'
|
|
6
|
+
},
|
|
7
|
+
web_search: {
|
|
8
|
+
permission: 'safe',
|
|
9
|
+
required: ['query'],
|
|
10
|
+
codeAgentOnly: true,
|
|
11
|
+
description: 'Search the internet when outside knowledge is required.'
|
|
12
|
+
},
|
|
13
|
+
list_files: {
|
|
14
|
+
permission: 'safe',
|
|
15
|
+
required: [],
|
|
16
|
+
codeAgentOnly: true,
|
|
17
|
+
description: 'List files under a workspace-relative path.'
|
|
18
|
+
},
|
|
19
|
+
read_file: {
|
|
20
|
+
permission: 'safe',
|
|
21
|
+
required: ['path'],
|
|
22
|
+
codeAgentOnly: true,
|
|
23
|
+
description: 'Read a workspace file, optionally bounded by startLine/endLine.'
|
|
24
|
+
},
|
|
25
|
+
search_code: {
|
|
26
|
+
permission: 'safe',
|
|
27
|
+
required: ['query'],
|
|
28
|
+
codeAgentOnly: true,
|
|
29
|
+
description: 'Search text in the workspace.'
|
|
30
|
+
},
|
|
31
|
+
find_path: {
|
|
32
|
+
permission: 'safe',
|
|
33
|
+
required: ['query'],
|
|
34
|
+
chatAction: true,
|
|
35
|
+
description: 'Find files or folders by name.'
|
|
36
|
+
},
|
|
37
|
+
run_shell: {
|
|
38
|
+
permission: 'approval',
|
|
39
|
+
required: ['command'],
|
|
40
|
+
codeAgentOnly: true,
|
|
41
|
+
important: true,
|
|
42
|
+
description: 'Run a non-destructive shell command after user approval.'
|
|
43
|
+
},
|
|
44
|
+
apply_patch: {
|
|
45
|
+
permission: 'approval',
|
|
46
|
+
required: ['patch'],
|
|
47
|
+
codeAgentOnly: true,
|
|
48
|
+
important: true,
|
|
49
|
+
description: 'Patch an existing file after user approval.'
|
|
50
|
+
},
|
|
51
|
+
write_file: {
|
|
52
|
+
permission: 'approval',
|
|
53
|
+
required: ['path', 'content'],
|
|
54
|
+
codeAgentOnly: true,
|
|
55
|
+
important: true,
|
|
56
|
+
description: 'Create or replace a file after user approval.'
|
|
57
|
+
},
|
|
58
|
+
ask_user: {
|
|
59
|
+
permission: 'safe',
|
|
60
|
+
required: ['question'],
|
|
61
|
+
codeAgentOnly: true,
|
|
62
|
+
description: 'Ask the user for clarification.'
|
|
63
|
+
},
|
|
64
|
+
open_url: {
|
|
65
|
+
permission: 'safe',
|
|
66
|
+
required: ['target'],
|
|
67
|
+
chatAction: true,
|
|
68
|
+
description: 'Open a URL.'
|
|
69
|
+
},
|
|
70
|
+
search: {
|
|
71
|
+
permission: 'safe',
|
|
72
|
+
required: ['target'],
|
|
73
|
+
chatAction: true,
|
|
74
|
+
description: 'Open a web search.'
|
|
75
|
+
},
|
|
76
|
+
open_app: {
|
|
77
|
+
permission: 'safe',
|
|
78
|
+
required: ['target'],
|
|
79
|
+
chatAction: true,
|
|
80
|
+
description: 'Open a local application.'
|
|
81
|
+
},
|
|
82
|
+
web_automation: {
|
|
83
|
+
permission: 'safe',
|
|
84
|
+
required: ['target'],
|
|
85
|
+
chatAction: true,
|
|
86
|
+
important: true,
|
|
87
|
+
description: 'Perform browser automation.'
|
|
88
|
+
},
|
|
89
|
+
create_folder: {
|
|
90
|
+
permission: 'safe',
|
|
91
|
+
required: ['target'],
|
|
92
|
+
chatAction: true,
|
|
93
|
+
description: 'Create a folder.'
|
|
94
|
+
},
|
|
95
|
+
open_file: {
|
|
96
|
+
permission: 'safe',
|
|
97
|
+
required: ['target'],
|
|
98
|
+
chatAction: true,
|
|
99
|
+
description: 'Open a local file.'
|
|
100
|
+
},
|
|
101
|
+
open_folder: {
|
|
102
|
+
permission: 'safe',
|
|
103
|
+
required: ['target'],
|
|
104
|
+
chatAction: true,
|
|
105
|
+
description: 'Open a local folder.'
|
|
106
|
+
},
|
|
107
|
+
delete_file: {
|
|
108
|
+
permission: 'dangerous',
|
|
109
|
+
required: ['target'],
|
|
110
|
+
chatAction: true,
|
|
111
|
+
important: true,
|
|
112
|
+
description: 'Delete a file only after explicit dangerous-action permission.'
|
|
113
|
+
},
|
|
114
|
+
clipboard_write: {
|
|
115
|
+
permission: 'safe',
|
|
116
|
+
required: ['target'],
|
|
117
|
+
chatAction: true,
|
|
118
|
+
description: 'Write text to clipboard.'
|
|
119
|
+
},
|
|
120
|
+
learn_file: {
|
|
121
|
+
permission: 'safe',
|
|
122
|
+
required: ['target'],
|
|
123
|
+
chatAction: true,
|
|
124
|
+
description: 'Index a file into the knowledge base.'
|
|
125
|
+
},
|
|
126
|
+
learn_folder: {
|
|
127
|
+
permission: 'safe',
|
|
128
|
+
required: ['target'],
|
|
129
|
+
chatAction: true,
|
|
130
|
+
description: 'Index a folder into the knowledge base.'
|
|
131
|
+
},
|
|
132
|
+
system_info: {
|
|
133
|
+
permission: 'safe',
|
|
134
|
+
required: [],
|
|
135
|
+
chatAction: true,
|
|
136
|
+
description: 'Read local system info, or weather when target is a city.'
|
|
137
|
+
},
|
|
138
|
+
plugin: {
|
|
139
|
+
permission: 'safe',
|
|
140
|
+
required: ['pluginName', 'target'],
|
|
141
|
+
chatAction: true,
|
|
142
|
+
description: 'Run a Mint plugin.'
|
|
143
|
+
},
|
|
144
|
+
mcp_tool: {
|
|
145
|
+
permission: 'safe',
|
|
146
|
+
required: ['server', 'target'],
|
|
147
|
+
chatAction: true,
|
|
148
|
+
description: 'Call an MCP tool.'
|
|
149
|
+
},
|
|
150
|
+
mouse_click: {
|
|
151
|
+
permission: 'safe',
|
|
152
|
+
required: ['x', 'y'],
|
|
153
|
+
chatAction: true,
|
|
154
|
+
important: true,
|
|
155
|
+
description: 'Click at screen coordinates.'
|
|
156
|
+
},
|
|
157
|
+
mouse_move: {
|
|
158
|
+
permission: 'safe',
|
|
159
|
+
required: ['x', 'y'],
|
|
160
|
+
chatAction: true,
|
|
161
|
+
description: 'Move the mouse.'
|
|
162
|
+
},
|
|
163
|
+
type_text: {
|
|
164
|
+
permission: 'safe',
|
|
165
|
+
required: ['target'],
|
|
166
|
+
chatAction: true,
|
|
167
|
+
important: true,
|
|
168
|
+
description: 'Type text into the active UI.'
|
|
169
|
+
},
|
|
170
|
+
key_tap: {
|
|
171
|
+
permission: 'safe',
|
|
172
|
+
required: ['target'],
|
|
173
|
+
chatAction: true,
|
|
174
|
+
important: true,
|
|
175
|
+
description: 'Press a key.'
|
|
176
|
+
},
|
|
177
|
+
system_automation: {
|
|
178
|
+
permission: 'approval',
|
|
179
|
+
required: ['target'],
|
|
180
|
+
chatAction: true,
|
|
181
|
+
important: true,
|
|
182
|
+
description: 'Change system settings after approval.'
|
|
183
|
+
},
|
|
184
|
+
finish: {
|
|
185
|
+
permission: 'safe',
|
|
186
|
+
required: ['summary'],
|
|
187
|
+
codeAgentOnly: true,
|
|
188
|
+
description: 'Finish the task and reply.'
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
function getTool(name) {
|
|
193
|
+
return TOOL_REGISTRY[name] || null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function listToolNames(filter = {}) {
|
|
197
|
+
return Object.entries(TOOL_REGISTRY)
|
|
198
|
+
.filter(([, tool]) => {
|
|
199
|
+
if (filter.chatAction === true && tool.chatAction !== true) return false;
|
|
200
|
+
if (filter.codeAgent === true && tool.chatAction === true && tool.codeAgentOnly !== true) return true;
|
|
201
|
+
return true;
|
|
202
|
+
})
|
|
203
|
+
.map(([name]) => name);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function listChatActionNames() {
|
|
207
|
+
return Object.entries(TOOL_REGISTRY)
|
|
208
|
+
.filter(([, tool]) => tool.chatAction === true)
|
|
209
|
+
.map(([name]) => name);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function listCodeAgentActionNames() {
|
|
213
|
+
return Object.entries(TOOL_REGISTRY)
|
|
214
|
+
.filter(([, tool]) => tool.codeAgentOnly === true || tool.chatAction === true || tool.required)
|
|
215
|
+
.map(([name]) => name);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function isEmptyToolValue(value) {
|
|
219
|
+
if (value === undefined || value === null) return true;
|
|
220
|
+
if (typeof value === 'string') return value.trim() === '';
|
|
221
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
222
|
+
if (typeof value === 'object') return Object.keys(value).length === 0;
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function validateToolInput(action, input = {}) {
|
|
227
|
+
const tool = getTool(action);
|
|
228
|
+
if (!tool) {
|
|
229
|
+
throw new Error(`Unsupported action: ${action}`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const missing = (tool.required || []).filter(field => {
|
|
233
|
+
if (!isEmptyToolValue(input[field])) return false;
|
|
234
|
+
if (field === 'target' && (!isEmptyToolValue(input.path) || !isEmptyToolValue(input.query))) return false;
|
|
235
|
+
if (field === 'query' && !isEmptyToolValue(input.target)) return false;
|
|
236
|
+
return true;
|
|
237
|
+
});
|
|
238
|
+
if (missing.length > 0) {
|
|
239
|
+
throw new Error(`Action "${action}" is missing required input field(s): ${missing.join(', ')}`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (action === 'apply_patch') {
|
|
243
|
+
const patchInput = input.patch || {};
|
|
244
|
+
if (!patchInput.path || !Array.isArray(patchInput.hunks) || patchInput.hunks.length === 0) {
|
|
245
|
+
throw new Error('Action "apply_patch" requires input.patch.path and at least one hunk.');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return tool;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function isImportantAction(action) {
|
|
253
|
+
const tool = getTool(action);
|
|
254
|
+
return !!(tool && tool.important);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function buildChatActionTypeUnion() {
|
|
258
|
+
return ['none', ...listChatActionNames()].filter((name, index, arr) => arr.indexOf(name) === index).map(name => `"${name}"`).join(' | ');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function buildToolPromptSection() {
|
|
262
|
+
const lines = ['\n\nAVAILABLE BUILT-IN ACTIONS:'];
|
|
263
|
+
for (const name of listChatActionNames()) {
|
|
264
|
+
const tool = getTool(name);
|
|
265
|
+
lines.push(`- ${name}: ${tool.description}`);
|
|
266
|
+
}
|
|
267
|
+
return lines.join('\n');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
module.exports = {
|
|
271
|
+
TOOL_REGISTRY,
|
|
272
|
+
getTool,
|
|
273
|
+
listToolNames,
|
|
274
|
+
listChatActionNames,
|
|
275
|
+
listCodeAgentActionNames,
|
|
276
|
+
validateToolInput,
|
|
277
|
+
isImportantAction,
|
|
278
|
+
buildChatActionTypeUnion,
|
|
279
|
+
buildToolPromptSection
|
|
280
|
+
};
|
|
@@ -10,8 +10,10 @@ function createWindowManager(projectRoot) {
|
|
|
10
10
|
|
|
11
11
|
function createMainWindow() {
|
|
12
12
|
mainWindow = new BrowserWindow({
|
|
13
|
-
width:
|
|
14
|
-
height:
|
|
13
|
+
width: 1180,
|
|
14
|
+
height: 860,
|
|
15
|
+
minWidth: 900,
|
|
16
|
+
minHeight: 680,
|
|
15
17
|
icon: path.join(projectRoot, 'assets', 'icon.png'),
|
|
16
18
|
webPreferences: {
|
|
17
19
|
preload: path.join(projectRoot, 'preload.js'),
|