igris-soul 1.0.0 → 1.1.0
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 +345 -31
- package/index.js +200 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Igris Soul
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Your personal AI assistant in the terminal, inspired by Igris from Solo Leveling.
|
|
4
|
+
>
|
|
5
|
+
> Install it globally and summon Igris from anywhere:
|
|
4
6
|
>
|
|
5
7
|
> ```bash
|
|
6
8
|
> npm install -g igris-soul
|
|
@@ -9,33 +11,231 @@
|
|
|
9
11
|
|
|
10
12
|
## Disclaimer
|
|
11
13
|
|
|
12
|
-
This project sends your prompts to Google Gemini and may send web-search requests to Tavily. Do not enter passwords, private keys, personal data, confidential business information, or any other sensitive information into the assistant.
|
|
14
|
+
This project sends your prompts to Google Gemini and may send web-search requests to Tavily. Do not enter passwords, private keys, personal data, confidential business information, or any other sensitive information into the assistant.
|
|
15
|
+
|
|
16
|
+
You are responsible for reviewing generated answers and for the API usage and charges associated with your API keys.
|
|
17
|
+
|
|
18
|
+
This project is provided for educational and personal use without guarantees about accuracy, availability, or fitness for a particular purpose.
|
|
19
|
+
|
|
20
|
+
---
|
|
13
21
|
|
|
14
22
|
## Requirements
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
Before installing Igris Soul, make sure you have:
|
|
25
|
+
|
|
26
|
+
* Node.js 20 or newer
|
|
27
|
+
* A Google Gemini API key
|
|
28
|
+
* A Tavily API key for current-information searches
|
|
29
|
+
* An npm account if you want to install or publish the package through npm
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# Installation
|
|
34
|
+
|
|
35
|
+
## Install Globally
|
|
36
|
+
|
|
37
|
+
To use Igris Soul from anywhere on your computer:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install -g igris-soul
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
After installation, start Igris with:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
Arise
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
You can run `Arise` from any directory.
|
|
50
|
+
|
|
51
|
+
For example:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
C:\Users\YourName> Arise
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
or:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
D:\Projects\MyProject> Arise
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
or:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
E:\Anything> Arise
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Igris does not depend on the directory from which you launch it.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
# First-Time Setup
|
|
74
|
+
|
|
75
|
+
On the first launch, Igris automatically creates its configuration directory in your home directory:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
~/.igris/
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
It will automatically create:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
~/.igris/
|
|
85
|
+
├── .env
|
|
86
|
+
└── user.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You do **not** need to manually create these files.
|
|
90
|
+
|
|
91
|
+
Igris will ask for the required API keys if they are not already configured:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
Enter your Gemini API key:
|
|
95
|
+
Enter your Tavily API key:
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The keys are then stored locally in:
|
|
19
99
|
|
|
20
|
-
|
|
100
|
+
```text
|
|
101
|
+
~/.igris/.env
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
On Windows, this is typically:
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
C:\Users\YourName\.igris\.env
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Your name is stored separately in:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
C:\Users\YourName\.igris\user.json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
On future launches, Igris automatically loads the saved configuration.
|
|
117
|
+
|
|
118
|
+
---
|
|
21
119
|
|
|
22
|
-
|
|
120
|
+
# Configuration
|
|
121
|
+
|
|
122
|
+
The automatically created `.env` file contains:
|
|
23
123
|
|
|
24
124
|
```env
|
|
25
125
|
GENAI_API_KEY=your_google_gemini_api_key
|
|
26
126
|
TAVILY_API_KEY=your_tavily_api_key
|
|
27
127
|
```
|
|
28
128
|
|
|
29
|
-
|
|
129
|
+
### Environment Variables
|
|
130
|
+
|
|
131
|
+
| Variable | Purpose |
|
|
132
|
+
| ---------------- | ------------------------------- |
|
|
133
|
+
| `GENAI_API_KEY` | Google Gemini API key |
|
|
134
|
+
| `TAVILY_API_KEY` | Tavily API key for web searches |
|
|
135
|
+
|
|
136
|
+
You can manually edit:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
~/.igris/.env
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
if you need to change your API keys.
|
|
143
|
+
|
|
144
|
+
### Security
|
|
145
|
+
|
|
146
|
+
Never commit or share your `.env` file.
|
|
147
|
+
|
|
148
|
+
Never put real API keys inside the source code.
|
|
149
|
+
|
|
150
|
+
The `.env` file contains sensitive credentials and should remain on your local machine.
|
|
151
|
+
|
|
152
|
+
The project includes `.env.example` as a safe template:
|
|
153
|
+
|
|
154
|
+
```env
|
|
155
|
+
GENAI_API_KEY=
|
|
156
|
+
TAVILY_API_KEY=
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
# Running Igris
|
|
162
|
+
|
|
163
|
+
After installation:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
Arise
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
You will see:
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
+----------------------+
|
|
173
|
+
| IGRIS |
|
|
174
|
+
| AGENT ONLINE |
|
|
175
|
+
+----------------------+
|
|
176
|
+
|
|
177
|
+
Hi, My Lord, I am Igris, your loyal servant.
|
|
178
|
+
How may I assist you today?
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
You can then enter your prompts directly in the terminal.
|
|
182
|
+
|
|
183
|
+
Example:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
You: Explain binary search in Java
|
|
187
|
+
|
|
188
|
+
Igris:
|
|
189
|
+
...
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
To exit the assistant:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
exit
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
or:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
quit
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
# Features
|
|
207
|
+
|
|
208
|
+
* Interactive terminal-based AI assistant
|
|
209
|
+
* Google Gemini-powered responses
|
|
210
|
+
* Streaming AI responses
|
|
211
|
+
* Tavily web search for current information
|
|
212
|
+
* Conversation history during the current session
|
|
213
|
+
* Personalized responses using your saved name
|
|
214
|
+
* First-launch name setup
|
|
215
|
+
* Persistent configuration
|
|
216
|
+
* Automatic `.igris` directory creation
|
|
217
|
+
* Automatic `.env` creation
|
|
218
|
+
* Global CLI access
|
|
219
|
+
* Runs from any directory
|
|
220
|
+
* `Arise` command for launching the assistant
|
|
30
221
|
|
|
31
|
-
|
|
222
|
+
---
|
|
32
223
|
|
|
33
|
-
|
|
224
|
+
# Local Development
|
|
34
225
|
|
|
35
|
-
|
|
226
|
+
If you want to run Igris Soul directly from the source code instead of installing it globally:
|
|
227
|
+
|
|
228
|
+
Clone or download the repository and enter the project directory.
|
|
229
|
+
|
|
230
|
+
Install dependencies:
|
|
36
231
|
|
|
37
232
|
```bash
|
|
38
233
|
npm install
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Then start Igris:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
39
239
|
npm start
|
|
40
240
|
```
|
|
41
241
|
|
|
@@ -45,50 +245,164 @@ You can also run:
|
|
|
45
245
|
node index.js
|
|
46
246
|
```
|
|
47
247
|
|
|
48
|
-
|
|
248
|
+
The same `~/.igris/.env` configuration is used.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
# Test the Package Locally
|
|
253
|
+
|
|
254
|
+
Before publishing a new version to npm, you can test the CLI directly from the package directory.
|
|
49
255
|
|
|
50
|
-
|
|
256
|
+
Install the local package globally:
|
|
51
257
|
|
|
52
258
|
```bash
|
|
53
|
-
npm install -g
|
|
54
|
-
Arise
|
|
259
|
+
npm install -g .
|
|
55
260
|
```
|
|
56
261
|
|
|
57
|
-
|
|
262
|
+
Then run:
|
|
58
263
|
|
|
59
264
|
```bash
|
|
60
|
-
npm install -g .
|
|
61
265
|
Arise
|
|
62
266
|
```
|
|
63
267
|
|
|
64
|
-
|
|
268
|
+
This allows you to test the global CLI behavior using your local source code.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
# Updating Igris Soul
|
|
65
273
|
|
|
66
|
-
|
|
67
|
-
- Google Gemini-powered answers
|
|
68
|
-
- Tavily web search for current information
|
|
69
|
-
- Conversation history during the current session
|
|
70
|
-
- First-launch name setup
|
|
71
|
-
- Persistent name storage in `~/.igris/user.json`
|
|
72
|
-
- `Arise`, `igris-soul`, and `igris` global commands
|
|
274
|
+
When a new version is published, update your global installation with:
|
|
73
275
|
|
|
74
|
-
|
|
276
|
+
```bash
|
|
277
|
+
npm install -g igris-soul@latest
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Your personal configuration remains outside the npm package:
|
|
281
|
+
|
|
282
|
+
```text
|
|
283
|
+
~/.igris/
|
|
284
|
+
├── .env
|
|
285
|
+
└── user.json
|
|
286
|
+
```
|
|
75
287
|
|
|
76
|
-
|
|
288
|
+
Therefore, updating the package does not require you to enter your API keys again.
|
|
77
289
|
|
|
78
|
-
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
# Uninstalling
|
|
293
|
+
|
|
294
|
+
To remove the globally installed package:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
npm uninstall -g igris-soul
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Your personal Igris configuration remains in:
|
|
301
|
+
|
|
302
|
+
```text
|
|
303
|
+
~/.igris/
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
If you want to completely remove your local Igris configuration as well, delete the `.igris` directory manually.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
# Publishing to npm
|
|
311
|
+
|
|
312
|
+
If you are the package maintainer and want to publish a new version:
|
|
313
|
+
|
|
314
|
+
First, log in to npm:
|
|
79
315
|
|
|
80
316
|
```bash
|
|
81
317
|
npm login
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Verify your account:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
npm whoami
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Run the tests:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
82
329
|
npm test
|
|
83
|
-
npm publish
|
|
84
330
|
```
|
|
85
331
|
|
|
86
|
-
|
|
332
|
+
Check what will be included in the package:
|
|
87
333
|
|
|
88
334
|
```bash
|
|
89
335
|
npm publish --dry-run
|
|
90
336
|
```
|
|
91
337
|
|
|
92
|
-
|
|
338
|
+
If everything looks correct, publish:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
npm publish
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Updating the Version
|
|
345
|
+
|
|
346
|
+
npm does not allow publishing the same package version twice.
|
|
347
|
+
|
|
348
|
+
For a bug fix:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
npm version patch
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
For a new feature:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
npm version minor
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
For a breaking change:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
npm version major
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Then publish the new version:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
npm publish
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Example:
|
|
373
|
+
|
|
374
|
+
```text
|
|
375
|
+
1.0.0 → 1.0.1
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
# Package Usage
|
|
381
|
+
|
|
382
|
+
Igris Soul is primarily designed as a global terminal assistant.
|
|
383
|
+
|
|
384
|
+
Install:
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
npm install -g igris-soul
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Run:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
Arise
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
The package is installed globally, while user-specific configuration is stored separately in:
|
|
397
|
+
|
|
398
|
+
```text
|
|
399
|
+
~/.igris/
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
This allows Igris to maintain its configuration independently of the directory from which it is launched.
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
# License
|
|
93
407
|
|
|
94
408
|
ISC
|
package/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
|
4
2
|
import { config } from "dotenv";
|
|
5
3
|
import { tavily } from "@tavily/core";
|
|
6
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
mkdir,
|
|
6
|
+
readFile,
|
|
7
|
+
writeFile,
|
|
8
|
+
access,
|
|
9
|
+
} from "node:fs/promises";
|
|
7
10
|
import { homedir } from "node:os";
|
|
8
11
|
import { join } from "node:path";
|
|
9
12
|
import rl from "readline/promises";
|
|
@@ -17,15 +20,128 @@ import {
|
|
|
17
20
|
} from "langchain";
|
|
18
21
|
import * as z from "zod";
|
|
19
22
|
|
|
23
|
+
/* =========================================================
|
|
24
|
+
IGRIS CONFIGURATION
|
|
25
|
+
========================================================= */
|
|
26
|
+
|
|
27
|
+
const igrisDir = join(homedir(), ".igris");
|
|
28
|
+
const envPath = join(igrisDir, ".env");
|
|
29
|
+
const userDataPath = join(igrisDir, "user.json");
|
|
30
|
+
|
|
31
|
+
// Create ~/.igris automatically
|
|
32
|
+
await mkdir(igrisDir, { recursive: true });
|
|
33
|
+
|
|
34
|
+
// Check whether .env exists
|
|
35
|
+
async function ensureEnvFile() {
|
|
36
|
+
try {
|
|
37
|
+
await access(envPath);
|
|
38
|
+
} catch {
|
|
39
|
+
await writeFile(
|
|
40
|
+
envPath,
|
|
41
|
+
`GENAI_API_KEY=\nTAVILY_API_KEY=\n`,
|
|
42
|
+
"utf8",
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
console.log(`
|
|
46
|
+
Igris configuration created.
|
|
47
|
+
|
|
48
|
+
Configuration file:
|
|
49
|
+
${envPath}
|
|
50
|
+
|
|
51
|
+
You will now be asked for your API keys.
|
|
52
|
+
`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await ensureEnvFile();
|
|
57
|
+
|
|
58
|
+
// Load environment variables from ~/.igris/.env
|
|
20
59
|
config({
|
|
21
|
-
path:
|
|
60
|
+
path: envPath,
|
|
22
61
|
quiet: true,
|
|
23
62
|
});
|
|
63
|
+
|
|
64
|
+
/* =========================================================
|
|
65
|
+
READ / SAVE API KEYS
|
|
66
|
+
========================================================= */
|
|
67
|
+
|
|
68
|
+
async function getApiKey(variableName, displayName) {
|
|
69
|
+
let value = process.env[variableName]?.trim();
|
|
70
|
+
|
|
71
|
+
if (value) {
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const key = await readline.question(
|
|
76
|
+
`${displayName}: `,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
value = key.trim();
|
|
80
|
+
|
|
81
|
+
if (!value) {
|
|
82
|
+
console.error(`\n${displayName} cannot be empty.`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Read existing .env
|
|
87
|
+
let envContent = "";
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
envContent = await readFile(envPath, "utf8");
|
|
91
|
+
} catch {
|
|
92
|
+
envContent = "";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const regex = new RegExp(`^${variableName}=.*$`, "m");
|
|
96
|
+
|
|
97
|
+
if (regex.test(envContent)) {
|
|
98
|
+
envContent = envContent.replace(
|
|
99
|
+
regex,
|
|
100
|
+
`${variableName}=${value}`,
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
envContent += `\n${variableName}=${value}\n`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
await writeFile(envPath, envContent.trim() + "\n", "utf8");
|
|
107
|
+
|
|
108
|
+
process.env[variableName] = value;
|
|
109
|
+
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* =========================================================
|
|
114
|
+
READLINE
|
|
115
|
+
========================================================= */
|
|
116
|
+
|
|
117
|
+
const readline = rl.createInterface({
|
|
118
|
+
input: process.stdin,
|
|
119
|
+
output: process.stdout,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
/* =========================================================
|
|
123
|
+
API CONFIGURATION
|
|
124
|
+
========================================================= */
|
|
125
|
+
|
|
126
|
+
const genaiApiKey = await getApiKey(
|
|
127
|
+
"GENAI_API_KEY",
|
|
128
|
+
"Enter your Gemini API key",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const tavilyApiKey = await getApiKey(
|
|
132
|
+
"TAVILY_API_KEY",
|
|
133
|
+
"Enter your Tavily API key",
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
/* =========================================================
|
|
137
|
+
TAVILY
|
|
138
|
+
========================================================= */
|
|
139
|
+
|
|
24
140
|
const tavly = tavily({
|
|
25
|
-
apiKey:
|
|
141
|
+
apiKey: tavilyApiKey,
|
|
26
142
|
});
|
|
143
|
+
|
|
27
144
|
async function getLetestInfos({ query }) {
|
|
28
|
-
// return "India's latest updates as per today are : New kolkata metro staion inaugurated, New AI policy released by the government, and the stock market is showing positive trends.";
|
|
29
145
|
const response = await tavly.search(query, {
|
|
30
146
|
searchDepth: "fast",
|
|
31
147
|
maxResults: 3,
|
|
@@ -33,8 +149,11 @@ async function getLetestInfos({ query }) {
|
|
|
33
149
|
});
|
|
34
150
|
|
|
35
151
|
const results = response.results;
|
|
36
|
-
|
|
37
|
-
|
|
152
|
+
|
|
153
|
+
const content = results
|
|
154
|
+
.map((result) => result.content)
|
|
155
|
+
.join("\n\n");
|
|
156
|
+
|
|
38
157
|
return content;
|
|
39
158
|
}
|
|
40
159
|
|
|
@@ -51,76 +170,115 @@ const getLatestInfosTool = tool(getLetestInfos, {
|
|
|
51
170
|
}),
|
|
52
171
|
});
|
|
53
172
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const userDataPath = join(homedir(), ".igris", "user.json");
|
|
173
|
+
/* =========================================================
|
|
174
|
+
USER DATA
|
|
175
|
+
========================================================= */
|
|
60
176
|
|
|
61
177
|
async function getUserName() {
|
|
62
178
|
try {
|
|
63
|
-
const userData = JSON.parse(
|
|
179
|
+
const userData = JSON.parse(
|
|
180
|
+
await readFile(userDataPath, "utf8"),
|
|
181
|
+
);
|
|
182
|
+
|
|
64
183
|
return userData.name;
|
|
65
184
|
} catch {
|
|
66
185
|
const name = (
|
|
67
|
-
await readline.question(
|
|
186
|
+
await readline.question(
|
|
187
|
+
"What is your name, My Lord? ",
|
|
188
|
+
)
|
|
68
189
|
).trim();
|
|
69
|
-
|
|
70
|
-
await writeFile(
|
|
190
|
+
|
|
191
|
+
await writeFile(
|
|
192
|
+
userDataPath,
|
|
193
|
+
JSON.stringify({ name }, null, 2),
|
|
194
|
+
"utf8",
|
|
195
|
+
);
|
|
196
|
+
|
|
71
197
|
return name;
|
|
72
198
|
}
|
|
73
199
|
}
|
|
74
200
|
|
|
75
201
|
const userName = await getUserName();
|
|
76
202
|
|
|
203
|
+
/* =========================================================
|
|
204
|
+
GEMINI MODEL
|
|
205
|
+
========================================================= */
|
|
206
|
+
|
|
77
207
|
const model = new ChatGoogleGenerativeAI({
|
|
78
208
|
model: "gemini-3.5-flash-lite",
|
|
79
|
-
apiKey:
|
|
209
|
+
apiKey: genaiApiKey,
|
|
80
210
|
});
|
|
81
211
|
|
|
212
|
+
/* =========================================================
|
|
213
|
+
AGENT
|
|
214
|
+
========================================================= */
|
|
215
|
+
|
|
82
216
|
const agent = createAgent({
|
|
83
217
|
model,
|
|
84
218
|
tools: [getLatestInfosTool],
|
|
85
219
|
});
|
|
86
220
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// }
|
|
91
|
-
|
|
92
|
-
// const prompt = await readline.question("Enter your prompt: ");
|
|
93
|
-
// console.log("Prompt:", prompt);
|
|
94
|
-
// readline.close();
|
|
221
|
+
/* =========================================================
|
|
222
|
+
SYSTEM MESSAGE
|
|
223
|
+
========================================================= */
|
|
95
224
|
|
|
96
225
|
const messages = [
|
|
97
226
|
new SystemMessage(`
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
227
|
+
You are Igris from Solo Leveling, and the user's name is ${userName}.
|
|
228
|
+
|
|
229
|
+
Always address the user as My Lord.
|
|
230
|
+
|
|
231
|
+
You are a Senior Software Developer and ML Engineer.
|
|
232
|
+
|
|
233
|
+
Your task is to answer queries in the Solo Leveling style.
|
|
234
|
+
|
|
235
|
+
Do not give unnecessarily long responses.
|
|
236
|
+
Give responses to the point.
|
|
237
|
+
Use plain text without markdown.
|
|
238
|
+
|
|
239
|
+
Today is ${new Date().toLocaleDateString()} and the time is ${new Date().toLocaleTimeString()}.
|
|
240
|
+
|
|
241
|
+
Do not always mention the date and time.
|
|
242
|
+
Use them only when needed for styling, context, or a poetic response.
|
|
243
|
+
`),
|
|
102
244
|
];
|
|
103
245
|
|
|
246
|
+
/* =========================================================
|
|
247
|
+
START IGRIS
|
|
248
|
+
========================================================= */
|
|
249
|
+
|
|
104
250
|
console.log(`
|
|
105
251
|
+----------------------+
|
|
106
252
|
| IGRIS |
|
|
107
253
|
| AGENT ONLINE |
|
|
108
254
|
+----------------------+
|
|
109
255
|
|
|
110
|
-
Hi, My Lord, I am Igris, your loyal servant.
|
|
256
|
+
Hi, My Lord, I am Igris, your loyal servant.
|
|
257
|
+
How may I assist you today?
|
|
111
258
|
`);
|
|
112
259
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
260
|
+
/* =========================================================
|
|
261
|
+
CHAT LOOP
|
|
262
|
+
========================================================= */
|
|
263
|
+
|
|
116
264
|
try {
|
|
117
265
|
while (true) {
|
|
118
266
|
const prompt = await readline.question("You: ");
|
|
119
|
-
|
|
267
|
+
|
|
268
|
+
if (
|
|
269
|
+
["exit", "quit"].includes(
|
|
270
|
+
prompt.trim().toLowerCase(),
|
|
271
|
+
)
|
|
272
|
+
) {
|
|
120
273
|
break;
|
|
121
274
|
}
|
|
122
275
|
|
|
276
|
+
if (!prompt.trim()) {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
|
|
123
280
|
messages.push(new HumanMessage(prompt));
|
|
281
|
+
|
|
124
282
|
const stream = await agent.stream(
|
|
125
283
|
{
|
|
126
284
|
messages,
|
|
@@ -129,17 +287,23 @@ try {
|
|
|
129
287
|
streamMode: "messages",
|
|
130
288
|
},
|
|
131
289
|
);
|
|
290
|
+
|
|
132
291
|
let aiResponse = "";
|
|
292
|
+
|
|
133
293
|
console.log("Igris: ");
|
|
294
|
+
|
|
134
295
|
for await (const [chunk] of stream) {
|
|
135
296
|
if (chunk instanceof AIMessageChunk) {
|
|
136
297
|
process.stdout.write(chunk.text);
|
|
137
298
|
aiResponse += chunk.text;
|
|
138
299
|
}
|
|
139
300
|
}
|
|
301
|
+
|
|
140
302
|
messages.push(new AIMessage(aiResponse));
|
|
303
|
+
|
|
141
304
|
process.stdout.write("\n\n");
|
|
142
305
|
}
|
|
143
306
|
} finally {
|
|
144
307
|
readline.close();
|
|
145
308
|
}
|
|
309
|
+
|