@umastro12/mino 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -0
- package/bun.lock +194 -0
- package/mino_banner.png +0 -0
- package/mino_oc.png +0 -0
- package/package.json +32 -0
- package/src/cli/main.ts +45 -0
- package/src/cli/tsconfig.json +10 -0
- package/src/commands/ask.ts +25 -0
- package/src/commands/token-limit.ts +64 -0
- package/src/executor.ts +139 -0
- package/src/index.ts +29 -0
- package/src/prompts/systemPrompt.ts +26 -0
- package/src/services/APIClient.ts +24 -0
- package/src/services/UpdaterService.ts +60 -0
- package/src/services/tsconfig.json +7 -0
- package/src/ui/renderer.ts +35 -0
- package/src/ui/spinner.ts +36 -0
- package/tsconfig.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# ๐ป Mino โ Personal Developer AI Assistent
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="mino_banner.png" alt="Mino" width="300">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
An AI Assistent that help developers directly into the terminal, with the power of **qwen/qwen3-32b** Model. Think of it as your personal AI pair programmer, researcher, and assistant โ always ready, always fast.
|
|
8
|
+
|
|
9
|
+
<h2 align=center>๐ธ Support Mino's Project</h2>
|
|
10
|
+
<p align=center>Loves Mino? Support us in <strong>Livepix</strong>, Your support keeps this project alive and growing! This is a 100% free, open-source project developed with countless hours of dedication.</p>
|
|
11
|
+
|
|
12
|
+
<div align=center>
|
|
13
|
+
|
|
14
|
+
**[๐ Click here to support the project](https://livepix.gg/astrooficial)**
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
## ๐ Installation
|
|
19
|
+
|
|
20
|
+
### Quick Install
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
npm install -g openmino
|
|
24
|
+
Or...
|
|
25
|
+
bun add openmino
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
After installation, the `mino` command is available globally:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
mino welcome
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## โ๏ธ Configuration
|
|
37
|
+
|
|
38
|
+
Mino uses **Groq API Key**, you can use your Own qwen3 API Key.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Linux/MacOS
|
|
42
|
+
export AI_API_KEY
|
|
43
|
+
|
|
44
|
+
# Windows
|
|
45
|
+
$env:AI_API_KEY
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## ๐ซ Tools
|
|
49
|
+
|
|
50
|
+
Mino can:
|
|
51
|
+
|
|
52
|
+
- write project structure files
|
|
53
|
+
- run commands
|
|
54
|
+
- search the web
|
|
55
|
+
|
|
56
|
+
## ๐ ๏ธ CLI Commands
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
mino welcome # - Show Mino's Welcome Panel
|
|
60
|
+
|
|
61
|
+
mino help # - Show Help(Alias: -h, --help)
|
|
62
|
+
|
|
63
|
+
mino ask # - Ask a Quick Question with qwen/qwen3-32b Model
|
|
64
|
+
|
|
65
|
+
mino update install # - Install a avaialable update
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
<h3 align=center>Developed with โค๏ธ by OpenMino and Astro</h3>
|
|
71
|
+
<p align=center><strong>Version 0.0.1 ยท 20+ Tests passing ยท 1 AI Model</strong></p>
|
package/bun.lock
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@types/node": "^25.8.0",
|
|
8
|
+
"boxen": "^8.0.1",
|
|
9
|
+
"chalk": "^5.6.2",
|
|
10
|
+
"commander": "^14.0.3",
|
|
11
|
+
"fs": "^0.0.1-security",
|
|
12
|
+
"groq-sdk": "^1.2.0",
|
|
13
|
+
"marked": "^18.0.3",
|
|
14
|
+
"marked-terminal": "^7.3.0",
|
|
15
|
+
"ora": "^9.4.0",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
"packages": {
|
|
20
|
+
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
|
21
|
+
|
|
22
|
+
"@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="],
|
|
23
|
+
|
|
24
|
+
"@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="],
|
|
25
|
+
|
|
26
|
+
"ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="],
|
|
27
|
+
|
|
28
|
+
"ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="],
|
|
29
|
+
|
|
30
|
+
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
|
31
|
+
|
|
32
|
+
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
33
|
+
|
|
34
|
+
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
|
|
35
|
+
|
|
36
|
+
"boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
|
|
37
|
+
|
|
38
|
+
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
|
|
39
|
+
|
|
40
|
+
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
41
|
+
|
|
42
|
+
"char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
|
43
|
+
|
|
44
|
+
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
|
45
|
+
|
|
46
|
+
"cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
|
|
47
|
+
|
|
48
|
+
"cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="],
|
|
49
|
+
|
|
50
|
+
"cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="],
|
|
51
|
+
|
|
52
|
+
"cli-table3": ["cli-table3@0.6.5", "", { "dependencies": { "string-width": "^4.2.0" }, "optionalDependencies": { "@colors/colors": "1.5.0" } }, "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ=="],
|
|
53
|
+
|
|
54
|
+
"cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="],
|
|
55
|
+
|
|
56
|
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
|
57
|
+
|
|
58
|
+
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
|
59
|
+
|
|
60
|
+
"commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
|
|
61
|
+
|
|
62
|
+
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
|
63
|
+
|
|
64
|
+
"emojilib": ["emojilib@2.4.0", "", {}, "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw=="],
|
|
65
|
+
|
|
66
|
+
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
|
67
|
+
|
|
68
|
+
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
|
69
|
+
|
|
70
|
+
"fs": ["fs@0.0.1-security", "", {}, "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="],
|
|
71
|
+
|
|
72
|
+
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
|
73
|
+
|
|
74
|
+
"get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="],
|
|
75
|
+
|
|
76
|
+
"groq-sdk": ["groq-sdk@1.2.0", "", { "bin": { "groq-sdk": "bin/cli" } }, "sha512-pMhSYXWcjiqvbOeKdv2zjci1BYjGdp04a40hnmQmJpKJyB6oa+gRndAqE128gwR0NLgYO+Wt1fIF46KNHcplsw=="],
|
|
77
|
+
|
|
78
|
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
|
79
|
+
|
|
80
|
+
"highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="],
|
|
81
|
+
|
|
82
|
+
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
|
83
|
+
|
|
84
|
+
"is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
|
|
85
|
+
|
|
86
|
+
"is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
|
|
87
|
+
|
|
88
|
+
"log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="],
|
|
89
|
+
|
|
90
|
+
"marked": ["marked@18.0.3", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-7VT90JOkDeaRWpfjOReRGPEKn0ecdARBkDGL+tT1wZY0efPPqkUxLUSmzy/C7TIylQYJC9STISEsCHrqb/7VIA=="],
|
|
91
|
+
|
|
92
|
+
"marked-terminal": ["marked-terminal@7.3.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "ansi-regex": "^6.1.0", "chalk": "^5.4.1", "cli-highlight": "^2.1.11", "cli-table3": "^0.6.5", "node-emoji": "^2.2.0", "supports-hyperlinks": "^3.1.0" }, "peerDependencies": { "marked": ">=1 <16" } }, "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw=="],
|
|
93
|
+
|
|
94
|
+
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
|
95
|
+
|
|
96
|
+
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
|
|
97
|
+
|
|
98
|
+
"node-emoji": ["node-emoji@2.2.0", "", { "dependencies": { "@sindresorhus/is": "^4.6.0", "char-regex": "^1.0.2", "emojilib": "^2.4.0", "skin-tone": "^2.0.0" } }, "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw=="],
|
|
99
|
+
|
|
100
|
+
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
|
101
|
+
|
|
102
|
+
"onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
|
|
103
|
+
|
|
104
|
+
"ora": ["ora@9.4.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.3.2", "string-width": "^8.1.0" } }, "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ=="],
|
|
105
|
+
|
|
106
|
+
"parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="],
|
|
107
|
+
|
|
108
|
+
"parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="],
|
|
109
|
+
|
|
110
|
+
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
|
111
|
+
|
|
112
|
+
"restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
|
|
113
|
+
|
|
114
|
+
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
|
115
|
+
|
|
116
|
+
"skin-tone": ["skin-tone@2.0.0", "", { "dependencies": { "unicode-emoji-modifier-base": "^1.0.0" } }, "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA=="],
|
|
117
|
+
|
|
118
|
+
"stdin-discarder": ["stdin-discarder@0.3.2", "", {}, "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A=="],
|
|
119
|
+
|
|
120
|
+
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
|
121
|
+
|
|
122
|
+
"strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
|
123
|
+
|
|
124
|
+
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
|
125
|
+
|
|
126
|
+
"supports-hyperlinks": ["supports-hyperlinks@3.2.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig=="],
|
|
127
|
+
|
|
128
|
+
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
|
|
129
|
+
|
|
130
|
+
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
|
|
131
|
+
|
|
132
|
+
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
|
133
|
+
|
|
134
|
+
"undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="],
|
|
135
|
+
|
|
136
|
+
"unicode-emoji-modifier-base": ["unicode-emoji-modifier-base@1.0.0", "", {}, "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g=="],
|
|
137
|
+
|
|
138
|
+
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
|
|
139
|
+
|
|
140
|
+
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
|
141
|
+
|
|
142
|
+
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
|
143
|
+
|
|
144
|
+
"yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="],
|
|
145
|
+
|
|
146
|
+
"yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
|
|
147
|
+
|
|
148
|
+
"yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
|
|
149
|
+
|
|
150
|
+
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
|
151
|
+
|
|
152
|
+
"cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
|
153
|
+
|
|
154
|
+
"cli-table3/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
|
155
|
+
|
|
156
|
+
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
|
157
|
+
|
|
158
|
+
"cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
159
|
+
|
|
160
|
+
"cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
|
161
|
+
|
|
162
|
+
"ora/string-width": ["string-width@8.2.1", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA=="],
|
|
163
|
+
|
|
164
|
+
"parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="],
|
|
165
|
+
|
|
166
|
+
"yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
|
167
|
+
|
|
168
|
+
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
169
|
+
|
|
170
|
+
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
171
|
+
|
|
172
|
+
"cli-highlight/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
|
173
|
+
|
|
174
|
+
"cli-table3/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
175
|
+
|
|
176
|
+
"cli-table3/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
177
|
+
|
|
178
|
+
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
179
|
+
|
|
180
|
+
"cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
181
|
+
|
|
182
|
+
"cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
|
183
|
+
|
|
184
|
+
"yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
185
|
+
|
|
186
|
+
"yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
187
|
+
|
|
188
|
+
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
189
|
+
|
|
190
|
+
"cli-table3/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
191
|
+
|
|
192
|
+
"yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
193
|
+
}
|
|
194
|
+
}
|
package/mino_banner.png
ADDED
|
Binary file
|
package/mino_oc.png
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@umastro12/mino",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "An AI Assistant that help developers directly into the terminal",
|
|
5
|
+
"main": "dist/index.ts",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"ai",
|
|
8
|
+
"cli",
|
|
9
|
+
"chatbot",
|
|
10
|
+
"qwen3",
|
|
11
|
+
"llm",
|
|
12
|
+
"ai-agents",
|
|
13
|
+
"assistant",
|
|
14
|
+
"mino"
|
|
15
|
+
],
|
|
16
|
+
"author": "umastro12",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=20.0.0"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@types/node": "^25.8.0",
|
|
23
|
+
"boxen": "^8.0.1",
|
|
24
|
+
"chalk": "^5.6.2",
|
|
25
|
+
"commander": "^14.0.3",
|
|
26
|
+
"fs": "^0.0.1-security",
|
|
27
|
+
"groq-sdk": "^1.2.0",
|
|
28
|
+
"marked": "^18.0.3",
|
|
29
|
+
"marked-terminal": "^7.3.0",
|
|
30
|
+
"ora": "^9.4.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/cli/main.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { APIClient } from "../services/APIClient.js";
|
|
3
|
+
|
|
4
|
+
async function showPanel() {
|
|
5
|
+
const panel = `
|
|
6
|
+
__ __ _____ _ _ ____
|
|
7
|
+
| \/ ||_ _|| \ | | / __ \
|
|
8
|
+
| \ / | | | | \| | | | | |
|
|
9
|
+
| |\/| | | | | . \`| | | | |
|
|
10
|
+
| | | | _| |_ | |\ | | |__| |
|
|
11
|
+
|_| |_||_____||_| \_| \____/
|
|
12
|
+
|
|
13
|
+
-------------------------------
|
|
14
|
+
Model: qwen/qwen3-32b
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
console.log(`\x1b[36m${panel}\x1b[0m`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const program = new Command();
|
|
21
|
+
|
|
22
|
+
program
|
|
23
|
+
.name("mino")
|
|
24
|
+
.description("Mino - Personal Developer AI Assistant")
|
|
25
|
+
.helpOption("-h", "--help");
|
|
26
|
+
|
|
27
|
+
program
|
|
28
|
+
.command("ask")
|
|
29
|
+
.alias("-a")
|
|
30
|
+
.description("Ask a quick question without starting a chat session")
|
|
31
|
+
.argument("<question>", "The question to ask")
|
|
32
|
+
.action(async (question) => {
|
|
33
|
+
const apiClient = new APIClient(process.env.AI_API_KEY!, "qwen/qwen3-32b");
|
|
34
|
+
console.log(`You asked: ${question}`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
program
|
|
38
|
+
.command("welcome")
|
|
39
|
+
.alias("-w")
|
|
40
|
+
.description("Show Welcome Panel")
|
|
41
|
+
.action(async () => {
|
|
42
|
+
await showPanel();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Spinner } from "../ui/spinner.js";
|
|
3
|
+
import { APIClient } from "../services/APIClient.js";
|
|
4
|
+
import { systemPrompt } from "../prompts/systemPrompt.js";
|
|
5
|
+
import * as executor from "../executor.js";
|
|
6
|
+
|
|
7
|
+
export class AskCommand {
|
|
8
|
+
private apiClient: APIClient;
|
|
9
|
+
private sysPrompt: typeof systemPrompt;
|
|
10
|
+
|
|
11
|
+
constructor(apiClient: APIClient) {
|
|
12
|
+
this.apiClient = apiClient;
|
|
13
|
+
this.sysPrompt = systemPrompt;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async startAskCommand(question: string) {
|
|
17
|
+
const messages = [
|
|
18
|
+
{ role: "system", content: this.sysPrompt },
|
|
19
|
+
{ role: "user", content: question },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const spinner = new Spinner();
|
|
23
|
+
spinner.start("Thinking...");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
|
|
3
|
+
export interface tokenLimitInfo {
|
|
4
|
+
modelId: string;
|
|
5
|
+
maxTokens: number;
|
|
6
|
+
currentTokens: number;
|
|
7
|
+
usagePercentage: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isTokenLimitApproaching(
|
|
11
|
+
currentTokens: number,
|
|
12
|
+
maxTokens: number,
|
|
13
|
+
threshold: number = 0.8,
|
|
14
|
+
): boolean {
|
|
15
|
+
return currentTokens >= maxTokens * threshold;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isTokenLimitExceeded(
|
|
19
|
+
currentTokens: number,
|
|
20
|
+
maxTokens: number,
|
|
21
|
+
): boolean {
|
|
22
|
+
return currentTokens >= maxTokens;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getTokenLimitInfo(
|
|
26
|
+
modelId: string,
|
|
27
|
+
maxTokens: number,
|
|
28
|
+
currentTokens: number,
|
|
29
|
+
): tokenLimitInfo {
|
|
30
|
+
return {
|
|
31
|
+
modelId,
|
|
32
|
+
maxTokens,
|
|
33
|
+
currentTokens,
|
|
34
|
+
usagePercentage: Math.round((currentTokens / maxTokens) * 100),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function showTokenLimitError(info: tokenLimitInfo) {
|
|
39
|
+
const error = [
|
|
40
|
+
`๐ซ Token limit exceeded`,
|
|
41
|
+
`Model: ${info.modelId}`,
|
|
42
|
+
`Usage: ${info.currentTokens.toLocaleString()} / ${info.maxTokens.toLocaleString()} (100%)`,
|
|
43
|
+
``,
|
|
44
|
+
`The model has reached its token limit. To continue:`,
|
|
45
|
+
`2. Restart the CLI to start a fresh session`,
|
|
46
|
+
`3. Or switch to a model with higher token limits`,
|
|
47
|
+
];
|
|
48
|
+
return error.join("\n");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a visual progress bar
|
|
53
|
+
*/
|
|
54
|
+
function createProgressBar(percentage: number, width: number): string {
|
|
55
|
+
const filled = Math.round((percentage / 100) * width);
|
|
56
|
+
const empty = width - filled;
|
|
57
|
+
|
|
58
|
+
const color =
|
|
59
|
+
percentage < 50 ? chalk.green : percentage < 80 ? chalk.yellow : chalk.red;
|
|
60
|
+
const filledChar = "โ";
|
|
61
|
+
const emptyChar = "โ";
|
|
62
|
+
|
|
63
|
+
return color(filledChar.repeat(filled) + emptyChar.repeat(empty));
|
|
64
|
+
}
|
package/src/executor.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
|
|
5
|
+
export interface ProjectFile {
|
|
6
|
+
path: string;
|
|
7
|
+
content: string;
|
|
8
|
+
executable?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RunCommandOptions {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
env?: NodeJS.ProcessEnv;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
captureOutput?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RunCommandResult {
|
|
19
|
+
stdout: string;
|
|
20
|
+
stderr: string;
|
|
21
|
+
exitCode: number | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SearchOptions {
|
|
25
|
+
engine?: "google" | "bing" | "duckduckgo";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function ensureDirectoryForFile(filePath: string) {
|
|
29
|
+
const dir = path.dirname(filePath);
|
|
30
|
+
if (!fs.existsSync(dir)) {
|
|
31
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function writeProjectFiles(
|
|
36
|
+
files: ProjectFile[],
|
|
37
|
+
rootDir: string = process.cwd(),
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
await Promise.all(
|
|
40
|
+
files.map(async (file) => {
|
|
41
|
+
const absolutePath = path.resolve(rootDir, file.path);
|
|
42
|
+
ensureDirectoryForFile(absolutePath);
|
|
43
|
+
await fs.promises.writeFile(absolutePath, file.content, "utf8");
|
|
44
|
+
|
|
45
|
+
if (file.executable && process.platform !== "win32") {
|
|
46
|
+
await fs.promises.chmod(absolutePath, 0o755);
|
|
47
|
+
}
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function runCommand(
|
|
53
|
+
command: string,
|
|
54
|
+
options: RunCommandOptions = {},
|
|
55
|
+
): Promise<RunCommandResult> {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const stdoutChunks: string[] = [];
|
|
58
|
+
const stderrChunks: string[] = [];
|
|
59
|
+
const proc = spawn(command, {
|
|
60
|
+
cwd: options.cwd ?? process.cwd(),
|
|
61
|
+
env: { ...process.env, ...options.env },
|
|
62
|
+
shell: true,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
proc.stdout.on("data", (data: Buffer) => {
|
|
66
|
+
const chunk = data.toString();
|
|
67
|
+
stdoutChunks.push(chunk);
|
|
68
|
+
if (options.captureOutput !== false) {
|
|
69
|
+
process.stdout.write(chunk);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
proc.stderr.on("data", (data: Buffer) => {
|
|
74
|
+
const chunk = data.toString();
|
|
75
|
+
stderrChunks.push(chunk);
|
|
76
|
+
if (options.captureOutput !== false) {
|
|
77
|
+
process.stderr.write(chunk);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (typeof options.timeoutMs === "number") {
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
proc.kill("SIGTERM");
|
|
84
|
+
}, options.timeoutMs);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
proc.on("close", (code: number | null) => {
|
|
88
|
+
resolve({
|
|
89
|
+
stdout: stdoutChunks.join(""),
|
|
90
|
+
stderr: stderrChunks.join(""),
|
|
91
|
+
exitCode: code,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
proc.on("error", (error: Error) => {
|
|
96
|
+
reject(error);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function buildSearchUrl(
|
|
102
|
+
query: string,
|
|
103
|
+
engine: "google" | "bing" | "duckduckgo" = "google",
|
|
104
|
+
): string {
|
|
105
|
+
const encoded = encodeURIComponent(query);
|
|
106
|
+
|
|
107
|
+
switch (engine) {
|
|
108
|
+
case "bing":
|
|
109
|
+
return `https://www.bing.com/search?q=${encoded}`;
|
|
110
|
+
case "duckduckgo":
|
|
111
|
+
return `https://duckduckgo.com/?q=${encoded}`;
|
|
112
|
+
default:
|
|
113
|
+
return `https://www.google.com/search?q=${encoded}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function searchWeb(
|
|
118
|
+
query: string,
|
|
119
|
+
options: SearchOptions = {},
|
|
120
|
+
): Promise<string> {
|
|
121
|
+
const url = buildSearchUrl(query, options.engine ?? "google");
|
|
122
|
+
await openUrl(url);
|
|
123
|
+
return url;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function openUrl(url: string): Promise<void> {
|
|
127
|
+
const safeUrl = url.replace(/"/g, '\\"');
|
|
128
|
+
let command = "";
|
|
129
|
+
|
|
130
|
+
if (process.platform === "win32") {
|
|
131
|
+
command = `start "" "${safeUrl}"`;
|
|
132
|
+
} else if (process.platform === "darwin") {
|
|
133
|
+
command = `open "${safeUrl}"`;
|
|
134
|
+
} else {
|
|
135
|
+
command = `xdg-open "${safeUrl}"`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
await runCommand(command, { captureOutput: true });
|
|
139
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Groq from "groq-sdk";
|
|
2
|
+
|
|
3
|
+
const groq = new Groq({
|
|
4
|
+
apiKey: process.env.AI_API_KEY,
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
export async function chatCompletion() {
|
|
8
|
+
const chatCompletion = await groq.chat.completions.create({
|
|
9
|
+
messages: [
|
|
10
|
+
{
|
|
11
|
+
role: "user",
|
|
12
|
+
content: "",
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
model: "qwen/qwen3-32b",
|
|
16
|
+
temperature: 0.6,
|
|
17
|
+
max_completion_tokens: 4096,
|
|
18
|
+
top_p: 0.95,
|
|
19
|
+
stream: true,
|
|
20
|
+
reasoning_effort: "default",
|
|
21
|
+
stop: null,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
for await (const chunk of chatCompletion) {
|
|
25
|
+
process.stdout.write(chunk.choices[0]?.delta?.content || "");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const chatComplet = chatCompletion();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const systemPrompt = `# Mino - Personal Developer AI Assistant
|
|
2
|
+
# Mino - Personal Developer AI Assistant
|
|
3
|
+
|
|
4
|
+
## IDENTITY
|
|
5
|
+
You are Mino, a personal AI assistant for developers working in the terminal. Be professional, precise, results-oriented, and helpful.
|
|
6
|
+
|
|
7
|
+
## TOOLS
|
|
8
|
+
You have three tools:
|
|
9
|
+
- write project structure files
|
|
10
|
+
- run commands
|
|
11
|
+
- search the web
|
|
12
|
+
|
|
13
|
+
## BEHAVIOR
|
|
14
|
+
- Always prefer concise, actionable answers.
|
|
15
|
+
- When the user asks for code or files, explain the structure and provide exact file content.
|
|
16
|
+
- Only perform file writes or command execution when explicitly requested.
|
|
17
|
+
- When searching the web, return relevant links and short summaries.
|
|
18
|
+
|
|
19
|
+
## CRITICAL RULES
|
|
20
|
+
1. BE PROACTIVE: offer useful follow-up suggestions and next steps.
|
|
21
|
+
2. DO NOT MODIFY FILES UNLESS THE USER ASKS YOU TO.
|
|
22
|
+
3. If the user asks to create a bot or implement a feature, explain the design and provide a clear example.
|
|
23
|
+
4. If the user asks for docs or language references, explain the topic and share relevant documentation links.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
|
|
4
|
+
export class APIClient {
|
|
5
|
+
private apiKey: string;
|
|
6
|
+
private model: "qwen/qwen3-32b";
|
|
7
|
+
|
|
8
|
+
constructor(apiKey: string, model: "qwen/qwen3-32b") {
|
|
9
|
+
this.apiKey = apiKey;
|
|
10
|
+
this.model = model;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
setup() {
|
|
14
|
+
console.log(`๐ป Starting API Client Setup...`);
|
|
15
|
+
const APIKey = prompt(`๐ Put your API Key here:`);
|
|
16
|
+
if (!APIKey) {
|
|
17
|
+
throw new Error("An API key was not provided.");
|
|
18
|
+
}
|
|
19
|
+
if (APIKey) {
|
|
20
|
+
fs.writeFileSync(".env", `AI_API_KEY=${APIKey}`);
|
|
21
|
+
console.log(`๐ป Setup complete.`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import boxen from "boxen";
|
|
3
|
+
|
|
4
|
+
export interface UpdateInfo {
|
|
5
|
+
updateAvaiable: boolean;
|
|
6
|
+
updateName: string;
|
|
7
|
+
latest?: string | undefined;
|
|
8
|
+
current?: string | undefined;
|
|
9
|
+
publishedAt?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
export class UpdaterService {
|
|
12
|
+
private packageName: string;
|
|
13
|
+
private currentVersion: string;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
this.currentVersion = process.env.APP_VERSION || "0.0.1";
|
|
17
|
+
this.packageName = process.env.APP_NAME || "mino";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
createUpdateNotification(
|
|
21
|
+
latest: string,
|
|
22
|
+
current: string,
|
|
23
|
+
publishedAt?: string,
|
|
24
|
+
) {
|
|
25
|
+
const dateInfo = publishedAt
|
|
26
|
+
? `\n${chalk.dim("Published:")} ${chalk.dim(new Date(publishedAt).toLocaleDateString())}`
|
|
27
|
+
: "";
|
|
28
|
+
|
|
29
|
+
const message = [
|
|
30
|
+
chalk.cyan.bold(`๐ซ Update Available!`),
|
|
31
|
+
"",
|
|
32
|
+
`Current: ${chalk.red(current)}`,
|
|
33
|
+
`Latest: ${chalk.green(latest)}${dateInfo}`,
|
|
34
|
+
"",
|
|
35
|
+
chalk.dim("Run ") +
|
|
36
|
+
chalk.cyan.bold("mino update install") +
|
|
37
|
+
chalk.dim(" to update"),
|
|
38
|
+
chalk.dim("Or: ") + chalk.cyan(`npm update -g ${this.packageName}`),
|
|
39
|
+
].join("\n");
|
|
40
|
+
|
|
41
|
+
return boxen(message, {
|
|
42
|
+
padding: 1,
|
|
43
|
+
borderColor: "cyan",
|
|
44
|
+
title: ` ${this.packageName} `,
|
|
45
|
+
titleAlignment: "center",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
showUpdateNotification(
|
|
50
|
+
latest: string,
|
|
51
|
+
current: string,
|
|
52
|
+
publishedAt?: string,
|
|
53
|
+
): void {
|
|
54
|
+
console.log("");
|
|
55
|
+
console.log(this.createUpdateNotification(latest, current, publishedAt));
|
|
56
|
+
console.log("");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const updaterService = new UpdaterService();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { marked } from "marked";
|
|
3
|
+
|
|
4
|
+
const mdRender = {
|
|
5
|
+
code: chalk.hex("#8afdda"),
|
|
6
|
+
|
|
7
|
+
heading: chalk.bold.hex("#0033ff"),
|
|
8
|
+
strong: chalk.bold.white,
|
|
9
|
+
em: chalk.italic.hex("#67E8F9"),
|
|
10
|
+
del: chalk.strikethrough.gray,
|
|
11
|
+
|
|
12
|
+
listitem: chalk.white,
|
|
13
|
+
checkbox: chalk.hex("#0296ff"),
|
|
14
|
+
|
|
15
|
+
blockquote: chalk.gray.italic,
|
|
16
|
+
table: chalk.hex("#00eaff"),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function renderMarkdown(content: string): string {
|
|
20
|
+
if (!content || typeof content !== "string") {
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const rendered = marked.parse(content);
|
|
26
|
+
|
|
27
|
+
if (typeof rendered !== "string") {
|
|
28
|
+
return content;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return rendered;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return content;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// this is based in the https://github.com/shindozk/luxyie.ai-cli/blob/main/src/ui/spinner.ts code.
|
|
2
|
+
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import ora, { Ora } from "ora";
|
|
5
|
+
|
|
6
|
+
export class Spinner {
|
|
7
|
+
private spinner: Ora | null = null;
|
|
8
|
+
|
|
9
|
+
start(text: string): void {
|
|
10
|
+
if (this.spinner) {
|
|
11
|
+
this.spinner.text = text;
|
|
12
|
+
this.spinner.start();
|
|
13
|
+
} else {
|
|
14
|
+
this.spinner = ora({
|
|
15
|
+
text: text,
|
|
16
|
+
color: "cyan",
|
|
17
|
+
spinner: "dots",
|
|
18
|
+
}).start();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
stop(): void {
|
|
23
|
+
if (this.spinner) {
|
|
24
|
+
this.spinner.stop();
|
|
25
|
+
this.spinner = null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fail(text: string) {
|
|
30
|
+
if (this.spinner) {
|
|
31
|
+
this.spinner.fail(chalk.red(text));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const spinner = new Spinner();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ES2020",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"forceConsistentCasingInFileNames": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"types": ["node"],
|
|
11
|
+
"resolveJsonModule": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"],
|
|
14
|
+
"exclude": ["node_modules"]
|
|
15
|
+
}
|