@pheem49/mint 1.5.1 → 1.5.3

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 (52) hide show
  1. package/GUIDE_TH.md +7 -7
  2. package/README.md +140 -66
  3. package/assets/Agent_Mint.png +0 -0
  4. package/assets/Settings.png +0 -0
  5. package/main.js +12 -0
  6. package/mint-cli.js +148 -921
  7. package/models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json +31 -1
  8. package/models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json +6 -1
  9. package/package.json +20 -21
  10. package/preload.js +2 -0
  11. package/scripts/install_linux_desktop_entry.js +48 -0
  12. package/src/AI_Brain/Gemini_API.js +194 -491
  13. package/src/AI_Brain/autonomous_brain.js +46 -19
  14. package/src/AI_Brain/headless_agent.js +21 -2
  15. package/src/AI_Brain/proactive_engine.js +12 -2
  16. package/src/AI_Brain/provider_adapter.js +358 -0
  17. package/src/Automation_Layer/browser_automation.js +26 -24
  18. package/src/CLI/approval_handler.js +47 -0
  19. package/src/CLI/chat_router.js +7 -0
  20. package/src/CLI/chat_ui.js +586 -80
  21. package/src/CLI/cli_colors.js +115 -0
  22. package/src/CLI/cli_formatters.js +94 -0
  23. package/src/CLI/code_agent.js +825 -283
  24. package/src/CLI/intent_detectors.js +181 -0
  25. package/src/CLI/interactive_chat.js +641 -0
  26. package/src/CLI/list_features.js +3 -0
  27. package/src/CLI/repo_summarizer.js +282 -0
  28. package/src/CLI/semantic_code_search.js +312 -0
  29. package/src/CLI/skill_manager.js +41 -0
  30. package/src/CLI/slash_command_handler.js +418 -0
  31. package/src/CLI/symbol_indexer.js +231 -0
  32. package/src/CLI/updater.js +21 -1
  33. package/src/Channels/discord_bridge.js +11 -13
  34. package/src/Channels/line_bridge.js +10 -10
  35. package/src/Channels/slack_bridge.js +7 -12
  36. package/src/Channels/telegram_bridge.js +6 -14
  37. package/src/Channels/whatsapp_bridge.js +11 -9
  38. package/src/System/chat_history_manager.js +20 -12
  39. package/src/System/config_manager.js +4 -1
  40. package/src/System/ipc_handlers.js +10 -0
  41. package/src/System/optional_require.js +23 -0
  42. package/src/System/picture_store.js +109 -0
  43. package/src/System/task_manager.js +127 -0
  44. package/src/System/tool_registry.js +13 -0
  45. package/src/System/window_manager.js +16 -8
  46. package/src/UI/live2d_manager.js +246 -14
  47. package/src/UI/renderer.js +620 -45
  48. package/src/UI/settings.css +738 -439
  49. package/src/UI/settings.html +487 -432
  50. package/src/UI/settings.js +44 -10
  51. package/src/UI/styles.css +1403 -106
  52. package/privacy.txt +0 -1
@@ -1,10 +1,10 @@
1
- const puppeteer = require('puppeteer');
1
+ 'use strict';
2
+
3
+ const { requireOptional } = require('../System/optional_require');
2
4
  const { GoogleGenAI } = require('@google/genai');
3
5
  const { readConfig } = require('../System/config_manager');
4
6
 
5
- const ai = new GoogleGenAI({});
6
- const DEFAULT_GEMINI_MODEL = 'gemini-2.5-flash';
7
- let lastLoggedModel = '';
7
+
8
8
 
9
9
  const BROWSER_SYSTEM_PROMPT = `You are an Autonomous Browser Agent. Your goal is to fulfill the user's web instruction by driving a headless browser.
10
10
 
@@ -24,6 +24,9 @@ Actions:
24
24
 
25
25
  You will receive the result of your previous action in the next message. If you get stuck or fail, try another approach or use "done" to report the failure.`;
26
26
 
