@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,282 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { execFileSync } = require('child_process');
4
-
5
- const IGNORED_DIRS = new Set([
6
- '.git',
7
- '.cache',
8
- '.next',
9
- '.nuxt',
10
- 'coverage',
11
- 'dist',
12
- 'build',
13
- 'out',
14
- 'node_modules'
15
- ]);
16
-
17
- const LANGUAGE_BY_EXT = {
18
- '.cjs': 'JavaScript',
19
- '.css': 'CSS',
20
- '.html': 'HTML',
21
- '.js': 'JavaScript',
22
- '.json': 'JSON',
23
- '.jsx': 'JavaScript',
24
- '.md': 'Markdown',
25
- '.mjs': 'JavaScript',
26
- '.py': 'Python',
27
- '.rs': 'Rust',
28
- '.sh': 'Shell',
29
- '.ts': 'TypeScript',
30
- '.tsx': 'TypeScript',
31
- '.vue': 'Vue',
32
- '.yaml': 'YAML',
33
- '.yml': 'YAML'
34
- };
35
-
36
- function safeReadJson(filePath) {
37
- try {
38
- return JSON.parse(fs.readFileSync(filePath, 'utf8'));
39
- } catch (_) {
40
- return null;
41
- }
42
- }
43
-
44
- function safeGit(root, args) {
45
- try {
46
- return execFileSync('git', args, {
47
- cwd: root,
48
- encoding: 'utf8',
49
- stdio: ['ignore', 'pipe', 'ignore'],
50
- maxBuffer: 1024 * 1024
51
- }).trim();
52
- } catch (_) {
53
- return '';
54
- }
55
- }
56
-
57
- function walkFiles(root, options = {}) {
58
- const maxFiles = options.maxFiles || 2500;
59
- const files = [];
60
-
61
- function visit(dir) {
62
- let entries = [];
63
- try {
64
- entries = fs.readdirSync(dir, { withFileTypes: true });
65
- } catch (_) {
66
- return;
67
- }
68
-
69
- entries.sort((a, b) => a.name.localeCompare(b.name));
70
- for (const entry of entries) {
71
- if (files.length >= maxFiles) return;
72
- const fullPath = path.join(dir, entry.name);
73
- const relativePath = path.relative(root, fullPath);
74
-
75
- if (entry.isDirectory()) {
76
- if (IGNORED_DIRS.has(entry.name)) continue;
77
- visit(fullPath);
78
- continue;
79
- }
80
-
81
- if (entry.isFile()) {
82
- files.push(relativePath);
83
- }
84
- }
85
- }
86
-
87
- visit(root);
88
- return files;
89
- }
90
-
91
- function summarizeLanguages(files) {
92
- const counts = new Map();
93
- for (const file of files) {
94
- const language = LANGUAGE_BY_EXT[path.extname(file).toLowerCase()] || 'Other';
95
- counts.set(language, (counts.get(language) || 0) + 1);
96
- }
97
-
98
- return Array.from(counts.entries())
99
- .map(([language, count]) => ({ language, count }))
100
- .sort((a, b) => b.count - a.count || a.language.localeCompare(b.language));
101
- }
102
-
103
- function findImportantFiles(files) {
104
- const importantPatterns = [
105
- /^README/i,
106
- /^package\.json$/,
107
- /^RELEASE_NOTES\.md$/,
108
- /^CHANGELOG/i,
109
- /^Dockerfile$/,
110
- /^docker-compose\./,
111
- /^\.github\//,
112
- /^src\//,
113
- /^tests?\//,
114
- /config/i,
115
- /\.(test|spec)\.[cm]?[jt]sx?$/
116
- ];
117
-
118
- return files
119
- .filter(file => importantPatterns.some(pattern => pattern.test(file)))
120
- .slice(0, 30);
121
- }
122
-
123
- function summarizeTopDirs(files) {
124
- const counts = new Map();
125
- for (const file of files) {
126
- const top = file.includes(path.sep) ? file.split(path.sep)[0] : '(root)';
127
- counts.set(top, (counts.get(top) || 0) + 1);
128
- }
129
-
130
- return Array.from(counts.entries())
131
- .map(([dir, count]) => ({ dir, count }))
132
- .sort((a, b) => b.count - a.count || a.dir.localeCompare(b.dir))
133
- .slice(0, 12);
134
- }
135
-
136
- function summarizePackage(root) {
137
- const pkg = safeReadJson(path.join(root, 'package.json'));
138
- if (!pkg) return null;
139
-
140
- return {
141
- name: pkg.name || '',
142
- version: pkg.version || '',
143
- description: pkg.description || '',
144
- scripts: Object.keys(pkg.scripts || {}),
145
- dependencies: Object.keys(pkg.dependencies || {}),
146
- devDependencies: Object.keys(pkg.devDependencies || {})
147
- };
148
- }
149
-
150
- function summarizeGit(root) {
151
- const inside = safeGit(root, ['rev-parse', '--is-inside-work-tree']) === 'true';
152
- if (!inside) {
153
- return { isRepo: false };
154
- }
155
-
156
- return {
157
- isRepo: true,
158
- branch: safeGit(root, ['branch', '--show-current']) || '(detached HEAD)',
159
- status: safeGit(root, ['status', '--short']) || '(clean)',
160
- diffStat: safeGit(root, ['diff', '--stat']) || '(no unstaged diff)'
161
- };
162
- }
163
-
164
- function summarizeRepository(targetPath = process.cwd(), options = {}) {
165
- const root = path.resolve(targetPath);
166
- const stat = fs.statSync(root);
167
- if (!stat.isDirectory()) {
168
- throw new Error(`Repository path is not a directory: ${root}`);
169
- }
170
-
171
- const files = walkFiles(root, options);
172
- return {
173
- root,
174
- fileCount: files.length,
175
- topDirs: summarizeTopDirs(files),
176
- languages: summarizeLanguages(files),
177
- importantFiles: findImportantFiles(files),
178
- package: summarizePackage(root),
179
- git: summarizeGit(root)
180
- };
181
- }
182
-
183
- function formatList(items, formatter, emptyText = '(none)') {
184
- if (!Array.isArray(items) || items.length === 0) return `- ${emptyText}`;
185
- return items.map(formatter).join('\n');
186
- }
187
-
188
- function formatMultilineField(label, value, emptyText) {
189
- const text = value || emptyText;
190
- const lines = String(text).split('\n');
191
- if (lines.length === 1) {
192
- return `- ${label}: ${lines[0]}`;
193
- }
194
- return [
195
- `- ${label}:`,
196
- ...lines.map(line => ` ${line}`)
197
- ].join('\n');
198
- }
199
-
200
- function formatRepoSummary(summary) {
201
- const pkg = summary.package;
202
- const git = summary.git;
203
- const lines = [];
204
-
205
- lines.push(`# Repository Summary`);
206
- lines.push('');
207
- lines.push(`Root: ${summary.root}`);
208
- if (pkg?.name) {
209
- lines.push(`Package: ${pkg.name}${pkg.version ? ` v${pkg.version}` : ''}`);
210
- }
211
- if (pkg?.description) {
212
- lines.push(`Description: ${pkg.description}`);
213
- lines.push('');
214
- }
215
- lines.push(`Files scanned: ${summary.fileCount}`);
216
-
217
- lines.push('');
218
- lines.push(`## Git`);
219
- if (!git?.isRepo) {
220
- lines.push('- Not a git repository');
221
- } else {
222
- lines.push(`- Branch: ${git.branch}`);
223
- lines.push(formatMultilineField('Status', git.status, '(clean)'));
224
- lines.push(formatMultilineField('Diff', git.diffStat, '(no unstaged diff)'));
225
- }
226
-
227
- lines.push('');
228
- lines.push(`## Top Directories`);
229
- lines.push(formatList(
230
- summary.topDirs,
231
- item => `- ${item.dir}: ${item.count} file(s)`
232
- ));
233
-
234
- lines.push('');
235
- lines.push(`## Languages`);
236
- lines.push(formatList(
237
- summary.languages.slice(0, 10),
238
- item => `- ${item.language}: ${item.count} file(s)`
239
- ));
240
-
241
- lines.push('');
242
- lines.push(`## Package Scripts`);
243
- lines.push(formatList(
244
- pkg?.scripts || [],
245
- script => `- ${script}`
246
- ));
247
-
248
- lines.push('');
249
- lines.push(`## Dependencies`);
250
- if (pkg) {
251
- const depCount = pkg.dependencies.length;
252
- const devDepCount = pkg.devDependencies.length;
253
- lines.push(`- Runtime: ${depCount}`);
254
- lines.push(`- Development: ${devDepCount}`);
255
- const notable = pkg.dependencies.slice(0, 12);
256
- if (notable.length > 0) {
257
- lines.push(`- Notable runtime deps: ${notable.join(', ')}`);
258
- }
259
- } else {
260
- lines.push('- No package.json found');
261
- }
262
-
263
- lines.push('');
264
- lines.push(`## Important Files`);
265
- lines.push(formatList(
266
- summary.importantFiles,
267
- file => `- ${file}`
268
- ));
269
-
270
- return lines.join('\n');
271
- }
272
-
273
- module.exports = {
274
- summarizeRepository,
275
- formatRepoSummary,
276
- _helpers: {
277
- walkFiles,
278
- summarizeLanguages,
279
- summarizeTopDirs,
280
- findImportantFiles
281
- }
282
- };
@@ -1,312 +0,0 @@
1
- const fs = require('fs');
2
- const os = require('os');
3
- const path = require('path');
4
- const crypto = require('crypto');
5
- const { GoogleGenAI } = require('@google/genai');
6
- const { readConfig } = require('../System/config_manager');
7
- const { _helpers: symbolHelpers } = require('./symbol_indexer');
8
-
9
- const DEFAULT_EMBEDDING_MODEL = 'gemini-embedding-001';
10
- const DEFAULT_MAX_CHARS = 1800;
11
- const DEFAULT_OVERLAP_LINES = 8;
12
- const DEFAULT_MAX_FILE_BYTES = 512 * 1024;
13
-
14
- function getStoreDir(options = {}) {
15
- const dir = path.join(os.homedir(), '.config', 'mint', 'semantic-code');
16
- if (options.create) {
17
- fs.mkdirSync(dir, { recursive: true });
18
- }
19
- return dir;
20
- }
21
-
22
- function getWorkspaceStorePath(root, options = {}) {
23
- const hash = crypto.createHash('sha1').update(path.resolve(root)).digest('hex').slice(0, 16);
24
- return path.join(getStoreDir(options), `${hash}.json`);
25
- }
26
-
27
- function resolveApiKey() {
28
- let settingsKey = '';
29
- try {
30
- settingsKey = (readConfig().apiKey || '').trim();
31
- } catch (_) {
32
- settingsKey = '';
33
- }
34
- return settingsKey || process.env.GEMINI_API_KEY || '';
35
- }
36
-
37
- async function defaultEmbedText(text, model = DEFAULT_EMBEDDING_MODEL) {
38
- const apiKey = resolveApiKey();
39
- if (!apiKey) {
40
- throw new Error('Gemini API key is required for semantic code embeddings.');
41
- }
42
-
43
- const client = new GoogleGenAI({ apiKey });
44
- const response = await client.models.embedContent({
45
- model,
46
- contents: text
47
- });
48
- return response.embeddings[0].values;
49
- }
50
-
51
- function hashFile(filePath) {
52
- return crypto.createHash('sha1').update(fs.readFileSync(filePath)).digest('hex');
53
- }
54
-
55
- function cosineSimilarity(vecA, vecB) {
56
- let dot = 0;
57
- let normA = 0;
58
- let normB = 0;
59
- const length = Math.min(vecA.length, vecB.length);
60
-
61
- for (let index = 0; index < length; index++) {
62
- const a = vecA[index];
63
- const b = vecB[index];
64
- dot += a * b;
65
- normA += a * a;
66
- normB += b * b;
67
- }
68
-
69
- if (normA === 0 || normB === 0) return 0;
70
- return dot / (Math.sqrt(normA) * Math.sqrt(normB));
71
- }
72
-
73
- function languageForFile(file) {
74
- const ext = path.extname(file).toLowerCase();
75
- if (ext === '.py') return 'Python';
76
- if (ext === '.rs') return 'Rust';
77
- if (ext === '.ts' || ext === '.tsx') return 'TypeScript';
78
- return 'JavaScript';
79
- }
80
-
81
- function chunkLines(lines, maxChars = DEFAULT_MAX_CHARS, overlapLines = DEFAULT_OVERLAP_LINES) {
82
- const chunks = [];
83
- let start = 0;
84
-
85
- while (start < lines.length) {
86
- let end = start;
87
- let charCount = 0;
88
-
89
- while (end < lines.length && (charCount + lines[end].length + 1 <= maxChars || end === start)) {
90
- charCount += lines[end].length + 1;
91
- end++;
92
- }
93
-
94
- chunks.push({
95
- startLine: start + 1,
96
- endLine: end,
97
- content: lines.slice(start, end).join('\n')
98
- });
99
-
100
- if (end >= lines.length) break;
101
- start = Math.max(end - overlapLines, start + 1);
102
- }
103
-
104
- return chunks;
105
- }
106
-
107
- function createCodeChunks(targetPath = process.cwd(), options = {}) {
108
- const root = path.resolve(targetPath);
109
- const stat = fs.statSync(root);
110
- if (!stat.isDirectory()) {
111
- throw new Error(`Semantic code search path is not a directory: ${root}`);
112
- }
113
-
114
- const files = symbolHelpers.walkSourceFiles(root, options);
115
- const maxFileBytes = options.maxFileBytes || DEFAULT_MAX_FILE_BYTES;
116
- const chunks = [];
117
- const fileHashes = {};
118
-
119
- for (const file of files) {
120
- const fullPath = path.join(root, file);
121
- let fileStat;
122
- try {
123
- fileStat = fs.statSync(fullPath);
124
- } catch (_) {
125
- continue;
126
- }
127
- if (!fileStat.isFile() || fileStat.size > maxFileBytes) continue;
128
-
129
- let content = '';
130
- try {
131
- content = fs.readFileSync(fullPath, 'utf8');
132
- } catch (_) {
133
- continue;
134
- }
135
- if (!content.trim()) continue;
136
-
137
- const language = languageForFile(file);
138
- const symbols = symbolHelpers.indexFileSymbols(root, file).map(symbol => symbol.name);
139
- fileHashes[file] = hashFile(fullPath);
140
-
141
- for (const chunk of chunkLines(content.split('\n'), options.maxChars || DEFAULT_MAX_CHARS, options.overlapLines || DEFAULT_OVERLAP_LINES)) {
142
- const header = [
143
- `File: ${file}`,
144
- `Language: ${language}`,
145
- symbols.length > 0 ? `Symbols: ${symbols.slice(0, 20).join(', ')}` : ''
146
- ].filter(Boolean).join('\n');
147
-
148
- chunks.push({
149
- id: `${file}:${chunk.startLine}-${chunk.endLine}`,
150
- file,
151
- language,
152
- startLine: chunk.startLine,
153
- endLine: chunk.endLine,
154
- symbols,
155
- text: `${header}\n\n${chunk.content}`
156
- });
157
- }
158
- }
159
-
160
- return { root, files, fileHashes, chunks };
161
- }
162
-
163
- function writeJson(filePath, data) {
164
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
165
- const tmpPath = `${filePath}.tmp`;
166
- fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2), 'utf8');
167
- fs.renameSync(tmpPath, filePath);
168
- }
169
-
170
- async function indexSemanticCode(targetPath = process.cwd(), options = {}) {
171
- const root = path.resolve(targetPath);
172
- const embedText = options.embedText || defaultEmbedText;
173
- const model = options.model || DEFAULT_EMBEDDING_MODEL;
174
- const storePath = options.storePath || getWorkspaceStorePath(root, { create: true });
175
- const prepared = createCodeChunks(root, options);
176
- const indexedChunks = [];
177
-
178
- for (let index = 0; index < prepared.chunks.length; index++) {
179
- const chunk = prepared.chunks[index];
180
- if (typeof options.onProgress === 'function') {
181
- options.onProgress({ current: index + 1, total: prepared.chunks.length, file: chunk.file });
182
- }
183
- const embedding = await embedText(chunk.text, model);
184
- indexedChunks.push({ ...chunk, embedding });
185
- }
186
-
187
- const payload = {
188
- version: 1,
189
- root: prepared.root,
190
- model,
191
- indexedAt: new Date().toISOString(),
192
- fileCount: prepared.files.length,
193
- chunkCount: indexedChunks.length,
194
- fileHashes: prepared.fileHashes,
195
- chunks: indexedChunks
196
- };
197
- writeJson(storePath, payload);
198
-
199
- return { ...payload, storePath };
200
- }
201
-
202
- function loadSemanticCodeIndex(targetPath = process.cwd(), options = {}) {
203
- const root = path.resolve(targetPath);
204
- const storePath = options.storePath || getWorkspaceStorePath(root);
205
- if (!fs.existsSync(storePath)) {
206
- throw new Error(`Semantic code index not found. Run "mint semantic-code index ${root}" first.`);
207
- }
208
-
209
- const payload = JSON.parse(fs.readFileSync(storePath, 'utf8'));
210
- if (path.resolve(payload.root) !== root) {
211
- throw new Error(`Semantic code index belongs to a different workspace: ${payload.root}`);
212
- }
213
- return { ...payload, storePath };
214
- }
215
-
216
- async function searchSemanticCode(query, targetPath = process.cwd(), options = {}) {
217
- const trimmedQuery = String(query || '').trim();
218
- if (!trimmedQuery) {
219
- throw new Error('Semantic code search query is required.');
220
- }
221
-
222
- const index = loadSemanticCodeIndex(targetPath, options);
223
- const embedText = options.embedText || defaultEmbedText;
224
- const topK = options.topK || 5;
225
- const queryEmbedding = await embedText(trimmedQuery, index.model || DEFAULT_EMBEDDING_MODEL);
226
-
227
- const results = index.chunks
228
- .filter(chunk => Array.isArray(chunk.embedding))
229
- .map(chunk => ({
230
- file: chunk.file,
231
- language: chunk.language,
232
- startLine: chunk.startLine,
233
- endLine: chunk.endLine,
234
- symbols: chunk.symbols || [],
235
- score: cosineSimilarity(queryEmbedding, chunk.embedding),
236
- text: chunk.text
237
- }))
238
- .sort((a, b) => b.score - a.score)
239
- .slice(0, topK);
240
-
241
- return {
242
- query: trimmedQuery,
243
- root: index.root,
244
- indexedAt: index.indexedAt,
245
- model: index.model,
246
- resultCount: results.length,
247
- results
248
- };
249
- }
250
-
251
- function formatSemanticCodeIndex(index) {
252
- return [
253
- '# Semantic Code Index',
254
- '',
255
- `Root: ${index.root}`,
256
- `Source files scanned: ${index.fileCount}`,
257
- `Chunks embedded: ${index.chunkCount}`,
258
- `Embedding model: ${index.model}`,
259
- `Index file: ${index.storePath}`
260
- ].join('\n');
261
- }
262
-
263
- function firstCodeLine(text) {
264
- return String(text || '')
265
- .split('\n')
266
- .map(line => line.trim())
267
- .find(line => line && !line.startsWith('File:') && !line.startsWith('Language:') && !line.startsWith('Symbols:')) || '';
268
- }
269
-
270
- function formatSemanticCodeSearch(results) {
271
- const lines = [
272
- '# Semantic Code Search',
273
- '',
274
- `Query: ${results.query}`,
275
- `Root: ${results.root}`,
276
- `Indexed at: ${results.indexedAt}`,
277
- ''
278
- ];
279
-
280
- if (!results.results.length) {
281
- lines.push('No matches found.');
282
- return lines.join('\n');
283
- }
284
-
285
- results.results.forEach((result, index) => {
286
- lines.push(`${index + 1}. ${result.file}:${result.startLine}-${result.endLine} (${result.score.toFixed(3)})`);
287
- if (result.symbols.length > 0) {
288
- lines.push(` Symbols: ${result.symbols.slice(0, 8).join(', ')}`);
289
- }
290
- const preview = firstCodeLine(result.text);
291
- if (preview) {
292
- lines.push(` ${preview}`);
293
- }
294
- });
295
-
296
- return lines.join('\n');
297
- }
298
-
299
- module.exports = {
300
- createCodeChunks,
301
- indexSemanticCode,
302
- loadSemanticCodeIndex,
303
- searchSemanticCode,
304
- formatSemanticCodeIndex,
305
- formatSemanticCodeSearch,
306
- _helpers: {
307
- chunkLines,
308
- cosineSimilarity,
309
- getWorkspaceStorePath,
310
- defaultEmbedText
311
- }
312
- };
@@ -1,41 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const memoryStore = require('../AI_Brain/memory_store');
6
-
7
- /**
8
- * Reads a local .md or .txt file and stores it as a persistent Mint skill.
9
- *
10
- * @param {string} filePath Path relative to process.cwd() or absolute.
11
- * @returns {object} The stored skill record from memoryStore.
12
- * @throws {Error} If the file doesn't exist, isn't a file, has the wrong extension,
13
- * or exceeds the size limit.
14
- */
15
- function learnSkillFile(filePath) {
16
- const targetPath = path.resolve(process.cwd(), filePath);
17
-
18
- if (!fs.existsSync(targetPath)) {
19
- throw new Error(`File not found: ${targetPath}`);
20
- }
21
-
22
- const stat = fs.statSync(targetPath);
23
- if (!stat.isFile()) {
24
- throw new Error(`Path is not a file: ${targetPath}`);
25
- }
26
-
27
- const ext = path.extname(targetPath).toLowerCase();
28
- if (ext !== '.md' && ext !== '.txt') {
29
- throw new Error('Mint learn currently supports .md and .txt files only.');
30
- }
31
-
32
- const maxBytes = 256 * 1024;
33
- if (stat.size > maxBytes) {
34
- throw new Error(`File is too large (${stat.size} bytes). Limit is ${maxBytes} bytes.`);
35
- }
36
-
37
- const content = fs.readFileSync(targetPath, 'utf8');
38
- return memoryStore.addLearnedSkill(path.basename(targetPath), targetPath, content);
39
- }
40
-
41
- module.exports = { learnSkillFile };