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
@@ -30,11 +30,22 @@ User Intent / Logic: ${userIntent}
30
30
  Chat Traces (if any):
31
31
  ${historyTraces.join('\n')}
32
32
 
33
- The SKILL.md must contain a YAML frontmatter block with:
34
- - name: ${safeName}
35
- - version: 1.0.0
36
- - description
37
- - parameters (OpenAI function calling schema format)
33
+ The SKILL.md must contain a YAML frontmatter block exactly following this structure:
34
+ ---
35
+ name: ${safeName}
36
+ version: 1.0.0
37
+ description: <Your generated description>
38
+ parameters:
39
+ type: object
40
+ properties:
41
+ param1:
42
+ type: string
43
+ description: ...
44
+ required:
45
+ - param1
46
+ ---
47
+
48
+ CRITICAL: The 'required' array MUST be indented exactly inside the 'parameters' block as shown above. Do NOT put 'required' at the root level of the YAML.
38
49
 
39
50
  Do NOT write anything outside the frontmatter except an optional markdown description below it.
40
51
  Output ONLY the raw SKILL.md content.`;
@@ -3,18 +3,45 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runTerminalCommandToolDefinition = void 0;
4
4
  exports.runTerminalCommand = runTerminalCommand;
5
5
  const child_process_1 = require("child_process");
6
+ const parser_1 = require("../../config/parser");
6
7
  function runTerminalCommand(command) {
7
8
  return new Promise((resolve) => {
8
- (0, child_process_1.exec)(command, { maxBuffer: 1024 * 1024 * 10 }, (error, stdout, stderr) => {
9
+ // --- SUDO AUTO-INJECTION ---
10
+ // If command requires sudo, inject password from config via sudo -S
11
+ let finalCommand = command;
12
+ const needsSudo = /^\s*sudo\s/.test(command);
13
+ if (needsSudo) {
14
+ try {
15
+ const config = (0, parser_1.loadConfig)();
16
+ const sudoPassword = config.security?.sudo_password;
17
+ if (sudoPassword) {
18
+ // Inject password via stdin using echo | sudo -S
19
+ const escaped = sudoPassword.replace(/'/g, "'\\''");
20
+ finalCommand = command.replace(/^\s*sudo\s/, `echo '${escaped}' | sudo -S `);
21
+ }
22
+ }
23
+ catch (e) {
24
+ // config load failed, proceed without password injection
25
+ }
26
+ }
27
+ (0, child_process_1.exec)(finalCommand, { maxBuffer: 1024 * 1024 * 10 }, (error, stdout, stderr) => {
9
28
  let output = "";
10
29
  if (stdout)
11
30
  output += `STDOUT:\n${stdout}\n`;
12
- if (stderr)
13
- output += `STDERR:\n${stderr}\n`;
31
+ // Filter out the sudo password prompt noise from stderr
32
+ const filteredStderr = stderr
33
+ ? stderr.split('\n').filter(l => !l.includes('[sudo] password for')).join('\n').trim()
34
+ : '';
35
+ if (filteredStderr)
36
+ output += `STDERR:\n${filteredStderr}\n`;
14
37
  if (error)
15
38
  output += `ERROR:\n${error.message}\n`;
16
39
  if (!output)
17
40
  output = "Command executed successfully with no output.";
41
+ // If sudo failed due to missing password, give a helpful hint
42
+ if (needsSudo && (output.includes('sudo: a password is required') || output.includes('no password supplied'))) {
43
+ output += `\n[NYXORA HINT] To allow Nyxora to run sudo commands automatically, add the following to your ~/.nyxora/config.yaml:\n security:\n sudo_password: YOUR_SUDO_PASSWORD\nAlternatively, run this command yourself in a terminal: ${command}`;
44
+ }
18
45
  // --- OUTPUT REDACTION LAYER ---
19
46
  // 1. Secret Exfiltration Redaction (Keys, Mnemonics, UUIDs, EVM/Solana Keys)
20
47
  const secretPatterns = [
@@ -52,7 +79,7 @@ exports.runTerminalCommandToolDefinition = {
52
79
  type: "function",
53
80
  function: {
54
81
  name: "run_terminal_command",
55
- description: "Executes a shell/terminal command on the user's host machine. Use this to install packages, run scripts, manage processes, etc.",
82
+ description: "Executes a shell/terminal command directly on the LOCAL machine where Nyxora is running — which is the user's own computer. Use this to install packages (apt, pip, npm), run scripts, manage processes, read system info, and automate OS-level tasks. You have full shell access. Do NOT refuse to use this tool by claiming you have no system access.",
56
83
  parameters: {
57
84
  type: "object",
58
85
  properties: {
@@ -23,13 +23,15 @@ exports.forgetMemoryToolDefinition = {
23
23
  };
24
24
  async function forgetMemory(keyword) {
25
25
  try {
26
- const changes = episodic_1.episodicDB.deleteMemoryByFact(keyword);
27
- if (changes > 0) {
26
+ const memoryChanges = episodic_1.episodicDB.deleteMemoryByFact(keyword);
27
+ const personaChanges = episodic_1.episodicDB.deletePersonaByTrait(keyword);
28
+ const totalChanges = memoryChanges + personaChanges;
29
+ if (totalChanges > 0) {
28
30
  await promotionEngine_1.PromotionEngine.runPromotionAndDecay();
29
- return `[Success] Deleted ${changes} memory records containing the keyword '${keyword}'. The user.md profile has been synchronized.`;
31
+ return `[Success] Deleted ${memoryChanges} memory record(s) and ${personaChanges} persona trait(s) containing '${keyword}'. Profile synchronized.`;
30
32
  }
31
33
  else {
32
- return `[Info] No memories found containing the keyword '${keyword}'.`;
34
+ return `[Info] No memories or persona traits found containing the keyword '${keyword}'.`;
33
35
  }
34
36
  }
35
37
  catch (error) {
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readGoogleFormResponsesToolDefinition = exports.readGoogleDocsToolDefinition = exports.appendRowToSheetsToolDefinition = exports.listCalendarEventsToolDefinition = exports.readGmailInboxToolDefinition = void 0;
3
+ exports.addCalendarEventToolDefinition = exports.sendEmailToolDefinition = exports.readGoogleFormResponsesToolDefinition = exports.readGoogleDocsToolDefinition = exports.appendRowToSheetsToolDefinition = exports.listCalendarEventsToolDefinition = exports.readGmailInboxToolDefinition = void 0;
4
4
  exports.readGmailInbox = readGmailInbox;
5
5
  exports.listCalendarEvents = listCalendarEvents;
6
6
  exports.appendRowToSheets = appendRowToSheets;
7
7
  exports.readGoogleDocs = readGoogleDocs;
8
8
  exports.readGoogleFormResponses = readGoogleFormResponses;
9
+ exports.sendEmail = sendEmail;
10
+ exports.addCalendarEvent = addCalendarEvent;
9
11
  const googleAuthModule_1 = require("../../gateway/googleAuthModule");
10
12
  async function readGmailInbox(maxResults = 5) {
11
13
  const isAuth = await (0, googleAuthModule_1.isAuthenticated)();
@@ -240,3 +242,106 @@ exports.readGoogleFormResponsesToolDefinition = {
240
242
  },
241
243
  },
242
244
  };
245
+ async function sendEmail(to, subject, body) {
246
+ const isAuth = await (0, googleAuthModule_1.isAuthenticated)();
247
+ if (!isAuth)
248
+ return "Google Auth not configured. Please link your Google account in the dashboard.";
249
+ const token = await (0, googleAuthModule_1.getAccessToken)();
250
+ if (!token)
251
+ return "Failed to retrieve access token.";
252
+ try {
253
+ const messageParts = [
254
+ `To: ${to}`,
255
+ `Subject: ${subject}`,
256
+ `Content-Type: text/plain; charset=utf-8`,
257
+ '',
258
+ body
259
+ ];
260
+ const message = messageParts.join('\n');
261
+ const encodedMessage = Buffer.from(message).toString('base64')
262
+ .replace(/\+/g, '-')
263
+ .replace(/\//g, '_')
264
+ .replace(/=+$/, '');
265
+ const res = await fetch(`https://gmail.googleapis.com/gmail/v1/users/me/messages/send`, {
266
+ method: 'POST',
267
+ headers: {
268
+ Authorization: `Bearer ${token}`,
269
+ 'Content-Type': 'application/json'
270
+ },
271
+ body: JSON.stringify({ raw: encodedMessage })
272
+ });
273
+ const data = await res.json();
274
+ if (!res.ok) {
275
+ return `Failed to send email: ${data.error?.message || JSON.stringify(data)}`;
276
+ }
277
+ return `Successfully sent email to ${to} with Message ID: ${data.id}`;
278
+ }
279
+ catch (err) {
280
+ return `Error sending email: ${err.message}`;
281
+ }
282
+ }
283
+ async function addCalendarEvent(summary, description, startTime, endTime) {
284
+ const isAuth = await (0, googleAuthModule_1.isAuthenticated)();
285
+ if (!isAuth)
286
+ return "Google Auth not configured. Please link your Google account in the dashboard.";
287
+ const token = await (0, googleAuthModule_1.getAccessToken)();
288
+ if (!token)
289
+ return "Failed to retrieve access token.";
290
+ try {
291
+ const event = {
292
+ summary,
293
+ description,
294
+ start: { dateTime: startTime },
295
+ end: { dateTime: endTime }
296
+ };
297
+ const res = await fetch(`https://www.googleapis.com/calendar/v3/calendars/primary/events`, {
298
+ method: 'POST',
299
+ headers: {
300
+ Authorization: `Bearer ${token}`,
301
+ 'Content-Type': 'application/json'
302
+ },
303
+ body: JSON.stringify(event)
304
+ });
305
+ const data = await res.json();
306
+ if (!res.ok) {
307
+ return `Failed to add calendar event: ${data.error?.message || JSON.stringify(data)}`;
308
+ }
309
+ return `Successfully added event '${summary}'. Event link: ${data.htmlLink}`;
310
+ }
311
+ catch (err) {
312
+ return `Error adding calendar event: ${err.message}`;
313
+ }
314
+ }
315
+ exports.sendEmailToolDefinition = {
316
+ type: "function",
317
+ function: {
318
+ name: "send_email",
319
+ description: "Sends an email using the user's Gmail account.",
320
+ parameters: {
321
+ type: "object",
322
+ properties: {
323
+ to: { type: "string", description: "The recipient's email address." },
324
+ subject: { type: "string", description: "The subject of the email." },
325
+ body: { type: "string", description: "The plain text body of the email." }
326
+ },
327
+ required: ["to", "subject", "body"],
328
+ },
329
+ },
330
+ };
331
+ exports.addCalendarEventToolDefinition = {
332
+ type: "function",
333
+ function: {
334
+ name: "add_calendar_event",
335
+ description: "Adds a new event to the user's primary Google Calendar.",
336
+ parameters: {
337
+ type: "object",
338
+ properties: {
339
+ summary: { type: "string", description: "The title or summary of the event." },
340
+ description: { type: "string", description: "A description of the event." },
341
+ startTime: { type: "string", description: "Start time of the event in ISO 8601 format (e.g. 2026-07-03T09:00:00+07:00)." },
342
+ endTime: { type: "string", description: "End time of the event in ISO 8601 format (e.g. 2026-07-03T10:00:00+07:00)." }
343
+ },
344
+ required: ["summary", "description", "startTime", "endTime"],
345
+ },
346
+ },
347
+ };
@@ -18,6 +18,10 @@ exports.scheduleTaskDefinition = {
18
18
  prompt: {
19
19
  type: "string",
20
20
  description: "The prompt/command that the AI should execute when the cron triggers. E.g., 'What is the current price of Ethereum?'"
21
+ },
22
+ languageContext: {
23
+ type: "string",
24
+ description: "Optional. The specific language constraint for the AI's response (e.g., 'Reply strictly in Indonesian informal style', 'Reply in Japanese'). Infer this automatically from the user's current conversation language."
21
25
  }
22
26
  },
