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
@@ -0,0 +1 @@
1
+ :root{--bg-color:#3b4252;--bg-secondary:#434c5e;--bg-sidebar:#2e3440;--text-primary:#eceff4;--text-secondary:#d8dee9;--accent:#88c0d0;--accent-hover:#81a1c1;--glass-bg:#2e3440b3;--glass-border:#d8dee91a;--chat-user:#88c0d0;--chat-user-text:#2e3440;--chat-agent:#2e3440;--tool-bg:#4c566a;--success:#a3be8c;--danger:#bf616a;--terminal-bg:#1e222a;--btn-primary-bg:#81a1c1}body.light-theme{--bg-color:#fdfbf6;--bg-secondary:#f4f1e1;--bg-sidebar:#fdfbf6;--text-primary:#1a2b2b;--text-secondary:#5c6b6b;--accent:#8a9a86;--accent-hover:#72826e;--glass-bg:#fdfbf6cc;--glass-border:#1a2b2b14;--chat-user:#eef0e5;--chat-user-text:#1a2b2b;--chat-agent:#fff;--tool-bg:#f4f1e1;--success:#6b8e23;--danger:#cd5c5c;--terminal-bg:#eef0e5;--nav-text:var(--text-secondary);--nav-section:var(--text-secondary);--btn-primary-bg:var(--text-secondary)}*{box-sizing:border-box;margin:0;padding:0}body{background-color:var(--bg-color);color:var(--text-primary);height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;overflow:hidden}.settings-menu-item{cursor:pointer;color:var(--text-secondary);border-radius:6px;align-items:center;gap:12px;margin-bottom:4px;padding:8px 12px;font-size:.9rem;transition:all .2s;display:flex}.settings-menu-item:hover{color:var(--text-primary);background:#ffffff0d}.settings-menu-item.active{background:var(--accent);color:var(--bg-secondary);font-weight:500}.settings-menu-item.active svg{color:var(--bg-secondary)}.settings-scroll-container::-webkit-scrollbar{width:6px}.settings-scroll-container::-webkit-scrollbar-track{background:0 0}.settings-scroll-container::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:10px}#root{width:100vw;height:100vh;display:flex}.sidebar{background-color:var(--bg-sidebar);border-right:1px solid var(--glass-border);z-index:100;flex-direction:column;width:280px;display:flex;overflow-x:hidden}.agent-identity-card{background:linear-gradient(#3b82f60d 0%,#0000 100%);border-bottom:1px solid #ffffff0d;align-items:center;gap:16px;margin-bottom:8px;padding:24px;display:flex}.agent-avatar{justify-content:center;align-items:center;display:flex}.agent-info{flex-direction:column;gap:4px;display:flex}.agent-name{color:var(--text-primary);letter-spacing:-.025em;font-size:1.1rem;font-weight:700}.agent-status{color:#4ade80;letter-spacing:.05em;align-items:center;gap:6px;font-size:.75rem;font-weight:600;display:flex}.status-dot{background-color:#4ade80;border-radius:50%;width:8px;height:8px;animation:2s infinite pulse-green;box-shadow:0 0 8px #4ade80}@keyframes pulse-green{0%{transform:scale(.95);box-shadow:0 0 #4ade80b3}70%{transform:scale(1);box-shadow:0 0 0 6px #4ade8000}to{transform:scale(.95);box-shadow:0 0 #4ade8000}}.sidebar-scroll-area{flex:1;padding-bottom:24px;overflow:hidden auto}.sidebar-scroll-area::-webkit-scrollbar{width:4px}.sidebar-scroll-area::-webkit-scrollbar-thumb{background:#ffffff0d}body.light-theme .sidebar-scroll-area::-webkit-scrollbar-thumb{background:#00000026}.sidebar-section{color:var(--nav-section,#8b9bb4);padding:24px 24px 8px;font-size:.75rem;font-weight:500}.sidebar-nav{flex-direction:column;gap:4px;padding:0 16px;display:flex}.nav-item{color:var(--nav-text,#94a3b8);cursor:pointer;border:1px solid #0000;border-radius:8px;align-items:center;gap:10px;padding:8px 12px;font-size:.8rem;font-weight:500;transition:all .25s cubic-bezier(.4,0,.2,1);display:flex}.nav-icon{transition:transform .25s cubic-bezier(.4,0,.2,1)}.nav-item:hover{color:var(--text-primary);background-color:#ffffff08;transform:translate(4px)}.nav-item:hover .nav-icon{color:var(--text-primary);transform:scale(1.1)}.sessions-list{flex:none!important;justify-content:flex-start!important;gap:0!important;height:max-content!important}.session-item{justify-content:space-between;flex:none!important;height:max-content!important;min-height:28px!important;margin-top:0!important;margin-bottom:2px!important;padding:4px 10px!important}.delete-session-btn{color:#bf616a;cursor:pointer;opacity:0;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:4px;transition:opacity .2s,transform .2s;display:flex}.delete-session-btn:hover{background:#bf616a33;transform:scale(1.1)}.session-item:hover .delete-session-btn{opacity:1}.nav-item.active{color:var(--text-primary);border-left:3px solid var(--accent);background:linear-gradient(90deg,#3b82f626 0%,#0000 100%);border-radius:4px 12px 12px 4px;font-weight:600}.nav-item.active .nav-icon{color:var(--accent)}.main-content{background-image:radial-gradient(at 0 0,#3b82f61a 0,#0000 50%),radial-gradient(at 100% 100%,#8b5cf61a 0,#0000 50%);flex-direction:column;flex:1;max-width:100vw;display:flex;overflow-x:hidden}.topbar{border-bottom:1px solid var(--glass-border);background:var(--bg-color);justify-content:space-between;align-items:center;height:64px;padding:0 24px;display:flex}.topbar-left{color:var(--text-secondary);align-items:center;gap:16px;font-size:.95rem;font-weight:500;display:flex}.topbar-right{align-items:center;gap:12px;display:flex}.custom-network-selector{position:relative}.network-selector-pill{background-color:var(--accent);color:#000;cursor:pointer;border:none;border-radius:9999px;outline:none;align-items:center;gap:8px;padding:8px 16px;font-family:inherit;font-size:.85rem;font-weight:600;transition:all .2s;display:flex}.network-selector-pill:hover{opacity:.9;box-shadow:0 0 10px #88c0d066}.network-selector-pill:focus-visible{box-shadow:0 0 0 2px #88c0d080}.network-icon{flex-shrink:0}.network-chevron{opacity:.7;margin-left:4px}.network-dropdown-menu{background:var(--bg-secondary);border:1px solid var(--glass-border);z-index:100;border-radius:12px;min-width:180px;margin:0;padding:6px;list-style:none;animation:.2s ease-out dropdownSlideIn;position:absolute;top:calc(100% + 8px);right:0;box-shadow:0 12px 32px #00000080}@keyframes dropdownSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.network-dropdown-item{cursor:pointer;color:var(--text-primary);border-radius:8px;padding:10px 14px;font-size:.85rem;transition:background .1s}.network-dropdown-item:hover{background:var(--glass-border)}.network-dropdown-item.active{background:var(--bg-hover);color:var(--accent);font-weight:600}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.workspace-container{width:100%;height:calc(100vh - 64px);display:flex}.chat-wrapper{flex-direction:column;height:100%;padding:24px 0;display:flex}.chat-wrapper.empty-state-wrapper{justify-content:center;padding-bottom:10vh}.resizer{background:var(--glass-border);cursor:col-resize;z-index:10;width:6px;transition:background .2s}.resizer:hover,.resizer:active{background:var(--accent)}.canvas-panel{background:var(--bg-sidebar);background-image:radial-gradient(#3b82f60d 0,#0000 80%);flex-direction:column;flex:1;padding:32px;display:flex;position:relative;overflow-y:auto}.canvas-panel::-webkit-scrollbar{width:6px}.canvas-panel::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:4px}body.light-theme .canvas-panel::-webkit-scrollbar-thumb{background:#00000026}.canvas-header{border-bottom:1px solid #ffffff0d;justify-content:space-between;align-items:center;margin-bottom:32px;padding-bottom:16px;display:flex}.canvas-title{color:#94a3b8;text-transform:uppercase;letter-spacing:.05em;align-items:center;gap:8px;font-family:monospace;font-size:.85rem;display:flex}.canvas-empty{color:#475569;flex-direction:column;justify-content:center;align-items:center;gap:16px;height:100%;display:flex}.empty-state-title{color:#fff}body.light-theme .empty-state-title{background:linear-gradient(135deg,#1e293b 0%,#475569 100%);-webkit-text-fill-color:transparent;-webkit-background-clip:text}.chat-container{flex-direction:column;flex:1;gap:20px;padding:0 24px;display:flex;overflow-y:auto}.chat-container::-webkit-scrollbar{width:6px}.chat-container::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:4px}.styled-scroll{scroll-behavior:smooth;-webkit-overflow-scrolling:touch;will-change:scroll-position}.styled-scroll::-webkit-scrollbar{width:6px}.styled-scroll::-webkit-scrollbar-track{background:0 0}.styled-scroll::-webkit-scrollbar-thumb{background:#fff3;border-radius:4px}.styled-scroll::-webkit-scrollbar-thumb:hover{background:#fff6}body.light-theme .chat-container::-webkit-scrollbar-thumb{background:#00000026}body.light-theme .styled-scroll::-webkit-scrollbar-thumb{background:#0003}body.light-theme .styled-scroll::-webkit-scrollbar-thumb:hover{background:#00000059}.message-wrapper{flex-direction:column;max-width:95%;animation:.3s ease-out forwards fadeIn;display:flex}.message-wrapper.agent{flex-direction:row;align-self:flex-start;align-items:flex-end;gap:8px}.message-wrapper.user{flex-direction:row-reverse;align-self:flex-end;align-items:flex-end;gap:8px}.copy-btn{color:var(--text-secondary);cursor:pointer;opacity:0;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:6px;transition:opacity .2s,background .2s;display:flex}.copy-btn:hover{background:var(--bg-secondary);color:var(--text-primary)}.message-wrapper:hover .copy-btn{opacity:1}.message-bubble{white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word;border-radius:18px;padding:14px 18px;font-size:.95rem;line-height:1.6;box-shadow:0 4px 6px -1px #0000001a}.user .message-bubble{background-color:var(--chat-user);color:var(--chat-user-text);border-bottom-right-radius:4px}.agent .message-bubble{background-color:var(--chat-agent);border:1px solid var(--glass-border);color:var(--text-primary);border-bottom-left-radius:4px}.tool-call{color:var(--text-secondary);background:var(--tool-bg);border:1px solid var(--glass-border);border-radius:12px;align-items:center;gap:8px;margin-top:10px;padding:10px 14px;font-size:.85rem;display:flex}.tool-call code{color:var(--accent);font-family:monospace}.input-area{padding:20px 24px 0}.input-form{background:var(--bg-secondary);border:1px solid var(--glass-border);border-radius:24px;align-items:flex-end;gap:8px;width:100%;max-width:900px;margin:0 auto;padding:10px 14px;transition:all .2s;display:flex;box-shadow:0 4px 15px #0000001a}.input-form:focus-within{border-color:var(--accent);box-shadow:0 0 0 2px #3b82f633}.chat-input{color:var(--text-primary);background:0 0;border:none;outline:none;flex:1;padding:8px 12px;font-family:inherit;font-size:.95rem}.send-button{background:var(--accent);color:var(--text-primary);cursor:pointer;border:none;border-radius:50%;justify-content:center;align-items:center;width:36px;height:36px;transition:all .2s;display:flex}.voice-button{background:var(--bg-secondary);color:var(--text-secondary);border:1px solid var(--glass-border);cursor:pointer;border-radius:50%;justify-content:center;align-items:center;width:36px;height:36px;transition:all .2s;display:flex}.voice-button:hover{color:var(--text-primary);border-color:#ef4444}.action-menu-container{background:0 0;border-radius:9999px;align-items:center;margin-right:8px;padding:0;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;position:relative;overflow:hidden}.action-menu-container:hover{background:var(--bg-secondary)}.action-menu-items{opacity:0;pointer-events:none;align-items:center;gap:4px;width:0;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;transform:translate(-10px)}.action-menu-container:hover .action-menu-items{opacity:1;pointer-events:auto;width:76px;margin-left:4px;margin-right:4px;transform:translate(0)}.plus-button{z-index:2;background:0 0;border:none;transition:transform .3s}.action-menu-container:hover .plus-button{color:var(--accent);transform:rotate(45deg)}.action-menu-items .voice-button{background:0 0;border:none;width:32px;height:32px}.action-menu-items .voice-button:hover{background:#ffffff1a;border-color:#0000}.voice-button.listening{color:#ef4444;background:#ef444433;border-color:#ef4444;animation:1.5s infinite pulse-red}.voice-button.active-mode{color:#3b82f6;border-color:#3b82f6}.voice-button.speaking{color:#3b82f6;background:#3b82f633;border-color:#3b82f6;animation:1.5s infinite pulse-blue}@keyframes pulse-red{0%{box-shadow:0 0 #ef444466}70%{box-shadow:0 0 0 10px #ef444400}to{box-shadow:0 0 #ef444400}}@keyframes pulse-blue{0%{box-shadow:0 0 #3b82f666}70%{box-shadow:0 0 0 10px #3b82f600}to{box-shadow:0 0 #3b82f600}}.send-button:hover:not(:disabled){background:var(--accent-hover);transform:scale(1.05)}.send-button:disabled{opacity:.5;cursor:not-allowed}.typing-indicator{background-color:var(--chat-agent);border:1px solid var(--glass-border);border-radius:18px 18px 18px 4px;align-self:flex-start;gap:4px;width:fit-content;padding:14px 18px;display:flex}.dot{background:var(--text-secondary);border-radius:50%;width:6px;height:6px;animation:1.4s ease-in-out infinite both bounce}.dot:first-child{animation-delay:-.32s}.dot:nth-child(2){animation-delay:-.16s}@keyframes bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}@keyframes fadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.prompt-suggestions{gap:12px;margin-bottom:12px;display:flex;overflow-x:auto}.prompt-suggestions button{background:var(--bg-secondary);color:var(--text-secondary);border:1px solid var(--glass-border);cursor:pointer;white-space:nowrap;border-radius:20px;padding:8px 16px;font-size:.85rem;transition:all .2s}.prompt-suggestions button:hover{border-color:var(--accent);color:var(--text-primary)}.trending-tokens{color:var(--text-secondary);justify-content:center;align-items:center;gap:12px;margin-top:12px;font-size:.8rem;display:flex}.token-tag{background:var(--accent);color:var(--bg-color);cursor:pointer;border-radius:12px;padding:4px 10px;font-weight:600;transition:transform .2s,filter .2s}.token-tag:hover{filter:brightness(1.2);transform:translateY(-2px)}.nord-label{color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px;font-size:.75rem;font-weight:700;display:block}.nord-pill-input{background-color:var(--glass-bg);border:1px solid var(--glass-border);width:100%;color:var(--accent);border-radius:9999px;outline:none;padding:10px 20px;font-size:.9rem;font-weight:600;transition:all .2s}.nord-pill-input:focus{border-color:var(--accent);box-shadow:0 0 10px var(--accent)}.nord-pill-input::placeholder{color:var(--text-secondary);opacity:.7}.nord-input{background-color:var(--bg-sidebar);border:1px solid var(--glass-border);width:100%;color:var(--text-primary);border-radius:6px;outline:none;padding:10px 14px;font-size:.9rem;transition:all .2s}.nord-input:focus{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent)}.nord-input::placeholder{color:var(--text-secondary);opacity:.7}.nord-slider{appearance:none;background:var(--tool-bg);border-radius:3px;outline:none;width:100%;height:6px;margin-top:10px}.nord-slider::-webkit-slider-thumb{appearance:none;background:var(--text-primary);cursor:pointer;border:2px solid var(--accent);border-radius:50%;width:18px;height:18px;transition:all .2s}.nord-slider::-webkit-slider-thumb:hover{background:#fff;transform:scale(1.1)}.nord-slider::-moz-range-thumb{background:var(--text-primary);cursor:pointer;border:2px solid var(--accent);border-radius:50%;width:18px;height:18px;transition:all .2s}.nord-btn-primary{background-color:var(--btn-primary-bg);color:var(--bg-sidebar);cursor:pointer;border:none;border-radius:6px;justify-content:center;align-items:center;padding:10px 20px;font-size:.9rem;font-weight:600;transition:background-color .2s;display:flex}.nord-btn-primary:hover{background-color:var(--accent)}.nord-btn-primary:disabled{background-color:var(--tool-bg);color:#8fbcbb;cursor:not-allowed}.nord-panel-header{border-bottom:1px solid var(--glass-border);align-items:center;gap:10px;margin-bottom:20px;padding-bottom:12px;display:flex}.nord-panel-header h3{color:var(--text-primary);margin:0;font-size:1.1rem;font-weight:600}.sidebar.collapsed{width:68px}.nav-label,.agent-info,.sidebar-section,.delete-session-btn,.agent-avatar,.sessions-list,.agent-identity-card,.sidebar-nav,.nav-item{white-space:nowrap;transition:all .3s cubic-bezier(.4,0,.2,1)}.sidebar.collapsed .nav-label,.sidebar.collapsed .agent-info,.sidebar.collapsed .sidebar-section,.sidebar.collapsed .delete-session-btn,.sidebar.collapsed .agent-avatar,.sidebar.collapsed .sessions-list{opacity:0!important;width:0!important;min-width:0!important;height:0!important;min-height:0!important;margin:0!important;padding:0!important;overflow:hidden!important}.sidebar.collapsed .agent-identity-card{justify-content:center;border-bottom-color:#0000!important;gap:0!important;min-height:60px!important;margin-bottom:0!important;padding:16px 0 4px!important}.sidebar.collapsed .sidebar-toggle-btn{border-radius:50%;margin-top:0;padding:8px;position:static!important}.sidebar.collapsed .sidebar-toggle-btn:hover{background-color:#ffffff0d!important}.sidebar.collapsed .sidebar-nav{align-items:center;gap:2px!important;padding:4px 0 0!important}.sidebar.collapsed .nav-item{justify-content:center;border-width:0!important;border-color:#0000!important;border-radius:50%!important;gap:0!important;width:36px!important;height:36px!important;margin:0 auto!important;padding:0!important}.sidebar.collapsed .nav-item.active{background:#3b82f633!important;border-width:0!important;border-color:#0000!important}.sidebar.collapsed .session-item{border-radius:50%}.sidebar.collapsed .nav-item .nav-icon{margin:0}.spinner{color:var(--text-secondary);animation:1s linear infinite spin}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.overview-container{height:calc(100vh - 64px);color:var(--text-primary);scroll-behavior:smooth;-webkit-overflow-scrolling:touch;will-change:scroll-position;padding:24px;font-family:Inter,sans-serif;overflow-y:auto}.settings-subpanel{width:100%;color:var(--text-primary);font-family:Inter,sans-serif}.overview-container::-webkit-scrollbar{width:6px}.overview-container::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:4px}body.light-theme .overview-container::-webkit-scrollbar-thumb{background:#00000026}.overview-header h1{margin-bottom:4px;font-size:1.5rem;font-weight:600}.overview-header p{color:var(--text-secondary);margin-bottom:24px;font-size:.9rem}.panel{background:var(--bg-secondary);border:1px solid var(--glass-border);border-radius:12px;margin-bottom:24px;padding:20px}.panel-header h3{margin-bottom:4px;font-size:1.1rem;font-weight:600}.panel-header p{color:var(--text-secondary);margin-bottom:16px;font-size:.85rem}.form-group{margin-bottom:16px}.form-row{gap:16px;display:flex}.flex-1{flex:1}label{text-transform:uppercase;color:var(--text-secondary);letter-spacing:.05em;margin-bottom:8px;font-size:.75rem;display:block}input,select{background:var(--bg-color);border:1px solid var(--glass-border);width:100%;color:var(--text-primary);border-radius:8px;padding:10px 12px;font-family:monospace;font-size:.9rem}input:read-only{color:var(--text-secondary)}.input-with-icon{align-items:center;display:flex;position:relative}.input-with-icon svg{color:var(--text-secondary);cursor:pointer;position:absolute;right:12px}.form-actions{align-items:center;gap:12px;margin-top:20px;display:flex}.btn-primary{color:var(--text-primary);cursor:pointer;background:#3b82f6;border:none;border-radius:6px;padding:8px 16px;font-size:.9rem}.btn-secondary{color:var(--text-primary);cursor:pointer;background:0 0;border:1px solid #fff3;border-radius:6px;padding:8px 16px;font-size:.9rem}.action-hint{color:var(--text-secondary);margin-left:8px;font-size:.85rem}.snapshot-grid{grid-template-columns:repeat(4,1fr);gap:20px;display:grid}.stat-val{margin-bottom:4px;font-size:1.5rem;font-weight:700}.text-green{color:#22c55e}.stat-block p{color:var(--text-secondary);margin-top:8px;font-size:.8rem;line-height:1.4}.metrics-grid{grid-template-columns:repeat(5,1fr);gap:16px;margin-bottom:32px;display:grid}.metric-card{background:var(--bg-secondary);border:1px solid var(--glass-border);border-radius:12px;padding:16px}.metric-val{margin-bottom:4px;font-size:1.5rem;font-weight:700}.metric-sub{color:var(--text-secondary);font-size:.75rem}.section-title{text-transform:uppercase;color:var(--text-secondary);letter-spacing:.05em;margin-bottom:12px;font-size:.75rem}.session-item{justify-content:space-between;margin-bottom:24px;padding:16px 20px;display:flex}.text-secondary{color:var(--text-secondary)}.attention-panel{background:#eab3081a;border:1px solid #eab30833;border-radius:12px;flex-direction:column;margin-bottom:24px;padding:16px 20px;display:flex}.attention-header{color:#eab308;align-items:center;gap:8px;margin-bottom:8px;display:flex}.attention-header h4{font-size:1rem;font-weight:600}.attention-content p{margin-bottom:4px;font-size:.95rem}.attention-content span{font-size:.85rem}.logs-grid{grid-template-columns:1fr 1fr;gap:16px;display:grid}.log-panel{background:var(--terminal-bg);border:1px solid var(--glass-border);border-radius:12px;flex-direction:column;height:300px;display:flex;overflow:hidden}.log-header{background:var(--glass-border);border-bottom:1px solid var(--glass-border);padding:12px 16px;font-size:.85rem;font-weight:600}.badge{background:#ffffff1a;border-radius:10px;margin-left:8px;padding:2px 6px;font-size:.7rem}.log-content{flex-direction:column;gap:4px;padding:12px 16px;display:flex;overflow:auto}.log-content::-webkit-scrollbar{width:6px;height:6px}.log-content::-webkit-scrollbar-thumb{background:var(--glass-border);border-radius:4px}.log-content::-webkit-scrollbar-thumb:hover{background:var(--glass-border)}.log-content::-webkit-scrollbar-corner{background:0 0}.memory-log-container::-webkit-scrollbar{width:6px;height:6px}.memory-log-container::-webkit-scrollbar-thumb{background:var(--glass-border);border-radius:4px}.memory-log-container::-webkit-scrollbar-thumb:hover{background:var(--glass-border)}.memory-log-container::-webkit-scrollbar-corner{background:0 0}.log-content code,.log-json{color:#a3a3a3;word-break:break-all;font-family:Consolas,Monaco,monospace;font-size:.75rem;line-height:1.4}.log-row{gap:12px;margin-bottom:4px;font-family:Consolas,Monaco,monospace;font-size:.75rem;display:flex}.log-time{color:#fb923c;min-width:60px}.log-msg{color:#d1d5db}.log-meta{color:#6b7280}.gateway-row{margin-bottom:2px}.search-chat-container{flex-direction:column;width:100%;max-width:800px;margin:0 auto;padding:40px 20px;animation:.3s ease-out fadeIn;display:flex}.search-chat-header{justify-content:center;margin-bottom:40px;display:flex}.search-input-wrapper{width:100%;max-width:600px;position:relative}.search-icon{color:var(--text-secondary);position:absolute;top:50%;left:20px;transform:translateY(-50%)}.search-input{border:1px solid var(--glass-border);background:var(--bg-sidebar);width:100%;color:var(--text-primary);border-radius:30px;outline:none;padding:16px 20px 16px 50px;font-size:1.1rem;transition:all .2s;box-shadow:0 4px 20px #0000000d}.search-input:focus{border-color:var(--accent);background:var(--bg-color);box-shadow:0 4px 25px #0000001a}.search-results-area{flex-direction:column;display:flex}.search-results-title{color:var(--text-secondary);margin-bottom:16px;padding-left:8px;font-size:.9rem;font-weight:500}.search-result-item{cursor:pointer;border-radius:12px;align-items:center;padding:16px;transition:background-color .2s;display:flex}.search-result-item:hover{background-color:var(--bg-sidebar)}.result-title{color:var(--text-primary);align-items:center;gap:12px;font-size:1rem;display:flex}.result-icon{color:var(--text-secondary)}.search-no-results{text-align:center;color:var(--text-secondary);padding:40px;font-style:italic}.login-container{background-color:var(--bg-color,#1e222a);background-image:linear-gradient(#ffffff08 1px,#0000 1px),linear-gradient(90deg,#ffffff08 1px,#0000 1px),radial-gradient(circle,#3b82f626,#0000 60%);background-size:40px 40px,40px 40px,100% 100%;justify-content:center;align-items:center;width:100vw;height:100vh;display:flex;overflow:hidden}.login-card{-webkit-backdrop-filter:blur(16px);background:#1e222a99;border:1px solid #ffffff14;border-radius:16px;flex-direction:column;width:420px;animation:.4s ease-out fadeInScale;display:flex;overflow:hidden;box-shadow:0 25px 50px -12px #00000080}@keyframes fadeInScale{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.login-card-header{background:#0003;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;height:38px;padding:0 16px;display:flex}.mac-dot{border-radius:50%;width:12px;height:12px}.mac-dot.red{background-color:#ff5f56}.mac-dot.yellow{background-color:#ffbd2e}.mac-dot.green{background-color:#27c93f}.login-card-body{flex-direction:column;align-items:center;padding:40px 32px 48px;display:flex}.login-logo{margin-bottom:12px;animation:4s ease-in-out infinite pulseLogo}@keyframes pulseLogo{0%{filter:drop-shadow(0 0 8px #a3be8c4d)}50%{filter:drop-shadow(0 0 16px #a3be8cb3)}to{filter:drop-shadow(0 0 8px #a3be8c4d)}}.login-title{color:var(--text-primary);margin-bottom:4px;font-size:1.5rem;font-weight:600}.login-subtitle{color:var(--text-secondary);text-align:center;margin-bottom:32px;font-size:.9rem}.login-form{flex-direction:column;gap:16px;width:100%;display:flex}.login-input-group{width:100%;position:relative}.login-input{border:1px solid var(--glass-border);width:100%;color:var(--text-primary);box-sizing:border-box;background:#0000004d;border-radius:24px;outline:none;padding:14px 16px 14px 44px;font-size:1rem;transition:all .2s}.login-input:focus{border-color:var(--accent);box-shadow:0 0 0 2px #a3be8c33}.login-input-icon{color:var(--text-secondary);pointer-events:none;position:absolute;top:50%;left:16px;transform:translateY(-50%)}.login-button{background-color:var(--accent);color:#1e222a;cursor:pointer;border:none;border-radius:24px;justify-content:center;align-items:center;gap:8px;width:100%;padding:14px;font-size:1rem;font-weight:600;transition:all .2s;display:flex}.login-button:hover:not(:disabled){background-color:#b4cf9a;transform:translateY(-1px)}.login-button:disabled{opacity:.7;cursor:not-allowed}.login-error{color:#bf616a;text-align:center;min-height:20px;margin-top:12px;font-size:.85rem}.login-hint{color:var(--text-secondary);text-align:center;opacity:.6;margin-top:24px;font-size:.75rem}body.light-theme .login-card{background:var(--glass-bg);border-color:var(--glass-border);box-shadow:0 25px 50px -12px #00000026}body.light-theme .login-card-header{border-bottom-color:var(--glass-border);background:#0000000d}body.light-theme .login-input{background:#00000008}body.light-theme .login-button{color:#fff}
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Nyxora Dashboard</title>
8
- <script type="module" crossorigin src="/assets/index-DbRWEoSr.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-CSoNa5cx.css">
8
+ <script type="module" crossorigin src="/assets/index-Czxksiao.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-DK2sTU47.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nyxora-dashboard",
3
3
  "private": true,
4
- "version": "26.7.2",
4
+ "version": "26.7.4",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -9,18 +9,18 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "lucide-react": "^0.474.0",
12
+ "lucide-react": "^1.22.0",
13
13
  "react": "^18.3.1",
14
14
  "react-dom": "^18.3.1",
15
- "viem": "^2.51.0"
15
+ "viem": "^2.53.1"
16
16
  },
