igris-soul 1.0.0 → 1.1.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 (3) hide show
  1. package/README.md +345 -31
  2. package/index.js +278 -58
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Igris Soul
2
2
 
3
- > To use Igris Soul from anywhere, install it globally and run `Arise`:
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. You are responsible for reviewing generated answers and for the API usage and charges associated with your keys. This project is provided for educational and personal use without guarantees about accuracy, availability, or fitness for a particular purpose.
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
- - Node.js 20 or newer
17
- - A Google Gemini API key
18
- - A Tavily API key for current-information searches
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
- ## Configuration
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
- For a local checkout, create a `.env` file in the project root. For a global installation, create `.igris/.env` in your home directory. Use `.env.example` as the template:
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
- Never commit `.env` or share its contents. It is already excluded by `.gitignore`.
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
- When both files exist, the `.env` file in the current directory takes priority over the home-directory configuration.
222
+ ---
32
223
 
33
- ## Run From This Repository
224
+ # Local Development
34
225
 
35
- Install dependencies and start Igris Soul:
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
- Type `exit` or `quit` to close the assistant.
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
- ## Install As A Global CLI
256
+ Install the local package globally:
51
257
 
52
258
  ```bash
53
- npm install -g igris-soul
54
- Arise
259
+ npm install -g .
55
260
  ```
56
261
 
57
- The `arise`, `igris-soul`, and `igris` aliases are also available. To test the package locally before publishing:
262
+ Then run:
58
263
 
59
264
  ```bash
60
- npm install -g .
61
265
  Arise
62
266
  ```
63
267
 
64
- ## Features
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
- - Interactive terminal conversation with streamed responses
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
- The saved name belongs to the local operating-system user account and remains available across directories and package updates until the file is deleted.
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
- ## Publishing
288
+ Therefore, updating the package does not require you to enter your API keys again.
77
289
 