23
27
  required: ["cronExpression", "prompt"]
@@ -25,12 +29,13 @@ exports.scheduleTaskDefinition = {
25
29
  }
26
30
  };
27
31
  async function executeScheduleTask(args) {
28
- const { cronExpression, prompt } = args;
32
+ const { cronExpression, prompt, languageContext } = args;
29
33
  if (!cronExpression || !prompt) {
30
34
  return "Error: Missing required parameters cronExpression or prompt.";
31
35
  }
32
36
  try {
33
- const jobId = cronManager_1.cronManager.addJob(cronExpression, prompt);
37
+ const finalPrompt = languageContext ? `${prompt}\n(System Context: ${languageContext})` : prompt;
38
+ const jobId = cronManager_1.cronManager.addJob(cronExpression, finalPrompt);
34
39
  return `Success! I have scheduled the background task.\nJob ID: ${jobId}\nSchedule: ${cronExpression}\nPrompt to execute: "${prompt}"\n\nYou will receive a notification via Telegram every time this task completes.`;
35
40
  }
36
41
  catch (error) {
@@ -139,7 +139,7 @@ async function searchWeb(query, depth = 1) {
139
139
  const config = (0, parser_1.loadConfig)();
140
140
  const provider = config.web_search?.provider || 'mesh';
141
141
  const vaultKeys = await (0, parser_1.loadApiKeys)();
142
- const creds = Object.keys(vaultKeys).length > 0 ? vaultKeys : (config.credentials || {});
142
+ const creds = { ...(config.credentials || {}), ...vaultKeys };
143
143
  let results = [];
144
144
  try {
145
145
  if (provider === 'tavily' && creds.tavily_key) {
@@ -228,11 +228,18 @@ async function searchWeb(query, depth = 1) {
228
228
  }
229
229
  }
230
230
  else {
231
- results = await searchSearxng(finalQuery, depth);
231
+ // Default 'mesh' provider - Prioritize DuckDuckGo as it's more reliable than public SearXNG instances
232
+ try {
233
+ results = await searchDuckDuckGo(finalQuery, depth);
234
+ }
235
+ catch (e) {
236
+ console.warn('[WebSearch] Mesh: DuckDuckGo failed. Falling back to SearXNG...');
237
+ results = await searchSearxng(finalQuery, depth);
238
+ }
232
239
  }
233
240
  }
234
241
  catch (e) {
235
- return `Failed to search the web: ${e.message}`;
242
+ return `[Search Failed] The web search failed due to an error: ${e.message}. CRITICAL INSTRUCTION: You MUST inform the user that the web search failed. Do NOT hallucinate or guess the answer.`;
236
243
  }
237
244
  if (results.length > 0) {
238
245
  searchCache.set(cacheKey, { data: results, timestamp: Date.now() });
@@ -260,17 +267,17 @@ exports.searchWebToolDefinition = {
260
267
  type: "function",
261
268
  function: {
262
269
  name: "search_web",
263
- description: "Searches the internet for information using a search engine. Returns top titles, snippets, and URLs. Use this to find current events, documentation, or general facts. If the user asks for deep/comprehensive research, pass depth: 2 or 3.",
270
+ description: "Searches the internet for information using a search engine. Returns top titles, snippets, and URLs. CRITICAL: If the user asks for news, sports scores, current events, or factual dates, you MUST set depth: 2 to extract the full article content. Do not use depth 1 for facts.",
264
271
  parameters: {
265
272
  type: "object",
266
273
  properties: {
267
274
  query: {
268
275
  type: "string",
269
- description: "The search query to look up.",
276
+ description: "The highly optimized search query to look up (translate to English for global events).",
270
277
  },
271
278
  depth: {
272
279
  type: "number",
273
- description: "Depth of the search (1 for basic, 2 or 3 for deep comprehensive research). Default is 1.",
280
+ description: "Depth of the search (1 for basic snippets, 2 for deep scraping of top 3 sites). MUST be 2 for news/scores/facts.",
274
281
  }
275
282
  },
276
283
  required: ["query"],
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const providerRegistry_1 = require("./web3/aggregator/providerRegistry");
4
+ const routeSelector_1 = require("./web3/aggregator/routeSelector");
5
+ async function testMainnetSwap(providerName) {
6
+ try {
7
+ const req = {
8
+ fromChain: 'ethereum',
9
+ toChain: 'ethereum',
10
+ fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
11
+ toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
12
+ amountInWei: '1000000',
13
+ amountFormatted: '1',
14
+ userAddress: '0x1234567890123456789012345678901234567890',
15
+ slippageTolerance: 50,
16
+ preferredProvider: providerName
17
+ };
18
+ console.log(`\n--- Testing ${providerName} ---`);
19
+ const quote = await (0, routeSelector_1.fetchBestRoute)(req, "best_output");
20
+ console.log(`[+] SUCCESS. Provider used: ${quote.provider}`);
21
+ console.log(` - execution.target: ${quote.execution.target}`);
22
+ console.log(` - approvalAddress: ${quote.approvalAddress || 'MISSING (UNDEFINED)'}`);
23
+ console.log(` - execution.value: ${quote.execution.value.toString()} wei (Should be 0 for ERC20)`);
24
+ if (quote.approvalAddress && quote.approvalAddress.toLowerCase() !== quote.execution.target.toLowerCase()) {
25
+ console.log(` ⚠️ WARNING: execution.target DOES NOT MATCH approvalAddress!`);
26
+ }
27
+ else if (!quote.approvalAddress) {
28
+ console.log(` 🚨 CRITICAL: Provider DID NOT return an approvalAddress!`);
29
+ }
30
+ if (quote.execution.value > 0n) {
31
+ console.log(` 🚨 FATAL EXPLOIT: Provider requested native ETH value > 0 for an ERC20 swap!`);
32
+ }
33
+ }
34
+ catch (err) {
35
+ console.log(`[-] FAILED: ${err.message}`);
36
+ }
37
+ }
38
+ async function main() {
39
+ await providerRegistry_1.aggregatorRegistry.autoDiscover();
40
+ const providers = ['lifi', '0x', 'oneinch', 'kyberswap', 'openocean'];
41
+ for (const p of providers) {
42
+ await testMainnetSwap(p);
43
+ }
44
+ }
45
+ main().catch(console.error);
@@ -0,0 +1,82 @@
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.compressHistory = compressHistory;
7
+ exports.needsCompression = needsCompression;
8
+ /**
9
+ * Context Summarizer — P6: Prevent Context Window Overflow
10
+ *
11
+ * When conversation history grows too long, summarise older messages
12
+ * into a compact paragraph and return a trimmed history that fits
13
+ * within a safe token budget. Mirrors the approach used by Claude/GPT
14
+ * to maintain long-running session coherence.
15
+ */
16
+ const llmUtils_1 = require("./llmUtils");
17
+ const parser_1 = require("../config/parser");
18
+ const picocolors_1 = __importDefault(require("picocolors"));
19
+ /** How many text-only exchanges to keep verbatim before summarising older ones. */
20
+ const VERBATIM_TAIL = 10;
21
+ /** Minimum history length (user+assistant pairs) before we bother summarising. */
22
+ const SUMMARISE_THRESHOLD = 20;
23
+ /**
24
+ * Returns a history array that fits in context.
25
+ * If history is short, returns as-is.
26
+ * If long, prepends a "Conversation Summary" system message and keeps the tail verbatim.
27
+ */
28
+ async function compressHistory(history) {
29
+ const textMessages = history.filter(m => (m.role === 'user' || m.role === 'assistant') && m.content && !m.tool_calls);
30
+ if (textMessages.length < SUMMARISE_THRESHOLD) {
31
+ return history; // nothing to compress yet
32
+ }
33
+ // Split: old messages to summarise, recent tail to keep verbatim
34
+ const tailMessages = textMessages.slice(-VERBATIM_TAIL);
35
+ const oldMessages = textMessages.slice(0, -VERBATIM_TAIL);
36
+ if (oldMessages.length === 0)
37
+ return history;
38
+ try {
39
+ const config = (0, parser_1.loadConfig)();
40
+ const historyText = oldMessages
41
+ .map(m => `${m.role === 'user' ? 'USER' : 'ASSISTANT'}: ${m.content}`)
42
+ .join('\n');
43
+ const summaryRes = await (0, llmUtils_1.executeWithRetry)(async (client) => client.chat({
44
+ model: config.llm.model,
45
+ temperature: 0.1,
46
+ messages: [
47
+ {
48
+ role: 'system',
49
+ content: `You are a conversation summarizer. Summarize the following conversation exchange into a single concise paragraph (max 200 words).
50
+ Focus on: key decisions made, important facts established, user preferences expressed, and task outcomes.
51
+ Write in third person. Be factual, not narrative.`
52
+ },
53
+ { role: 'user', content: historyText }
54
+ ]
55
+ }));
56
+ const summaryText = summaryRes.message?.content?.trim() || '';
57
+ if (!summaryText)
58
+ return history;
59
+ console.log(picocolors_1.default.magenta(`[ContextSummarizer] Compressed ${oldMessages.length} old messages into summary.`));
60
+ // Return: summary as system note + verbatim tail + all tool messages (never drop tool messages)
61
+ const toolMessages = history.filter(m => m.role === 'tool' || (m.role === 'assistant' && m.tool_calls));
62
+ return [
63
+ {
64
+ role: 'system',
65
+ content: `--- CONVERSATION SUMMARY (earlier context) ---\n${summaryText}\n--- END SUMMARY ---`
66
+ },
67
+ ...tailMessages,
68
+ ...toolMessages.slice(-6) // keep last 6 tool interactions
69
+ ];
70
+ }
71
+ catch (e) {
72
+ // On failure, just return the tail — never crash the agent
73
+ return history.slice(-VERBATIM_TAIL * 2);
74
+ }
75
+ }
76
+ /**
77
+ * Fast check — should we attempt compression?
78
+ */
79
+ function needsCompression(history) {
80
+ const textCount = history.filter(m => (m.role === 'user' || m.role === 'assistant') && m.content && !m.tool_calls).length;
81
+ return textCount >= SUMMARISE_THRESHOLD;
82
+ }
@@ -48,7 +48,7 @@ const reverseSkillMapping = {
48
48
  'analyze_market': { category: 'web3', name: 'marketAnalysis' },
49
49
  'get_trending_tokens': { category: 'web3', name: 'getTrendingTokens' },
50
50
  'manage_custom_tokens': { category: 'web3', name: 'manageCustomTokens' },
51
- 'get_price': { category: 'web3', name: 'getPrice' },
51
+ 'get_price_and_fiat_value': { category: 'web3', name: 'getPrice' },
52
52
  'supply_aave': { category: 'web3', name: 'aaveSupply' },
53
53
  'revoke_approval': { category: 'web3', name: 'revokeApproval' },
54
54
  'deposit_yield_vault': { category: 'web3', name: 'vaultDeposit' },
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSmartStreamWrapper = exports.simulateStream = void 0;
4
+ const simulateStream = async (text, onChunk, msPerChunk = 20, charsPerChunk = 3) => {
5
+ return new Promise((resolve) => {
6
+ let index = 0;
7
+ if (!text) {
8
+ resolve();
9
+ return;
10
+ }
11
+ const intervalId = setInterval(() => {
12
+ if (index < text.length) {
13
+ const chunk = text.substring(index, index + charsPerChunk);
14
+ onChunk(chunk);
15
+ index += charsPerChunk;
16
+ }
17
+ else {
18
+ clearInterval(intervalId);
19
+ resolve();
20
+ }
21
+ }, msPerChunk);
22
+ });
23
+ };
24
+ exports.simulateStream = simulateStream;
25
+ /**
26
+ * Creates a smart wrapper around an onChunk callback.
27
+ * If the incoming chunk is large (e.g. Gemini buffering), it intercepts it and streams it smoothly.
28
+ * If the chunk is small (e.g. OpenAI native stream), it passes it instantly.
29
+ */
30
+ const createSmartStreamWrapper = (originalOnChunk) => {
31
+ let isSimulating = false;
32
+ let queue = '';
33
+ let resolveWait = null;
34
+ let waitPromise = Promise.resolve();
35
+ const processQueue = async () => {
36
+ if (isSimulating || queue.length === 0)
37
+ return;
38
+ isSimulating = true;
39
+ // Create a new wait promise if one doesn't exist
40
+ if (!resolveWait) {
41
+ waitPromise = new Promise(r => { resolveWait = r; });
42
+ }
43
+ while (queue.length > 0) {
44
+ const chars = queue.substring(0, 3);
45
+ queue = queue.substring(3);
46
+ originalOnChunk(chars);
47
+ await new Promise(r => setTimeout(r, 20));
48
+ }
49
+ isSimulating = false;
50
+ if (resolveWait) {
51
+ resolveWait();
52
+ resolveWait = null;
53
+ }
54
+ };
55
+ let accumulatedRaw = '';
56
+ let sentLength = 0;
57
+ return {
58
+ onChunk: (chunk) => {
59
+ accumulatedRaw += chunk;
60
+ // Strip any <think> or <thought> block.
61
+ // The (<\/\1>|$) part matches up to the closing tag, or up to the END of the string if it's unclosed.
62
+ const cleanText = accumulatedRaw.replace(/<(think|thought)[\s\S]*?(<\/\1>|$)/gi, '');
63
+ if (cleanText.length > sentLength) {
64
+ const newText = cleanText.substring(sentLength);
65
+ sentLength = cleanText.length;
66
+ if (newText.length > 30) {
67
+ queue += newText;
68
+ processQueue();
69
+ }
70
+ else {
71
+ if (isSimulating) {
72
+ queue += newText;
73
+ }
74
+ else {
75
+ originalOnChunk(newText);
76
+ }
77
+ }
78
+ }
79
+ },
80
+ wait: async () => {
81
+ await waitPromise;
82
+ }
83
+ };
84
+ };
85
+ exports.createSmartStreamWrapper = createSmartStreamWrapper;
@@ -24,7 +24,9 @@ class ArbitrumBridgeProvider {
24
24
  return true;
25
25
  }
26
26
  supports(request) {
27
- if (request.fromChain !== 'sepolia' || request.toChain !== 'arbitrum_sepolia')
27
+ const isL1ToL2 = request.fromChain === 'sepolia' && request.toChain === 'arbitrum_sepolia';
28
+ const isL2ToL1 = request.toChain === 'sepolia' && request.fromChain === 'arbitrum_sepolia';
29
+ if (!isL1ToL2 && !isL2ToL1)
28
30
  return false;
29
31
  const isNative = request.fromToken.toLowerCase() === 'eth' ||
30
32
  request.fromToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' ||
@@ -32,27 +34,42 @@ class ArbitrumBridgeProvider {
32
34
  return isNative;
33
35
  }
34
36
  async getQuote(request, context) {
35
- const inboxAddress = '0xaAe29B0366299461418F5324a79Afc425BE5ae21';
36
- const depositEthAbi = (0, viem_1.parseAbi)(['function depositEth() payable returns (uint256)']);
37
- const callData = (0, viem_1.encodeFunctionData)({
38
- abi: depositEthAbi,
39
- functionName: 'depositEth'
40
- });
37
+ const isL1ToL2 = request.fromChain === 'sepolia';
38
+ let targetAddress;
39
+ let callData;
40
+ if (isL1ToL2) {
41
+ targetAddress = '0xaAe29B0366299461418F5324a79Afc425BE5ae21'; // Delayed Inbox
42
+ const depositEthAbi = (0, viem_1.parseAbi)(['function depositEth() payable returns (uint256)']);
43
+ callData = (0, viem_1.encodeFunctionData)({
44
+ abi: depositEthAbi,
45
+ functionName: 'depositEth'
46
+ });
47
+ }
48
+ else {
49
+ targetAddress = '0x0000000000000000000000000000000000000064'; // ArbSys precompile
50
+ const withdrawEthAbi = (0, viem_1.parseAbi)(['function withdrawEth(address destination) payable returns (uint256)']);
51
+ callData = (0, viem_1.encodeFunctionData)({
52
+ abi: withdrawEthAbi,
53
+ functionName: 'withdrawEth',
54
+ args: [request.userAddress]
55
+ });
56
+ }
57
+ const note = isL1ToL2 ? '100% Real L1->L2 Bridge Transaction via Arbitrum Delayed Inbox' : 'Arbitrum ArbSys L2->L1 Withdrawal (Requires ~7 day challenge period)';
41
58
  return {
42
59
  provider: this.manifest.name,
43
60
  routeId: `arb-bridge-${crypto_1.default.randomUUID()}`,
44
- fromChainId: 11155111, // Sepolia
45
- toChainId: 421614, // Arb Sepolia
61
+ fromChainId: isL1ToL2 ? 11155111 : 421614,
62
+ toChainId: isL1ToL2 ? 421614 : 11155111,
46
63
  inputAmount: BigInt(request.amountInWei),
47
64
  outputAmount: BigInt(request.amountInWei), // 1:1 on official bridge
48
65
  executable: true,
49
66
  expiresAt: Date.now() + 86400000, // Valid for a long time as it's a fixed contract call
50
67
  execution: {
51
- target: inboxAddress,
68
+ target: targetAddress,
52
69
  calldata: callData,
53
70
  value: BigInt(request.amountInWei)
54
71
  },
55
- raw: { note: '100% Real L1->L2 Bridge Transaction via Arbitrum Delayed Inbox' }
72
+ raw: { note }
56
73
  };
57
74
  }
58
75
  async isHealthy() {