@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,62 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const crypto = require('crypto');
4
- const { CONFIG_PATH } = require('../System/config_manager');
5
-
6
- const SESSION_FILE = path.join(path.dirname(CONFIG_PATH), 'code-sessions.json');
7
-
8
- function ensureSessionStore() {
9
- if (!fs.existsSync(SESSION_FILE)) {
10
- fs.writeFileSync(SESSION_FILE, JSON.stringify({}, null, 2), 'utf8');
11
- }
12
- }
13
-
14
- function readAllSessions() {
15
- ensureSessionStore();
16
- try {
17
- return JSON.parse(fs.readFileSync(SESSION_FILE, 'utf8'));
18
- } catch (error) {
19
- return {};
20
- }
21
- }
22
-
23
- function writeAllSessions(data) {
24
- ensureSessionStore();
25
- fs.writeFileSync(SESSION_FILE, JSON.stringify(data, null, 2), 'utf8');
26
- }
27
-
28
- function getWorkspaceKey(workspaceRoot) {
29
- return crypto.createHash('sha1').update(path.resolve(workspaceRoot)).digest('hex');
30
- }
31
-
32
- function readWorkspaceSession(workspaceRoot) {
33
- const sessions = readAllSessions();
34
- const key = getWorkspaceKey(workspaceRoot);
35
- return sessions[key] || {
36
- workspaceRoot: path.resolve(workspaceRoot),
37
- summary: '',
38
- lastTask: '',
39
- lastVerification: '',
40
- updatedAt: null
41
- };
42
- }
43
-
44
- function writeWorkspaceSession(workspaceRoot, updates) {
45
- const sessions = readAllSessions();
46
- const key = getWorkspaceKey(workspaceRoot);
47
- const current = readWorkspaceSession(workspaceRoot);
48
- sessions[key] = {
49
- ...current,
50
- ...updates,
51
- workspaceRoot: path.resolve(workspaceRoot),
52
- updatedAt: new Date().toISOString()
53
- };
54
- writeAllSessions(sessions);
55
- return sessions[key];
56
- }
57
-
58
- module.exports = {
59
- readWorkspaceSession,
60
- writeWorkspaceSession,
61
- SESSION_FILE
62
- };
@@ -1,210 +0,0 @@
1
- const http = require('http');
2
- const { execFile } = require('child_process');
3
- const crypto = require('crypto');
4
- const axios = require('axios');
5
- const { readConfig, writeConfig } = require('../System/config_manager');
6
-
7
- const TOKEN_URL = 'https://oauth2.googleapis.com/token';
8
- const AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
9
- const DEFAULT_SCOPES = [
10
- 'https://www.googleapis.com/auth/gmail.readonly',
11
- 'https://www.googleapis.com/auth/gmail.compose'
12
- ];
13
-
14
- function buildRedirectUri(port) {
15
- return `http://127.0.0.1:${port}/oauth2callback`;
16
- }
17
-
18
- function buildAuthUrl({ clientId, redirectUri, state, scopes = DEFAULT_SCOPES }) {
19
- const params = new URLSearchParams({
20
- client_id: clientId,
21
- redirect_uri: redirectUri,
22
- response_type: 'code',
23
- scope: scopes.join(' '),
24
- access_type: 'offline',
25
- prompt: 'consent',
26
- state
27
- });
28
-
29
- return `${AUTH_URL}?${params.toString()}`;
30
- }
31
-
32
- function openBrowser(url) {
33
- const command = process.platform === 'darwin'
34
- ? 'open'
35
- : process.platform === 'win32'
36
- ? 'cmd'
37
- : 'xdg-open';
38
- const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
39
-
40
- return new Promise((resolve, reject) => {
41
- execFile(command, args, (error) => {
42
- if (error) {
43
- reject(error);
44
- return;
45
- }
46
- resolve();
47
- });
48
- });
49
- }
50
-
51
- async function exchangeCodeForToken({ clientId, clientSecret, code, redirectUri }) {
52
- const params = new URLSearchParams({
53
- client_id: clientId,
54
- client_secret: clientSecret,
55
- code,
56
- redirect_uri: redirectUri,
57
- grant_type: 'authorization_code'
58
- });
59
-
60
- const response = await axios.post(TOKEN_URL, params.toString(), {
61
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
62
- });
63
-
64
- return response.data;
65
- }
66
-
67
- function waitForOAuthCode({ port = 0, state, timeoutMs = 180000 }) {
68
- return new Promise((resolve, reject) => {
69
- let settled = false;
70
- let timer = null;
71
-
72
- const finish = (error, value) => {
73
- if (settled) return;
74
- settled = true;
75
- if (timer) clearTimeout(timer);
76
- server.close(() => {
77
- if (error) reject(error);
78
- else resolve(value);
79
- });
80
- };
81
-
82
- const server = http.createServer((req, res) => {
83
- try {
84
- const url = new URL(req.url, 'http://127.0.0.1');
85
- if (url.pathname !== '/oauth2callback') {
86
- res.writeHead(404, { 'Content-Type': 'text/plain' });
87
- res.end('Not found');
88
- return;
89
- }
90
-
91
- const returnedState = url.searchParams.get('state');
92
- const error = url.searchParams.get('error');
93
- const code = url.searchParams.get('code');
94
-
95
- if (error) {
96
- res.writeHead(400, { 'Content-Type': 'text/plain' });
97
- res.end(`Gmail authorization failed: ${error}`);
98
- finish(new Error(`Gmail authorization failed: ${error}`));
99
- return;
100
- }
101
-
102
- if (!code || returnedState !== state) {
103
- res.writeHead(400, { 'Content-Type': 'text/plain' });
104
- res.end('Invalid Gmail authorization response.');
105
- finish(new Error('Invalid Gmail authorization response.'));
106
- return;
107
- }
108
-
109
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
110
- res.end('<h1>Gmail connected</h1><p>You can close this window and return to Mint.</p>');
111
- finish(null, code);
112
- } catch (err) {
113
- res.writeHead(500, { 'Content-Type': 'text/plain' });
114
- res.end('Internal error.');
115
- finish(err);
116
- }
117
- });
118
-
119
- server.on('error', finish);
120
- server.listen(port, '127.0.0.1', () => {
121
- timer = setTimeout(() => {
122
- finish(new Error('Timed out waiting for Gmail authorization callback.'));
123
- }, timeoutMs);
124
- });
125
- });
126
- }
127
-
128
- async function runGmailAuth(options = {}) {
129
- const logger = options.logger || console;
130
- const config = options.readConfig ? options.readConfig() : readConfig();
131
- const clientId = (config.gmailClientId || '').trim();
132
- const clientSecret = (config.gmailClientSecret || '').trim();
133
- const userId = (config.gmailUserId || 'me').trim() || 'me';
134
-
135
- if (!clientId || !clientSecret) {
136
- throw new Error('Missing Gmail OAuth Client ID or Client Secret. Run `mint onboard` and fill Gmail API credentials first.');
137
- }
138
-
139
- const state = crypto.randomBytes(16).toString('hex');
140
- const actualPort = options.getAuthorizationCode ? Number(options.port || 8787) : await reserveLocalPort(Number(options.port || 0));
141
- const redirectUri = buildRedirectUri(actualPort);
142
- const codePromise = options.getAuthorizationCode
143
- ? null
144
- : waitForOAuthCode({
145
- port: actualPort,
146
- state,
147
- timeoutMs: options.timeoutMs || 180000
148
- });
149
- const authUrl = buildAuthUrl({ clientId, redirectUri, state, scopes: options.scopes || DEFAULT_SCOPES });
150
-
151
- logger.log(`Open this Google OAuth consent link for Gmail (${userId}):\n${authUrl}\n`);
152
-
153
- if (options.openBrowser !== false) {
154
- const browserOpener = options.openBrowser || openBrowser;
155
- await browserOpener(authUrl);
156
- }
157
-
158
- const code = options.getAuthorizationCode
159
- ? await options.getAuthorizationCode({ authUrl, state, redirectUri })
160
- : await codePromise;
161
- const token = await exchangeCodeForToken({
162
- clientId,
163
- clientSecret,
164
- code,
165
- redirectUri
166
- });
167
-
168
- if (!token.refresh_token) {
169
- throw new Error('Google did not return a refresh token. Re-run `mint gmail auth`; the flow uses prompt=consent to request one.');
170
- }
171
-
172
- const nextConfig = {
173
- ...config,
174
- gmailRefreshToken: token.refresh_token,
175
- gmailUserId: userId,
176
- pluginGmailEnabled: true
177
- };
178
-
179
- const writeResult = options.writeConfig ? options.writeConfig(nextConfig) : writeConfig(nextConfig);
180
- if (writeResult && writeResult.success === false) {
181
- throw new Error(writeResult.message || 'Failed to save Gmail refresh token.');
182
- }
183
-
184
- return {
185
- success: true,
186
- userId,
187
- scopes: options.scopes || DEFAULT_SCOPES
188
- };
189
- }
190
-
191
- function reserveLocalPort(port = 0) {
192
- return new Promise((resolve, reject) => {
193
- const server = http.createServer();
194
- server.on('error', reject);
195
- server.listen(port, '127.0.0.1', () => {
196
- const actualPort = server.address().port;
197
- server.close(() => resolve(actualPort));
198
- });
199
- });
200
- }
201
-
202
- module.exports = {
203
- DEFAULT_SCOPES,
204
- buildRedirectUri,
205
- buildAuthUrl,
206
- exchangeCodeForToken,
207
- waitForOAuthCode,
208
- reserveLocalPort,
209
- runGmailAuth
210
- };
@@ -1,90 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { execFileSync } = require('child_process');
4
-
5
- const IMAGE_MIME_TYPES = {
6
- '.png': 'image/png',
7
- '.jpg': 'image/jpeg',
8
- '.jpeg': 'image/jpeg',
9
- '.webp': 'image/webp',
10
- '.gif': 'image/gif'
11
- };
12
-
13
- function resolveImagePath(imagePath, cwd = process.cwd()) {
14
- if (!imagePath || typeof imagePath !== 'string') {
15
- throw new Error('Image path is required.');
16
- }
17
-
18
- return path.resolve(cwd, imagePath);
19
- }
20
-
21
- function getImageMimeType(imagePath) {
22
- const ext = path.extname(imagePath).toLowerCase();
23
- const mimeType = IMAGE_MIME_TYPES[ext];
24
- if (!mimeType) {
25
- throw new Error(`Unsupported image type "${ext || '(none)'}". Supported: ${Object.keys(IMAGE_MIME_TYPES).join(', ')}`);
26
- }
27
- return mimeType;
28
- }
29
-
30
- function loadImageAsDataUri(imagePath, cwd = process.cwd()) {
31
- const resolved = resolveImagePath(imagePath, cwd);
32
- if (!fs.existsSync(resolved)) {
33
- throw new Error(`Image file not found: ${imagePath}`);
34
- }
35
-
36
- const stat = fs.statSync(resolved);
37
- if (!stat.isFile()) {
38
- throw new Error(`Image path is not a file: ${imagePath}`);
39
- }
40
-
41
- const mimeType = getImageMimeType(resolved);
42
- const data = fs.readFileSync(resolved).toString('base64');
43
- return {
44
- path: resolved,
45
- mimeType,
46
- dataUri: `data:${mimeType};base64,${data}`
47
- };
48
- }
49
-
50
- function tryReadClipboardCommand(command, args) {
51
- try {
52
- return execFileSync(command, args, {
53
- encoding: 'buffer',
54
- maxBuffer: 1024 * 1024 * 20,
55
- stdio: ['ignore', 'pipe', 'ignore']
56
- });
57
- } catch (_) {
58
- return null;
59
- }
60
- }
61
-
62
- function loadClipboardImageAsDataUri() {
63
- const attempts = [
64
- { command: 'wl-paste', args: ['--type', 'image/png', '--no-newline'] },
65
- { command: 'xclip', args: ['-selection', 'clipboard', '-t', 'image/png', '-o'] }
66
- ];
67
-
68
- for (const attempt of attempts) {
69
- const data = tryReadClipboardCommand(attempt.command, attempt.args);
70
- if (data && data.length > 0) {
71
- return {
72
- path: 'clipboard',
73
- mimeType: 'image/png',
74
- dataUri: `data:image/png;base64,${data.toString('base64')}`
75
- };
76
- }
77
- }
78
-
79
- throw new Error('No clipboard image found. On Linux, install wl-clipboard or xclip, then copy an image and try Ctrl+V again.');
80
- }
81
-
82
- module.exports = {
83
- loadImageAsDataUri,
84
- loadClipboardImageAsDataUri,
85
- _helpers: {
86
- getImageMimeType,
87
- resolveImagePath,
88
- tryReadClipboardCommand
89
- }
90
- };
@@ -1,181 +0,0 @@
1
- 'use strict';
2
-
3
- // ---------------------------------------------------------------------------
4
- // Repository Summary
5
- // ---------------------------------------------------------------------------
6
-
7
- /**
8
- * Returns true when the user's plain-language input is asking for a repo summary.
9
- * @param {string} text
10
- * @returns {boolean}
11
- */
12
- function isRepoSummaryRequest(text) {
13
- const input = (text || '').trim().toLowerCase();
14
- if (!input) return false;
15
-
16
- const hasRepoTarget = /\b(repo|repository|project|workspace|codebase)\b|รีโป|โปรเจค|โปรเจ็กต์|โปรเจกต์|โปรเจ็ค/.test(input);
17
- const asksSummary = /\b(summarize|summary|overview)\b|สรุป|ภาพรวม/.test(input);
18
- const asksQuestion = /\b(have|has|มีไหม|มีมั้ย|มีหรือเปล่า)\b/.test(input);
19
-
20
- return hasRepoTarget && asksSummary && !asksQuestion;
21
- }
22
-
23
- /**
24
- * Parses raw CLI args for the summarize tool.
25
- * @param {string} rawArgs
26
- * @returns {{ targetPath: string, json: boolean }}
27
- */
28
- function parseRepoSummaryArgs(rawArgs) {
29
- const args = (rawArgs || '').split(/\s+/).filter(Boolean);
30
- const json = args.includes('--json');
31
- const pathArgs = args.filter(arg => arg !== '--json');
32
- return {
33
- targetPath: pathArgs.length > 0 ? pathArgs.join(' ') : process.cwd(),
34
- json
35
- };
36
- }
37
-
38
- // ---------------------------------------------------------------------------
39
- // Symbol Index
40
- // ---------------------------------------------------------------------------
41
-
42
- /**
43
- * Returns true when the user's input is asking for a symbol index.
44
- * @param {string} text
45
- * @returns {boolean}
46
- */
47
- function isSymbolIndexRequest(text) {
48
- const input = (text || '').trim().toLowerCase();
49
- if (!input) return false;
50
-
51
- const hasSymbolTarget = /\b(symbol|symbols|ast|lsp)\b|ซิมโบล|สัญลักษณ์/.test(input);
52
- const asksIndex = /\b(index|list|show|build|scan|overview)\b|ทำ|สร้าง|แสดง|ลิสต์|สแกน/.test(input);
53
- const referencesWorkspace = /\b(repo|repository|project|workspace|codebase|source|code)\b|รีโป|โปรเจค|โปรเจ็กต์|โปรเจกต์|โค้ด/.test(input);
54
- const asksQuestion = /\b(do i|have|has)\b|มีไหม|มีมั้ย|มีหรือเปล่า/.test(input);
55
-
56
- return hasSymbolTarget && (asksIndex || referencesWorkspace) && !asksQuestion;
57
- }
58
-
59
- /**
60
- * Parses raw CLI args for the symbol index tool.
61
- * @param {string} rawArgs
62
- * @returns {{ targetPath: string, json: boolean, limit: number }}
63
- */
64
- function parseSymbolIndexArgs(rawArgs) {
65
- const args = (rawArgs || '').split(/\s+/).filter(Boolean);
66
- const json = args.includes('--json');
67
- let limit = 80;
68
- const pathArgs = [];
69
-
70
- for (let i = 0; i < args.length; i++) {
71
- const arg = args[i];
72
- if (arg === '--json') continue;
73
- if (arg === '--limit') {
74
- const next = Number(args[i + 1]);
75
- if (Number.isFinite(next) && next >= 0) { limit = next; i++; }
76
- continue;
77
- }
78
- if (arg.startsWith('--limit=')) {
79
- const next = Number(arg.slice('--limit='.length));
80
- if (Number.isFinite(next) && next >= 0) limit = next;
81
- continue;
82
- }
83
- pathArgs.push(arg);
84
- }
85
-
86
- return {
87
- targetPath: pathArgs.length > 0 ? pathArgs.join(' ') : process.cwd(),
88
- json,
89
- limit
90
- };
91
- }
92
-
93
- // ---------------------------------------------------------------------------
94
- // Semantic Code Search
95
- // ---------------------------------------------------------------------------
96
-
97
- /**
98
- * Returns true when the user's input is asking for a semantic code search.
99
- * @param {string} text
100
- * @returns {boolean}
101
- */
102
- function isSemanticCodeSearchRequest(text) {
103
- const input = (text || '').trim().toLowerCase();
104
- if (!input) return false;
105
-
106
- const hasSemanticSearch = /\bsemantic\b/.test(input) && /\b(search|find|look for)\b/.test(input);
107
- const referencesCode = /\b(code|repo|repository|project|workspace|codebase|source)\b|โค้ด|รีโป|โปรเจค|โปรเจ็กต์|โปรเจกต์/.test(input);
108
- const thaiSemanticSearch = /ค้นหา/.test(input) && /ความหมาย|semantic/.test(input) && /โค้ด|โปรเจค|รีโป/.test(input);
109
- const asksQuestion = /\b(do i|have|has)\b|มีไหม|มีมั้ย|มีหรือเปล่า/.test(input);
110
-
111
- return (hasSemanticSearch && referencesCode || thaiSemanticSearch) && !asksQuestion;
112
- }
113
-
114
- /**
115
- * Parses raw CLI args for the semantic code search tool.
116
- * @param {string} rawArgs
117
- * @returns {{ mode: string, query: string, targetPath: string, json: boolean, topK: number }}
118
- */
119
- function parseSemanticCodeArgs(rawArgs) {
120
- const args = (rawArgs || '').split(/\s+/).filter(Boolean);
121
- const json = args.includes('--json');
122
- let topK = 5;
123
- const pathArgs = [];
124
- const queryArgs = [];
125
- let mode = 'search';
126
-
127
- for (let i = 0; i < args.length; i++) {
128
- const arg = args[i];
129
- if (arg === 'index' || arg === 'search') { mode = arg; continue; }
130
- if (arg === '--json') continue;
131
- if (arg === '--top-k' || arg === '--limit') {
132
- const next = Number(args[i + 1]);
133
- if (Number.isFinite(next) && next > 0) { topK = next; i++; }
134
- continue;
135
- }
136
- if (arg.startsWith('--top-k=') || arg.startsWith('--limit=')) {
137
- const next = Number(arg.slice(arg.indexOf('=') + 1));
138
- if (Number.isFinite(next) && next > 0) topK = next;
139
- continue;
140
- }
141
- if (arg === '--path') {
142
- if (args[i + 1]) { pathArgs.push(args[i + 1]); i++; }
143
- continue;
144
- }
145
- queryArgs.push(arg);
146
- }
147
-
148
- return {
149
- mode,
150
- query: queryArgs.join(' ').trim(),
151
- targetPath: pathArgs.length > 0 ? pathArgs.join(' ') : process.cwd(),
152
- json,
153
- topK
154
- };
155
- }
156
-
157
- /**
158
- * Strips intent phrases from text to extract the raw search query.
159
- * @param {string} text
160
- * @returns {string}
161
- */
162
- function extractSemanticCodeQuery(text) {
163
- return String(text || '')
164
- .replace(/semantic\s+code\s+search/ig, '')
165
- .replace(/semantic\s+search/ig, '')
166
- .replace(/search\s+code/ig, '')
167
- .replace(/ค้นหาโค้ดแบบความหมาย/g, '')
168
- .replace(/ค้นหาแบบ semantic/g, '')
169
- .replace(/ใน repo นี้|ในโปรเจคนี้|ในรีโปนี้/g, '')
170
- .trim();
171
- }
172
-
173
- module.exports = {
174
- isRepoSummaryRequest,
175
- parseRepoSummaryArgs,
176
- isSymbolIndexRequest,
177
- parseSymbolIndexArgs,
178
- isSemanticCodeSearchRequest,
179
- parseSemanticCodeArgs,
180
- extractSemanticCodeQuery
181
- };