17
17
  "devDependencies": {
18
- "@types/node": "^22.0.0",
19
- "@types/react": "^18.3.3",
20
- "@types/react-dom": "^18.3.0",
21
- "@vitejs/plugin-react": "^6.0.2",
22
- "globals": "^17.6.0",
23
- "typescript": "~6.0.2",
24
- "vite": "^8.0.16"
18
+ "@types/node": "^26.0.1",
19
+ "@types/react": "^18.3.31",
20
+ "@types/react-dom": "^18.3.7",
21
+ "@vitejs/plugin-react": "^6.0.3",
22
+ "globals": "^17.7.0",
23
+ "typescript": "~6.0.3",
24
+ "vite": "^8.1.0"
25
25
  }
26
26
  }
@@ -96,9 +96,13 @@ server.tool("get_wallet_address", "Fetch the secure Ethereum wallet address mana
96
96
  server.tool("request_transaction", "Request an EVM transaction (transfer, swap, bridge). This will be evaluated by the Policy Engine. If approved, it returns a pending Transaction ID.", {
97
97
  type: zod_1.z.enum(['transfer', 'swap', 'bridge', 'mint', 'custom']).describe("The type of transaction"),
98
98
  chainName: zod_1.z.string().describe("The target blockchain network (e.g. 'ethereum', 'base', 'arbitrum')"),
99
- details: zod_1.z.any().describe("Detailed payload. For 'transfer': { to: string, amountWei: string }. For 'swap': { tokenIn: string, tokenOut: string, amountInWei: string }.")
99
+ details: zod_1.z.string().describe("JSON string payload. For 'transfer': { to: string, amountWei: string }. For 'swap': { tokenIn: string, tokenOut: string, amountInWei: string }.")
100
100
  }, async (args) => {
101
101
  try {
102
+ // Parse details back to object since it's passed as string
103
+ if (typeof args.details === 'string') {
104
+ args.details = JSON.parse(args.details);
105
+ }
102
106
  const response = await callPolicyEngine('/request-tx', 'POST', args);
103
107
  return {
104
108
  content: [{ type: "text", text: `Transaction requested successfully. Transaction ID: ${response.id}. Status: ${response.status}` }]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nyxora-mcp-server",
3
- "version": "26.7.2",
3
+ "version": "26.7.4",
4
4
  "description": "Nyxora MCP Subserver, for external AI clients",
5
5
  "main": "dist/server.js",
6
6
  "scripts": {
@@ -10,12 +10,12 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/sdk": "^1.29.0",
13
- "jsonwebtoken": "^9.0.2",
14
- "zod": "^3.24.2"
13
+ "jsonwebtoken": "^9.0.3",
14
+ "zod": "^4.4.3"
15
15
  },
16
16
  "devDependencies": {
17
- "@types/jsonwebtoken": "^9.0.5",
18
- "@types/node": "^20.0.0",
19
- "typescript": "^5.0.0"
17
+ "@types/jsonwebtoken": "^9.0.10",
18
+ "@types/node": "^26.0.1",
19
+ "typescript": "^6.0.3"
20
20
  }
21
21
  }
@@ -90,12 +90,12 @@ server.tool(
90
90
  try {
91
91
  const response = await callPolicyEngine('/address', 'GET');
92
92
  return {
93
- content: [{ type: "text", text: `Wallet Address: ${response.address}` }]
93
+ content: [{ type: "text" as const, text: `Wallet Address: ${response.address}` }]
94
94
  };
95
95
  } catch (e: any) {
96
96
  return {
97
97
  isError: true,
98
- content: [{ type: "text", text: e.message }]
98
+ content: [{ type: "text" as const, text: e.message }]
99
99
  };
100
100
  }
101
101
  }
@@ -108,18 +108,22 @@ server.tool(
108
108
  {
109
109
  type: z.enum(['transfer', 'swap', 'bridge', 'mint', 'custom']).describe("The type of transaction"),
110
110
  chainName: z.string().describe("The target blockchain network (e.g. 'ethereum', 'base', 'arbitrum')"),
111
- details: z.any().describe("Detailed payload. For 'transfer': { to: string, amountWei: string }. For 'swap': { tokenIn: string, tokenOut: string, amountInWei: string }.")
112
- },
113
- async (args) => {
111
+ details: z.string().describe("JSON string payload. For 'transfer': { to: string, amountWei: string }. For 'swap': { tokenIn: string, tokenOut: string, amountInWei: string }.")
112
+ } as any,
113
+ async (args: any) => {
114
114
  try {
115
+ // Parse details back to object since it's passed as string
116
+ if (typeof args.details === 'string') {
117
+ args.details = JSON.parse(args.details);
118
+ }
115
119
  const response = await callPolicyEngine('/request-tx', 'POST', args);
116
120
  return {
117
- content: [{ type: "text", text: `Transaction requested successfully. Transaction ID: ${response.id}. Status: ${response.status}` }]
121
+ content: [{ type: "text" as const, text: `Transaction requested successfully. Transaction ID: ${response.id}. Status: ${response.status}` }]
118
122
  };
119
123
  } catch (e: any) {
120
124
  return {
121
125
  isError: true,
122
- content: [{ type: "text", text: `Transaction Request Failed! ${e.message}` }]
126
+ content: [{ type: "text" as const, text: `Transaction Request Failed! ${e.message}` }]
123
127
  };
124
128
  }
125
129
  }
@@ -0,0 +1,59 @@
1
+ import os
2
+ import yaml
3
+ from pathlib import Path
4
+ from typing import Dict, Any
5
+
6
+ def get_app_dir() -> Path:
7
+ """Returns the base Nyxora app directory (~/.nyxora)"""
8
+ home = Path.home()
9
+ app_dir = home / '.nyxora'
10
+ return app_dir
11
+
12
+ def get_config_dir() -> Path:
13
+ """Returns the Nyxora config directory (~/.nyxora/config)"""
14
+ return get_app_dir() / 'config'
15
+
16
+ def load_yaml(file_name: str) -> Dict[str, Any]:
17
+ """Safely load a YAML file from the config directory"""
18
+ file_path = get_config_dir() / file_name
19
+ if not file_path.exists():
20
+ return {}
21
+
22
+ try:
23
+ with open(file_path, 'r', encoding='utf-8') as f:
24
+ parsed = yaml.safe_load(f)
25
+ return parsed if parsed is not None else {}
26
+ except Exception as e:
27
+ print(f"[Config] Error loading {file_name}: {e}")
28
+ return {}
29
+
30
+ class NyxoraConfig:
31
+ _instance = None
32
+
33
+ def __new__(cls):
34
+ if cls._instance is None:
35
+ cls._instance = super(NyxoraConfig, cls).__new__(cls)
36
+ cls._instance.refresh()
37
+ return cls._instance
38
+
39
+ def refresh(self):
40
+ """Reload all configuration files"""
41
+ self.core = load_yaml('config.yaml')
42
+ self.market_keys = load_yaml('market_keys.yaml')
43
+ self.policy = load_yaml('policy.yaml')
44
+ self.rpc_keys = load_yaml('rpc_key.yaml')
45
+
46
+ def get_llm_provider(self) -> str:
47
+ return self.core.get('llm', {}).get('provider', 'openai')
48
+
49
+ def get_llm_model(self) -> str:
50
+ return self.core.get('llm', {}).get('model', 'gpt-4o-mini')
51
+
52
+ def get_credentials(self) -> Dict[str, str]:
53
+ return self.core.get('credentials', {})
54
+
55
+ def get_market_key(self, service: str) -> str:
56
+ """Get a market key, e.g. 'coingecko_pro'"""
57
+ return self.market_keys.get(service, '')
58
+
59
+ config = NyxoraConfig()
@@ -0,0 +1,34 @@
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from config import config
4
+ from routers import market, cognitive, memory, critic
5
+
6
+ app = FastAPI(
7
+ title="Nyxora ML Engine",
8
+ description="Universal AI & Data Science Sidecar for Nyxora",
9
+ version="1.0.0"
10
+ )
11
+
12
+ # CORS middleware so Node.js can easily call it if needed
13
+ app.add_middleware(
14
+ CORSMiddleware,
15
+ allow_origins=["*"],
16
+ allow_credentials=True,
17
+ allow_methods=["*"],
18
+ allow_headers=["*"],
19
+ )
20
+
21
+ app.include_router(market.router, prefix="/web3")
22
+ app.include_router(cognitive.router, prefix="/cognitive")
23
+ app.include_router(critic.router, prefix="/cognitive")
24
+ app.include_router(memory.router, prefix="/memory")
25
+
26
+ @app.get("/health")
27
+ async def health_check():
28
+ """Simple health check endpoint"""
29
+ return {
30
+ "status": "ok",
31
+ "llm_provider": config.get_llm_provider(),
32
+ "llm_model": config.get_llm_model()
33
+ }
34
+
@@ -0,0 +1,22 @@
1
+ fastapi
2
+ uvicorn
3
+ pydantic
4
+ pyyaml
5
+ pandas
6
+ numpy
7
+ xgboost
8
+ scikit-learn
9
+ httpx
10
+ certifi
11
+ ccxt
12
+ chromadb
13
+ sentence-transformers
14
+ langgraph
15
+ langchain-core
16
+ langchain-openai
17
+ langchain
18
+ langchain-google-genai
19
+ langchain-anthropic
20
+ langchain-chroma
21
+ langchain-community
22
+ langchain-huggingface
@@ -0,0 +1 @@
1
+ # Nyxora ML Engine — Routers package
@@ -0,0 +1,98 @@
1
+ from fastapi import APIRouter, HTTPException
2
+ from pydantic import BaseModel, Field
3
+ from typing import List, Optional
4
+ from routers.llm import get_llm
5
+ from langchain_core.prompts import ChatPromptTemplate
6
+ import json
7
+ import re
8
+
9
+ router = APIRouter()
10
+
11
+ class ChatMessage(BaseModel):
12
+ role: str
13
+ content: str
14
+
15
+ class CognitiveRequest(BaseModel):
16
+ messages: List[ChatMessage]
17
+
18
+ class PersonaResponse(BaseModel):
19
+ language: Optional[str] = Field(description="User's language style, e.g., 'Informal English with technical jargon'")
20
+ tone: Optional[str] = Field(description="Communication tone, e.g., 'Casual and playful'")
21
+ trading_style: Optional[str] = Field(description="Trading behavior, e.g., 'Aggressive, high-frequency'")
22
+ behavior: Optional[str] = Field(description="General behavior, e.g., 'Task-oriented, concise'")
23
+
24
+ @router.post("/reason", response_model=PersonaResponse)
25
+ async def dialectic_reasoning(request: CognitiveRequest):
26
+ if not request.messages or len(request.messages) < 5:
27
+ # Not enough messages to form a strong persona
28
+ return PersonaResponse(language=None, tone=None, trading_style=None, behavior=None)
29
+
30
+ llm = get_llm()
31
+
32
+ # We use structured output if supported, else fallback to raw JSON
33
+ try:
34
+ structured_llm = llm.with_structured_output(PersonaResponse)
35
+ except Exception:
36
+ structured_llm = None
37
+
38
+ prompt = ChatPromptTemplate.from_messages([
39
+ ("system", """You are Nyx, Nyxora's background Persona Auditor.
40
+ Analyze the following recent conversation between the USER and Nyxora.
41
+ Identify persistent user traits and preferences across EXACTLY these 4 categories.
42
+
43
+ RULES:
44
+ - If a category is unclear or not enough data, use null for that key.
45
+ - Be SPECIFIC and DESCRIPTIVE. Include examples of slang/words if identifiable.
46
+ - Focus especially on language & tone — capture the EXACT language the user speaks and their style.
47
+ - Include informal markers if present (e.g., slang, abbreviations, emojis, code-switching).
48
+
49
+ OUTPUT FORMAT: You MUST return ONLY valid JSON matching this schema:
50
+ {{"language": "...", "tone": "...", "trading_style": "...", "behavior": "..."}}
51
+ CRITICAL: Do NOT wrap the JSON in ```json ... ``` markdown blocks. Return the raw '{{' character immediately.
52
+ """),
53
+ ("user", "Conversation History:\n{history}")
54
+ ])
55
+
56
+ # Format the history
57
+ history_str = "\n".join([f"{'USER' if m.role == 'user' else 'NYXORA'}: {m.content}" for m in request.messages])
58
+
59
+ try:
60
+ if structured_llm:
61
+ try:
62
+ chain = prompt | structured_llm
63
+ result = chain.invoke({"history": history_str})
64
+ return result
65
+ except Exception as inner_e:
66
+ print(f"[Cognitive] Structured LLM Failed, trying raw: {str(inner_e)}")
67
+ # If structured fails, fallback to raw parsing
68
+ chain = prompt | llm
69
+ raw_result = chain.invoke({"history": history_str})
70
+ content = raw_result.content
71
+ # Clean markdown with robust regex
72
+ content = re.sub(r"^```(?:json)?\s*", "", content.strip(), flags=re.IGNORECASE)
73
+ content = re.sub(r"\s*```$", "", content).strip()
74
+ try:
75
+ data = json.loads(content)
76
+ return PersonaResponse(**data)
77
+ except json.JSONDecodeError:
78
+ return PersonaResponse(language=None, tone=None, trading_style=None, behavior=None)
79
+ else:
80
+ # Fallback for models that don't support with_structured_output well
81
+ chain = prompt | llm
82
+ raw_result = chain.invoke({"history": history_str})
83
+ content = raw_result.content
84
+
85
+ # Clean markdown with robust regex
86
+ content = re.sub(r"^```(?:json)?\s*", "", content.strip(), flags=re.IGNORECASE)
87
+ content = re.sub(r"\s*```$", "", content).strip()
88
+
89
+ try:
90
+ data = json.loads(content)
91
+ return PersonaResponse(**data)
92
+ except json.JSONDecodeError:
93
+ return PersonaResponse(language=None, tone=None, trading_style=None, behavior=None)
94
+
95
+ except Exception as e:
96
+ print(f"[Cognitive] LLM Error: {str(e)}")
97
+ # JANGAN raise 500, return kosong saja agar percakapan tetap berjalan
98
+ return PersonaResponse(language=None, tone=None, trading_style=None, behavior=None)
@@ -0,0 +1,111 @@
1
+ from fastapi import APIRouter
2
+ from pydantic import BaseModel
3
+ from typing import Optional
4
+ from routers.llm import get_llm
5
+ from langchain_core.prompts import ChatPromptTemplate
6
+ import json
7
+ import re
8
+
9
+ router = APIRouter()
10
+
11
+
12
+ class CriticRequest(BaseModel):
13
+ user_input: str
14
+ draft_answer: str
15
+ current_utc_datetime: Optional[str] = None # e.g. "2026-07-04T06:43:00Z"
16
+
17
+
18
+ class CriticResponse(BaseModel):
19
+ needs_revision: bool
20
+ factual_confidence: float # 0.0 – 1.0
21
+ completeness: float # 0.0 – 1.0
22
+ revision_instructions: str # Kosong jika lolos
23
+
24
+
25
+ CRITIC_SYSTEM_PROMPT = """You are a STRICT QUALITY EVALUATOR for an AI assistant called Nyxora, used by global users across different timezones and languages.
26
+ You must evaluate a DRAFT ANSWER against the USER'S QUESTION and return ONLY a JSON object.
27
+
28
+ The current UTC date and time is: {current_utc_datetime}
29
+
30
+ Evaluate on these dimensions:
31
+ - "factual_confidence" (float 0.0-1.0): How certain are you all facts, dates, numbers, and events in the draft are accurate and not hallucinated? If the draft uses tools/search results as evidence, confidence can be higher.
32
+ - "completeness" (float 0.0-1.0): Does the draft fully and directly answer what the user asked?
33
+ - "needs_revision" (boolean): Set TRUE if factual_confidence < 0.75 OR completeness < 0.75.
34
+ - "revision_instructions" (string): If needs_revision is true, write concise, specific instructions on EXACTLY what to fix. If false, return "".
35
+
36
+ RULES:
37
+ - Return ONLY raw JSON. No markdown, no explanation outside the JSON.
38
+ - Be strict. Prefer to flag rather than pass.
39
+ - If the draft contains phrases like "I think", "probably", "might be", "kemungkinan besar", or vague hedging on factual claims WITHOUT supporting tool evidence, lower factual_confidence significantly.
40
+ - If the draft says it "cannot" find information but did not actually try searching, set needs_revision=true.
41
+ - Short conversational replies (greetings, acknowledgements, simple confirmations) should always pass with high scores.
42
+
43
+ STALENESS RULE (Critical for Global Users):
44
+ - If the user's question contains ANY time-sensitive reference in ANY language (e.g. "today", "this morning", "now", "latest", "current", "tadi", "hari ini", "sekarang", "terbaru", "今日", "сегодня", "aujourd'hui", "hoy", "heute", etc.)...
45
+ AND the draft answer provides factual data (scores, prices, news, events) WITHOUT any explicit mention of having searched/retrieved live data...
46
+ THEN set needs_revision=true and set revision_instructions to: "The question is time-sensitive. The draft may contain stale data from conversation history. Instruct the AI to call search_web NOW with the current UTC date ({current_utc_datetime}) to retrieve fresh results."
47
+ - If the draft explicitly states it searched and found results, this rule does NOT apply.
48
+
49
+ Return format (raw JSON only):
50
+ {{"needs_revision": false, "factual_confidence": 0.95, "completeness": 0.9, "revision_instructions": ""}}
51
+ """
52
+
53
+
54
+ @router.post("/critic", response_model=CriticResponse)
55
+ async def evaluate_draft(request: CriticRequest):
56
+ """
57
+ Critic Engine — evaluates a draft answer before it is sent to the user.
58
+ Accepts current_utc_datetime to detect stale answers for global users.
59
+ """
60
+ # Skip evaluation for very short responses (greetings, confirmations, etc.)
61
+ if len(request.draft_answer.strip()) < 100:
62
+ return CriticResponse(
63
+ needs_revision=False,
64
+ factual_confidence=1.0,
65
+ completeness=1.0,
66
+ revision_instructions=""
67
+ )
68
+
69
+ current_utc = request.current_utc_datetime or "unknown"
70
+
71
+ llm = get_llm()
72
+ prompt = ChatPromptTemplate.from_messages([
73
+ ("system", CRITIC_SYSTEM_PROMPT),
74
+ ("user", "USER QUESTION:\n{user_input}\n\nDRAFT ANSWER:\n{draft_answer}\n\nEvaluate the draft now and return only JSON.")
75
+ ])
76
+
77
+ try:
78
+ chain = prompt | llm
79
+ result = chain.invoke({
80
+ "user_input": request.user_input,
81
+ "draft_answer": request.draft_answer,
82
+ "current_utc_datetime": current_utc
83
+ })
84
+ content = result.content.strip()
85
+
86
+ # Strip potential markdown code fences from LLM response
87
+ content = re.sub(r"^```(?:json)?\s*", "", content, flags=re.IGNORECASE)
88
+ content = re.sub(r"\s*```$", "", content).strip()
89
+
90
+ # Extract JSON object if there is surrounding text
91
+ json_match = re.search(r'\{.*\}', content, re.DOTALL)
92
+ if json_match:
93
+ content = json_match.group(0)
94
+
95
+ data = json.loads(content)
96
+
97
+ return CriticResponse(
98
+ needs_revision=bool(data.get("needs_revision", False)),
99
+ factual_confidence=float(data.get("factual_confidence", 1.0)),
100
+ completeness=float(data.get("completeness", 1.0)),
101
+ revision_instructions=str(data.get("revision_instructions", ""))
102
+ )
103
+
104
+ except Exception as e:
105
+ print(f"[Critic] Evaluation error (passing through): {e}")
106
+ return CriticResponse(
107
+ needs_revision=False,
108
+ factual_confidence=1.0,
109
+ completeness=1.0,
110
+ revision_instructions=""
111
+ )
@@ -0,0 +1,38 @@
1
+ import os
2
+ from config import config
3
+
4
+ def get_llm():
5
+ provider = config.get_llm_provider().lower()
6
+ model_name = config.get_llm_model()
7
+ creds = config.get_credentials()
8
+
9
+ if provider == 'openai':
10
+ from langchain_openai import ChatOpenAI
11
+ api_key = creds.get('openai')
12
+ if not api_key:
13
+ api_key = os.environ.get('OPENAI_API_KEY', '')
14
+ return ChatOpenAI(model=model_name, openai_api_key=api_key, temperature=0.2)
15
+
16
+ elif provider == '9router' or provider == 'ollama':
17
+ from langchain_openai import ChatOpenAI
18
+ base_url = "http://localhost:20128/v1" if provider == '9router' else "http://localhost:11434/v1"
19
+ return ChatOpenAI(model=model_name, openai_api_key="local", base_url=base_url, temperature=0.2)
20
+
21
+ elif provider == 'gemini':
22
+ from langchain_google_genai import ChatGoogleGenerativeAI
23
+ api_key = creds.get('gemini')
24
+ if not api_key:
25
+ api_key = os.environ.get('GEMINI_API_KEY', '')
26
+ return ChatGoogleGenerativeAI(model=model_name, google_api_key=api_key, temperature=0.2)
27
+
28
+ elif provider == 'anthropic':
29
+ from langchain_anthropic import ChatAnthropic
30
+ api_key = creds.get('anthropic')
31
+ if not api_key:
32
+ api_key = os.environ.get('ANTHROPIC_API_KEY', '')
33
+ return ChatAnthropic(model_name=model_name, anthropic_api_key=api_key, temperature=0.2)
34
+
35
+ else:
36
+ # Fallback to OpenAI if unknown
37
+ from langchain_openai import ChatOpenAI
38
+ return ChatOpenAI(model='gpt-4o-mini', temperature=0.2)