nyxora 26.7.2 → 26.7.4

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 (192) hide show
  1. package/CHANGELOG.md +112 -47
  2. package/README.md +25 -21
  3. package/bin/nyxora.mjs +4 -6
  4. package/dist/launcher.js +44 -8
  5. package/dist/packages/core/src/agent/bridgeWatcher.js +3 -2
  6. package/dist/packages/core/src/agent/cronManager.js +2 -2
  7. package/dist/packages/core/src/agent/llmProvider.js +245 -0
  8. package/dist/packages/core/src/agent/nyxDaemon.js +97 -0
  9. package/dist/packages/core/src/agent/osAgent.js +351 -29
  10. package/dist/packages/core/src/agent/reasoning.js +353 -60
  11. package/dist/packages/core/src/agent/reasoningScratchpad.js +47 -0
  12. package/dist/packages/core/src/agent/transactionManager.js +36 -31
  13. package/dist/packages/core/src/agent/web3Agent.js +263 -37
  14. package/dist/packages/core/src/cognitive/cognitiveManager.js +63 -10
  15. package/dist/packages/core/src/config/parser.js +10 -4
  16. package/dist/packages/core/src/gateway/chat.js +56 -13
  17. package/dist/packages/core/src/gateway/cli.js +3 -0
  18. package/dist/packages/core/src/gateway/discordAdapter.js +81 -0
  19. package/dist/packages/core/src/gateway/googleAuthModule.js +2 -0
  20. package/dist/packages/core/src/gateway/server.js +58 -9
  21. package/dist/packages/core/src/gateway/setup-ml.js +64 -0
  22. package/dist/packages/core/src/gateway/setup.js +39 -3
  23. package/dist/packages/core/src/gateway/telegram.js +123 -27
  24. package/dist/packages/core/src/memory/episodic.js +58 -3
  25. package/dist/packages/core/src/memory/logger.js +120 -2
  26. package/dist/packages/core/src/memory/promotionEngine.js +18 -5
  27. package/dist/packages/core/src/system/agentskills.js +10 -0
  28. package/dist/packages/core/src/system/plugins/GoogleWorkspacePlugin.js +10 -2
  29. package/dist/packages/core/src/system/plugins/SystemCorePlugin.js +1 -1
  30. package/dist/packages/core/src/system/plugins/SystemExternalPlugin.js +1 -1
  31. package/dist/packages/core/src/system/plugins/SystemPluginInstallerPlugin.js +1 -1
  32. package/dist/packages/core/src/system/plugins/SystemSocialPlugin.js +1 -1
  33. package/dist/packages/core/src/system/plugins/SystemWebPlugin.js +1 -1
  34. package/dist/packages/core/src/system/plugins/SystemWorkspacePlugin.js +3 -3
  35. package/dist/packages/core/src/system/plugins/createSkill.js +1 -1
  36. package/dist/packages/core/src/system/skillExtractor.js +16 -5
  37. package/dist/packages/core/src/system/skills/executeShell.js +31 -4
  38. package/dist/packages/core/src/system/skills/forgetMemory.js +6 -4
  39. package/dist/packages/core/src/system/skills/googleWorkspace.js +106 -1
  40. package/dist/packages/core/src/system/skills/scheduleTask.js +7 -2
  41. package/dist/packages/core/src/system/skills/searchWeb.js +13 -6
  42. package/dist/packages/core/src/test_mainnet.js +45 -0
  43. package/dist/packages/core/src/utils/contextSummarizer.js +82 -0
  44. package/dist/packages/core/src/utils/skillManager.js +1 -1
  45. package/dist/packages/core/src/utils/streamSimulator.js +85 -0
  46. package/dist/packages/core/src/web3/aggregator/providers/ArbitrumBridgeProvider.js +28 -11
  47. package/dist/packages/core/src/web3/aggregator/providers/OpBridgeProvider.js +41 -27
  48. package/dist/packages/core/src/web3/aggregator/providers/TestnetSwapProvider.js +65 -0
  49. package/dist/packages/core/src/web3/aggregator/routeSelector.js +7 -1
  50. package/dist/packages/core/src/web3/plugins/Web3DefiPlugin.js +1 -1
  51. package/dist/packages/core/src/web3/plugins/Web3MarketPlugin.js +5 -125
  52. package/dist/packages/core/src/web3/plugins/Web3SecurityPlugin.js +1 -1
  53. package/dist/packages/core/src/web3/plugins/Web3WalletPlugin.js +1 -1
  54. package/dist/packages/core/src/web3/skills/bridgeToken.js +19 -4
  55. package/dist/packages/core/src/web3/skills/checkAddress.js +2 -0
  56. package/dist/packages/core/src/web3/skills/checkPortfolio.js +22 -2
  57. package/dist/packages/core/src/web3/skills/checkSecurity.js +2 -0
  58. package/dist/packages/core/src/web3/skills/confirmPendingTx.js +1 -1
  59. package/dist/packages/core/src/web3/skills/createLimitOrder.js +15 -1
  60. package/dist/packages/core/src/web3/skills/customTx.js +3 -0
  61. package/dist/packages/core/src/web3/skills/defiLending.js +2 -0
  62. package/dist/packages/core/src/web3/skills/getBalance.js +2 -0
  63. package/dist/packages/core/src/web3/skills/getPrice.js +134 -27
  64. package/dist/packages/core/src/web3/skills/getTxHistory.js +2 -0
  65. package/dist/packages/core/src/web3/skills/marketAnalysis.js +28 -191
  66. package/dist/packages/core/src/web3/skills/mintNft.js +3 -0
  67. package/dist/packages/core/src/web3/skills/provideLiquidity.js +16 -12
  68. package/dist/packages/core/src/web3/skills/revokeApprovals.js +2 -0
  69. package/dist/packages/core/src/web3/skills/swapToken.js +20 -2
  70. package/dist/packages/core/src/web3/skills/transfer.js +2 -0
  71. package/dist/packages/core/src/web3/skills/yieldVault.js +2 -0
  72. package/dist/packages/core/src/web3/utils/chains.js +19 -0
  73. package/dist/packages/core/src/web3/utils/marketEngine.js +26 -33
  74. package/dist/packages/signer/src/NyxoraSigner.js +181 -0
  75. package/dist/packages/signer/src/index.js +17 -0
  76. package/dist/packages/signer/src/server.js +25 -161
  77. package/launcher.ts +38 -9
  78. package/package.json +8 -3
  79. package/packages/core/package.json +21 -10
  80. package/packages/core/src/agent/bridgeWatcher.ts +3 -2
  81. package/packages/core/src/agent/cronManager.ts +2 -2
  82. package/packages/core/src/agent/llmProvider.ts +221 -0
  83. package/packages/core/src/agent/nyxDaemon.ts +104 -0
  84. package/packages/core/src/agent/osAgent.ts +381 -32
  85. package/packages/core/src/agent/reasoning.ts +376 -64
  86. package/packages/core/src/agent/reasoningScratchpad.ts +45 -0
  87. package/packages/core/src/agent/transactionManager.ts +36 -28
  88. package/packages/core/src/agent/web3Agent.ts +291 -40
  89. package/packages/core/src/cognitive/cognitiveManager.ts +65 -10
  90. package/packages/core/src/cognitive/prompts/web3/market-analysis.md +24 -0
  91. package/packages/core/src/cognitive/prompts/web3/portfolio-review.md +29 -0
  92. package/packages/core/src/cognitive/prompts/web3/risk-assessment.md +28 -0
  93. package/packages/core/src/cognitive/prompts/web3/trade-planning.md +30 -0
  94. package/packages/core/src/config/parser.ts +15 -4
  95. package/packages/core/src/gateway/chat.ts +57 -15
  96. package/packages/core/src/gateway/cli.ts +4 -0
  97. package/packages/core/src/gateway/discordAdapter.ts +87 -0
  98. package/packages/core/src/gateway/googleAuthModule.ts +2 -0
  99. package/packages/core/src/gateway/server.ts +66 -10
  100. package/packages/core/src/gateway/setup-ml.ts +68 -0
  101. package/packages/core/src/gateway/setup.ts +41 -3
  102. package/packages/core/src/gateway/telegram.ts +141 -30
  103. package/packages/core/src/memory/episodic.ts +76 -3
  104. package/packages/core/src/memory/logger.ts +142 -2
  105. package/packages/core/src/memory/promotionEngine.ts +19 -5
  106. package/packages/core/src/system/agentskills.ts +10 -0
  107. package/packages/core/src/system/plugins/GoogleWorkspacePlugin.ts +15 -3
  108. package/packages/core/src/system/plugins/SystemCorePlugin.ts +1 -1
  109. package/packages/core/src/system/plugins/SystemExternalPlugin.ts +1 -1
  110. package/packages/core/src/system/plugins/SystemPluginInstallerPlugin.ts +1 -1
  111. package/packages/core/src/system/plugins/SystemSocialPlugin.ts +1 -1
  112. package/packages/core/src/system/plugins/SystemWebPlugin.ts +1 -1
  113. package/packages/core/src/system/plugins/SystemWorkspacePlugin.ts +3 -3
  114. package/packages/core/src/system/plugins/createSkill.ts +1 -1
  115. package/packages/core/src/system/skillExtractor.ts +16 -5
  116. package/packages/core/src/system/skills/executeShell.ts +38 -7
  117. package/packages/core/src/system/skills/forgetMemory.ts +7 -4
  118. package/packages/core/src/system/skills/googleWorkspace.ts +109 -0
  119. package/packages/core/src/system/skills/scheduleTask.ts +7 -2
  120. package/packages/core/src/system/skills/searchWeb.ts +12 -6
  121. package/packages/core/src/utils/contextSummarizer.ts +100 -0
  122. package/packages/core/src/utils/skillManager.ts +1 -1
  123. package/packages/core/src/utils/streamSimulator.ts +88 -0
  124. package/packages/core/src/web3/aggregator/providers/ArbitrumBridgeProvider.ts +30 -11
  125. package/packages/core/src/web3/aggregator/providers/OpBridgeProvider.ts +43 -29
  126. package/packages/core/src/web3/aggregator/routeSelector.ts +6 -1
  127. package/packages/core/src/web3/plugins/Web3DefiPlugin.ts +1 -1
  128. package/packages/core/src/web3/plugins/Web3MarketPlugin.ts +6 -125
  129. package/packages/core/src/web3/plugins/Web3SecurityPlugin.ts +1 -1
  130. package/packages/core/src/web3/plugins/Web3WalletPlugin.ts +1 -1
  131. package/packages/core/src/web3/skills/bridgeToken.ts +21 -7
  132. package/packages/core/src/web3/skills/checkAddress.ts +2 -0
  133. package/packages/core/src/web3/skills/checkPortfolio.ts +23 -2
  134. package/packages/core/src/web3/skills/checkSecurity.ts +2 -0
  135. package/packages/core/src/web3/skills/confirmPendingTx.ts +1 -1
  136. package/packages/core/src/web3/skills/createLimitOrder.ts +17 -2
  137. package/packages/core/src/web3/skills/customTx.ts +3 -0
  138. package/packages/core/src/web3/skills/defiLending.ts +2 -0
  139. package/packages/core/src/web3/skills/getBalance.ts +2 -0
  140. package/packages/core/src/web3/skills/getPrice.ts +134 -30
  141. package/packages/core/src/web3/skills/getTxHistory.ts +2 -0
  142. package/packages/core/src/web3/skills/marketAnalysis.ts +45 -188
  143. package/packages/core/src/web3/skills/mintNft.ts +3 -0
  144. package/packages/core/src/web3/skills/provideLiquidity.ts +16 -10
  145. package/packages/core/src/web3/skills/revokeApprovals.ts +2 -0
  146. package/packages/core/src/web3/skills/swapToken.ts +20 -3
  147. package/packages/core/src/web3/skills/transfer.ts +2 -0
  148. package/packages/core/src/web3/skills/yieldVault.ts +2 -0
  149. package/packages/core/src/web3/utils/chains.ts +12 -0
  150. package/packages/core/src/web3/utils/marketEngine.ts +27 -33
  151. package/packages/dashboard/dist/assets/index-Czxksiao.js +18 -0
  152. package/packages/dashboard/dist/assets/index-DK2sTU47.css +1 -0
  153. package/packages/dashboard/dist/index.html +2 -2
  154. package/packages/dashboard/package.json +10 -10
  155. package/packages/mcp-server/dist/server.js +5 -1
  156. package/packages/mcp-server/package.json +6 -6
  157. package/packages/mcp-server/src/server.ts +11 -7
  158. package/packages/ml-engine/__pycache__/config.cpython-313.pyc +0 -0
  159. package/packages/ml-engine/__pycache__/main.cpython-313.pyc +0 -0
  160. package/packages/ml-engine/config.py +59 -0
  161. package/packages/ml-engine/main.py +34 -0
  162. package/packages/ml-engine/requirements.txt +22 -0
  163. package/packages/ml-engine/routers/__init__.py +1 -0
  164. package/packages/ml-engine/routers/__pycache__/__init__.cpython-313.pyc +0 -0
  165. package/packages/ml-engine/routers/__pycache__/cognitive.cpython-313.pyc +0 -0
  166. package/packages/ml-engine/routers/__pycache__/critic.cpython-313.pyc +0 -0
  167. package/packages/ml-engine/routers/__pycache__/llm.cpython-313.pyc +0 -0
  168. package/packages/ml-engine/routers/__pycache__/market.cpython-313.pyc +0 -0
  169. package/packages/ml-engine/routers/__pycache__/memory.cpython-313.pyc +0 -0
  170. package/packages/ml-engine/routers/cognitive.py +98 -0
  171. package/packages/ml-engine/routers/critic.py +111 -0
  172. package/packages/ml-engine/routers/llm.py +38 -0
  173. package/packages/ml-engine/routers/market.py +332 -0
  174. package/packages/ml-engine/routers/memory.py +125 -0
  175. package/packages/policy/package.json +3 -3
  176. package/packages/signer/package.json +16 -6
  177. package/packages/signer/src/NyxoraSigner.ts +161 -0
  178. package/packages/signer/src/index.ts +1 -0
  179. package/packages/signer/src/server.ts +25 -135
  180. package/dist/packages/core/src/agent/honchoDaemon.js +0 -91
  181. package/dist/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +0 -54
  182. package/dist/packages/core/src/gateway/test.js +0 -15
  183. package/dist/packages/core/src/web3/Web3DefiPlugin.js +0 -28
  184. package/dist/packages/core/src/web3/aggregator/aggregatorMainnet.js +0 -260
  185. package/dist/packages/core/src/web3/aggregator/aggregatorTestnet.js +0 -119
  186. package/dist/packages/core/src/web3/skills/nativeOpBridge.js +0 -71
  187. package/packages/core/src/agent/honchoDaemon.ts +0 -96
  188. package/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +0 -41
  189. package/packages/core/src/plugin/registry.test.ts +0 -46
  190. package/packages/core/src/utils/formatter.test.ts +0 -41
  191. package/packages/dashboard/dist/assets/index-CSoNa5cx.css +0 -1
  192. package/packages/dashboard/dist/assets/index-DbRWEoSr.js +0 -16
