@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.
Files changed (222) hide show
  1. package/.codex +0 -0
  2. package/.github/FUNDING.yml +2 -0
  3. package/.github/workflows/ci.yml +45 -0
  4. package/.github/workflows/release.yml +79 -0
  5. package/Cargo.lock +5792 -0
  6. package/Cargo.toml +32 -0
  7. package/README.md +387 -353
  8. package/assets/icon.png +0 -0
  9. package/bin/mint +0 -0
  10. package/crates/mint-cli/Cargo.toml +23 -0
  11. package/crates/mint-cli/src/agent.rs +851 -0
  12. package/crates/mint-cli/src/gmail.rs +216 -0
  13. package/crates/mint-cli/src/image.rs +142 -0
  14. package/crates/mint-cli/src/main.rs +2837 -0
  15. package/crates/mint-cli/src/mcp.rs +63 -0
  16. package/crates/mint-cli/src/onboard.rs +1149 -0
  17. package/crates/mint-cli/src/setup.rs +390 -0
  18. package/crates/mint-cli/src/skills.rs +8 -0
  19. package/crates/mint-cli/src/updater.rs +279 -0
  20. package/crates/mint-core/Cargo.toml +22 -0
  21. package/crates/mint-core/src/agent_loop.rs +94 -0
  22. package/crates/mint-core/src/api_server.rs +991 -0
  23. package/crates/mint-core/src/channels.rs +248 -0
  24. package/crates/mint-core/src/chat.rs +895 -0
  25. package/crates/mint-core/src/code_tools.rs +729 -0
  26. package/crates/mint-core/src/config.rs +368 -0
  27. package/crates/mint-core/src/files.rs +159 -0
  28. package/crates/mint-core/src/knowledge.rs +541 -0
  29. package/crates/mint-core/src/lib.rs +84 -0
  30. package/crates/mint-core/src/mcp.rs +273 -0
  31. package/crates/mint-core/src/memory.rs +673 -0
  32. package/crates/mint-core/src/orchestration.rs +2157 -0
  33. package/crates/mint-core/src/pictures.rs +314 -0
  34. package/crates/mint-core/src/plugins.rs +727 -0
  35. package/crates/mint-core/src/safety.rs +416 -0
  36. package/crates/mint-core/src/semantic.rs +254 -0
  37. package/crates/mint-core/src/shell.rs +317 -0
  38. package/crates/mint-core/src/skills.rs +71 -0
  39. package/crates/mint-core/src/symbols.rs +157 -0
  40. package/crates/mint-core/src/tasks.rs +308 -0
  41. package/crates/mint-core/src/tts.rs +92 -0
  42. package/crates/mint-core/src/weather.rs +93 -0
  43. package/crates/mint-core/src/web_search.rs +200 -0
  44. package/crates/mint-core/src/workflows.rs +81 -0
  45. package/crates/mint-core/tests/mcp_stdio.rs +45 -0
  46. package/crates/mint-core/tests/memory_persistence.rs +172 -0
  47. package/crates/mint-core/tests/pictures_storage.rs +14 -0
  48. package/crates/mint-core/tests/task_lifecycle.rs +87 -0
  49. package/package.json +35 -99
  50. package/src/bin/index.js +16 -0
  51. package/src/renderer/index-web.html +17 -0
  52. package/src/renderer/index.html +17 -0
  53. package/src/renderer/public/Live2DCubismCore.js +9 -0
  54. package/src/renderer/public/assets/icon.png +0 -0
  55. package/src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.model3.json +36 -0
  56. package/src/renderer/src/App.tsx +33 -0
  57. package/src/renderer/src/calculator.ts +47 -0
  58. package/src/renderer/src/components/ChatPanel.tsx +1598 -0
  59. package/src/renderer/src/components/DashboardSidebar.tsx +358 -0
  60. package/src/renderer/src/components/Live2DStage.tsx +374 -0
  61. package/src/renderer/src/components/MintDashboard.tsx +950 -0
  62. package/src/renderer/src/components/ModelPanel.tsx +154 -0
  63. package/src/renderer/src/components/PicturesLibrary.tsx +46 -0
  64. package/src/renderer/src/components/ProactiveGlow.tsx +19 -0
  65. package/src/renderer/src/components/ScreenPicker.tsx +579 -0
  66. package/src/renderer/src/components/SettingsWindow.tsx +1467 -0
  67. package/src/renderer/src/components/SpotlightWindow.tsx +280 -0
  68. package/src/renderer/src/components/WidgetWindow.tsx +36 -0
  69. package/src/renderer/src/components/WorkspacePanel.tsx +268 -0
  70. package/src/{UI → renderer/src/css}/settings.css +69 -16
  71. package/src/renderer/src/css/spotlight.css +113 -0
  72. package/src/renderer/src/css/styles.css +3722 -0
  73. package/src/renderer/src/css/widget.css +185 -0
  74. package/src/renderer/src/env.d.ts +116 -0
  75. package/src/renderer/src/index.css +379 -0
  76. package/src/renderer/src/main.tsx +13 -0
  77. package/src/renderer/src/tauri.ts +996 -0
  78. package/src/renderer/src-web/App.tsx +25 -0
  79. package/src/renderer/src-web/calculator.ts +47 -0
  80. package/src/renderer/src-web/components/ChatPanel.tsx +1662 -0
  81. package/src/renderer/src-web/components/DashboardSidebar.tsx +242 -0
  82. package/src/renderer/src-web/components/MintDashboard.tsx +763 -0
  83. package/src/renderer/src-web/components/PicturesLibrary.tsx +73 -0
  84. package/src/renderer/src-web/components/SettingsWindow.tsx +1500 -0
  85. package/src/renderer/src-web/css/settings.css +1100 -0
  86. package/src/{UI → renderer/src-web/css}/spotlight.css +4 -4
  87. package/src/{UI → renderer/src-web/css}/styles.css +1055 -159
  88. package/src/{UI → renderer/src-web/css}/widget.css +2 -2
  89. package/src/renderer/src-web/env.d.ts +107 -0
  90. package/src/renderer/src-web/index.css +379 -0
  91. package/src/renderer/src-web/main.tsx +13 -0
  92. package/src/renderer/src-web/tauri.ts +983 -0
  93. package/tsconfig.json +30 -0
  94. package/vite.config.ts +33 -0
  95. package/vite.config.web.ts +51 -0
  96. package/GUIDE_TH.md +0 -125
  97. package/assets/Agent_Mint.png +0 -0
  98. package/assets/CLI_Screen.png +0 -0
  99. package/assets/Settings.png +0 -0
  100. package/benchmark_ai.js +0 -71
  101. package/install.ps1 +0 -64
  102. package/install.sh +0 -54
  103. package/main.js +0 -139
  104. package/mint-cli-logic.js +0 -3
  105. package/mint-cli.js +0 -410
  106. package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.model3.json +0 -47
  107. 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
  108. package/preload-picker.js +0 -11
  109. package/preload-settings.js +0 -11
  110. package/preload.js +0 -41
  111. package/scripts/install_linux_desktop_entry.js +0 -48
  112. package/src/AI_Brain/Gemini_API.js +0 -813
  113. package/src/AI_Brain/agent_orchestrator.js +0 -73
  114. package/src/AI_Brain/autonomous_brain.js +0 -179
  115. package/src/AI_Brain/behavior_memory.js +0 -135
  116. package/src/AI_Brain/headless_agent.js +0 -143
  117. package/src/AI_Brain/knowledge_base.js +0 -349
  118. package/src/AI_Brain/memory_store.js +0 -662
  119. package/src/AI_Brain/proactive_engine.js +0 -172
  120. package/src/AI_Brain/provider_adapter.js +0 -365
  121. package/src/Automation_Layer/browser_automation.js +0 -149
  122. package/src/Automation_Layer/file_operations.js +0 -286
  123. package/src/Automation_Layer/open_app.js +0 -85
  124. package/src/Automation_Layer/open_website.js +0 -38
  125. package/src/CLI/approval_handler.js +0 -47
  126. package/src/CLI/chat_router.js +0 -247
  127. package/src/CLI/chat_ui.js +0 -1159
  128. package/src/CLI/cli_colors.js +0 -115
  129. package/src/CLI/cli_formatters.js +0 -94
  130. package/src/CLI/code_agent.js +0 -1667
  131. package/src/CLI/code_session_memory.js +0 -62
  132. package/src/CLI/gmail_auth.js +0 -210
  133. package/src/CLI/image_input.js +0 -90
  134. package/src/CLI/intent_detectors.js +0 -181
  135. package/src/CLI/interactive_chat.js +0 -658
  136. package/src/CLI/list_features.js +0 -64
  137. package/src/CLI/onboarding.js +0 -416
  138. package/src/CLI/repo_summarizer.js +0 -282
  139. package/src/CLI/semantic_code_search.js +0 -312
  140. package/src/CLI/skill_manager.js +0 -41
  141. package/src/CLI/slash_command_handler.js +0 -418
  142. package/src/CLI/symbol_indexer.js +0 -231
  143. package/src/CLI/updater.js +0 -230
  144. package/src/CLI/workspace_manager.js +0 -90
  145. package/src/Channels/brave_search_bridge.js +0 -35
  146. package/src/Channels/discord_bridge.js +0 -66
  147. package/src/Channels/google_search_bridge.js +0 -38
  148. package/src/Channels/line_bridge.js +0 -60
  149. package/src/Channels/slack_bridge.js +0 -48
  150. package/src/Channels/telegram_bridge.js +0 -41
  151. package/src/Channels/whatsapp_bridge.js +0 -57
  152. package/src/Command_Parser/parser.js +0 -45
  153. package/src/Plugins/dev_tools.js +0 -41
  154. package/src/Plugins/discord.js +0 -20
  155. package/src/Plugins/docker.js +0 -47
  156. package/src/Plugins/gmail.js +0 -251
  157. package/src/Plugins/google_calendar.js +0 -252
  158. package/src/Plugins/mcp_manager.js +0 -95
  159. package/src/Plugins/notion.js +0 -256
  160. package/src/Plugins/obsidian.js +0 -54
  161. package/src/Plugins/plugin_manager.js +0 -81
  162. package/src/Plugins/spotify.js +0 -173
  163. package/src/Plugins/system_metrics.js +0 -31
  164. package/src/Plugins/system_monitor.js +0 -72
  165. package/src/System/action_executor.js +0 -178
  166. package/src/System/bridge_manager.js +0 -76
  167. package/src/System/chat_history_manager.js +0 -83
  168. package/src/System/config_manager.js +0 -194
  169. package/src/System/custom_workflows.js +0 -163
  170. package/src/System/daemon_manager.js +0 -67
  171. package/src/System/google_tts_urls.js +0 -51
  172. package/src/System/granular_automation.js +0 -157
  173. package/src/System/ipc_handlers.js +0 -332
  174. package/src/System/notifications.js +0 -23
  175. package/src/System/optional_require.js +0 -23
  176. package/src/System/picture_store.js +0 -109
  177. package/src/System/proactive_loop.js +0 -153
  178. package/src/System/safety_manager.js +0 -273
  179. package/src/System/sandbox_runner.js +0 -182
  180. package/src/System/screen_capture.js +0 -175
  181. package/src/System/smart_context.js +0 -227
  182. package/src/System/system_automation.js +0 -162
  183. package/src/System/system_events.js +0 -79
  184. package/src/System/system_info.js +0 -125
  185. package/src/System/task_manager.js +0 -222
  186. package/src/System/tool_registry.js +0 -293
  187. package/src/System/window_manager.js +0 -220
  188. package/src/UI/floating.css +0 -80
  189. package/src/UI/floating.html +0 -17
  190. package/src/UI/floating.js +0 -67
  191. package/src/UI/live2d_manager.js +0 -600
  192. package/src/UI/preload-floating.js +0 -7
  193. package/src/UI/preload-spotlight.js +0 -11
  194. package/src/UI/preload-widget.js +0 -5
  195. package/src/UI/proactive-glow.html +0 -42
  196. package/src/UI/renderer.js +0 -2127
  197. package/src/UI/screenPicker.html +0 -214
  198. package/src/UI/screenPicker.js +0 -262
  199. package/src/UI/settings.html +0 -577
  200. package/src/UI/settings.js +0 -770
  201. package/src/UI/spotlight.html +0 -23
  202. package/src/UI/spotlight.js +0 -185
  203. package/src/UI/widget.html +0 -29
  204. package/src/UI/widget.js +0 -10
  205. /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/72d86db84cfa9730b894c241fd24c0db.png +0 -0
  206. /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
  207. /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
  208. /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
  209. /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
  210. /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
  211. /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
  212. /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/items_pinned_to_model.json +0 -0
  213. /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
  214. /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
  215. /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
  216. /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
  217. /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
  218. /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
  219. /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
  220. /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
  221. /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
  222. /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,332 +0,0 @@