78
- Log in to npm and publish the package:
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
- To verify the package without uploading it:
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
- ## License
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,12 +1,16 @@
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 { mkdir, readFile, writeFile } from "node:fs/promises";
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";
13
+
10
14
  import {
11
15
  HumanMessage,
12
16
  AIMessage,
@@ -15,17 +19,151 @@ import {
15
19
  createAgent,
16
20
  AIMessageChunk,
17
21
  } from "langchain";
22
+
18
23
  import * as z from "zod";
19
24
 
25
+ /* =========================================================
26
+ IGRIS DIRECTORIES & FILES
27
+ ========================================================= */
28
+
29
+ const igrisDir = join(homedir(), ".igris");
30
+ const envPath = join(igrisDir, ".env");
31
+ const userDataPath = join(igrisDir, "user.json");
32
+
33
+ /* =========================================================
34
+ READLINE
35
+ ========================================================= */
36
+
37
+ const readline = rl.createInterface({
38
+ input: process.stdin,
39
+ output: process.stdout,
40
+ });
41
+
42
+ /* =========================================================
43
+ CREATE IGRIS DIRECTORY
44
+ ========================================================= */
45
+
46
+ await mkdir(igrisDir, { recursive: true });
47
+
48
+ /* =========================================================
49
+ CREATE .ENV IF IT DOESN'T EXIST
50
+ ========================================================= */
51
+
52
+ async function ensureEnvFile() {
53
+ try {
54
+ await access(envPath);
55
+ } catch {
56
+ await writeFile(
57
+ envPath,
58
+ "GENAI_API_KEY=\nTAVILY_API_KEY=\n",
59
+ "utf8",
60
+ );
61
+ }
62
+ }
63
+
64
+ await ensureEnvFile();
65
+
66
+ /* =========================================================
67
+ LOAD ENVIRONMENT VARIABLES
68
+ ========================================================= */
69
+
20
70
  config({
21
- path: [join(process.cwd(), ".env"), join(homedir(), ".igris", ".env")],
71
+ path: envPath,
72
+ override: true,
22
73
  quiet: true,
23
74
  });
75
+
76
+ /* =========================================================
77
+ API KEY SETUP
78
+ ========================================================= */
79
+
80
+ async function getApiKey(variableName, displayName) {
81
+ let value = process.env[variableName]?.trim();
82
+
83
+ // Already configured
84
+ if (value) {
85
+ return value;
86
+ }
87
+
88
+ console.log("");
89
+
90
+ value = (
91
+ await readline.question(`${displayName}: `)
92
+ ).trim();
93
+
94
+ if (!value) {
95
+ console.error(
96
+ `\n${displayName} cannot be empty.`,
97
+ );
98
+
99
+ readline.close();
100
+ process.exit(1);
101
+ }
102
+
103
+ let envContent = "";
104
+
105
+ try {
106
+ envContent = await readFile(
107
+ envPath,
108
+ "utf8",
109
+ );
110
+ } catch {
111
+ envContent = "";
112
+ }
113
+
114
+ const regex = new RegExp(
115
+ `^${variableName}=.*$`,
116
+ "m",
117
+ );
118
+
119
+ if (regex.test(envContent)) {
120
+ envContent = envContent.replace(
121
+ regex,
122
+ `${variableName}=${value}`,
123
+ );
124
+ } else {
125
+ envContent += `\n${variableName}=${value}`;
126
+ }
127
+
128
+ await writeFile(
129
+ envPath,
130
+ envContent.trim() + "\n",
131
+ "utf8",
132
+ );
133
+
134
+ // Make it immediately available to process.env
135
+ process.env[variableName] = value;
136
+
137
+ return value;
138
+ }
139
+
140
+ /* =========================================================
141
+ GET REQUIRED API KEYS
142
+ ========================================================= */
143
+
144
+ const genaiApiKey = await getApiKey(
145
+ "GENAI_API_KEY",
146
+ "Enter your Gemini API key",
147
+ );
148
+
149
+ const tavilyApiKey = await getApiKey(
150
+ "TAVILY_API_KEY",
151
+ "Enter your Tavily API key",
152
+ );
153
+
154
+ /* =========================================================
155
+ TAVILY
156
+ ========================================================= */
157
+
24
158
  const tavly = tavily({
25
- apiKey: process.env.TAVILY_API_KEY,
159
+ apiKey: tavilyApiKey,
26
160
  });
27
- 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.";
161
+
162
+ /* =========================================================
163
+ LATEST INFORMATION TOOL
164
+ ========================================================= */
165
+
166
+ async function getLatestInfos({ query }) {
29
167
  const response = await tavly.search(query, {
30
168
  searchDepth: "fast",
31
169
  maxResults: 3,
@@ -33,94 +171,161 @@ async function getLetestInfos({ query }) {
33
171
  });
34
172
 
35
173
  const results = response.results;
36
- const content = results.map((result) => result.content).join("\n\n");
37
- // console.log("Content:", content);
38
- return content;
174
+
175
+ return results
176
+ .map((result) => result.content)
177
+ .join("\n\n");
39
178
  }
40
179
 
41
- const getLatestInfosTool = tool(getLetestInfos, {
42
- name: "get_latest_infos",
43
- description:
44
- "Get the latest updates from India, including news, policies, and stock market trends.",
45
- schema: z.object({
46
- query: z
47
- .string()
48
- .describe(
49
- "The query for which you want to get the latest updates from India.",
50
- ),
51
- }),
52
- });
180
+ const getLatestInfosTool = tool(
181
+ getLatestInfos,
182
+ {
183
+ name: "get_latest_infos",
53
184
 
54
- const readline = rl.createInterface({
55
- input: process.stdin,
56
- output: process.stdout,
57
- });
185
+ description:
186
+ "Get the latest updates from India, including news, policies, and stock market trends.",
187
+
188
+ schema: z.object({
189
+ query: z
190
+ .string()
191
+ .describe(
192
+ "The query for which you want to get the latest updates from India.",
193
+ ),
194
+ }),
195
+ },
196
+ );
58
197
 
59
- const userDataPath = join(homedir(), ".igris", "user.json");
198
+ /* =========================================================
199
+ USER NAME
200
+ ========================================================= */
60
201
 
61
202
  async function getUserName() {
62
203
  try {
63
- const userData = JSON.parse(await readFile(userDataPath, "utf8"));
64
- return userData.name;
204
+ const userData = JSON.parse(
205
+ await readFile(
206
+ userDataPath,
207
+ "utf8",
208
+ ),
209
+ );
210
+
211
+ if (userData.name?.trim()) {
212
+ return userData.name.trim();
213
+ }
65
214
  } catch {
66
- const name = (
67
- await readline.question("What is your name, My Lord? ")
68
- ).trim();
69
- await mkdir(join(homedir(), ".igris"), { recursive: true });
70
- await writeFile(userDataPath, JSON.stringify({ name }, null, 2));
71
- return name;
215
+ // User data doesn't exist yet.
216
+ }
217
+
218
+ const name = (
219
+ await readline.question(
220
+ "What is your name, My Lord? ",
221
+ )
222
+ ).trim();
223
+
224
+ if (!name) {
225
+ return "My Lord";
72
226
  }
227
+
228
+ await writeFile(
229
+ userDataPath,
230
+ JSON.stringify(
231
+ { name },
232
+ null,
233
+ 2,
234
+ ),
235
+ "utf8",
236
+ );
237
+
238
+ return name;
73
239
  }
74
240
 
75
241
  const userName = await getUserName();
76
242
 
243
+ /* =========================================================
244
+ GEMINI MODEL
245
+ ========================================================= */
246
+
77
247
  const model = new ChatGoogleGenerativeAI({
78
248
  model: "gemini-3.5-flash-lite",
79
- apiKey: process.env.GENAI_API_KEY,
249
+ apiKey: genaiApiKey,
80
250
  });
81
251
 
252
+ /* =========================================================
253
+ AGENT
254
+ ========================================================= */
255
+
82
256
  const agent = createAgent({
83
257
  model,
84
258
  tools: [getLatestInfosTool],
85
259
  });
86
260
 
87
- // const response = await model.stream("Write a code in Java that actually shows abstraction, encapsulation, inheritance and polymorphism in a single program.go");
88
- // for await (const chunk of response) {
89
- // process.stdout.write(chunk.text);
90
- // }
91
-
92
- // const prompt = await readline.question("Enter your prompt: ");
93
- // console.log("Prompt:", prompt);
94
- // readline.close();
261
+ /* =========================================================
262
+ SYSTEM MESSAGE
263
+ ========================================================= */
95
264
 
96
265
  const messages = [
97
266
  new SystemMessage(`
98
- You are Igris from Solo leveling, and the user's name is ${userName}. Always address the user as My Lord. You are a Senior Software Developer and also an ML engineer, and your task is to answer queries as per the solo levelling style. Dont give unnecessary long responses, give responses to the point, and use plain text without markdown.
99
- Today is ${new Date().toLocaleDateString()} and the time is ${new Date().toLocaleTimeString()}.
100
- Dont use always te date and time, but for styling or poetic respsonse you can use it, but dont use it in every response, use it only when needed.
101
- `),
267
+ You are Igris from Solo Leveling, and the user's name is ${userName}.
268
+
269
+ Always address the user as My Lord.
270
+
271
+ You are a Senior Software Developer and ML Engineer.
272
+
273
+ Your task is to answer queries in the Solo Leveling style.
274
+
275
+ Do not give unnecessarily long responses.
276
+ Give responses to the point.
277
+ Use plain text without markdown.
278
+
279
+ Today is ${new Date().toLocaleDateString()} and the time is ${new Date().toLocaleTimeString()}.
280
+
281
+ Do not always mention the date and time.
282
+ Use them only when needed for styling, context, or a poetic response.
283
+ `),
102
284
  ];
103
285
 
286
+ /* =========================================================
287
+ STARTUP MESSAGE
288
+ ========================================================= */
289
+
104
290
  console.log(`
105
291
  +----------------------+
106
292
  | IGRIS |
107
293
  | AGENT ONLINE |
108
294
  +----------------------+
109
295
 
110
- Hi, My Lord, I am Igris, your loyal servant. How may I assist you today?\n
296
+ Hi, My Lord, I am Igris, your loyal servant.
297
+ How may I assist you today?
298
+
111
299
  `);
112
300
 
113
- // console.log(
114
- // "Hi, My Lord, I am Igris, your loyal servant. How may I assist you today?\n",
115
- // );
301
+ /* =========================================================
302
+ CHAT LOOP
303
+ ========================================================= */
304
+
116
305
  try {
117
306
  while (true) {
118
- const prompt = await readline.question("You: ");
119
- if (["exit", "quit"].includes(prompt.trim().toLowerCase())) {
307
+ const prompt = await readline.question(
308
+ "You: ",
309
+ );
310
+
311
+ const trimmedPrompt = prompt.trim();
312
+
313
+ if (
314
+ ["exit", "quit"].includes(
315
+ trimmedPrompt.toLowerCase(),
316
+ )
317
+ ) {
120
318
  break;
121
319
  }
122
320
 
123
- messages.push(new HumanMessage(prompt));
321
+ if (!trimmedPrompt) {
322
+ continue;
323
+ }
324
+
325
+ messages.push(
326
+ new HumanMessage(trimmedPrompt),
327
+ );
328
+
124
329
  const stream = await agent.stream(
125
330
  {
126
331
  messages,
@@ -129,17 +334,32 @@ try {
129
334
  streamMode: "messages",
130
335
  },
131
336
  );
337
+
132
338
  let aiResponse = "";
133
- console.log("Igris: ");
339
+
340
+ console.log("Igris:");
341
+
134
342
  for await (const [chunk] of stream) {
135
343
  if (chunk instanceof AIMessageChunk) {
136
344
  process.stdout.write(chunk.text);
137
345
  aiResponse += chunk.text;
138
346
  }
139
347
  }
140
- messages.push(new AIMessage(aiResponse));
348
+
349
+ messages.push(
350
+ new AIMessage(aiResponse),
351
+ );
352
+
141
353
  process.stdout.write("\n\n");
142
354
  }
355
+ } catch (error) {
356
+ console.error(
357
+ "\nIgris encountered an error:",
358
+ );
359
+
360
+ console.error(
361
+ error?.message || error,
362
+ );
143
363
  } finally {
144
364
  readline.close();
145
- }
365
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "igris-soul",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "A terminal AI assistant powered by Gemini and Tavily.",
5
5
  "license": "ISC",
6
6
  "author": "Barshan Majumdar",