27
+ const DEFAULT_GEMINI_MODEL = 'gemini-2.5-flash';
28
+ let lastLoggedModel = '';
29
+
27
30
  function resolveGeminiModel() {
28
31
  try {
29
32
  const cfg = readConfig();
@@ -35,11 +38,14 @@ function resolveGeminiModel() {
35
38
  }
36
39
 
37
40
  async function performWebAutomation(query) {
38
- if (!query) return "No query provided.";
41
+ if (!query) return 'No query provided.';
39
42
 
40
- console.log("Starting web automation for:", query);
43
+ // Dynamic require user must install puppeteer separately
44
+ const puppeteer = requireOptional('puppeteer', 'npm install puppeteer');
41
45
 
42
46
  const config = readConfig();
47
+ const apiKey = config.apiKey || process.env.GEMINI_API_KEY;
48
+ const ai = new GoogleGenAI({ apiKey });
43
49
  const browserPath = config.automationBrowser;
44
50
 
45
51
  let browser;
@@ -50,7 +56,6 @@ async function performWebAutomation(query) {
50
56
  args: ['--start-maximized']
51
57
  };
52
58
 
53
- // If it's a specific path (like /usr/bin/firefox), set executablePath
54
59
  if (browserPath && browserPath !== 'chromium') {
55
60
  launchOptions.executablePath = browserPath;
56
61
  if (browserPath.toLowerCase().includes('firefox')) {
@@ -59,9 +64,8 @@ async function performWebAutomation(query) {
59
64
  }
60
65
 
61
66
  browser = await puppeteer.launch(launchOptions);
62
-
63
67
  const page = await browser.newPage();
64
-
68
+
65
69
  const model = resolveGeminiModel();
66
70
  if (model && model !== lastLoggedModel) {
67
71
  console.log(`[Gemini] Web Automation model: ${model}`);
@@ -72,12 +76,12 @@ async function performWebAutomation(query) {
72
76
  model,
73
77
  config: {
74
78
  systemInstruction: BROWSER_SYSTEM_PROMPT,
75
- responseMimeType: "application/json"
79
+ responseMimeType: 'application/json'
76
80
  }
77
81
  });
78
82
 
79
83
  let currentObservation = `Goal: ${query}\nSystem Note: You have a blank browser page. What is your first action? Start by using "goto" to navigate to a relevant search engine or website.`;
80
-
84
+
81
85
  let maxSteps = 10;
82
86
  let step = 0;
83
87
 
@@ -87,27 +91,26 @@ async function performWebAutomation(query) {
87
91
  console.log(`Observation:`, currentObservation.substring(0, 150) + (currentObservation.length > 150 ? '...' : ''));
88
92
 
89
93
  const response = await chat.sendMessage({ message: currentObservation });
90
-
94
+
91
95
  let parsed;
92
96
  try {
93
97
  const text = response.text;
94
98
  const cleanText = text.replace(/^```json\n/, '').replace(/\n```$/, '').trim();
95
99
  parsed = JSON.parse(cleanText);
96
100
  } catch (e) {
97
- console.error("Agent failed to return valid JSON:", response.text);
98
- currentObservation = "Error: Invalid JSON returned. Please reply with ONLY valid JSON matching the schema.";
101
+ console.error('Agent failed to return valid JSON:', response.text);
102
+ currentObservation = 'Error: Invalid JSON returned. Please reply with ONLY valid JSON matching the schema.';
99
103
  continue;
100
104
  }
101
105
 
102
- console.log("Agent Thought:", parsed.thought);
103
- console.log("Agent Action:", parsed.action);
104
- console.log("Agent Target:", parsed.target);
106
+ console.log('Agent Thought:', parsed.thought);
107
+ console.log('Agent Action:', parsed.action);
108
+ console.log('Agent Target:', parsed.target);
105
109
 
106
110
  const { action, target } = parsed;
107
111
 
108
112
  if (action === 'done') {
109
- console.log("Agent finished with answer:", target);
110
- // Intentionally keeping the browser open so the user can see the page.
113
+ console.log('Agent finished with answer:', target);
111
114
  return `🤖 Web Automation Result: ${target}`;
112
115
  }
113
116
 
@@ -119,7 +122,7 @@ async function performWebAutomation(query) {
119
122
  } else if (action === 'click') {
120
123
  await page.waitForSelector(target, { timeout: 5000 });
121
124
  await page.click(target);
122
- await new Promise(r => setTimeout(r, 2000));
125
+ await new Promise(r => setTimeout(r, 2000));
123
126
  const pageTitle = await page.title();
124
127
  currentObservation = `Clicked element. Current page: ${pageTitle}. ` + await page.evaluate(() => document.body.innerText.substring(0, 1500));
125
128
  } else if (action === 'eval') {
@@ -129,16 +132,15 @@ async function performWebAutomation(query) {
129
132
  currentObservation = `Error: Unknown action type "${action}".`;
130
133
  }
131
134
  } catch (actionError) {
132
- console.error("Action execution failed:", actionError);
135
+ console.error('Action execution failed:', actionError);
133
136
  currentObservation = `Action failed: ${actionError.message}. Please try again or use another method (for instance, try a different CSS selector or just read the current page).`;
134
137
  }
135
138
  }
136
139
 
137
- // Intentionally keeping the browser open
138
- return "Agent reached maximum steps (10) without finding a final answer.";
140
+ return 'Agent reached maximum steps (10) without finding a final answer.';
139
141
 
140
142
  } catch (error) {
141
- console.error("Web Automation Error:", error);
143
+ console.error('Web Automation Error:', error);
142
144
  if (browser) browser.close();
143
145
  return `I encountered an overall error while automating the browser: ${error.message}`;
144
146
  }
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ const readline = require('readline');
4
+ const { colors } = require('./cli_colors');
5
+
6
+ /**
7
+ * Prompts the user in the terminal to approve or deny a code-agent action.
8
+ * Used by the non-interactive `mint code <task>` command.
9
+ *
10
+ * @param {{ type: string, label?: string, preview?: string }} request
11
+ * @returns {Promise<boolean>} true = approved, false = denied
12
+ */
13
+ async function requestCodeApproval(request) {
14
+ const typeLabel =
15
+ request.type === 'shell' ? 'Shell Command' :
16
+ request.type === 'patch' ? 'Patch Edit' :
17
+ 'File Write';
18
+
19
+ console.log(`\n${colors.yellow}${colors.bright}[Approval Required]${colors.reset} ${typeLabel}`);
20
+ if (request.label) console.log(`${colors.gray}${request.label}${colors.reset}`);
21
+ if (Array.isArray(request.warnings) && request.warnings.length > 0) {
22
+ request.warnings.forEach((warning) => {
23
+ console.log(`${colors.yellow}Warning:${colors.reset} ${warning}`);
24
+ });
25
+ }
26
+ if (request.preview) console.log(`${colors.gray}${request.preview}${colors.reset}\n`);
27
+
28
+ const rl = readline.createInterface({
29
+ input: process.stdin,
30
+ output: process.stdout
31
+ });
32
+
33
+ const answer = await new Promise((resolve) => {
34
+ rl.question('Approve this action? [y/N]: ', (value) => {
35
+ rl.close();
36
+ resolve((value || '').trim().toLowerCase());
37
+ });
38
+ });
39
+
40
+ const approved = answer === 'y' || answer === 'yes';
41
+ console.log(approved
42
+ ? `${colors.mint}[Mint Code] Approved.${colors.reset}\n`
43
+ : `${colors.pink}[Mint Code] Denied.${colors.reset}\n`);
44
+ return approved;
45
+ }
46
+
47
+ module.exports = { requestCodeApproval };
@@ -119,6 +119,13 @@ async function detectCodeIntent(text, workspaceRoot = process.cwd(), history = [
119
119
  }
120
120
 
121
121
  const heuristicRoute = detectCodeIntentHeuristic(input, workspaceRoot);
122
+ if (!heuristicRoute) {
123
+ return {
124
+ route: 'chat',
125
+ reason: 'No substantial code intent detected.'
126
+ };
127
+ }
128
+
122
129
  const routerClient = getRouterClient();
123
130
  if (!routerClient) {
124
131
  return {