1
- const safetyManager = require('./safety_manager');
2
- const { getSmartContext } = require('./smart_context');
3
-
4
- function buildApprovalRequest(action) {
5
- const classification = safetyManager.classifyAction(action);
6
- if (
7
- classification.tier !== safetyManager.TIERS.APPROVAL &&
8
- classification.tier !== safetyManager.TIERS.DANGEROUS
9
- ) {
10
- return null;
11
- }
12
-
13
- return {
14
- required: true,
15
- tier: classification.tier,
16
- reason: classification.reason,
17
- action
18
- };
19
- }
20
-
21
- async function executeApprovedAction(executeAction, action, clipboard) {
22
- const classification = safetyManager.classifyAction(action);
23
- const options = {
24
- clipboard,
25
- source: 'user_approved_action',
26
- allowApproval: classification.tier === safetyManager.TIERS.APPROVAL,
27
- allowDangerous: classification.tier === safetyManager.TIERS.DANGEROUS
28
- };
29
- const result = await executeAction(action, options);
30
- return {
31
- success: true,
32
- action,
33
- tier: classification.tier,
34
- result,
35
- message: result && typeof result === 'string'
36
- ? result
37
- : 'Action completed.'
38
- };
39
- }
40
-
41
- function registerIpcHandlers({
42
- app,
43
- ipcMain,
44
- shell,
45
- clipboard,
46
- windowManager,
47
- proactiveLoop,
48
- screenCapture,
49
- services
50
- }) {
51
- const {
52
- handleChat,
53
- resetChat,
54
- getChatTranscript,
55
- refreshApiKeyFromConfig,
56
- getSystemInfo,
57
- getWeather,
58
- readConfig,
59
- writeConfig,
60
- saveChatImages,
61
- listSavedPictures,
62
- parseCommand,
63
- executeAction,
64
- getGoogleTtsUrls,
65
- customWorkflows
66
- } = services;
67
-
68
- ipcMain.handle('chat-message', async (event, message, base64Image = null, base64Audio = null) => {
69
- try {
70
- if (base64Image && saveChatImages) {
71
- saveChatImages(base64Image, { source: 'chat', message });
72
- }
73
-
74
- const rawResponse = await handleChat(message, base64Image, base64Audio);
75
- const aiResponse = parseCommand(rawResponse);
76
-
77
- if (aiResponse.action && aiResponse.action.type !== 'none') {
78
- try {
79
- const approval = buildApprovalRequest(aiResponse.action);
80
- if (approval) {
81
- aiResponse.approval = approval;
82
- return aiResponse;
83
- }
84
-
85
- const actionResult = await executeAction(aiResponse.action, { clipboard });
86
- if (actionResult && typeof actionResult === 'string') {
87
- aiResponse.response += `\n\n${actionResult}`;
88
- }
89
- } catch (err) {
90
- console.error("Action execution error:", err);
91
- aiResponse.response += "\n\n(Note: I tried to execute the action, but an error occurred.)";
92
- }
93
- }
94
-
95
- return aiResponse;
96
- } catch (error) {
97
- console.error('Chat error:', error);
98
- return { response: 'Error communicating with Gemini API. Check your console and API key.', action: { type: 'none' } };
99
- }
100
- });
101
-
102
- ipcMain.handle('execute-approved-action', async (event, action) => {
103
- try {
104
- if (!action || action.type === 'none') {
105
- return { success: false, message: 'No action to execute.' };
106
- }
107
- return await executeApprovedAction(executeAction, action, clipboard);
108
- } catch (err) {
109
- console.error('[ApprovedAction] Error:', err);
110
- return { success: false, message: err.message || 'Action failed.' };
111
- }
112
- });
113
-
114
- ipcMain.on('close-window', () => {
115
- const mainWindow = windowManager.getMainWindow();
116
- if (mainWindow) mainWindow.hide();
117
- });
118
-
119
- ipcMain.on('minimize-window', () => {
120
- const mainWindow = windowManager.getMainWindow();
121
- if (mainWindow) mainWindow.minimize();
122
- });
123
-
124
- ipcMain.on('quit-app', () => {
125
- app.isQuiting = true;
126
- app.quit();
127
- });
128
-
129
- ipcMain.on('maximize-window', () => {
130
- const mainWindow = windowManager.getMainWindow();
131
- if (!mainWindow) return;
132
- if (mainWindow.isMaximized()) {
133
- mainWindow.unmaximize();
134
- } else {
135
- mainWindow.maximize();
136
- }
137
- });
138
-
139
- ipcMain.handle('reset-chat', () => {
140
- resetChat();
141
- return { success: true };
142
- });
143
-
144
- ipcMain.handle('get-chat-history', () => getChatTranscript());
145
-
146
- ipcMain.handle('list-saved-pictures', () => {
147
- return listSavedPictures ? listSavedPictures() : [];
148
- });
149
-
150
- ipcMain.handle('open-settings', () => {
151
- windowManager.createSettingsWindow();
152
- });
153
-
154
- ipcMain.handle('get-settings', () => readConfig());
155
-
156
- ipcMain.handle('save-settings', (event, config) => {
157
- console.log('[Settings] Saving new config. MCP Servers count:', Object.keys(config.mcpServers || {}).length);
158
- const result = writeConfig(config);
159
- refreshApiKeyFromConfig();
160
-
161
- const mainWindow = windowManager.getMainWindow();
162
- if (mainWindow && !mainWindow.isDestroyed()) {
163
- mainWindow.webContents.send('settings-changed', config);
164
- }
165
-
166
- if (proactiveLoop.isRunning()) {
167
- proactiveLoop.start(config.proactiveInterval);
168
- }
169
-
170
- if (config.enableCustomWorkflows !== false) {
171
- customWorkflows.startMonitoring(mainWindow.webContents);
172
- } else {
173
- customWorkflows.stopMonitoring();
174
- }
175
-
176
- if (config.showDesktopWidget === false) {
177
- windowManager.closeWidgetWindow();
178
- } else {
179
- windowManager.ensureWidgetWindow();
180
- }
181
-
182
- return result;
183
- });
184
-
185
- ipcMain.on('set-ai-state', (event, state) => {
186
- const widgetWindow = windowManager.getWidgetWindow();
187
- if (widgetWindow && !widgetWindow.isDestroyed()) {
188
- widgetWindow.webContents.send('widget-state', state);
189
- }
190
- });
191
-
192
- ipcMain.on('close-settings', () => {
193
- const settingsWindow = windowManager.getSettingsWindow();
194
- if (settingsWindow) settingsWindow.close();
195
- });
196
-
197
- ipcMain.handle('open-custom-workflows', () => {
198
- customWorkflows.openConfigFile();
199
- });
200
-
201
- ipcMain.handle('reload-custom-workflows', () => {
202
- customWorkflows.loadWorkflows();
203
- return { success: true };
204
- });
205
-
206
- ipcMain.on('spotlight-close', () => {
207
- const spotlightWindow = windowManager.getSpotlightWindow();
208
- if (spotlightWindow) spotlightWindow.close();
209
- });
210
-
211
- ipcMain.on('spotlight-hide', () => {
212
- const spotlightWindow = windowManager.getSpotlightWindow();
213
- if (spotlightWindow) spotlightWindow.hide();
214
- });
215
-
216
- ipcMain.on('spotlight-submit', async (event, query) => {
217
- console.log('[Spotlight] Submit:', query);
218
- const spotlightWindow = windowManager.getSpotlightWindow();
219
- if (spotlightWindow) spotlightWindow.hide();
220
-
221
- const mainWindow = windowManager.getMainWindow();
222
- if (mainWindow) {
223
- mainWindow.show();
224
- mainWindow.webContents.send('spotlight-to-chat', query);
225
- }
226
- });
227
-
228
- ipcMain.handle('spotlight-action', async (event, action) => {
229
- const spotlightWindow = windowManager.getSpotlightWindow();
230
- if (spotlightWindow) spotlightWindow.hide();
231
-
232
- if (!action || action.type === 'none') {
233
- return { success: false, message: 'No Spotlight action to execute.' };
234
- }
235
-
236
- try {
237
- const result = await executeAction(action, {
238
- clipboard,
239
- source: 'spotlight'
240
- });
241
- return {
242
- success: true,
243
- action,
244
- message: result && typeof result === 'string' ? result : 'Spotlight action completed.'
245
- };
246
- } catch (err) {
247
- console.error('[SpotlightAction] Error:', err);
248
- return { success: false, message: err.message || 'Spotlight action failed.' };
249
- }
250
- });
251
-
252
- ipcMain.on('spotlight-resize', (event, width, height) => {
253
- const spotlightWindow = windowManager.getSpotlightWindow();
254
- if (spotlightWindow) spotlightWindow.setSize(width, height);
255
- });
256
-
257
- ipcMain.handle('open-external', (event, url) => {
258
- shell.openExternal(url);
259
- });
260
-
261
- ipcMain.handle('clipboard-read', () => clipboard.readText());
262
-
263
- ipcMain.handle('clipboard-write', (event, text) => {
264
- clipboard.writeText(text);
265
- return { success: true };
266
- });
267
-
268
- ipcMain.handle('get-tts-urls', async (event, text) => {
269
- try {
270
- const isThai = /[\u0E00-\u0E7F]/.test(text);
271
- return getGoogleTtsUrls(text, {
272
- lang: isThai ? 'th' : 'en',
273
- host: 'https://translate.google.com',
274
- });
275
- } catch (e) {
276
- console.error("TTS Error:", e);
277
- return [];
278
- }
279
- });
280
-
281
- ipcMain.handle('get-system-info', async () => getSystemInfo());
282
- ipcMain.handle('get-weather', async (event, city) => getWeather(city));
283
-
284
- ipcMain.handle('start-screen-capture', () => screenCapture.startScreenCapture());
285
- ipcMain.on('vision-selection', (event, base64Image) => screenCapture.handleSelection(base64Image));
286
- ipcMain.on('vision-translate-start', (event, rect) => screenCapture.startLiveTranslate(rect));
287
- ipcMain.on('vision-translate-stop', () => screenCapture.stopLiveTranslate());
288
- ipcMain.on('vision-overlay-interactable', (event, isInteractable) => screenCapture.setOverlayInteractable(isInteractable));
289
- ipcMain.on('vision-cancel', () => screenCapture.cancel());
290
- ipcMain.handle('capture-silent-screen', () => screenCapture.captureSilentScreen());
291
-
292
- ipcMain.handle('get-smart-context', () => getSmartContext({ clipboard }));
293
-
294
- ipcMain.on('toggle-proactive', (event, isOn) => {
295
- if (isOn) {
296
- proactiveLoop.start();
297
- } else {
298
- proactiveLoop.stop();
299
- }
300
- });
301
-
302
- ipcMain.on('record-behavior', (event, contextDescription) => {
303
- proactiveLoop.recordBehavior(contextDescription);
304
- });
305
-
306
- ipcMain.handle('execute-proactive-action', async (event, action) => {
307
- if (!action || action.type === 'none') {
308
- return { success: false, message: 'ไม่มี action ที่จะดำเนินการค่ะ' };
309
- }
310
- try {
311
- const result = await executeAction(action, { clipboard });
312
- const messages = {
313
- open_url: `เปิดเว็บไซต์ให้แล้วค่ะ 🌐`,
314
- open_app: `เปิดแอป ${action.target} ให้แล้วค่ะ 🚀`,
315
- search: `ค้นหา "${action.target}" ให้แล้วค่ะ 🔍`,
316
- web_automation: result || 'ดำเนินการเสร็จแล้วค่ะ ✅',
317
- create_folder: `สร้างโฟลเดอร์ "${action.target}" แล้วค่ะ 📁`,
318
- clipboard_write: `คัดลอกข้อความแล้วค่ะ 📋`,
319
- learn_file: result || `เรียนรู้เอกสารเรียบร้อยค่ะ 📚`,
320
- };
321
- return {
322
- success: true,
323
- message: messages[action.type] || 'ดำเนินการเสร็จแล้วค่ะ ✅'
324
- };
325
- } catch (err) {
326
- console.error('[ProactiveAction] Error:', err);
327
- return { success: false, message: `เกิดข้อผิดพลาด: ${err.message}` };
328
- }
329
- });
330
- }
331
-
332
- module.exports = { registerIpcHandlers, buildApprovalRequest, executeApprovedAction };
@@ -1,23 +0,0 @@
1
- /**
2
- * Mint Notification System
3
- * ------------------------
4
- * Sends system-level notifications to the user.
5
- * Supports Linux (notify-send) as a primary target for CLI.
6
- */
7
-
8
- const { exec } = require('child_process');
9
-
10
- function sendNotification(title, message, urgency = 'normal') {
11
- // Attempt to use notify-send (Linux)
12
- const cmd = `notify-send -u ${urgency} "${title}" "${message}"`;
13
- exec(cmd, (err) => {
14
- if (err) {
15
- // Fallback: Silent console log if no notifier found
16
- console.log(`[Notification] ${title}: ${message}`);
17
- }
18
- });
19
- }
20
-
21
- module.exports = {
22
- sendNotification
23
- };
@@ -1,23 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Helper: ลอง require package แบบ dynamic
5
- * ถ้าหาไม่เจอให้ throw Error พร้อม install guide
6
- */
7
- function requireOptional(pkg, installHint) {
8
- try {
9
- return require(pkg);
10
- } catch (e) {
11
- if (e.code === 'MODULE_NOT_FOUND') {
12
- const hint = installHint || `npm install ${pkg}`;
13
- throw new Error(
14
- `[Mint] Optional package "${pkg}" is not installed.\n` +
15
- `To use this feature, run: ${hint}\n` +
16
- `(This package is not bundled by default to keep Mint lightweight.)`
17
- );
18
- }
19
- throw e;
20
- }
21
- }
22
-
23
- module.exports = { requireOptional };
@@ -1,109 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const os = require('os');
4
- const crypto = require('crypto');
5
- const { pathToFileURL } = require('url');
6
-
7
- const PICTURES_DIR = path.join(os.homedir(), '.config', 'mint', 'Pictures');
8
- const INDEX_PATH = path.join(PICTURES_DIR, 'pictures.json');
9
-
10
- const EXTENSIONS = {
11
- 'image/png': 'png',
12
- 'image/jpeg': 'jpg',
13
- 'image/jpg': 'jpg',
14
- 'image/webp': 'webp',
15
- 'image/gif': 'gif'
16
- };
17
-
18
- function ensurePicturesDir() {
19
- fs.mkdirSync(PICTURES_DIR, { recursive: true });
20
- }
21
-
22
- function readIndex() {
23
- try {
24
- if (!fs.existsSync(INDEX_PATH)) return [];
25
- const parsed = JSON.parse(fs.readFileSync(INDEX_PATH, 'utf8'));
26
- return Array.isArray(parsed) ? parsed : [];
27
- } catch (error) {
28
- console.error('[Pictures] Failed to read index:', error.message);
29
- return [];
30
- }
31
- }
32
-
33
- function writeIndex(entries) {
34
- ensurePicturesDir();
35
- fs.writeFileSync(INDEX_PATH, JSON.stringify(entries, null, 2), 'utf8');
36
- }
37
-
38
- function parseImageDataUri(dataUri) {
39
- if (!dataUri || typeof dataUri !== 'string') return null;
40
- const match = dataUri.match(/^data:(image\/[\w.+-]+);base64,([\s\S]+)$/);
41
- if (!match) return null;
42
-
43
- const mimeType = match[1].toLowerCase();
44
- const extension = EXTENSIONS[mimeType] || 'png';
45
- return {
46
- mimeType,
47
- extension,
48
- buffer: Buffer.from(match[2], 'base64')
49
- };
50
- }
51
-
52
- function createFilename(extension) {
53
- const stamp = new Date().toISOString()
54
- .replace(/[-:]/g, '')
55
- .replace(/\..+$/, '')
56
- .replace('T', '-');
57
- const id = crypto.randomBytes(4).toString('hex');
58
- return `mint-${stamp}-${id}.${extension}`;
59
- }
60
-
61
- function saveChatImages(base64Image, metadata = {}) {
62
- const images = Array.isArray(base64Image) ? base64Image : (base64Image ? [base64Image] : []);
63
- const saved = [];
64
- if (images.length === 0) return saved;
65
-
66
- ensurePicturesDir();
67
- const index = readIndex();
68
-
69
- for (const item of images) {
70
- const parsed = parseImageDataUri(item);
71
- if (!parsed || parsed.buffer.length === 0) continue;
72
-
73
- const filename = createFilename(parsed.extension);
74
- const filePath = path.join(PICTURES_DIR, filename);
75
- fs.writeFileSync(filePath, parsed.buffer);
76
-
77
- const entry = {
78
- id: path.basename(filename, path.extname(filename)),
79
- filename,
80
- path: filePath,
81
- mimeType: parsed.mimeType,
82
- createdAt: new Date().toISOString(),
83
- source: metadata.source || 'chat',
84
- message: String(metadata.message || '').slice(0, 240)
85
- };
86
-
87
- index.unshift(entry);
88
- saved.push(entry);
89
- }
90
-
91
- writeIndex(index);
92
- return saved;
93
- }
94
-
95
- function listSavedPictures() {
96
- ensurePicturesDir();
97
- return readIndex()
98
- .filter(entry => entry && entry.path && fs.existsSync(entry.path))
99
- .map(entry => ({
100
- ...entry,
101
- url: pathToFileURL(entry.path).href
102
- }));
103
- }
104
-
105
- module.exports = {
106
- PICTURES_DIR,
107
- saveChatImages,
108
- listSavedPictures
109
- };
@@ -1,153 +0,0 @@
1
- const { BrowserWindow, desktopCapturer, screen, powerMonitor } = require('electron');
2
- const path = require('path');
3
-
4
- const IDLE_THRESHOLD_SEC = 300;
5
-
6
- let proactiveEngine = null;
7
- function getProactiveEngine() {
8
- if (!proactiveEngine) {
9
- proactiveEngine = require('../AI_Brain/proactive_engine');
10
- }
11
- return proactiveEngine;
12
- }
13
-
14
- let behaviorMemory = null;
15
- function getBehaviorMemory() {
16
- if (!behaviorMemory) {
17
- behaviorMemory = require('../AI_Brain/behavior_memory');
18
- }
19
- return behaviorMemory;
20
- }
21
-
22
- function createProactiveLoop({ app, projectRoot, readConfig, getMainWindow }) {
23
- let proactiveGlowWindow = null;
24
- let proactiveIntervalHandle = null;
25
- let idleWatcherHandle = null;
26
-
27
- async function runProactiveCycle() {
28
- const mainWindow = getMainWindow();
29
- if (!mainWindow || mainWindow.isDestroyed()) return;
30
-
31
- try {
32
- showProactiveGlow();
33
-
34
- const primaryDisplay = screen.getPrimaryDisplay();
35
- const width = Math.floor(primaryDisplay.size.width * 0.5);
36
- const height = Math.floor(primaryDisplay.size.height * 0.5);
37
- const sources = await desktopCapturer.getSources({
38
- types: ['screen'],
39
- thumbnailSize: { width, height }
40
- });
41
-
42
- const primarySource = sources[0];
43
- if (!primarySource || !primarySource.thumbnail) return;
44
-
45
- const base64Image = primarySource.thumbnail.toJPEG(60).toString('base64');
46
- const { analyzeAndSuggest } = getProactiveEngine();
47
- const { recordBehavior, getBehaviorSummary } = getBehaviorMemory();
48
- const result = await analyzeAndSuggest(base64Image, getBehaviorSummary());
49
-
50
- if (result && result.message && Array.isArray(result.suggestions)) {
51
- if (result.context) recordBehavior(result.context);
52
-
53
- const currentMainWindow = getMainWindow();
54
- if (currentMainWindow && !currentMainWindow.isDestroyed()) {
55
- currentMainWindow.webContents.send('proactive-suggestion', result);
56
- }
57
- }
58
-
59
- hideProactiveGlow();
60
- } catch (err) {
61
- console.error('[Proactive] Cycle error:', err.message);
62
- hideProactiveGlow();
63
- }
64
- }
65
-
66
- function createProactiveGlowWindow() {
67
- if (proactiveGlowWindow) return proactiveGlowWindow;
68
- const { width, height } = screen.getPrimaryDisplay().bounds;
69
-
70
- proactiveGlowWindow = new BrowserWindow({
71
- width,
72
- height,
73
- x: 0,
74
- y: 0,
75
- frame: false,
76
- transparent: true,
77
- alwaysOnTop: true,
78
- skipTaskbar: true,
79
- focusable: false,
80
- show: false,
81
- webPreferences: {
82
- nodeIntegration: false,
83
- contextIsolation: true
84
- }
85
- });
86
-
87
- proactiveGlowWindow.setIgnoreMouseEvents(true);
88
- proactiveGlowWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
89
- proactiveGlowWindow.setAlwaysOnTop(true, 'screen-saver');
90
- proactiveGlowWindow.loadFile(path.join(projectRoot, 'src/UI/proactive-glow.html'));
91
- proactiveGlowWindow.on('closed', () => { proactiveGlowWindow = null; });
92
- return proactiveGlowWindow;
93
- }
94
-
95
- function showProactiveGlow() {
96
- if (!proactiveGlowWindow) createProactiveGlowWindow();
97
- if (proactiveGlowWindow) proactiveGlowWindow.showInactive();
98
- }
99
-
100
- function hideProactiveGlow() {
101
- if (proactiveGlowWindow && !proactiveGlowWindow.isDestroyed()) {
102
- proactiveGlowWindow.hide();
103
- }
104
- }
105
-
106
- function start(intervalSec) {
107
- stop();
108
- const cfg = readConfig();
109
- const ms = (intervalSec || cfg.proactiveInterval || 60) * 1000;
110
- console.log(`[Proactive] Starting loop — interval: ${ms / 1000}s`);
111
- proactiveIntervalHandle = setInterval(runProactiveCycle, ms);
112
- }
113
-
114
- function stop() {
115
- if (proactiveIntervalHandle) {
116
- clearInterval(proactiveIntervalHandle);
117
- proactiveIntervalHandle = null;
118
- console.log('[Proactive] Stopped proactive loop.');
119
- }
120
- }
121
-
122
- function startIdleWatcher() {
123
- if (idleWatcherHandle) return;
124
- idleWatcherHandle = setInterval(() => {
125
- if (!proactiveIntervalHandle) return;
126
- if (!app.isReady()) return;
127
-
128
- const idleSec = powerMonitor.getSystemIdleTime();
129
- if (idleSec < IDLE_THRESHOLD_SEC) return;
130
-
131
- console.log(`[System Idle] User idle for ${idleSec}s. Pausing Proactive loop to save resources.`);
132
- stop();
133
-
134
- const resumeChecker = setInterval(() => {
135
- if (powerMonitor.getSystemIdleTime() < 10) {
136
- console.log('[System Idle] User returned. Resuming Proactive loop.');
137
- clearInterval(resumeChecker);
138
- start();
139
- }
140
- }, 5000);
141
- }, 60000);
142
- }
143
-
144
- return {
145
- start,
146
- stop,
147
- startIdleWatcher,
148
- isRunning: () => Boolean(proactiveIntervalHandle),
149
- recordBehavior: (...args) => getBehaviorMemory().recordBehavior(...args)
150
- };
151
- }
152
-
153
- module.exports = { createProactiveLoop };