@pheem49/mint 1.5.5 → 1.6.1
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/.codex +0 -0
- package/.github/FUNDING.yml +2 -0
- package/.github/workflows/ci.yml +45 -0
- package/.github/workflows/release.yml +79 -0
- package/Cargo.lock +5792 -0
- package/Cargo.toml +32 -0
- package/README.md +387 -353
- package/assets/icon.png +0 -0
- package/bin/mint +0 -0
- package/crates/mint-cli/Cargo.toml +23 -0
- package/crates/mint-cli/src/agent.rs +851 -0
- package/crates/mint-cli/src/gmail.rs +216 -0
- package/crates/mint-cli/src/image.rs +142 -0
- package/crates/mint-cli/src/main.rs +2837 -0
- package/crates/mint-cli/src/mcp.rs +63 -0
- package/crates/mint-cli/src/onboard.rs +1149 -0
- package/crates/mint-cli/src/setup.rs +390 -0
- package/crates/mint-cli/src/skills.rs +8 -0
- package/crates/mint-cli/src/updater.rs +279 -0
- package/crates/mint-core/Cargo.toml +22 -0
- package/crates/mint-core/src/agent_loop.rs +94 -0
- package/crates/mint-core/src/api_server.rs +991 -0
- package/crates/mint-core/src/channels.rs +248 -0
- package/crates/mint-core/src/chat.rs +895 -0
- package/crates/mint-core/src/code_tools.rs +729 -0
- package/crates/mint-core/src/config.rs +368 -0
- package/crates/mint-core/src/files.rs +159 -0
- package/crates/mint-core/src/knowledge.rs +541 -0
- package/crates/mint-core/src/lib.rs +84 -0
- package/crates/mint-core/src/mcp.rs +273 -0
- package/crates/mint-core/src/memory.rs +673 -0
- package/crates/mint-core/src/orchestration.rs +2157 -0
- package/crates/mint-core/src/pictures.rs +314 -0
- package/crates/mint-core/src/plugins.rs +727 -0
- package/crates/mint-core/src/safety.rs +416 -0
- package/crates/mint-core/src/semantic.rs +254 -0
- package/crates/mint-core/src/shell.rs +317 -0
- package/crates/mint-core/src/skills.rs +71 -0
- package/crates/mint-core/src/symbols.rs +157 -0
- package/crates/mint-core/src/tasks.rs +308 -0
- package/crates/mint-core/src/tts.rs +92 -0
- package/crates/mint-core/src/weather.rs +93 -0
- package/crates/mint-core/src/web_search.rs +200 -0
- package/crates/mint-core/src/workflows.rs +81 -0
- package/crates/mint-core/tests/mcp_stdio.rs +45 -0
- package/crates/mint-core/tests/memory_persistence.rs +172 -0
- package/crates/mint-core/tests/pictures_storage.rs +14 -0
- package/crates/mint-core/tests/task_lifecycle.rs +87 -0
- package/package.json +35 -99
- package/src/bin/index.js +16 -0
- package/src/renderer/index-web.html +17 -0
- package/src/renderer/index.html +17 -0
- package/src/renderer/public/Live2DCubismCore.js +9 -0
- package/src/renderer/public/assets/icon.png +0 -0
- package/src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.model3.json +36 -0
- package/src/renderer/src/App.tsx +33 -0
- package/src/renderer/src/calculator.ts +47 -0
- package/src/renderer/src/components/ChatPanel.tsx +1598 -0
- package/src/renderer/src/components/DashboardSidebar.tsx +358 -0
- package/src/renderer/src/components/Live2DStage.tsx +374 -0
- package/src/renderer/src/components/MintDashboard.tsx +950 -0
- package/src/renderer/src/components/ModelPanel.tsx +154 -0
- package/src/renderer/src/components/PicturesLibrary.tsx +46 -0
- package/src/renderer/src/components/ProactiveGlow.tsx +19 -0
- package/src/renderer/src/components/ScreenPicker.tsx +579 -0
- package/src/renderer/src/components/SettingsWindow.tsx +1467 -0
- package/src/renderer/src/components/SpotlightWindow.tsx +280 -0
- package/src/renderer/src/components/WidgetWindow.tsx +36 -0
- package/src/renderer/src/components/WorkspacePanel.tsx +268 -0
- package/src/{UI → renderer/src/css}/settings.css +69 -16
- package/src/renderer/src/css/spotlight.css +113 -0
- package/src/renderer/src/css/styles.css +3722 -0
- package/src/renderer/src/css/widget.css +185 -0
- package/src/renderer/src/env.d.ts +116 -0
- package/src/renderer/src/index.css +379 -0
- package/src/renderer/src/main.tsx +13 -0
- package/src/renderer/src/tauri.ts +996 -0
- package/src/renderer/src-web/App.tsx +25 -0
- package/src/renderer/src-web/calculator.ts +47 -0
- package/src/renderer/src-web/components/ChatPanel.tsx +1662 -0
- package/src/renderer/src-web/components/DashboardSidebar.tsx +242 -0
- package/src/renderer/src-web/components/MintDashboard.tsx +763 -0
- package/src/renderer/src-web/components/PicturesLibrary.tsx +73 -0
- package/src/renderer/src-web/components/SettingsWindow.tsx +1500 -0
- package/src/renderer/src-web/css/settings.css +1100 -0
- package/src/{UI → renderer/src-web/css}/spotlight.css +4 -4
- package/src/{UI → renderer/src-web/css}/styles.css +1055 -159
- package/src/{UI → renderer/src-web/css}/widget.css +2 -2
- package/src/renderer/src-web/env.d.ts +107 -0
- package/src/renderer/src-web/index.css +379 -0
- package/src/renderer/src-web/main.tsx +13 -0
- package/src/renderer/src-web/tauri.ts +983 -0
- package/tsconfig.json +30 -0
- package/vite.config.ts +33 -0
- package/vite.config.web.ts +51 -0
- package/GUIDE_TH.md +0 -125
- package/assets/Agent_Mint.png +0 -0
- package/assets/CLI_Screen.png +0 -0
- package/assets/Settings.png +0 -0
- package/benchmark_ai.js +0 -71
- package/install.ps1 +0 -64
- package/install.sh +0 -54
- package/main.js +0 -139
- package/mint-cli-logic.js +0 -3
- package/mint-cli.js +0 -410
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.model3.json +0 -47
- 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 +0 -23
- package/preload-picker.js +0 -11
- package/preload-settings.js +0 -11
- package/preload.js +0 -41
- package/scripts/install_linux_desktop_entry.js +0 -48
- package/src/AI_Brain/Gemini_API.js +0 -813
- package/src/AI_Brain/agent_orchestrator.js +0 -73
- package/src/AI_Brain/autonomous_brain.js +0 -179
- package/src/AI_Brain/behavior_memory.js +0 -135
- package/src/AI_Brain/headless_agent.js +0 -143
- package/src/AI_Brain/knowledge_base.js +0 -349
- package/src/AI_Brain/memory_store.js +0 -662
- package/src/AI_Brain/proactive_engine.js +0 -172
- package/src/AI_Brain/provider_adapter.js +0 -365
- package/src/Automation_Layer/browser_automation.js +0 -149
- package/src/Automation_Layer/file_operations.js +0 -286
- package/src/Automation_Layer/open_app.js +0 -85
- package/src/Automation_Layer/open_website.js +0 -38
- package/src/CLI/approval_handler.js +0 -47
- package/src/CLI/chat_router.js +0 -247
- package/src/CLI/chat_ui.js +0 -1159
- package/src/CLI/cli_colors.js +0 -115
- package/src/CLI/cli_formatters.js +0 -94
- package/src/CLI/code_agent.js +0 -1667
- package/src/CLI/code_session_memory.js +0 -62
- package/src/CLI/gmail_auth.js +0 -210
- package/src/CLI/image_input.js +0 -90
- package/src/CLI/intent_detectors.js +0 -181
- package/src/CLI/interactive_chat.js +0 -658
- package/src/CLI/list_features.js +0 -64
- package/src/CLI/onboarding.js +0 -416
- package/src/CLI/repo_summarizer.js +0 -282
- package/src/CLI/semantic_code_search.js +0 -312
- package/src/CLI/skill_manager.js +0 -41
- package/src/CLI/slash_command_handler.js +0 -418
- package/src/CLI/symbol_indexer.js +0 -231
- package/src/CLI/updater.js +0 -230
- package/src/CLI/workspace_manager.js +0 -90
- package/src/Channels/brave_search_bridge.js +0 -35
- package/src/Channels/discord_bridge.js +0 -66
- package/src/Channels/google_search_bridge.js +0 -38
- package/src/Channels/line_bridge.js +0 -60
- package/src/Channels/slack_bridge.js +0 -48
- package/src/Channels/telegram_bridge.js +0 -41
- package/src/Channels/whatsapp_bridge.js +0 -57
- package/src/Command_Parser/parser.js +0 -45
- package/src/Plugins/dev_tools.js +0 -41
- package/src/Plugins/discord.js +0 -20
- package/src/Plugins/docker.js +0 -47
- package/src/Plugins/gmail.js +0 -251
- package/src/Plugins/google_calendar.js +0 -252
- package/src/Plugins/mcp_manager.js +0 -95
- package/src/Plugins/notion.js +0 -256
- package/src/Plugins/obsidian.js +0 -54
- package/src/Plugins/plugin_manager.js +0 -81
- package/src/Plugins/spotify.js +0 -173
- package/src/Plugins/system_metrics.js +0 -31
- package/src/Plugins/system_monitor.js +0 -72
- package/src/System/action_executor.js +0 -178
- package/src/System/bridge_manager.js +0 -76
- package/src/System/chat_history_manager.js +0 -83
- package/src/System/config_manager.js +0 -194
- package/src/System/custom_workflows.js +0 -163
- package/src/System/daemon_manager.js +0 -67
- package/src/System/google_tts_urls.js +0 -51
- package/src/System/granular_automation.js +0 -157
- package/src/System/ipc_handlers.js +0 -332
- package/src/System/notifications.js +0 -23
- package/src/System/optional_require.js +0 -23
- package/src/System/picture_store.js +0 -109
- package/src/System/proactive_loop.js +0 -153
- package/src/System/safety_manager.js +0 -273
- package/src/System/sandbox_runner.js +0 -182
- package/src/System/screen_capture.js +0 -175
- package/src/System/smart_context.js +0 -227
- package/src/System/system_automation.js +0 -162
- package/src/System/system_events.js +0 -79
- package/src/System/system_info.js +0 -125
- package/src/System/task_manager.js +0 -222
- package/src/System/tool_registry.js +0 -293
- package/src/System/window_manager.js +0 -220
- package/src/UI/floating.css +0 -80
- package/src/UI/floating.html +0 -17
- package/src/UI/floating.js +0 -67
- package/src/UI/live2d_manager.js +0 -600
- package/src/UI/preload-floating.js +0 -7
- package/src/UI/preload-spotlight.js +0 -11
- package/src/UI/preload-widget.js +0 -5
- package/src/UI/proactive-glow.html +0 -42
- package/src/UI/renderer.js +0 -2127
- package/src/UI/screenPicker.html +0 -214
- package/src/UI/screenPicker.js +0 -262
- package/src/UI/settings.html +0 -577
- package/src/UI/settings.js +0 -770
- package/src/UI/spotlight.html +0 -23
- package/src/UI/spotlight.js +0 -185
- package/src/UI/widget.html +0 -29
- package/src/UI/widget.js +0 -10
- /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/72d86db84cfa9730b894c241fd24c0db.png +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/233/264/350/243/231.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/apron.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/214/253/345/222/252/346/273/244/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/catfilter.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/click.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazed.exp3.json} +0 -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" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazedeyes.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/234/274/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/glasses.exp3.json} +0 -0
- /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/items_pinned_to_model.json +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/277/347/254/224.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/pen.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/215/347/205/247.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/photo.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_00.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_00.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_01.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_01.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_02.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_02.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_03.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_03.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.cdi3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.cdi3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.moc3" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.moc3} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.physics3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.physics3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.vtube.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.vtube.json} +0 -0
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
const { execFile } = require('child_process');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
|
|
4
|
-
const MAX_TEXT_LENGTH = 2000;
|
|
5
|
-
const BROWSER_NAMES = [
|
|
6
|
-
'chrome',
|
|
7
|
-
'chromium',
|
|
8
|
-
'brave',
|
|
9
|
-
'firefox',
|
|
10
|
-
'edge',
|
|
11
|
-
'safari',
|
|
12
|
-
'opera',
|
|
13
|
-
'vivaldi'
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
function run(command, args = [], options = {}) {
|
|
17
|
-
return new Promise((resolve) => {
|
|
18
|
-
execFile(command, args, { timeout: options.timeout || 1200 }, (error, stdout) => {
|
|
19
|
-
if (error) {
|
|
20
|
-
resolve(null);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
resolve(String(stdout || '').trim() || null);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function truncateText(value, maxLength = MAX_TEXT_LENGTH) {
|
|
29
|
-
const text = String(value || '').replace(/\0/g, '').trim();
|
|
30
|
-
if (text.length <= maxLength) return text;
|
|
31
|
-
return `${text.slice(0, maxLength)}\n[truncated ${text.length - maxLength} chars]`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function normalizeProcessName(value) {
|
|
35
|
-
return String(value || '').trim().replace(/\.exe$/i, '');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function isBrowserProcess(name = '') {
|
|
39
|
-
const normalized = normalizeProcessName(name).toLowerCase();
|
|
40
|
-
return BROWSER_NAMES.some(browser => normalized.includes(browser));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function getLinuxActiveWindow() {
|
|
44
|
-
const windowId = await run('xdotool', ['getactivewindow']);
|
|
45
|
-
if (!windowId) return null;
|
|
46
|
-
|
|
47
|
-
const [title, pid] = await Promise.all([
|
|
48
|
-
run('xdotool', ['getwindowname', windowId]),
|
|
49
|
-
run('xdotool', ['getwindowpid', windowId])
|
|
50
|
-
]);
|
|
51
|
-
|
|
52
|
-
let processName = '';
|
|
53
|
-
if (pid) {
|
|
54
|
-
processName = await run('ps', ['-p', pid, '-o', 'comm=']) || '';
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
id: windowId,
|
|
59
|
-
title: title || '',
|
|
60
|
-
appName: normalizeProcessName(processName),
|
|
61
|
-
processName: normalizeProcessName(processName),
|
|
62
|
-
pid: pid ? Number(pid) : null,
|
|
63
|
-
platform: 'linux'
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async function getMacActiveWindow() {
|
|
68
|
-
const script = [
|
|
69
|
-
'tell application "System Events"',
|
|
70
|
-
'set frontApp to first application process whose frontmost is true',
|
|
71
|
-
'set appName to name of frontApp',
|
|
72
|
-
'set windowTitle to ""',
|
|
73
|
-
'try',
|
|
74
|
-
'set windowTitle to name of front window of frontApp',
|
|
75
|
-
'end try',
|
|
76
|
-
'return appName & linefeed & windowTitle',
|
|
77
|
-
'end tell'
|
|
78
|
-
].join('\n');
|
|
79
|
-
const output = await run('osascript', ['-e', script]);
|
|
80
|
-
if (!output) return null;
|
|
81
|
-
const [appName = '', title = ''] = output.split(/\r?\n/);
|
|
82
|
-
return {
|
|
83
|
-
title,
|
|
84
|
-
appName,
|
|
85
|
-
processName: appName,
|
|
86
|
-
pid: null,
|
|
87
|
-
platform: 'darwin'
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function getWindowsActiveWindow() {
|
|
92
|
-
const script = [
|
|
93
|
-
'Add-Type @\'',
|
|
94
|
-
'using System;',
|
|
95
|
-
'using System.Runtime.InteropServices;',
|
|
96
|
-
'using System.Text;',
|
|
97
|
-
'public class Win {',
|
|
98
|
-
'[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();',
|
|
99
|
-
'[DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);',
|
|
100
|
-
'[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);',
|
|
101
|
-
'}',
|
|
102
|
-
'\'@',
|
|
103
|
-
'$hwnd = [Win]::GetForegroundWindow()',
|
|
104
|
-
'$builder = New-Object System.Text.StringBuilder 1024',
|
|
105
|
-
'[void][Win]::GetWindowText($hwnd, $builder, $builder.Capacity)',
|
|
106
|
-
'$pid = 0',
|
|
107
|
-
'[void][Win]::GetWindowThreadProcessId($hwnd, [ref]$pid)',
|
|
108
|
-
'$proc = Get-Process -Id $pid -ErrorAction SilentlyContinue',
|
|
109
|
-
'[PSCustomObject]@{ title = $builder.ToString(); appName = $proc.ProcessName; pid = $pid } | ConvertTo-Json -Compress'
|
|
110
|
-
].join('\n');
|
|
111
|
-
const output = await run('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], { timeout: 1800 });
|
|
112
|
-
if (!output) return null;
|
|
113
|
-
try {
|
|
114
|
-
const parsed = JSON.parse(output);
|
|
115
|
-
return {
|
|
116
|
-
title: parsed.title || '',
|
|
117
|
-
appName: normalizeProcessName(parsed.appName),
|
|
118
|
-
processName: normalizeProcessName(parsed.appName),
|
|
119
|
-
pid: parsed.pid ? Number(parsed.pid) : null,
|
|
120
|
-
platform: 'win32'
|
|
121
|
-
};
|
|
122
|
-
} catch (_) {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function getActiveWindowContext(platform = process.platform) {
|
|
128
|
-
try {
|
|
129
|
-
if (platform === 'darwin') return await getMacActiveWindow();
|
|
130
|
-
if (platform === 'win32') return await getWindowsActiveWindow();
|
|
131
|
-
return await getLinuxActiveWindow();
|
|
132
|
-
} catch (_) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function getLinuxSelectedText() {
|
|
138
|
-
const attempts = [
|
|
139
|
-
['wl-paste', ['--primary', '--no-newline']],
|
|
140
|
-
['xclip', ['-selection', 'primary', '-out']],
|
|
141
|
-
['xsel', ['--primary', '--output']]
|
|
142
|
-
];
|
|
143
|
-
|
|
144
|
-
for (const [command, args] of attempts) {
|
|
145
|
-
const text = await run(command, args);
|
|
146
|
-
if (text) return truncateText(text);
|
|
147
|
-
}
|
|
148
|
-
return '';
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async function getSelectedText(platform = process.platform) {
|
|
152
|
-
if (platform === 'linux') return getLinuxSelectedText();
|
|
153
|
-
return '';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function getMacBrowserContext(appName) {
|
|
157
|
-
const normalized = String(appName || '').toLowerCase();
|
|
158
|
-
let script = '';
|
|
159
|
-
if (normalized.includes('safari')) {
|
|
160
|
-
script = 'tell application "Safari" to return name of front document & linefeed & URL of front document';
|
|
161
|
-
} else if (normalized.includes('chrome') || normalized.includes('chromium') || normalized.includes('brave') || normalized.includes('edge')) {
|
|
162
|
-
script = `tell application "${appName}" to return title of active tab of front window & linefeed & URL of active tab of front window`;
|
|
163
|
-
}
|
|
164
|
-
if (!script) return null;
|
|
165
|
-
const output = await run('osascript', ['-e', script], { timeout: 1500 });
|
|
166
|
-
if (!output) return null;
|
|
167
|
-
const [title = '', url = ''] = output.split(/\r?\n/);
|
|
168
|
-
return { title, url };
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async function getBrowserContext(activeWindow, platform = process.platform) {
|
|
172
|
-
if (!activeWindow || !isBrowserProcess(activeWindow.appName || activeWindow.processName)) {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
if (platform === 'darwin') {
|
|
176
|
-
const browser = await getMacBrowserContext(activeWindow.appName);
|
|
177
|
-
if (browser) return browser;
|
|
178
|
-
}
|
|
179
|
-
return {
|
|
180
|
-
title: activeWindow.title || '',
|
|
181
|
-
url: '',
|
|
182
|
-
urlUnavailableReason: 'Browser URL is not available from the current OS context without browser integration.'
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async function getSmartContext(options = {}) {
|
|
187
|
-
const platform = options.platform || process.platform;
|
|
188
|
-
const clipboard = options.clipboard || null;
|
|
189
|
-
const [activeWindow, selectedText] = await Promise.all([
|
|
190
|
-
getActiveWindowContext(platform),
|
|
191
|
-
getSelectedText(platform)
|
|
192
|
-
]);
|
|
193
|
-
|
|
194
|
-
let clipboardText = '';
|
|
195
|
-
try {
|
|
196
|
-
clipboardText = clipboard && typeof clipboard.readText === 'function'
|
|
197
|
-
? truncateText(clipboard.readText())
|
|
198
|
-
: '';
|
|
199
|
-
} catch (_) {
|
|
200
|
-
clipboardText = '';
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const browser = await getBrowserContext(activeWindow, platform);
|
|
204
|
-
return {
|
|
205
|
-
capturedAt: new Date().toISOString(),
|
|
206
|
-
platform,
|
|
207
|
-
host: os.hostname(),
|
|
208
|
-
activeWindow,
|
|
209
|
-
currentApp: activeWindow ? {
|
|
210
|
-
name: activeWindow.appName || activeWindow.processName || '',
|
|
211
|
-
processName: activeWindow.processName || activeWindow.appName || '',
|
|
212
|
-
pid: activeWindow.pid || null
|
|
213
|
-
} : null,
|
|
214
|
-
browser,
|
|
215
|
-
selectedText,
|
|
216
|
-
clipboardText
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
module.exports = {
|
|
221
|
-
getSmartContext,
|
|
222
|
-
getActiveWindowContext,
|
|
223
|
-
getBrowserContext,
|
|
224
|
-
getSelectedText,
|
|
225
|
-
truncateText,
|
|
226
|
-
isBrowserProcess
|
|
227
|
-
};
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
const { execFile } = require('child_process');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
|
|
4
|
-
function execPromise(command, args = []) {
|
|
5
|
-
return new Promise((resolve, reject) => {
|
|
6
|
-
execFile(command, args, (error, stdout, stderr) => {
|
|
7
|
-
if (error) {
|
|
8
|
-
error.stderr = stderr;
|
|
9
|
-
reject(error);
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
resolve(String(stdout || '').trim());
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
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 = {
|
|
28
|
-
async setVolume(percent) {
|
|
29
|
-
const value = clampPercent(percent);
|
|
30
|
-
try {
|
|
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}%`;
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
async mute() {
|
|
39
|
-
try {
|
|
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
|
-
}
|
|
46
|
-
},
|
|
47
|
-
async setBrightness(percent) {
|
|
48
|
-
const value = clampPercent(percent);
|
|
49
|
-
try {
|
|
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}%`;
|
|
55
|
-
}
|
|
56
|
-
},
|
|
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';
|
|
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
|
-
};
|
|
79
|
-
|
|
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}%`;
|
|
85
|
-
},
|
|
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';
|
|
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
|
-
};
|
|
106
|
-
|
|
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']),
|
|
114
|
-
async minimizeAll() {
|
|
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';
|
|
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
|
-
};
|
|
135
|
-
|
|
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();
|
|
152
|
-
return `System info for ${target} is not yet implemented.`;
|
|
153
|
-
},
|
|
154
|
-
_providers: {
|
|
155
|
-
linux: linuxProvider,
|
|
156
|
-
darwin: macProvider,
|
|
157
|
-
win32: windowsProvider,
|
|
158
|
-
getProvider
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
module.exports = SystemAutomation;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
const { exec } = require('child_process');
|
|
2
|
-
const EventEmitter = require('events');
|
|
3
|
-
|
|
4
|
-
class SystemEvents extends EventEmitter {
|
|
5
|
-
constructor() {
|
|
6
|
-
super();
|
|
7
|
-
this.lastBatteryLevel = null;
|
|
8
|
-
this.lastConnectionStatus = null;
|
|
9
|
-
this.checkInterval = 60000; // 1 minute
|
|
10
|
-
this.isMonitoring = false;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
startMonitoring() {
|
|
14
|
-
if (this.isMonitoring) return;
|
|
15
|
-
this.isMonitoring = true;
|
|
16
|
-
this.check();
|
|
17
|
-
this.timer = setInterval(() => this.check(), this.checkInterval);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
stopMonitoring() {
|
|
21
|
-
if (this.timer) clearInterval(this.timer);
|
|
22
|
-
this.isMonitoring = false;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async check() {
|
|
26
|
-
await this.checkBattery();
|
|
27
|
-
await this.checkNetwork();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async checkBattery() {
|
|
31
|
-
try {
|
|
32
|
-
// Linux: upower -i $(upower -e | grep 'BAT') | grep -E "percentage"
|
|
33
|
-
const cmd = "upower -i $(upower -e | grep 'BAT') | grep -E 'percentage' | awk '{print $2}' | tr -d '%'";
|
|
34
|
-
const output = await this.execPromise(cmd);
|
|
35
|
-
const level = parseInt(output);
|
|
36
|
-
|
|
37
|
-
if (isNaN(level)) return;
|
|
38
|
-
|
|
39
|
-
// Notify if battery is low (below 20%) and has dropped
|
|
40
|
-
if (level <= 20 && (this.lastBatteryLevel === null || this.lastBatteryLevel > 20)) {
|
|
41
|
-
this.emit('low-battery', level);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
this.lastBatteryLevel = level;
|
|
45
|
-
} catch (err) {
|
|
46
|
-
// Ignore if upower fails (e.g. desktop)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async checkNetwork() {
|
|
51
|
-
try {
|
|
52
|
-
// Check internet connection
|
|
53
|
-
const online = await this.execPromise("ping -c 1 8.8.8.8 > /dev/null && echo 'online' || echo 'offline'");
|
|
54
|
-
const isOnline = online === 'online';
|
|
55
|
-
|
|
56
|
-
if (this.lastConnectionStatus !== null && this.lastConnectionStatus !== isOnline) {
|
|
57
|
-
this.emit('connection-change', isOnline);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
this.lastConnectionStatus = isOnline;
|
|
61
|
-
} catch (err) {
|
|
62
|
-
// Ignore ping errors
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
execPromise(command) {
|
|
67
|
-
return new Promise((resolve) => {
|
|
68
|
-
exec(command, (error, stdout) => {
|
|
69
|
-
if (error) {
|
|
70
|
-
resolve('');
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
resolve(stdout.trim());
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
module.exports = new SystemEvents();
|
|
@@ -1,125 +0,0 @@
|
|
|
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
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* ดึงข้อมูล RAM, CPU, เวลาปัจจุบัน
|
|
71
|
-
*/
|
|
72
|
-
function getSystemInfo() {
|
|
73
|
-
const totalRAM = os.totalmem();
|
|
74
|
-
const freeRAM = os.freemem();
|
|
75
|
-
const usedRAM = totalRAM - freeRAM;
|
|
76
|
-
const ramPercent = ((usedRAM / totalRAM) * 100).toFixed(1);
|
|
77
|
-
|
|
78
|
-
const now = new Date();
|
|
79
|
-
const timeStr = now.toLocaleTimeString('th-TH', { hour: '2-digit', minute: '2-digit' });
|
|
80
|
-
const dateStr = now.toLocaleDateString('th-TH', { year: 'numeric', month: 'long', day: 'numeric' });
|
|
81
|
-
|
|
82
|
-
const cpuModel = os.cpus()[0]?.model || 'Unknown CPU';
|
|
83
|
-
const cpuCores = os.cpus().length;
|
|
84
|
-
const platform = os.platform();
|
|
85
|
-
const distro = platform === 'linux' ? getLinuxDistro() : '';
|
|
86
|
-
const hostname = os.hostname();
|
|
87
|
-
const machine = getMachineModel();
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
machine,
|
|
91
|
-
ram: {
|
|
92
|
-
total: (totalRAM / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
93
|
-
used: (usedRAM / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
94
|
-
free: (freeRAM / 1024 / 1024 / 1024).toFixed(2) + ' GB',
|
|
95
|
-
percent: ramPercent + '%'
|
|
96
|
-
},
|
|
97
|
-
cpu: {
|
|
98
|
-
model: cpuModel,
|
|
99
|
-
cores: cpuCores
|
|
100
|
-
},
|
|
101
|
-
time: timeStr,
|
|
102
|
-
date: dateStr,
|
|
103
|
-
platform,
|
|
104
|
-
distro,
|
|
105
|
-
hostname
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* ดึงข้อมูลอากาศจาก wttr.in (ไม่ต้อง API key)
|
|
111
|
-
* @param {string} city - ชื่อเมือง เช่น Bangkok
|
|
112
|
-
*/
|
|
113
|
-
async function getWeather(city = 'Bangkok') {
|
|
114
|
-
try {
|
|
115
|
-
const response = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=3&lang=th`);
|
|
116
|
-
if (!response.ok) throw new Error('Weather fetch failed');
|
|
117
|
-
const text = await response.text();
|
|
118
|
-
return { success: true, data: text.trim() };
|
|
119
|
-
} catch (err) {
|
|
120
|
-
console.error('getWeather error:', err);
|
|
121
|
-
return { success: false, data: 'ไม่สามารถดึงข้อมูลอากาศได้ในขณะนี้' };
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
module.exports = { getSystemInfo, getWeather };
|