@@ -102,7 +102,9 @@ function loadRpcConfig() {
102
102
  function saveRpcConfig(rpcUrls) {
103
103
  const rpcPath = (0, paths_1.getPath)('rpc_key.yaml');
104
104
  try {
105
- fs_1.default.writeFileSync(rpcPath, yaml_1.default.stringify(rpcUrls), 'utf8');
105
+ const tempPath = rpcPath + '.tmp.' + Date.now();
106
+ fs_1.default.writeFileSync(tempPath, yaml_1.default.stringify(rpcUrls), 'utf8');
107
+ fs_1.default.renameSync(tempPath, rpcPath);
106
108
  }
107
109
  catch (error) {
108
110
  console.error('Failed to save rpc_key.yaml', error);
@@ -203,7 +205,8 @@ function loadConfig() {
203
205
  memory: parsed.memory || { type: 'file', path: './memory.json' },
204
206
  web3: { ...parsed.web3, rpc_urls: rpcUrls },
205
207
  integrations: parsed.integrations || {
206
- telegram: { enabled: false }
208
+ telegram: { enabled: false },
209
+ discord: { enabled: false }
207
210
  },
208
211
  security: parsed.security || { dashboard_password: '123456' },
209
212
  skills: parsed.skills
@@ -244,7 +247,8 @@ function loadConfig() {
244
247
  memory: { type: 'file', path: './memory.json' },
245
248
  web3: { rpc_urls: rpcUrls },
246
249
  integrations: {
247
- telegram: { enabled: false }
250
+ telegram: { enabled: false },
251
+ discord: { enabled: false }
248
252
  }
249
253
  };
250
254
  cachedNyxoraConfig = defaultConfig;
@@ -263,7 +267,9 @@ function saveConfig(newConfig) {
263
267
  }
264
268
  // Keys are no longer encrypted before saving. They are stored in plain text.
265
269
  const yamlStr = yaml_1.default.stringify(configToSave);
266
- fs_1.default.writeFileSync(configPath, yamlStr, 'utf8');
270
+ const tempPath = configPath + '.tmp.' + Date.now();
271
+ fs_1.default.writeFileSync(tempPath, yamlStr, 'utf8');
272
+ fs_1.default.renameSync(tempPath, configPath);
267
273
  }
268
274
  catch (error) {
269
275
  console.error('Failed to save config.yaml', error);
@@ -48,13 +48,14 @@ async function chatInteractive() {
48
48
  const s = (0, prompts_1.spinner)();
49
49
  s.start('Thinking...');
50
50
  try {
51
- const response = await fetch('http://localhost:3000/api/chat', {
52
- method: 'POST',
53
- headers: {
54
- 'Content-Type': 'application/json',
55
- 'x-nyxora-token': token,
56
- },
57
- body: JSON.stringify({ message: messageStr, session_id: 'cli-chat' })
51
+ // Use SSE streaming endpoint for real-time token output
52
+ const params = new URLSearchParams({
53
+ message: messageStr,
54
+ session_id: 'cli-chat',
55
+ token,
56
+ });
57
+ const response = await fetch(`http://localhost:3000/api/chat/stream?${params}`, {
58
+ headers: { 'x-nyxora-token': token },
58
59
  });
59
60
  if (!response.ok) {
60
61
  s.stop(picocolors_1.default.red('API Error.'));
@@ -67,12 +68,54 @@ async function chatInteractive() {
67
68
  }
68
69
  continue;
69
70
  }
70
- const data = await response.json();
71
- s.stop(picocolors_1.default.green('Nyxora:'));
72
- let finalReply = data.response || '';
73
- // Strip <think> tags for clean UI
74
- finalReply = finalReply.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
75
- console.log(finalReply + '\n');
71
+ let firstChunk = true;
72
+ let finalReply = '';
73
+ // Read SSE stream line by line
74
+ const reader = response.body?.getReader();
75
+ const decoder = new TextDecoder();
76
+ if (reader) {
77
+ let buffer = '';
78
+ while (true) {
79
+ const { done, value } = await reader.read();
80
+ if (done)
81
+ break;
82
+ buffer += decoder.decode(value, { stream: true });
83
+ const lines = buffer.split('\n');
84
+ buffer = lines.pop() || '';
85
+ for (const line of lines) {
86
+ if (!line.startsWith('data: '))
87
+ continue;
88
+ const raw = line.slice(6).trim();
89
+ if (raw === '[DONE]')
90
+ break;
91
+ try {
92
+ const data = JSON.parse(raw);
93
+ if (data.progress) {
94
+ // Show tool progress on same line, overwriting previous
95
+ if (firstChunk) {
96
+ s.stop(picocolors_1.default.cyan('Nyxora:'));
97
+ firstChunk = false;
98
+ }
99
+ process.stdout.write(`\r${picocolors_1.default.italic(picocolors_1.default.gray(data.progress))} `);
100
+ }
101
+ if (data.chunk) {
102
+ if (firstChunk) {
103
+ s.stop(picocolors_1.default.green('Nyxora:'));
104
+ process.stdout.write('\n');
105
+ firstChunk = false;
106
+ }
107
+ // Clear progress line if any, then write chunk
108
+ finalReply += data.chunk;
109
+ process.stdout.write(data.chunk);
110
+ }
111
+ }
112
+ catch { }
113
+ }
114
+ }
115
+ }
116
+ // Newline after streaming completes
117
+ if (!firstChunk)
118
+ process.stdout.write('\n\n');
76
119
  // Check for pending transactions
77
120
  try {
78
121
  const txRes = await fetch('http://localhost:3000/api/transactions', {
@@ -39,6 +39,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  const safeLogger_1 = require("../utils/safeLogger");
41
41
  (0, safeLogger_1.initSafeLogger)();
42
+ const dns_1 = __importDefault(require("dns"));
43
+ // Fix Node 18+ native fetch randomly failing on dual-stack VPS (IPv6 issues)
44
+ dns_1.default.setDefaultResultOrder('ipv4first');
42
45
  const fs_1 = __importDefault(require("fs"));
43
46
  const path_1 = __importDefault(require("path"));
44
47
  const os_1 = __importDefault(require("os"));
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startDiscordBot = startDiscordBot;
4
+ const discord_js_1 = require("discord.js");
5
+ const reasoning_1 = require("../agent/reasoning");
6
+ const parser_1 = require("../config/parser");
7
+ let discordClient = null;
8
+ function startDiscordBot() {
9
+ const config = (0, parser_1.loadConfig)();
10
+ const token = config.integrations?.discord?.bot_token;
11
+ if (!token || !config.integrations?.discord?.enabled) {
12
+ console.log('[Discord] Bot is disabled or missing bot_token in config.yaml.');
13
+ return;
14
+ }
15
+ discordClient = new discord_js_1.Client({
16
+ intents: [
17
+ discord_js_1.GatewayIntentBits.Guilds,
18
+ discord_js_1.GatewayIntentBits.GuildMessages,
19
+ discord_js_1.GatewayIntentBits.MessageContent,
20
+ ],
21
+ });
22
+ discordClient.once('ready', () => {
23
+ console.log(`🤖 Discord Bot is online and logged in as ${discordClient?.user?.tag}`);
24
+ });
25
+ discordClient.on('messageCreate', async (message) => {
26
+ // Ignore messages from bots
27
+ if (message.author.bot)
28
+ return;
29
+ // Check if the bot is mentioned
30
+ if (discordClient?.user && message.mentions.has(discordClient.user)) {
31
+ // Strip the mention from the message
32
+ const prompt = message.content.replace(new RegExp(`<@!?${discordClient.user.id}>`, 'g'), '').trim();
33
+ if (!prompt)
34
+ return;
35
+ console.log(`[Discord] Received mention from ${message.author.username} in #${message.channel.name}: ${prompt}`);
36
+ // Send initial thinking indicator
37
+ let replyMessage = null;
38
+ try {
39
+ replyMessage = await message.reply('⏳ *Thinking...*');
40
+ }
41
+ catch (err) {
42
+ console.error('[Discord] Failed to send initial reply', err);
43
+ return;
44
+ }
45
+ const onProgress = async (progressText) => {
46
+ try {
47
+ if (replyMessage) {
48
+ await replyMessage.edit(`*${progressText}*`);
49
+ }
50
+ }
51
+ catch (err) {
52
+ // Ignore minor edit errors
53
+ }
54
+ };
55
+ try {
56
+ const sessionId = `discord_${message.author.id}`;
57
+ const response = await (0, reasoning_1.processUserInput)(prompt, 'user', onProgress, sessionId);
58
+ // Clean up thought blocks if any
59
+ let finalResponse = response.replace(/<thought>[\s\S]*?<\/thought>\n?/g, '').replace(/<think>[\s\S]*?<\/think>\n?/g, '');
60
+ if (replyMessage) {
61
+ // Discord has a 2000 character limit per message
62
+ if (finalResponse.length > 2000) {
63
+ await replyMessage.edit(finalResponse.slice(0, 1997) + '...');
64
+ }
65
+ else {
66
+ await replyMessage.edit(finalResponse);
67
+ }
68
+ }
69
+ }
70
+ catch (error) {
71
+ console.error('[Discord] Error processing message:', error);
72
+ if (replyMessage) {
73
+ await replyMessage.edit('❌ Sorry, I encountered an error while processing your request.');
74
+ }
75
+ }
76
+ }
77
+ });
78
+ discordClient.login(token).catch(err => {
79
+ console.error('[Discord] Failed to login:', err);
80
+ });
81
+ }
@@ -15,7 +15,9 @@ const CREDENTIALS_PATH = (0, paths_1.getPath)('google-credentials.json');
15
15
  const FALLBACK_TOKEN_PATH = (0, paths_1.getPath)('google-tokens.json');
16
16
  const SCOPES = [
17
17
  'https://www.googleapis.com/auth/gmail.readonly',
18
+ 'https://www.googleapis.com/auth/gmail.send',
18
19
  'https://www.googleapis.com/auth/calendar.readonly',
20
+ 'https://www.googleapis.com/auth/calendar.events',
19
21
  'https://www.googleapis.com/auth/documents.readonly',
20
22
  'https://www.googleapis.com/auth/spreadsheets',
21
23
  'https://www.googleapis.com/auth/forms.responses.readonly',
@@ -51,19 +51,22 @@ const customTx_1 = require("../web3/skills/customTx");
51
51
  const executeDefi_1 = require("../web3/skills/executeDefi");
52
52
  const revokeApprovals_1 = require("../web3/skills/revokeApprovals");
53
53
  const telegram_1 = require("./telegram");
54
+ const discordAdapter_1 = require("./discordAdapter");
54
55
  const bridgeWatcher_1 = require("../agent/bridgeWatcher");
55
56
  const eventListener_1 = require("../web3/eventListener");
56
57
  const googleAuthModule_1 = require("./googleAuthModule");
57
58
  const legalGenerator_1 = require("./legalGenerator");
58
59
  const episodic_1 = require("../memory/episodic");
59
60
  const reflection_1 = require("../memory/reflection");
60
- const honchoDaemon_1 = require("../agent/honchoDaemon");
61
+ const nyxDaemon_1 = require("../agent/nyxDaemon");
61
62
  // Initialize Google Auth
62
63
  (0, googleAuthModule_1.initGoogleAuth)();
63
- // Start Background Honcho Daemon
64
- honchoDaemon_1.honchoDaemon.start();
64
+ // Start Background Nyx Daemon
65
+ nyxDaemon_1.nyxDaemon.start();
65
66
  // Synchronize all active skills to config.yaml on startup
66
67
  (0, skillManager_1.syncAllSkillsToConfig)();
68
+ // Start messaging adapters
69
+ (0, discordAdapter_1.startDiscordBot)();
67
70
  const util_1 = __importDefault(require("util"));
68
71
  // Intercept console.log and console.error
69
72
  const originalLog = console.log;
@@ -115,7 +118,7 @@ app.use('/api', (req, res, next) => {
115
118
  if (allowedPaths.includes(currentPath) || allowedPaths.includes(currentPath.replace(/\/$/, ''))) {
116
119
  return next();
117
120
  }
118
- const token = req.headers['x-nyxora-token'];
121
+ const token = req.headers['x-nyxora-token'] || req.query.token;
119
122
  const validation = (0, state_1.validateToken)(token);
120
123
  if (!validation.valid) {
121
124
  console.error(`[Auth] Rejected ${req.method} ${req.originalUrl} - Received invalid token.`);
@@ -174,7 +177,9 @@ app.post('/api/upload-google-credentials', (req, res) => {
174
177
  const credsPath = (0, paths_1.getPath)('google-credentials.json');
175
178
  // The format needs to wrap it in "web" or "installed"
176
179
  const finalPayload = credentials.client_id ? { installed: credentials } : credentials;
177
- fs_1.default.writeFileSync(credsPath, JSON.stringify(finalPayload, null, 2));
180
+ const tempPath = credsPath + '.tmp.' + Date.now();
181
+ fs_1.default.writeFileSync(tempPath, JSON.stringify(finalPayload, null, 2));
182
+ fs_1.default.renameSync(tempPath, credsPath);
178
183
  // Re-initialize google auth module
179
184
  (0, googleAuthModule_1.initGoogleAuth)();
180
185
  res.json({ success: true });
@@ -609,7 +614,7 @@ app.post('/api/transactions/:id/approve', async (req, res) => {
609
614
  transactionManager_1.txManager.updateStatus(id, 'approved', 'Executing on-chain...');
610
615
  res.json({ success: true, status: 'processing', message: 'Transaction submitted to background processing.' });
611
616
  // Execute in background
612
- (async () => {
617
+ const txPromise = (async () => {
613
618
  try {
614
619
  let result = '';
615
620
  if (tx.type === 'transfer') {
@@ -689,6 +694,7 @@ app.post('/api/transactions/:id/approve', async (req, res) => {
689
694
  reasoning_1.logger.addEntry({ role: 'assistant', content: `❌ **Transaction Failed**\n\n${err.message}` }, sessionId);
690
695
  }
691
696
  })();
697
+ transactionManager_1.txManager.trackPromise(txPromise);
692
698
  }
693
699
  catch (err) {
694
700
  transactionManager_1.txManager.updateStatus(req.params.id, 'failed', err.message);
@@ -975,7 +981,47 @@ app.post('/api/chat', async (req, res) => {
975
981
  res.status(500).json({ error: error.message });
976
982
  }
977
983
  });
978
- // --- Memory API Endpoints ---
984
+ // --- Streaming Chat Endpoint (SSE) ---
985
+ // Sends LLM tokens to the client as they arrive via Server-Sent Events.
986
+ // The old /api/chat endpoint remains untouched for backward compatibility.
987
+ app.get('/api/chat/stream', async (req, res) => {
988
+ const { message, session_id } = req.query;
989
+ if (!message) {
990
+ res.status(400).json({ error: 'Message is required' });
991
+ return;
992
+ }
993
+ // Setup SSE headers
994
+ res.setHeader('Content-Type', 'text/event-stream');
995
+ res.setHeader('Cache-Control', 'no-cache');
996
+ res.setHeader('Connection', 'keep-alive');
997
+ res.setHeader('X-Accel-Buffering', 'no'); // Disable Nginx buffering
998
+ res.flushHeaders();
999
+ const sendEvent = (data) => {
1000
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
1001
+ };
1002
+ const onChunk = (text) => sendEvent({ chunk: text });
1003
+ const onProgress = (msg) => sendEvent({ progress: msg });
1004
+ try {
1005
+ await (0, reasoning_1.processUserInputStream)(message, onChunk, onProgress, session_id);
1006
+ // Trigger memory mechanisms after response completes
1007
+ resetIdleTimer(session_id);
1008
+ messageCounter++;
1009
+ if (messageCounter >= 5) {
1010
+ messageCounter = 0;
1011
+ reflection_1.ReflectionEngine.runReflection(session_id).then(() => {
1012
+ const { PromotionEngine } = require('../memory/promotionEngine');
1013
+ PromotionEngine.runPromotionAndDecay();
1014
+ }).catch(console.error);
1015
+ }
1016
+ }
1017
+ catch (err) {
1018
+ sendEvent({ error: err.message });
1019
+ }
1020
+ finally {
1021
+ res.write('data: [DONE]\n\n');
1022
+ res.end();
1023
+ }
1024
+ });
979
1025
  app.get('/api/memory', (req, res) => {
980
1026
  try {
981
1027
  const memories = episodic_1.episodicDB.getMemories();
@@ -988,9 +1034,10 @@ app.get('/api/memory', (req, res) => {
988
1034
  app.delete('/api/memory/all', (req, res) => {
989
1035
  try {
990
1036
  episodic_1.episodicDB.clearAllMemories();
1037
+ episodic_1.episodicDB.clearAllPersonas();
991
1038
  const { PromotionEngine } = require('../memory/promotionEngine');
992
1039
  PromotionEngine.runPromotionAndDecay();
993
- res.json({ success: true, message: "Episodic memory wiped completely." });
1040
+ res.json({ success: true, message: "Episodic memory and persona traits wiped completely." });
994
1041
  }
995
1042
  catch (error) {
996
1043
  res.status(500).json({ error: error.message });
@@ -1158,11 +1205,13 @@ async function startServer() {
1158
1205
  }
1159
1206
  });
1160
1207
  let isShuttingDown = false;
1161
- const gracefulShutdown = () => {
1208
+ const gracefulShutdown = async () => {
1162
1209
  if (isShuttingDown)
1163
1210
  return;
1164
1211
  isShuttingDown = true;
1165
1212
  console.log('[Nyxora Gateway] Received shutdown signal. Closing server...');
1213
+ // Wait for active transactions
1214
+ await transactionManager_1.txManager.waitForAll(10000);
1166
1215
  if (server.closeAllConnections) {
1167
1216
  server.closeAllConnections();
1168
1217
  }
@@ -0,0 +1,64 @@
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.setupMlEngine = setupMlEngine;
7
+ const child_process_1 = require("child_process");
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const picocolors_1 = __importDefault(require("picocolors"));
12
+ const prompts_1 = require("@clack/prompts");
13
+ const appDir = path_1.default.join(os_1.default.homedir(), '.nyxora');
14
+ const mlEngineDir = path_1.default.join(appDir, 'ml-engine');
15
+ const venvDir = path_1.default.join(mlEngineDir, 'venv');
16
+ const sourceReqPath = path_1.default.join(process.cwd(), 'packages', 'ml-engine', 'requirements.txt');
17
+ function runCommand(command, args, cwd) {
18
+ return new Promise((resolve, reject) => {
19
+ const child = (0, child_process_1.spawn)(command, args, { cwd, stdio: 'ignore' });
20
+ child.on('close', (code) => {
21
+ if (code === 0)
22
+ resolve();
23
+ else
24
+ reject(new Error(`Command ${command} ${args.join(' ')} failed with code ${code}`));
25
+ });
26
+ child.on('error', reject);
27
+ });
28
+ }
29
+ async function setupMlEngine() {
30
+ console.log(picocolors_1.default.cyan('\n⚙️ Initializing Universal Python ML Engine...\n'));
31
+ const s = (0, prompts_1.spinner)();
32
+ try {
33
+ if (!fs_1.default.existsSync(mlEngineDir)) {
34
+ fs_1.default.mkdirSync(mlEngineDir, { recursive: true });
35
+ }
36
+ s.start('Creating Python Virtual Environment (venv)...');
37
+ if (!fs_1.default.existsSync(venvDir)) {
38
+ await runCommand('python3', ['-m', 'venv', venvDir], mlEngineDir);
39
+ }
40
+ s.stop(picocolors_1.default.green('Virtual Environment created successfully.'));
41
+ s.start('Installing heavy Data Science & AI dependencies (this may take a while)...');
42
+ const pipPath = path_1.default.join(venvDir, 'bin', 'pip');
43
+ // Upgrade pip
44
+ await runCommand(pipPath, ['install', '--upgrade', 'pip'], mlEngineDir);
45
+ // Install requirements
46
+ if (fs_1.default.existsSync(sourceReqPath)) {
47
+ await runCommand(pipPath, ['install', '-r', sourceReqPath], mlEngineDir);
48
+ s.stop(picocolors_1.default.green('Dependencies installed successfully.'));
49
+ }
50
+ else {
51
+ s.stop(picocolors_1.default.yellow('requirements.txt not found. Skipping dependency installation.'));
52
+ }
53
+ (0, prompts_1.note)('The Python Sidecar is ready.\nIt will automatically start in the background when you run `nyxora start`.', 'ML Engine Configured');
54
+ }
55
+ catch (error) {
56
+ s.stop(picocolors_1.default.red('Failed to setup ML Engine.'));
57
+ console.error(picocolors_1.default.red(`Error: ${error.message}`));
58
+ console.log(picocolors_1.default.yellow('\nPlease ensure python3 and python3-venv are installed on your system.'));
59
+ }
60
+ }
61
+ // Allow running directly
62
+ if (require.main === module) {
63
+ setupMlEngine().then(() => process.exit(0));
64
+ }
@@ -23,13 +23,33 @@ async function runSetupWizard() {
23
23
  `;
24
24
  console.log(picocolors_1.default.cyan(logo));
25
25
  (0, prompts_1.intro)(picocolors_1.default.inverse(' Nyxora CLI Setup '));
26
+ try {
27
+ const nodeVersion = parseInt(process.versions.node.split('.')[0], 10);
28
+ if (nodeVersion < 18) {
29
+ console.error(picocolors_1.default.red(`\n❌ Unsupported Node.js version. Nyxora requires Node.js 18 or higher. You are running v${process.versions.node}`));
30
+ process.exit(1);
31
+ }
32
+ const { execSync } = require('child_process');
33
+ const pythonCmd = process.platform === 'win32' ? 'python' : 'python3';
34
+ const pyVersionStr = execSync(`${pythonCmd} -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
35
+ const [major, minor] = pyVersionStr.split('.').map(Number);
36
+ if (major < 3 || (major === 3 && minor < 10)) {
37
+ console.error(picocolors_1.default.red(`\n❌ Unsupported Python version. Nyxora ML Engine requires Python 3.10+. You are running v${pyVersionStr}`));
38
+ process.exit(1);
39
+ }
40
+ (0, prompts_1.note)(`Node.js: v${process.versions.node}\nPython: v${pyVersionStr}`, 'System Requirements Met');
41
+ }
42
+ catch (error) {
43
+ console.error(picocolors_1.default.red(`\n❌ Python 3 is not installed or not in your PATH. Nyxora requires Python 3.10+ for the ML Engine.`));
44
+ process.exit(1);
45
+ }
26
46
  const appDir = (0, paths_1.getAppDir)();
27
47
  const config = (0, parser_1.loadConfig)();
28
48
  const disclaimer = `Nyxora is a Web3 Assistant that operates with full access under your control.
29
49
 
30
50
  Critical Precautions:
31
- - Your Private Key is the lifeblood of your assets. NEVER copy or share the keystore.json file.
32
- - Any instructions you provide via Telegram or Dashboard can trigger on-chain transactions.
51
+ - Your Private Key is the lifeblood of your assets. NEVER copy or share your vault.key file or OS Keyring password.
52
+ - Any instructions you provide via Telegram, Discord, or the Dashboard can trigger on-chain transactions.
33
53
  - It is recommended to use a smart AI model for maximum accuracy.
34
54
 
35
55
  By using Nyxora, you retain full control over your own keys.`;
@@ -300,6 +320,7 @@ Provider: ${config.llm.provider}`;
300
320
  message: '💬 Select Integration Channels to enable:',
301
321
  options: [
302
322
  { value: 'telegram', label: 'Telegram Bot', hint: 'Requires Token' },
323
+ { value: 'discord', label: 'Discord Bot', hint: 'Requires Token' },
303
324
  { value: 'dashboard', label: 'Local Web Dashboard', hint: 'enabled by default' },
304
325
  ],
305
326
  initialValues: ['dashboard'],
@@ -405,6 +426,15 @@ Provider: ${config.llm.provider}`;
405
426
  }
406
427
  }
407
428
  }
429
+ const setupDiscord = activeChannels.includes('discord');
430
+ let discordToken = '';
431
+ if (setupDiscord) {
432
+ discordToken = (await (0, prompts_1.password)({
433
+ message: 'Enter Discord Bot Token (Leave empty if already set):',
434
+ }));
435
+ if ((0, prompts_1.isCancel)(discordToken))
436
+ return process.exit(0);
437
+ }
408
438
  // --- SAVING ---
409
439
  // Update Config.yaml
410
440
  config.llm.provider = provider;
@@ -456,6 +486,12 @@ Provider: ${config.llm.provider}`;
456
486
  else if (config.integrations.telegram) {
457
487
  delete config.integrations.telegram.authorized_chat_id;
458
488
  }
489
+ if (!config.integrations.discord)
490
+ config.integrations.discord = { enabled: false };
491
+ config.integrations.discord.enabled = setupDiscord;
492
+ if (setupDiscord && discordToken) {
493
+ config.integrations.discord.bot_token = discordToken;
494
+ }
459
495
  (0, parser_1.saveConfig)(config);
460
496
  // Sync disabled_skills.json based on user selection
461
497
  const allWeb3Skills = [
@@ -507,7 +543,7 @@ Provider: ${config.llm.provider}`;
507
543
  getBalance: 'get_balance',
508
544
  getMyAddress: 'get_my_address',
509
545
  checkPortfolio: 'check_portfolio',
510
- getPrice: 'get_price',
546
+ getPrice: 'get_price_and_fiat_value',
511
547
  marketAnalysis: 'analyze_market',
512
548
  getTxHistory: 'get_tx_history',
513
549
  checkSecurity: 'check_token_security',