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 +2 -0
- package/README.md +94 -0
- package/index.js +145 -0
- package/package.json +35 -0
package/.env.example
ADDED
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
|
+
}
|