igris-soul 1.0.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/.env.example ADDED
@@ -0,0 +1,2 @@
1
+ GENAI_API_KEY=your_google_gemini_api_key
2
+ TAVILY_API_KEY=your_tavily_api_key
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Igris Soul
2
+
3
+ > To use Igris Soul from anywhere, install it globally and run `Arise`:
4
+ >
5
+ > ```bash
6
+ > npm install -g igris-soul
7
+ > Arise
8
+ > ```
9
+
10
+ ## Disclaimer
11
+
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.
13
+
14
+ ## Requirements
15
+
16
+ - Node.js 20 or newer
17
+ - A Google Gemini API key
18
+ - A Tavily API key for current-information searches
19
+
20
+ ## Configuration
21
+
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:
23
+
24
+ ```env
25
+ GENAI_API_KEY=your_google_gemini_api_key
26
+ TAVILY_API_KEY=your_tavily_api_key
27
+ ```
28
+
29
+ Never commit `.env` or share its contents. It is already excluded by `.gitignore`.
30
+
31
+ When both files exist, the `.env` file in the current directory takes priority over the home-directory configuration.
32
+
33
+ ## Run From This Repository
34
+
35
+ Install dependencies and start Igris Soul:
36
+
37
+ ```bash
38
+ npm install
39
+ npm start
40
+ ```
41
+
42
+ You can also run:
43
+
44
+ ```bash
45
+ node index.js
46
+ ```
47
+
48
+ Type `exit` or `quit` to close the assistant.
49
+
50
+ ## Install As A Global CLI
51
+
52
+ ```bash
53
+ npm install -g igris-soul
54
+ Arise
55
+ ```
56
+
57
+ The `arise`, `igris-soul`, and `igris` aliases are also available. To test the package locally before publishing:
58
+
59
+ ```bash
60
+ npm install -g .
61
+ Arise
62
+ ```
63
+
64
+ ## Features
65
+
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
73
+
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.
75
+
76
+ ## Publishing
77
+
78
+ Log in to npm and publish the package:
79
+
80
+ ```bash
81
+ npm login
82
+ npm test
83
+ npm publish
84
+ ```
85
+
86
+ To verify the package without uploading it:
87
+
88
+ ```bash
89
+ npm publish --dry-run
90
+ ```
91
+
92
+ ## License
93
+
94
+ ISC
package/index.js ADDED
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
4
+ import { config } from "dotenv";
5
+ import { tavily } from "@tavily/core";
6
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
7
+ import { homedir } from "node:os";
8
+ import { join } from "node:path";
9
+ import rl from "readline/promises";
10
+ import {
11
+ HumanMessage,
12
+ AIMessage,
13
+ SystemMessage,
14
+ tool,
15
+ createAgent,
16
+ AIMessageChunk,
17
+ } from "langchain";
18
+ import * as z from "zod";
19
+
20
+ config({
21
+ path: [join(process.cwd(), ".env"), join(homedir(), ".igris", ".env")],
22
+ quiet: true,
23
+ });
24
+ const tavly = tavily({
25
+ apiKey: process.env.TAVILY_API_KEY,
26
+ });
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.";
29
+ const response = await tavly.search(query, {
30
+ searchDepth: "fast",
31
+ maxResults: 3,
32
+ timeout: 5000,
33
+ });
34
+
35
+ const results = response.results;
36
+ const content = results.map((result) => result.content).join("\n\n");
37
+ // console.log("Content:", content);
38
+ return content;
39
+ }
40
+
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
+ });
53
+
54
+ const readline = rl.createInterface({
55
+ input: process.stdin,
56
+ output: process.stdout,
57
+ });
58
+
59
+ const userDataPath = join(homedir(), ".igris", "user.json");
60
+
61
+ async function getUserName() {
62
+ try {
63
+ const userData = JSON.parse(await readFile(userDataPath, "utf8"));
64
+ return userData.name;
65
+ } 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;
72
+ }
73
+ }
74
+
75
+ const userName = await getUserName();
76
+
77
+ const model = new ChatGoogleGenerativeAI({
78
+ model: "gemini-3.5-flash-lite",
79
+ apiKey: process.env.GENAI_API_KEY,
80
+ });
81
+
82
+ const agent = createAgent({
83
+ model,
84
+ tools: [getLatestInfosTool],
85
+ });
86
+
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();
95
+
96
+ const messages = [
97
+ 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
+ `),
102
+ ];
103
+
104
+ console.log(`
105
+ +----------------------+
106
+ | IGRIS |
107
+ | AGENT ONLINE |
108
+ +----------------------+
109
+
110
+ Hi, My Lord, I am Igris, your loyal servant. How may I assist you today?\n
111
+ `);
112
+
113
+ // console.log(
114
+ // "Hi, My Lord, I am Igris, your loyal servant. How may I assist you today?\n",
115
+ // );
116
+ try {
117
+ while (true) {
118
+ const prompt = await readline.question("You: ");
119
+ if (["exit", "quit"].includes(prompt.trim().toLowerCase())) {
120
+ break;
121
+ }
122
+
123
+ messages.push(new HumanMessage(prompt));
124
+ const stream = await agent.stream(
125
+ {
126
+ messages,
127
+ },
128
+ {
129
+ streamMode: "messages",
130
+ },
131
+ );
132
+ let aiResponse = "";
133
+ console.log("Igris: ");
134
+ for await (const [chunk] of stream) {
135
+ if (chunk instanceof AIMessageChunk) {
136
+ process.stdout.write(chunk.text);
137
+ aiResponse += chunk.text;
138
+ }
139
+ }
140
+ messages.push(new AIMessage(aiResponse));
141
+ process.stdout.write("\n\n");
142
+ }
143
+ } finally {
144
+ readline.close();
145
+ }
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "igris-soul",
3
+ "version": "1.0.0",
4
+ "description": "A terminal AI assistant powered by Gemini and Tavily.",
5
+ "license": "ISC",
6
+ "author": "Barshan Majumdar",
7
+ "type": "module",
8
+ "main": "index.js",
9
+ "bin": {
10
+ "Arise": "index.js",
11
+ "arise": "index.js",
12
+ "igris-soul": "index.js",
13
+ "igris": "index.js"
14
+ },
15
+ "files": [
16
+ "index.js",
17
+ ".env.example"
18
+ ],
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "scripts": {
23
+ "start": "node index.js",
24
+ "test": "node --check index.js"
25
+ },
26
+ "dependencies": {
27
+ "@langchain/google-genai": "^2.3.2",
28
+ "@langchain/mistralai": "^1.2.0",
29
+ "@tavily/core": "^0.7.11",
30
+ "dotenv": "^17.4.2",
31
+ "langchain": "^1.5.11",
32
+ "readline": "^1.3.0",
33
+ "zod": "^4.6.4"
34
+ }
35
+ }