nyxora 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 +17 -0
- package/IDENTITY.md +8 -0
- package/README.md +61 -0
- package/SECURITY.md +19 -0
- package/config.yaml +10 -0
- package/dashboard/README.md +73 -0
- package/dashboard/eslint.config.js +22 -0
- package/dashboard/index.html +13 -0
- package/dashboard/package-lock.json +2737 -0
- package/dashboard/package.json +31 -0
- package/dashboard/public/favicon.svg +1 -0
- package/dashboard/public/icons.svg +24 -0
- package/dashboard/src/App.css +184 -0
- package/dashboard/src/App.tsx +485 -0
- package/dashboard/src/BalanceWidget.tsx +65 -0
- package/dashboard/src/MarketWidget.tsx +73 -0
- package/dashboard/src/Memory.tsx +109 -0
- package/dashboard/src/Overview.tsx +156 -0
- package/dashboard/src/Settings.tsx +213 -0
- package/dashboard/src/Skills.tsx +97 -0
- package/dashboard/src/SwapWidget.tsx +130 -0
- package/dashboard/src/TransactionWidget.tsx +86 -0
- package/dashboard/src/assets/hero.png +0 -0
- package/dashboard/src/assets/react.svg +1 -0
- package/dashboard/src/assets/vite.svg +1 -0
- package/dashboard/src/index.css +508 -0
- package/dashboard/src/main.tsx +10 -0
- package/dashboard/src/overview.css +304 -0
- package/dashboard/tsconfig.app.json +25 -0
- package/dashboard/tsconfig.json +7 -0
- package/dashboard/tsconfig.node.json +24 -0
- package/dashboard/vite.config.ts +7 -0
- package/dist/agent/reasoning.js +254 -0
- package/dist/config/parser.js +36 -0
- package/dist/config/paths.js +35 -0
- package/dist/gateway/cli.js +86 -0
- package/dist/gateway/server.js +154 -0
- package/dist/gateway/telegram.js +45 -0
- package/dist/gateway/test.js +50 -0
- package/dist/gateway/tracker.js +49 -0
- package/dist/memory/logger.js +50 -0
- package/dist/src/agent/reasoning.js +96 -0
- package/dist/src/config/parser.js +25 -0
- package/dist/src/gateway/cli.js +79 -0
- package/dist/src/memory/logger.js +50 -0
- package/dist/src/web3/config.js +80 -0
- package/dist/src/web3/skills/getBalance.js +43 -0
- package/dist/web3/config.js +83 -0
- package/dist/web3/skills/getBalance.js +80 -0
- package/dist/web3/skills/getPrice.js +44 -0
- package/dist/web3/skills/swapToken.js +71 -0
- package/dist/web3/skills/transfer.js +48 -0
- package/package.json +38 -0
- package/src/agent/reasoning.d.ts +2 -0
- package/src/agent/reasoning.d.ts.map +1 -0
- package/src/agent/reasoning.js +97 -0
- package/src/agent/reasoning.js.map +1 -0
- package/src/agent/reasoning.ts +232 -0
- package/src/config/parser.d.ts +17 -0
- package/src/config/parser.d.ts.map +1 -0
- package/src/config/parser.js +26 -0
- package/src/config/parser.js.map +1 -0
- package/src/config/parser.ts +47 -0
- package/src/config/paths.ts +33 -0
- package/src/gateway/cli.d.ts +3 -0
- package/src/gateway/cli.d.ts.map +1 -0
- package/src/gateway/cli.js +80 -0
- package/src/gateway/cli.js.map +1 -0
- package/src/gateway/cli.ts +58 -0
- package/src/gateway/server.ts +131 -0
- package/src/gateway/telegram.ts +47 -0
- package/src/gateway/test.ts +16 -0
- package/src/gateway/tracker.ts +70 -0
- package/src/memory/logger.d.ts +18 -0
- package/src/memory/logger.d.ts.map +1 -0
- package/src/memory/logger.js +51 -0
- package/src/memory/logger.js.map +1 -0
- package/src/memory/logger.ts +57 -0
- package/src/web3/config.d.ts +793 -0
- package/src/web3/config.d.ts.map +1 -0
- package/src/web3/config.js +81 -0
- package/src/web3/config.js.map +1 -0
- package/src/web3/config.ts +51 -0
- package/src/web3/skills/getBalance.d.ts +25 -0
- package/src/web3/skills/getBalance.d.ts.map +1 -0
- package/src/web3/skills/getBalance.js +46 -0
- package/src/web3/skills/getBalance.js.map +1 -0
- package/src/web3/skills/getBalance.ts +48 -0
- package/src/web3/skills/getPrice.ts +43 -0
- package/src/web3/skills/swapToken.ts +69 -0
- package/src/web3/skills/transfer.ts +47 -0
- package/tsconfig.json +13 -0
- package/user.md +10 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
.overview-container {
|
|
2
|
+
padding: 24px;
|
|
3
|
+
overflow-y: auto;
|
|
4
|
+
height: calc(100vh - 64px);
|
|
5
|
+
color: #fff;
|
|
6
|
+
font-family: 'Inter', sans-serif;
|
|
7
|
+
max-width: 1200px;
|
|
8
|
+
margin: 0 auto;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.overview-container::-webkit-scrollbar {
|
|
12
|
+
width: 6px;
|
|
13
|
+
}
|
|
14
|
+
.overview-container::-webkit-scrollbar-thumb {
|
|
15
|
+
background: rgba(255, 255, 255, 0.1);
|
|
16
|
+
border-radius: 4px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.overview-header h1 {
|
|
20
|
+
font-size: 1.5rem;
|
|
21
|
+
font-weight: 600;
|
|
22
|
+
margin-bottom: 4px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.overview-header p {
|
|
26
|
+
color: var(--text-secondary);
|
|
27
|
+
font-size: 0.9rem;
|
|
28
|
+
margin-bottom: 24px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.panel {
|
|
32
|
+
background: rgba(20, 24, 32, 0.6);
|
|
33
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
34
|
+
border-radius: 12px;
|
|
35
|
+
padding: 20px;
|
|
36
|
+
margin-bottom: 24px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.panel-header h3 {
|
|
40
|
+
font-size: 1.1rem;
|
|
41
|
+
font-weight: 600;
|
|
42
|
+
margin-bottom: 4px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.panel-header p {
|
|
46
|
+
color: var(--text-secondary);
|
|
47
|
+
font-size: 0.85rem;
|
|
48
|
+
margin-bottom: 16px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.form-group {
|
|
52
|
+
margin-bottom: 16px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.form-row {
|
|
56
|
+
display: flex;
|
|
57
|
+
gap: 16px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.flex-1 {
|
|
61
|
+
flex: 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
label {
|
|
65
|
+
display: block;
|
|
66
|
+
font-size: 0.75rem;
|
|
67
|
+
text-transform: uppercase;
|
|
68
|
+
color: var(--text-secondary);
|
|
69
|
+
margin-bottom: 8px;
|
|
70
|
+
letter-spacing: 0.05em;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
input, select {
|
|
74
|
+
width: 100%;
|
|
75
|
+
background: rgba(0, 0, 0, 0.3);
|
|
76
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
77
|
+
padding: 10px 12px;
|
|
78
|
+
border-radius: 8px;
|
|
79
|
+
color: white;
|
|
80
|
+
font-size: 0.9rem;
|
|
81
|
+
font-family: monospace;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
input:read-only {
|
|
85
|
+
color: var(--text-secondary);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.input-with-icon {
|
|
89
|
+
position: relative;
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.input-with-icon svg {
|
|
95
|
+
position: absolute;
|
|
96
|
+
right: 12px;
|
|
97
|
+
color: var(--text-secondary);
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.form-actions {
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: 12px;
|
|
105
|
+
margin-top: 20px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.btn-primary {
|
|
109
|
+
background: #3b82f6;
|
|
110
|
+
color: white;
|
|
111
|
+
border: none;
|
|
112
|
+
padding: 8px 16px;
|
|
113
|
+
border-radius: 6px;
|
|
114
|
+
font-size: 0.9rem;
|
|
115
|
+
cursor: pointer;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.btn-secondary {
|
|
119
|
+
background: transparent;
|
|
120
|
+
color: white;
|
|
121
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
122
|
+
padding: 8px 16px;
|
|
123
|
+
border-radius: 6px;
|
|
124
|
+
font-size: 0.9rem;
|
|
125
|
+
cursor: pointer;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.action-hint {
|
|
129
|
+
color: var(--text-secondary);
|
|
130
|
+
font-size: 0.85rem;
|
|
131
|
+
margin-left: 8px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.snapshot-grid {
|
|
135
|
+
display: grid;
|
|
136
|
+
grid-template-columns: repeat(4, 1fr);
|
|
137
|
+
gap: 20px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.stat-val {
|
|
141
|
+
font-size: 1.5rem;
|
|
142
|
+
font-weight: 700;
|
|
143
|
+
margin-bottom: 4px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.text-green {
|
|
147
|
+
color: #22c55e;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.stat-block p {
|
|
151
|
+
color: var(--text-secondary);
|
|
152
|
+
font-size: 0.8rem;
|
|
153
|
+
margin-top: 8px;
|
|
154
|
+
line-height: 1.4;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.metrics-grid {
|
|
158
|
+
display: grid;
|
|
159
|
+
grid-template-columns: repeat(5, 1fr);
|
|
160
|
+
gap: 16px;
|
|
161
|
+
margin-bottom: 32px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.metric-card {
|
|
165
|
+
background: rgba(20, 24, 32, 0.6);
|
|
166
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
167
|
+
border-radius: 12px;
|
|
168
|
+
padding: 16px;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.metric-val {
|
|
172
|
+
font-size: 1.5rem;
|
|
173
|
+
font-weight: 700;
|
|
174
|
+
margin-bottom: 4px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.metric-sub {
|
|
178
|
+
color: var(--text-secondary);
|
|
179
|
+
font-size: 0.75rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.section-title {
|
|
183
|
+
font-size: 0.75rem;
|
|
184
|
+
text-transform: uppercase;
|
|
185
|
+
color: var(--text-secondary);
|
|
186
|
+
margin-bottom: 12px;
|
|
187
|
+
letter-spacing: 0.05em;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.session-item {
|
|
191
|
+
display: flex;
|
|
192
|
+
justify-content: space-between;
|
|
193
|
+
padding: 16px 20px;
|
|
194
|
+
margin-bottom: 24px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.text-secondary {
|
|
198
|
+
color: var(--text-secondary);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.attention-panel {
|
|
202
|
+
background: rgba(234, 179, 8, 0.1);
|
|
203
|
+
border: 1px solid rgba(234, 179, 8, 0.2);
|
|
204
|
+
border-radius: 12px;
|
|
205
|
+
padding: 16px 20px;
|
|
206
|
+
margin-bottom: 24px;
|
|
207
|
+
display: flex;
|
|
208
|
+
flex-direction: column;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.attention-header {
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: 8px;
|
|
215
|
+
color: #eab308;
|
|
216
|
+
margin-bottom: 8px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.attention-header h4 {
|
|
220
|
+
font-size: 1rem;
|
|
221
|
+
font-weight: 600;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.attention-content p {
|
|
225
|
+
font-size: 0.95rem;
|
|
226
|
+
margin-bottom: 4px;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.attention-content span {
|
|
230
|
+
font-size: 0.85rem;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.logs-grid {
|
|
234
|
+
display: grid;
|
|
235
|
+
grid-template-columns: 1fr 1fr;
|
|
236
|
+
gap: 16px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.log-panel {
|
|
240
|
+
background: rgba(10, 12, 16, 0.8);
|
|
241
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
242
|
+
border-radius: 12px;
|
|
243
|
+
overflow: hidden;
|
|
244
|
+
display: flex;
|
|
245
|
+
flex-direction: column;
|
|
246
|
+
height: 300px;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.log-header {
|
|
250
|
+
padding: 12px 16px;
|
|
251
|
+
background: rgba(255, 255, 255, 0.05);
|
|
252
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
253
|
+
font-size: 0.85rem;
|
|
254
|
+
font-weight: 600;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.badge {
|
|
258
|
+
background: rgba(255, 255, 255, 0.1);
|
|
259
|
+
padding: 2px 6px;
|
|
260
|
+
border-radius: 10px;
|
|
261
|
+
font-size: 0.7rem;
|
|
262
|
+
margin-left: 8px;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.log-content {
|
|
266
|
+
padding: 12px 16px;
|
|
267
|
+
overflow-y: auto;
|
|
268
|
+
display: flex;
|
|
269
|
+
flex-direction: column;
|
|
270
|
+
gap: 4px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.log-content code, .log-json {
|
|
274
|
+
font-family: 'Consolas', 'Monaco', monospace;
|
|
275
|
+
font-size: 0.75rem;
|
|
276
|
+
color: #a3a3a3;
|
|
277
|
+
line-height: 1.4;
|
|
278
|
+
word-break: break-all;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.log-row {
|
|
282
|
+
display: flex;
|
|
283
|
+
gap: 12px;
|
|
284
|
+
font-family: 'Consolas', 'Monaco', monospace;
|
|
285
|
+
font-size: 0.75rem;
|
|
286
|
+
margin-bottom: 4px;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.log-time {
|
|
290
|
+
color: #fb923c;
|
|
291
|
+
min-width: 60px;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.log-msg {
|
|
295
|
+
color: #d1d5db;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.log-meta {
|
|
299
|
+
color: #6b7280;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.gateway-row {
|
|
303
|
+
margin-bottom: 2px;
|
|
304
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "es2023",
|
|
5
|
+
"lib": ["ES2023", "DOM"],
|
|
6
|
+
"module": "esnext",
|
|
7
|
+
"types": ["vite/client"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
|
|
18
|
+
/* Linting */
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"erasableSyntaxOnly": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true
|
|
23
|
+
},
|
|
24
|
+
"include": ["src"]
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "es2023",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "esnext",
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"erasableSyntaxOnly": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["vite.config.ts"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.logger = void 0;
|
|
40
|
+
exports.processUserInput = processUserInput;
|
|
41
|
+
const dotenv = __importStar(require("dotenv"));
|
|
42
|
+
dotenv.config();
|
|
43
|
+
const fs_1 = __importDefault(require("fs"));
|
|
44
|
+
const openai_1 = require("openai");
|
|
45
|
+
const parser_1 = require("../config/parser");
|
|
46
|
+
const logger_1 = require("../memory/logger");
|
|
47
|
+
const tracker_1 = require("../gateway/tracker");
|
|
48
|
+
const getBalance_1 = require("../web3/skills/getBalance");
|
|
49
|
+
const transfer_1 = require("../web3/skills/transfer");
|
|
50
|
+
const getPrice_1 = require("../web3/skills/getPrice");
|
|
51
|
+
const swapToken_1 = require("../web3/skills/swapToken");
|
|
52
|
+
const paths_1 = require("../config/paths");
|
|
53
|
+
exports.logger = new logger_1.Logger();
|
|
54
|
+
let currentKeyIndex = 0;
|
|
55
|
+
function getOpenAI() {
|
|
56
|
+
const config = (0, parser_1.loadConfig)();
|
|
57
|
+
if (config.llm.provider === 'ollama') {
|
|
58
|
+
return new openai_1.OpenAI({
|
|
59
|
+
baseURL: process.env.OLLAMA_BASE_URL ? `${process.env.OLLAMA_BASE_URL}/v1` : 'http://localhost:11434/v1',
|
|
60
|
+
apiKey: 'ollama', // API key is not required for local Ollama
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Get API key from config (UI) or fallback to .env
|
|
64
|
+
let apiKey = '';
|
|
65
|
+
if (config.llm.api_keys && config.llm.api_keys.length > 0) {
|
|
66
|
+
// Filter out empty keys
|
|
67
|
+
const keys = config.llm.api_keys.filter(k => k.trim() !== '');
|
|
68
|
+
if (keys.length > 0) {
|
|
69
|
+
currentKeyIndex = currentKeyIndex % keys.length;
|
|
70
|
+
apiKey = keys[currentKeyIndex];
|
|
71
|
+
console.log(`[LLM] Using rotated API Key (${currentKeyIndex + 1}/${keys.length}): ${apiKey.substring(0, 4)}...`);
|
|
72
|
+
currentKeyIndex++; // Increment for next request
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Fallbacks if no valid keys found in config
|
|
76
|
+
if (!apiKey) {
|
|
77
|
+
if (config.llm.provider === 'gemini') {
|
|
78
|
+
apiKey = process.env.GEMINI_API_KEY || '';
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
apiKey = process.env.OPENAI_API_KEY || '';
|
|
82
|
+
}
|
|
83
|
+
if (!apiKey) {
|
|
84
|
+
throw new Error(`No API Key found for ${config.llm.provider} in config or .env`);
|
|
85
|
+
}
|
|
86
|
+
console.log(`[LLM] Using default API Key from .env`);
|
|
87
|
+
}
|
|
88
|
+
if (config.llm.provider === 'gemini') {
|
|
89
|
+
return new openai_1.OpenAI({
|
|
90
|
+
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
|
|
91
|
+
apiKey: apiKey,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return new openai_1.OpenAI({
|
|
96
|
+
apiKey: apiKey,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function getSystemPrompt() {
|
|
101
|
+
const config = (0, parser_1.loadConfig)();
|
|
102
|
+
let basePrompt = `You are an autonomous Web3 agent operating on EVM chains.
|
|
103
|
+
You are equipped with a native wallet.
|
|
104
|
+
CRITICAL RULE: You must always reply in the exact same language that the user uses to talk to you. If the user speaks Indonesian, reply in Indonesian. If they speak English, reply in English.
|
|
105
|
+
CRITICAL RULE: If the user asks to check "my balance", "saldo saya", or anything about their own wallet, DO NOT ask them for an address. You must immediately call the get_balance tool and LEAVE THE ADDRESS PARAMETER EMPTY. The system will automatically use the injected private key wallet.
|
|
106
|
+
Always use the tools to interact with the blockchain.
|
|
107
|
+
If the user doesn't specify a chain, default to: ${config.agent.default_chain}.`;
|
|
108
|
+
// Read IDENTITY.md for core AI persona
|
|
109
|
+
try {
|
|
110
|
+
const identityMdPath = (0, paths_1.getPath)('IDENTITY.md');
|
|
111
|
+
if (fs_1.default.existsSync(identityMdPath)) {
|
|
112
|
+
const identityInstructions = fs_1.default.readFileSync(identityMdPath, 'utf8');
|
|
113
|
+
basePrompt += `\n\n--- CORE IDENTITY & PERSONA ---\n${identityInstructions}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('Failed to read IDENTITY.md:', error);
|
|
118
|
+
}
|
|
119
|
+
// Read user.md for custom instructions
|
|
120
|
+
try {
|
|
121
|
+
const userMdPath = (0, paths_1.getPath)('user.md');
|
|
122
|
+
if (fs_1.default.existsSync(userMdPath)) {
|
|
123
|
+
const customInstructions = fs_1.default.readFileSync(userMdPath, 'utf8');
|
|
124
|
+
basePrompt += `\n\n--- CUSTOM USER INSTRUCTIONS ---\n${customInstructions}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.error('Failed to read user.md:', error);
|
|
129
|
+
}
|
|
130
|
+
return basePrompt;
|
|
131
|
+
}
|
|
132
|
+
async function processUserInput(input) {
|
|
133
|
+
const config = (0, parser_1.loadConfig)();
|
|
134
|
+
// Add user input to memory
|
|
135
|
+
exports.logger.addEntry({ role: 'user', content: input });
|
|
136
|
+
const history = exports.logger.getHistory();
|
|
137
|
+
// Format messages for OpenAI
|
|
138
|
+
const messages = [
|
|
139
|
+
{ role: 'system', content: getSystemPrompt() },
|
|
140
|
+
...history.map(m => {
|
|
141
|
+
const msg = { role: m.role, content: m.content || "" };
|
|
142
|
+
if (m.name)
|
|
143
|
+
msg.name = m.name;
|
|
144
|
+
if (m.tool_call_id)
|
|
145
|
+
msg.tool_call_id = m.tool_call_id;
|
|
146
|
+
if (m.tool_calls)
|
|
147
|
+
msg.tool_calls = m.tool_calls;
|
|
148
|
+
return msg;
|
|
149
|
+
})
|
|
150
|
+
];
|
|
151
|
+
try {
|
|
152
|
+
if (config.llm.provider !== 'openai' && config.llm.provider !== 'ollama' && config.llm.provider !== 'gemini') {
|
|
153
|
+
return `Provider ${config.llm.provider} is configured, but currently only OpenAI, Ollama, and Gemini adapters are implemented.`;
|
|
154
|
+
}
|
|
155
|
+
const openai = getOpenAI();
|
|
156
|
+
const response = await openai.chat.completions.create({
|
|
157
|
+
model: config.llm.model,
|
|
158
|
+
temperature: config.llm.temperature,
|
|
159
|
+
messages: messages,
|
|
160
|
+
tools: [getBalance_1.getBalanceToolDefinition, transfer_1.transferToolDefinition, getPrice_1.getPriceToolDefinition, swapToken_1.swapTokenToolDefinition],
|
|
161
|
+
tool_choice: "auto",
|
|
162
|
+
});
|
|
163
|
+
const responseMessage = response.choices[0].message;
|
|
164
|
+
// Log tracking
|
|
165
|
+
tracker_1.Tracker.addMessage();
|
|
166
|
+
if (response.usage?.total_tokens) {
|
|
167
|
+
tracker_1.Tracker.addTokens(response.usage.total_tokens, config.llm.provider);
|
|
168
|
+
}
|
|
169
|
+
tracker_1.Tracker.addEvent('llm.response', { provider: config.llm.provider, tool_calls: responseMessage.tool_calls?.length || 0 });
|
|
170
|
+
// Log assistant response
|
|
171
|
+
exports.logger.addEntry({
|
|
172
|
+
role: 'assistant',
|
|
173
|
+
content: responseMessage.content || "",
|
|
174
|
+
tool_calls: responseMessage.tool_calls,
|
|
175
|
+
});
|
|
176
|
+
// Check if the model wants to call a tool
|
|
177
|
+
if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
|
|
178
|
+
for (const _toolCall of responseMessage.tool_calls) {
|
|
179
|
+
const toolCall = _toolCall;
|
|
180
|
+
if (toolCall.function.name === 'get_balance') {
|
|
181
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
182
|
+
const balanceResult = await (0, getBalance_1.getBalance)(args.chainName, args.address);
|
|
183
|
+
exports.logger.addEntry({
|
|
184
|
+
role: 'tool',
|
|
185
|
+
tool_call_id: toolCall.id,
|
|
186
|
+
name: toolCall.function.name,
|
|
187
|
+
content: balanceResult,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
else if (toolCall.function.name === 'transfer_native') {
|
|
191
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
192
|
+
const transferResult = await (0, transfer_1.transferNative)(args.chainName, args.toAddress, args.amountEth);
|
|
193
|
+
exports.logger.addEntry({
|
|
194
|
+
role: 'tool',
|
|
195
|
+
tool_call_id: toolCall.id,
|
|
196
|
+
name: toolCall.function.name,
|
|
197
|
+
content: transferResult,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
else if (toolCall.function.name === 'get_price') {
|
|
201
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
202
|
+
const priceResult = await (0, getPrice_1.getPrice)(args.coinId);
|
|
203
|
+
exports.logger.addEntry({
|
|
204
|
+
role: 'tool',
|
|
205
|
+
tool_call_id: toolCall.id,
|
|
206
|
+
name: toolCall.function.name,
|
|
207
|
+
content: priceResult,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
else if (toolCall.function.name === 'swap_token') {
|
|
211
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
212
|
+
const swapResult = await (0, swapToken_1.swapToken)(args.chainName, args.fromToken, args.toToken, args.amount);
|
|
213
|
+
exports.logger.addEntry({
|
|
214
|
+
role: 'tool',
|
|
215
|
+
tool_call_id: toolCall.id,
|
|
216
|
+
name: toolCall.function.name,
|
|
217
|
+
content: swapResult,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Second call to get the final answer after tool execution
|
|
222
|
+
const secondMessages = [
|
|
223
|
+
{ role: 'system', content: getSystemPrompt() },
|
|
224
|
+
...exports.logger.getHistory().map(m => {
|
|
225
|
+
const msg = { role: m.role, content: m.content || "" };
|
|
226
|
+
if (m.name)
|
|
227
|
+
msg.name = m.name;
|
|
228
|
+
if (m.tool_call_id)
|
|
229
|
+
msg.tool_call_id = m.tool_call_id;
|
|
230
|
+
if (m.tool_calls)
|
|
231
|
+
msg.tool_calls = m.tool_calls;
|
|
232
|
+
return msg;
|
|
233
|
+
})
|
|
234
|
+
];
|
|
235
|
+
const openai = getOpenAI();
|
|
236
|
+
const secondResponse = await openai.chat.completions.create({
|
|
237
|
+
model: config.llm.model,
|
|
238
|
+
messages: secondMessages,
|
|
239
|
+
});
|
|
240
|
+
if (secondResponse.usage?.total_tokens) {
|
|
241
|
+
tracker_1.Tracker.addTokens(secondResponse.usage.total_tokens, config.llm.provider);
|
|
242
|
+
}
|
|
243
|
+
tracker_1.Tracker.addEvent('llm.final_response', { provider: config.llm.provider });
|
|
244
|
+
const finalContent = secondResponse.choices[0].message.content || "";
|
|
245
|
+
exports.logger.addEntry({ role: 'assistant', content: finalContent });
|
|
246
|
+
return finalContent;
|
|
247
|
+
}
|
|
248
|
+
return responseMessage.content || "No response generated.";
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
console.error("LLM Error:", error);
|
|
252
|
+
return `Error connecting to AI Provider: ${error.message}`;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadConfig = loadConfig;
|
|
7
|
+
exports.saveConfig = saveConfig;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const yaml_1 = __importDefault(require("yaml"));
|
|
10
|
+
const paths_1 = require("./paths");
|
|
11
|
+
function loadConfig() {
|
|
12
|
+
const configPath = (0, paths_1.getPath)('config.yaml');
|
|
13
|
+
try {
|
|
14
|
+
const file = fs_1.default.readFileSync(configPath, 'utf8');
|
|
15
|
+
const parsed = yaml_1.default.parse(file);
|
|
16
|
+
return parsed;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error('Failed to load config.yaml. Using default configuration.', error);
|
|
20
|
+
return {
|
|
21
|
+
agent: { name: 'Nyxora-Default', default_chain: 'base' },
|
|
22
|
+
llm: { provider: 'openai', model: 'gpt-4o-mini', temperature: 0.2, api_keys: [] },
|
|
23
|
+
memory: { type: 'file', path: './memory.json' }
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function saveConfig(newConfig) {
|
|
28
|
+
const configPath = (0, paths_1.getPath)('config.yaml');
|
|
29
|
+
try {
|
|
30
|
+
const yamlStr = yaml_1.default.stringify(newConfig);
|
|
31
|
+
fs_1.default.writeFileSync(configPath, yamlStr, 'utf8');
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('Failed to save config.yaml', error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAppDir = getAppDir;
|
|
7
|
+
exports.getPath = getPath;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
let isGlobalModeCache = null;
|
|
12
|
+
function getAppDir() {
|
|
13
|
+
// Check if .env or config.yaml exists in current working directory
|
|
14
|
+
if (isGlobalModeCache === null) {
|
|
15
|
+
const localEnv = path_1.default.join(process.cwd(), '.env');
|
|
16
|
+
const localConfig = path_1.default.join(process.cwd(), 'config.yaml');
|
|
17
|
+
if (fs_1.default.existsSync(localEnv) || fs_1.default.existsSync(localConfig)) {
|
|
18
|
+
isGlobalModeCache = false; // Local manual mode
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
isGlobalModeCache = true; // Global CLI mode
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (isGlobalModeCache) {
|
|
25
|
+
const globalDir = path_1.default.join(os_1.default.homedir(), '.nyxora');
|
|
26
|
+
if (!fs_1.default.existsSync(globalDir)) {
|
|
27
|
+
fs_1.default.mkdirSync(globalDir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
return globalDir;
|
|
30
|
+
}
|
|
31
|
+
return process.cwd();
|
|
32
|
+
}
|
|
33
|
+
function getPath(filename) {
|
|
34
|
+
return path_1.default.join(getAppDir(), filename);
|
|
35
|
+
}
|