nyxora 1.7.2 → 26.6.5-1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +65 -2
  2. package/README.md +8 -0
  3. package/SECURITY.md +10 -1
  4. package/bin/nyxora.mjs +29 -0
  5. package/clean-bridge.js +11 -0
  6. package/package.json +4 -2
  7. package/packages/core/package.json +2 -1
  8. package/packages/core/src/agent/reasoning.ts +77 -92
  9. package/packages/core/src/config/parser.ts +16 -7
  10. package/packages/core/src/gateway/cli.ts +20 -1
  11. package/packages/core/src/gateway/server.ts +58 -40
  12. package/packages/core/src/gateway/setup.ts +75 -25
  13. package/packages/core/src/memory/logger.ts +3 -0
  14. package/packages/core/src/web3/config.ts +2 -1
  15. package/packages/core/src/web3/skills/bridgeToken.ts +33 -24
  16. package/packages/core/src/web3/skills/checkSecurity.ts +1 -0
  17. package/packages/core/src/web3/skills/customTx.ts +12 -2
  18. package/packages/core/src/web3/skills/mintNft.ts +13 -2
  19. package/packages/core/src/web3/skills/swapToken.ts +66 -19
  20. package/packages/core/src/web3/skills/transfer.ts +13 -3
  21. package/packages/core/src/web3/utils/routers.ts +102 -0
  22. package/packages/core/src/web3/utils/tokens.ts +5 -2
  23. package/packages/dashboard/dist/assets/index-DWxWzOS7.js +306 -0
  24. package/packages/dashboard/dist/index.html +1 -1
  25. package/packages/dashboard/package.json +1 -1
  26. package/packages/mcp-server/package.json +1 -1
  27. package/packages/policy/package.json +1 -1
  28. package/packages/policy/src/server.ts +3 -3
  29. package/packages/signer/package.json +1 -1
  30. package/packages/signer/src/server.ts +10 -1
  31. package/scratch.js +1 -0
  32. package/packages/dashboard/dist/assets/index-cGPka4s1.js +0 -295
package/CHANGELOG.md CHANGED
@@ -2,14 +2,77 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ The format is based on [Keep a Changelog](https://keepashangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [1.7.2] - Unreleased
8
+ ## [26.6.5-1.0] - 2026-06-05
9
+ ### Bug Fixes & Improvements
10
+ - **Transaction Stability**: Added 30-second `AbortSignal` timeout safety net across all Web3 skills (`swapToken`, `transfer`, `bridgeToken`, `mintNft`, `customTx`) to prevent UI hanging when RPC nodes are unresponsive.
11
+ - **Multi-Session Transaction Logs**: Fixed an issue where Web3 transaction status messages (Approve/Reject/Success/Failure) were logged to the `default` session instead of the user's active session window, by attaching the correct `sessionId` with `Content-Type: application/json` headers in dashboard API requests.
12
+ - **UI Tool Rendering Bug**: Fixed a React rendering bug in `App.tsx` where the AI's internal tool execution notification (green bubble) would be hidden if the AI generated both conversational text and a tool execution in the same response.
13
+ - **Base Sepolia Support**: Officially added `base_sepolia` testnet to the supported networks list and `bridgeToken` mappings to prevent AI confusion when resolving bridge destinations.
14
+ - **Default Policy Override (Plug & Play)**: Adjusted the default `config.yaml` template and internal Policy Engine defaults to set `allow_transfer`, `allow_swap`, `allow_shell_execution`, and `allow_file_write` to `true`. Also uncapped `max_usd_per_tx` to `$999,999,999` by default, ensuring a seamless "plug and play" experience for new users without needing manual configuration edits.
15
+ - **Viem RPC Timeout**: Injected a strict 15-second timeout inside the `signer` vault's `viem` HTTP transport to prevent indefinite freezing during blockchain gas estimation when the node is heavily rate-limited.
16
+ - **Auto-Approve Signature Fix**: Added internal HMAC signature generation across all Web3 transaction execution modules (Transfer, Bridge, Mint, CustomTx) to resolve the `Missing internal signature for autoApprove` error during manual dashboard approvals or policy bypasses.
17
+ - **LayerZero Testnet Route**: Upgraded the testnet Bridge mock implementation to utilize LayerZero's V2 Endpoint router (`0x1a44...`) for simulated testnet bridging transactions.
18
+ - **Transaction Result Formatting**: Fixed an issue where the AI would output raw JSON stringified payloads for successful transactions. The chat notification is now properly formatted to clearly display the transaction hash.
19
+ - **Base Sepolia UI Integration**: Synchronized the Dashboard's Network Selector dropdown and Default Web3 Chain settings menu to include the newly added `Base Sepolia (Testnet)` network.
20
+ - **LayerZero Mainnet Removal (Stargate V2)**: Completely removed the experimental LayerZero/Stargate V2 integration from the core bridging engine to prevent interaction with potentially outdated or unverified mainnet smart contracts. Removed the corresponding "LayerZero" routing option from the Dashboard UI dropdown to ensure a highly stable and secure bridging experience exclusively via Li.Fi and Relay.
21
+ - **Relay MEV Protection (Slippage)**: Hardened the `getRelayQuote` HTTP POST request by injecting a strict `slippageTolerance` parameter (default 0.5%). This closes a critical vulnerability where unbounded Relay executions could expose user funds to front-running and MEV attacks during volatile market conditions.
22
+ - **Strict NLP Exactness (Rule 8)**: Injected CRITICAL RULE 8 into the core reasoning pipeline (`reasoning.ts`). The AI is now strictly forbidden from hallucinating or guessing ambiguous transaction parameters (tokens, amounts, or destination networks). It will automatically halt and politely ask the user for explicit clarification before constructing any Web3 payloads.
23
+ - **NLP Context Override System**: Documented the NLP fallback override mechanism in `README.md` and Vitepress documentation to clarify how explicit user chat instructions dynamically bypass Dashboard configurations.
24
+
25
+ ### UI/UX Fixes
26
+ - **Pending Transactions Widget**: Fixed a rendering bug where the Approve/Reject popup was not being injected into the DOM, preventing users from signing transactions.
27
+
28
+ ### Core AI Engine
29
+ - **Strict Language Matching**: Optimized CRITICAL RULE 2 in the System Prompt. The AI now completely ignores historical chat language context and strictly matches the language of the user's latest prompt.
30
+
31
+ ## [26.6.5] - 2026-06-04 (Hotfix Patch)
32
+ ### Fixed
33
+ - **NPM Monorepo Resolution:** Synced `@inquirer/search` and `duck-duck-scrape` to root `package.json` to prevent `MODULE_NOT_FOUND` and `ERR_CONNECTION_REFUSED` on global installations.
34
+
35
+ ## [26.6.4] - 2026-06-04
36
+
37
+ ### AI Engine Optimizations
38
+ - **Semantic Keyword Router (Zero-Latency)**: Restructured the `reasoning.ts` pipeline to dynamically group tools into specific clusters (`WEB3`, `SYSTEM`, `GOOGLE`). The engine now intercepts the user's prompt using highly optimized Regex keyword-matching. This eliminates "Context Bloat" by only injecting relevant tools into the LLM payload, dramatically increasing LLM responsiveness and minimizing API token consumption.
39
+ - **Zero-LLM Fast Return Expansion**: Expanded the V2 `Fast Return` optimization (which skips the redundant secondary LLM summarization step) to include 7 additional data-heavy read-only tools: `get_price`, `get_my_address`, `analyze_market`, `check_token_security`, `search_web`, `read_gmail_inbox`, and `list_calendar_events`. For these queries, the agent now returns the raw markdown payload instantaneously, cutting response latency by 50-80%.
40
+
41
+ ### Universal LLM Expansion
42
+ - **Dictionary Mapping Refactor**: Completely flattened the massive `if-else` blocks in `reasoning.ts` into a highly dynamic 15-line dictionary map. Adding new LLM providers in the future now only takes a single line of code.
43
+ - **Expanded Provider Ecosystem**: Added native support for **Groq, Mistral AI, xAI (Grok), dan DeepSeek**, seamlessly integrated into the React Dashboard UI's dropdown.
44
+
45
+ ### CLI Enhancements
46
+ - **Searchable Model Prompt**: Replaced the static `@clack/prompts` list with `@inquirer/search` inside `nyxora setup`. Users can now instantly fuzzy-search their desired AI model out of dozens of variants using their keyboard.
47
+ - **2026 Model Roster**: Injected an exhaustive list of the latest frontier models into the CLI (including `gpt-5.5`, `o3-mini`, `gemini-3.1-pro`, `deepseek-reasoner`). A fail-safe `[Tulis Manual / Custom Model]` option is also hardcoded at the bottom of every list.
48
+
49
+ ### Backend Stability (Core Engine)
50
+ - **Zero-Crash SQLite (WAL Mode)**: Enabled `PRAGMA journal_mode = WAL` and `busy_timeout = 5000` on the `node:sqlite` database engine (`logger.ts`). This allows parallel reads and writes without throwing fatal `SQLITE_BUSY` (database locked) errors during high-concurrency operations.
51
+ - **Anti-Zombie LLM Timeout**: Hardcoded a `timeout: 120000` (120 seconds) limit on the core OpenAI SDK instantiation (`reasoning.ts`). If an external AI provider (e.g., local Ollama or OpenRouter) hangs, the system will now correctly severe the connection and trigger Exponential Backoff rather than freezing indefinitely. Disabled internal SDK retries (`maxRetries: 0`) to prevent retry collisions with Nyxora's native retry wrapper.
52
+
53
+ ### UI & Developer Experience
54
+ - **CLI Memory Purge**: Introduced a new developer utility command: `nyxora clear`. It instantly and atomically resets the AI's short-term/long-term memory SQLite database. Includes a mandatory `--force` flag safeguard to prevent accidental data destruction.
55
+ ## [1.7.3] - 2026-06-04
56
+
57
+ ### Web3 Routing & Integrations
58
+ - **Multi-Router Selection (DeFi)**: Added a dynamic Router dropdown to the Dashboard UI, allowing users to forcefully route transactions through specific protocols natively. Supported routers include `1inch`, `CowSwap (MEV-Protected)`, `Li.Fi`, `Relay`, `Uniswap V2`, `Uniswap V3`, and `PancakeSwap`. This integration heavily relies on deep aggregator proxying (bypassing the need for complex V2/V3 ABI calldata overhead) to ensure 100% smooth, anti-fail execution without requiring additional API keys.
59
+
60
+ ### Security & Polish
61
+ - **Dashboard:** Redacted the sensitive Nyxora Auth Token from appearing in the Gateway Logs component on the frontend to prevent visual leakage during screen sharing or screenshots.
62
+
63
+ ## [1.7.2] - 2026-06-04
9
64
 
10
65
  ### UI/UX Enhancements
11
66
  - **Google Workspace Logout**: Users can now easily disconnect their Google Workspace accounts directly from the Dashboard (OS Skills tab). This triggers a secure token purge from both the OS Keyring and local storage, ensuring privacy and seamless account switching.
12
67
 
68
+ ### Cloud-Native Deployment
69
+ - **Official Docker & GHCR Support**: Added comprehensive Docker containerization support (`Dockerfile`) and automated publishing pipelines to GitHub Container Registry (GHCR).
70
+ - **Docker Documentation**: Added a dedicated `DOCKER.md` guide explaining how to pull, interactively configure, and run the Nyxora daemon via Docker with isolated Volume storage (`/root/.nyxora`).
71
+
72
+ ### Documentation & Compliance
73
+ - **Legal Infrastructure**: Added standard `Privacy Policy` (`privacy.md`) and `Terms of Service` (`terms.md`) to the VitePress documentation to prepare for official Google OAuth App Verification.
74
+ - **Enterprise Roadmap Evolution**: Updated the documentation roadmap to reflect our "Nyxora Next Update" vision, outlining future plans for a Rust-Native Signer, Idempotent Policy Engine, Multi-VM Architecture, and Google App Verification.
75
+
13
76
  ## [1.7.1]
14
77
 
15
78
  ### CLI Enhancements
package/README.md CHANGED
@@ -23,9 +23,11 @@ It operates under an institutional-grade **Cryptographically Bound Human-in-the-
23
23
  * **Cryptographically Bound Approval**: Policy changes and transactions requested by the AI are drafted as hashes (`sha256`). Approval via the UI requires a challenge nonce, preventing Man-in-the-Middle (MITM) attacks.
24
24
  * **Immutable Policy Guardrails**: Transaction limits (e.g. `max_usd_per_tx`) are strictly enforced by the Policy Engine. The LLM has zero write-access to bypass these rules.
25
25
  * **Plugin Sandbox VM**: Execute community-built external skills securely inside an airtight Node.js `vm` chamber with zero access to your file system or terminal processes.
26
+ * **Enterprise-Grade Stability**: Runs on a WAL-enabled SQLite backend with resilient anti-zombie connection timeouts to ensure maximum concurrency without database locks.
26
27
 
27
28
  ### 🌐 Web3 Skills (On-Chain)
28
29
  * **Security Scanner**: Nyxora can scan smart contracts via GoPlus Labs to detect Honeypots, Hidden Taxes, and malicious proxy upgrades before you buy.
30
+ * **Anti-MEV Slippage Protection**: Hardened routing engine with dynamic Slippage Tolerance (default 0.5%) for Relay and Li.Fi. You can manually adjust slippage via the UI or dynamically override it using natural language (e.g., "Swap 1 ETH to PEPE with 10% slippage").
29
31
  * **Automated Take Profit (TP) & Cut Loss (CL)**: The trader's holy grail. Set natural language rules (e.g., "Sell my PEPE if price drops below $0.001"). Nyxora runs a background cron monitor and executes the swap while you sleep.
30
32
  * **Cross-Chain Hybrid Market Scanner**: Real-time asset tracking combining CoinGecko global data with DexScreener on-chain metrics across Ethereum, Base, Solana, BSC, and more.
31
33
  * **"Lean Degen" Auto-Whitelist**: Automatically intercepts Contract Addresses (CAs) whenever you check balances or swap tokens, saving them to your localized `user_whitelist.json` for future tracking.
@@ -40,6 +42,9 @@ It operates under an institutional-grade **Cryptographically Bound Human-in-the-
40
42
  * **Zero-Click Multi-Session**: Instantly create isolated chat sessions with smart auto-naming triggered by your first prompt, exactly like ChatGPT.
41
43
  * **Dynamic Trending Tokens**: Live top 5 crypto assets feed directly injected into the dashboard, completely clickable for instant AI market analysis.
42
44
  * **Premium Utility-Centric UI**: A sleek, dark-themed dashboard built for high readability and professional Web3 execution, featuring Pseudo-Generative UI widgets (`<BalanceWidget>`, `<MarketWidget>`, `<SwapWidget>`).
45
+ * **Massive 2026 Model Roster**: Out-of-the-box support for cutting-edge models via Google Gemini, OpenAI, Groq, Mistral, xAI, DeepSeek, OpenRouter, and local Ollama, equipped with a searchable CLI prompt to instantly find your favorite model.
46
+ * **Strict NLP Exactness (Rule 8)**: The AI is rigorously instructed never to hallucinate or guess missing transaction parameters (like destination chains or swap amounts). It halts and requests human clarification, guaranteeing 100% precision.
47
+ * **Context Overrides Defaults (NLP Intelligence)**: The Dashboard configuration (default chain & router) acts only as a safety net. If you issue an explicit command via Telegram (e.g., *"Swap 10 USDC to USDT on Arbitrum using Li.Fi"*), the NLP engine dynamically bypasses the default settings and executes exactly what you asked for, ensuring maximum flexibility.
43
48
  * **Deep Personalization**: Feed the agent custom rules via `user.md` and define its core persona via `IDENTITY.md`.
44
49
 
45
50
  ---
@@ -82,6 +87,9 @@ nyxora start
82
87
 
83
88
  # 4. Open the Web Dashboard
84
89
  nyxora dashboard
90
+
91
+ # Utility: Atomically clear the AI's short-term and long-term memory
92
+ nyxora clear --force
85
93
  ```
86
94
  > **⚠️ IMPORTANT:** Whenever you re-run `nyxora setup` or manually edit the config files, you **must restart the daemon** by running `nyxora restart` for the changes to take effect.
87
95
 
package/SECURITY.md CHANGED
@@ -78,7 +78,16 @@ To prevent Supply Chain Attacks, the sandbox **permanently blacklists** critical
78
78
  * `child_process`: Plugins cannot spawn silent background terminals or malicious `curl | bash` supply chain payloads.
79
79
  * `os`, `net`, `cluster`: Blocked to prevent network-level exploitation.
80
80
 
81
- ## 5. Reporting Vulnerabilities
81
+ ## 5. Anti-MEV & Slippage Defense
82
+
83
+ To protect user funds from front-running and Maximal Extractable Value (MEV) attacks, Nyxora strictly enforces a **Default Slippage Tolerance of 0.5%** for all decentralized exchange (DEX) routing via Li.Fi and Relay.
84
+
85
+ Unlike typical web3 interfaces that might expose you to unlimited slippage if left unconfigured, Nyxora's backend hardcodes this protection layer into the API payload.
86
+ If an AI agent attempts to execute a swap without explicit slippage instructions, the `swapToken` and `bridgeToken` engines will automatically inject the `0.5%` boundary.
87
+
88
+ Users can safely override this limit globally via the Dashboard UI Settings or dynamically via NLP chat commands for specific high-volatility pairs (e.g., "Swap with 10% slippage").
89
+
90
+ ## 6. Reporting Vulnerabilities
82
91
 
83
92
  If you discover a vulnerability in the Nyxora architecture, please DO NOT open a public issue.
84
93
  Instead, email the core maintainer directly at **ainyxor@gmail.com**.
package/bin/nyxora.mjs CHANGED
@@ -208,9 +208,31 @@ async function setup() {
208
208
  await new Promise(resolve => child.on('close', resolve));
209
209
  }
210
210
 
211
+ async function clearMemory(args) {
212
+ const child = spawn('npx', ['ts-node', '-T', 'packages/core/src/gateway/cli.ts', 'clear', ...args], {
213
+ cwd: projectRoot,
214
+ stdio: 'inherit',
215
+ env: { ...process.env, TS_NODE_CACHE: 'false' }
216
+ });
217
+
218
+ await new Promise(resolve => child.on('close', resolve));
219
+ }
220
+
221
+ async function setKey(args) {
222
+ const child = spawn('npx', ['ts-node', '-T', 'packages/core/src/gateway/cli.ts', 'set-key', ...args], {
223
+ cwd: projectRoot,
224
+ stdio: 'inherit',
225
+ env: { ...process.env, TS_NODE_CACHE: 'false' }
226
+ });
227
+
228
+ await new Promise(resolve => child.on('close', resolve));
229
+ }
230
+
211
231
  async function main() {
212
232
  switch (command) {
213
233
  case 'setup': await setup(); break;
234
+ case 'clear': await clearMemory(process.argv.slice(3)); break;
235
+ case 'set-key': await setKey(process.argv.slice(3)); break;
214
236
  case 'start': await start(); break;
215
237
  case 'stop': await stop(); break;
216
238
  case 'restart': await restart(); break;
@@ -234,9 +256,16 @@ Commands:
234
256
  start Start the Nyxora background daemon
235
257
  stop Stop the running daemon
236
258
  restart Restart the daemon
259
+ setup Run the interactive Setup Wizard
237
260
  dashboard Open the dashboard in your browser
261
+ clear Atomically clear the AI's short/long-term memory SQLite database
238
262
  clean-logs Clear the daemon logs
239
263
  autostart Enable/disable autostart on boot (usage: nyxora autostart enable)
264
+ set-key Securely save API Key (usage: nyxora set-key <provider> <key>)
265
+
266
+ Options:
267
+ -v, --version Show current version
268
+ -h, --help Show this help menu
240
269
  `);
241
270
  }
242
271
  }
@@ -0,0 +1,11 @@
1
+ const fs = require('fs');
2
+ const file = 'packages/core/src/web3/skills/bridgeToken.ts';
3
+ let lines = fs.readFileSync(file, 'utf8').split('\n');
4
+
5
+ // Delete lines in reverse order so indices don't shift
6
+ lines.splice(204, 54); // Lines 205 to 258
7
+ lines.splice(192, 4); // Lines 193 to 196
8
+ lines.splice(59, 93); // Lines 60 to 152
9
+
10
+ fs.writeFileSync(file, lines.join('\n'));
11
+ console.log('Successfully removed LayerZero from bridgeToken.ts');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nyxora",
3
- "version": "1.7.2",
3
+ "version": "26.6.5-1.0",
4
4
  "license": "MIT",
5
5
  "workspaces": [
6
6
  "packages/*"
@@ -9,7 +9,7 @@
9
9
  "nyxora": "bin/nyxora.mjs"
10
10
  },
11
11
  "scripts": {
12
- "postinstall": "npm run build --workspace=dashboard || echo '⚠️ Build failed – dashboard UI may be missing'",
12
+ "prepare": "npm run build --workspace=dashboard || echo '⚠️ Build failed – dashboard UI may be missing'",
13
13
  "dev": "concurrently -n \"BACKEND,FRONTEND\" -c \"blue,green\" \"npx ts-node -T launcher.ts\" \"npm run dev --workspace=dashboard\"",
14
14
  "start": "node ./bin/nyxora.mjs start",
15
15
  "stop": "node ./bin/nyxora.mjs stop",
@@ -21,11 +21,13 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@clack/prompts": "^1.4.0",
24
+ "@inquirer/search": "^4.2.1",
24
25
  "@modelcontextprotocol/sdk": "^1.5.0",
25
26
  "@napi-rs/keyring": "^1.3.0",
26
27
  "concurrently": "^9.2.1",
27
28
  "cors": "^2.8.6",
28
29
  "dotenv": "^17.4.2",
30
+ "duck-duck-scrape": "^2.2.7",
29
31
  "express": "^5.2.1",
30
32
  "express-rate-limit": "^7.5.0",
31
33
  "helmet": "^8.0.0",
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "nyxora-agent-core",
3
- "version": "1.7.2",
3
+ "version": "26.6.5-1.0",
4
4
  "private": true,
5
5
  "main": "src/gateway/server.ts",
6
6
  "dependencies": {
7
7
  "@clack/prompts": "^1.4.0",
8
+ "@inquirer/search": "^4.2.1",
8
9
  "cors": "^2.8.6",
9
10
  "duck-duck-scrape": "^2.2.7",
10
11
  "express": "^5.2.1",
@@ -48,66 +48,58 @@ export const logger = new Logger();
48
48
 
49
49
  let currentKeyIndex = 0;
50
50
 
51
+ const PROVIDER_CONFIGS: Record<string, { baseURL?: string; requiresApiKey: boolean }> = {
52
+ ollama: { baseURL: process.env.OLLAMA_BASE_URL ? `${process.env.OLLAMA_BASE_URL}/v1` : 'http://localhost:11434/v1', requiresApiKey: false },
53
+ gemini: { baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/', requiresApiKey: true },
54
+ openrouter: { baseURL: 'https://openrouter.ai/api/v1', requiresApiKey: true },
55
+ groq: { baseURL: 'https://api.groq.com/openai/v1', requiresApiKey: true },
56
+ mistral: { baseURL: 'https://api.mistral.ai/v1', requiresApiKey: true },
57
+ xai: { baseURL: 'https://api.x.ai/v1', requiresApiKey: true },
58
+ deepseek: { baseURL: 'https://api.deepseek.com', requiresApiKey: true },
59
+ openai: { requiresApiKey: true }
60
+ };
61
+
51
62
  async function getOpenAI(): Promise<OpenAI> {
52
63
  const config = loadConfig();
53
64
  const vaultKeys = await loadApiKeys();
54
-
55
- if (config.llm.provider === 'ollama') {
56
- return new OpenAI({
57
- baseURL: process.env.OLLAMA_BASE_URL ? `${process.env.OLLAMA_BASE_URL}/v1` : 'http://localhost:11434/v1',
58
- apiKey: 'ollama', // API key is not required for local Ollama
59
- });
60
- }
65
+ const providerName = config.llm.provider || 'openai';
66
+ const providerConf = PROVIDER_CONFIGS[providerName] || PROVIDER_CONFIGS['openai'];
61
67
 
62
- // Get API key from config (UI) or fallback to .env
63
- let apiKey = '';
64
-
65
- let configuredKeys = config.llm.api_keys;
66
- if (typeof configuredKeys === 'string') {
67
- configuredKeys = [configuredKeys];
68
- }
69
-
70
- if (Array.isArray(configuredKeys) && configuredKeys.length > 0) {
71
- // Filter out empty keys
72
- const keys = configuredKeys.filter(k => typeof k === 'string' && k.trim() !== '');
73
- if (keys.length > 0) {
74
- currentKeyIndex = currentKeyIndex % keys.length;
75
- apiKey = keys[currentKeyIndex];
76
- console.log(`[LLM] Using rotated API Key (${currentKeyIndex + 1}/${keys.length}): ${apiKey.substring(0, 4)}...`);
77
- currentKeyIndex++; // Increment for next request
68
+ let apiKey = 'local';
69
+ if (providerConf.requiresApiKey) {
70
+ apiKey = '';
71
+ let configuredKeys = config.llm.api_keys;
72
+ if (typeof configuredKeys === 'string') {
73
+ configuredKeys = [configuredKeys];
78
74
  }
79
- }
80
-
81
- // Fallbacks if no valid keys found in config.llm.api_keys
82
- if (!apiKey) {
83
- if (config.llm.provider === 'gemini') {
84
- apiKey = vaultKeys.gemini_key || config.credentials?.gemini_key || '';
85
- } else if (config.llm.provider === 'openrouter') {
86
- apiKey = vaultKeys.openrouter_key || config.credentials?.openrouter_key || '';
87
- } else {
88
- apiKey = vaultKeys.openai_key || config.credentials?.openai_key || '';
75
+
76
+ if (Array.isArray(configuredKeys) && configuredKeys.length > 0) {
77
+ const keys = configuredKeys.filter(k => typeof k === 'string' && k.trim() !== '');
78
+ if (keys.length > 0) {
79
+ currentKeyIndex = currentKeyIndex % keys.length;
80
+ apiKey = keys[currentKeyIndex];
81
+ console.log(`[LLM] Using rotated API Key (${currentKeyIndex + 1}/${keys.length}): ${apiKey.substring(0, 4)}...`);
82
+ currentKeyIndex++;
83
+ }
89
84
  }
85
+
90
86
  if (!apiKey) {
91
- throw new Error(`No API Key found for ${config.llm.provider}. Please run 'nyxora setup' to configure it.`);
87
+ const fallbackKeyName = `${providerName}_key`;
88
+ apiKey = vaultKeys[fallbackKeyName] || config.credentials?.[fallbackKeyName] || '';
89
+
90
+ if (!apiKey) {
91
+ throw new Error(`No API Key found for ${providerName}. Please run 'nyxora setup' to configure it.`);
92
+ }
93
+ console.log(`[LLM] Using API Key from secure vault`);
92
94
  }
93
- console.log(`[LLM] Using API Key from secure vault`);
94
95
  }
95
96
 
96
- if (config.llm.provider === 'gemini') {
97
- return new OpenAI({
98
- baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
99
- apiKey: apiKey,
100
- });
101
- } else if (config.llm.provider === 'openrouter') {
102
- return new OpenAI({
103
- baseURL: 'https://openrouter.ai/api/v1',
104
- apiKey: apiKey,
105
- });
106
- } else {
107
- return new OpenAI({
108
- apiKey: apiKey,
109
- });
110
- }
97
+ return new OpenAI({
98
+ baseURL: providerConf.baseURL,
99
+ apiKey: apiKey,
100
+ timeout: 120 * 1000,
101
+ maxRetries: 0
102
+ });
111
103
  }
112
104
 
113
105
  async function executeWithRetry(
@@ -160,15 +152,16 @@ You are equipped with a native wallet.
160
152
  The current real-world date and time is: ${currentDateTime}. Use this for any time-related questions.
161
153
 
162
154
  CRITICAL RULE 1: ADVANCED NLP & PERSONA. You must act as a highly intelligent, adaptive, and intuitive assistant (similar to ChatGPT or Gemini). You must seamlessly understand the user's language structure, including slang, shorthand, informal context, and mixed languages. However, you must maintain a professional and highly accurate Web3 operational standard.
163
- CRITICAL RULE 2: LANGUAGE MATCHING. You must always reply in the exact same language that the user uses to talk to you. If the user speaks Indonesian, reply in Indonesian. If they speak English, reply in English.
155
+ CRITICAL RULE 2: STRICT LANGUAGE MATCHING. You MUST strictly reply in the exact same language as the user's LATEST prompt. If the user's latest prompt is in English, you MUST reply entirely in English, completely ignoring the language of previous messages. If their latest prompt is in Indonesian, reply in Indonesian.
164
156
  CRITICAL RULE 3: FORMATTING & CONCISENESS.
165
157
  - Your responses MUST be concise and to the point. Do not add unnecessary fluff or overly long explanations unless explicitly asked.
166
158
  - When displaying numbers or monetary values, separate thousands with commas (e.g., $1,000,000) for readability.
167
159
  - When displaying a list of assets, tokens, portfolio, or transaction history, YOU MUST USE MARKDOWN TABLES. Do not use bullet points for financial data.
168
160
  CRITICAL RULE 4: When the user asks to check "my balance", "saldo saya", or anything about their own wallet generally, ALWAYS use the check_portfolio tool to show all assets on the chain that have a USD value greater than 0. LEAVE THE ADDRESS PARAMETER EMPTY. Do NOT use get_balance unless the user explicitly asks for the balance of ONE specific token.
169
- CRITICAL RULE 5: If the user doesn't specify a chain, default to: ${config.agent.default_chain}. If the user mentions a specific chain (e.g., "on BNB", "di Base"), you MUST override the default and execute the tool on that specific chain.
161
+ CRITICAL RULE 5: If the user doesn't specify a chain, default to: ${config.agent.default_chain}. If the user mentions a specific chain (e.g., "on BNB", "di Base"), you MUST override the default and execute the tool on that specific chain. For transactions that require two chains (like bridge_token), if the user only provides the destination chain, you MUST automatically use ${config.agent.default_chain} as the source chain (fromChainName) without asking for clarification.
170
162
  CRITICAL RULE 6: If you use the default chain because the user forgot to specify one, you MUST politely confirm which chain you checked in your response (e.g., "I checked your balance on the ${config.agent.default_chain} network..."). Do not issue scary warnings.
171
- CRITICAL RULE 7: TOOL PRIORITIZATION. When the user asks about crypto prices, market analysis, token security, or blockchain data, YOU MUST prioritize using the dedicated Web3 skills (e.g., get_price, analyze_market, check_security) FIRST. Only if those tools fail or cannot provide the requested information, you may fallback to using search_web.`;
163
+ CRITICAL RULE 7: TOOL PRIORITIZATION. When the user asks about crypto prices, market analysis, token security, or blockchain data, YOU MUST prioritize using the dedicated Web3 skills (e.g., get_price, analyze_market, check_security) FIRST. Only if those tools fail or cannot provide the requested information, you may fallback to using search_web.
164
+ CRITICAL RULE 8: EXACTNESS AND SAFETY IN TRANSACTIONS. Never guess or hallucinate token symbols, network chains, or amounts for Web3 transactions. If the user's intent is ambiguous, you MUST politely ask for clarification instead of attempting a potentially risky transaction. Before confirming any swap or bridge, reiterate the exact tokens, chains, and amounts.`;
172
165
 
173
166
  // Read IDENTITY.md for core AI persona
174
167
  try {
@@ -234,45 +227,33 @@ export async function processUserInput(input: string, role: 'user' | 'system' =
234
227
  return `Provider ${config.llm.provider} is configured, but currently only OpenAI, OpenRouter, Ollama, and Gemini adapters are implemented.`;
235
228
  }
236
229
 
230
+ // --- v1.7.4 Semantic Keyword Router ---
231
+ const lowerInput = input.toLowerCase();
232
+ const hasWeb3Keyword = /swap|transfer|price|token|crypto|bridge|wallet|balance|portfolio|buy|sell|send|receive|address|market|limit|mint|nft/i.test(lowerInput);
233
+ const hasGoogleKeyword = /email|gmail|calendar|sheet|doc|form|event/i.test(lowerInput);
234
+
235
+ const WEB3_TOOLS = [getBalanceToolDefinition, transferToolDefinition, getPriceToolDefinition, swapTokenToolDefinition, bridgeTokenToolDefinition, mintNftToolDefinition, customTxToolDefinition, createWalletToolDefinition, checkSecurityToolDefinition, marketAnalysisToolDefinition, checkPortfolioToolDefinition, checkAddressToolDefinition, getMyAddressToolDefinition, createLimitOrderToolDefinition, listLimitOrdersToolDefinition, cancelLimitOrderToolDefinition];
236
+ const SYSTEM_TOOLS = [updateProfileToolDefinition, updateSecurityPolicyToolDefinition, analyzeDocumentToolDefinition, readLocalFileToolDefinition, writeLocalFileToolDefinition, runTerminalCommandToolDefinition, browseWebsiteToolDefinition, searchWebToolDefinition, installExternalSkillToolDefinition];
237
+ const GOOGLE_TOOLS = [readGmailInboxToolDefinition, listCalendarEventsToolDefinition, appendRowToSheetsToolDefinition, readGoogleDocsToolDefinition, readGoogleFormResponsesToolDefinition];
238
+
239
+ let activeTools: any[] = [];
240
+ if (hasGoogleKeyword && !hasWeb3Keyword) {
241
+ activeTools = [...GOOGLE_TOOLS, ...SYSTEM_TOOLS, ...pluginManager.getToolDefinitions()];
242
+ } else if (hasWeb3Keyword && !hasGoogleKeyword) {
243
+ activeTools = [...WEB3_TOOLS, ...SYSTEM_TOOLS, ...pluginManager.getToolDefinitions()];
244
+ } else {
245
+ activeTools = [...WEB3_TOOLS, ...SYSTEM_TOOLS, ...GOOGLE_TOOLS, ...pluginManager.getToolDefinitions()];
246
+ }
247
+ activeTools = activeTools.filter(t => isSkillActive(t.function.name));
248
+ // ----------------------------------------
249
+
237
250
  const response = await executeWithRetry(async (client) => {
238
251
  return await client.chat.completions.create({
239
- model: config.llm.model,
240
- temperature: config.llm.temperature,
241
- messages: messages,
242
- tools: [
243
- getBalanceToolDefinition as any,
244
- transferToolDefinition as any,
245
- getPriceToolDefinition as any,
246
- swapTokenToolDefinition as any,
247
- bridgeTokenToolDefinition as any,
248
- mintNftToolDefinition as any,
249
- customTxToolDefinition as any,
250
- createWalletToolDefinition as any,
251
- checkSecurityToolDefinition as any,
252
- marketAnalysisToolDefinition as any,
253
- checkPortfolioToolDefinition as any,
254
- checkAddressToolDefinition as any,
255
- getMyAddressToolDefinition as any,
256
- createLimitOrderToolDefinition as any,
257
- listLimitOrdersToolDefinition as any,
258
- cancelLimitOrderToolDefinition as any,
259
- updateProfileToolDefinition as any,
260
- updateSecurityPolicyToolDefinition as any,
261
- analyzeDocumentToolDefinition as any,
262
- readLocalFileToolDefinition as any,
263
- writeLocalFileToolDefinition as any,
264
- runTerminalCommandToolDefinition as any,
265
- browseWebsiteToolDefinition as any,
266
- searchWebToolDefinition as any,
267
- installExternalSkillToolDefinition as any,
268
- readGmailInboxToolDefinition as any,
269
- listCalendarEventsToolDefinition as any,
270
- appendRowToSheetsToolDefinition as any,
271
- readGoogleDocsToolDefinition as any,
272
- readGoogleFormResponsesToolDefinition as any,
273
- ...pluginManager.getToolDefinitions()
274
- ].filter(t => isSkillActive(t.function.name)),
275
- tool_choice: "auto",
252
+ model: config.llm.model,
253
+ temperature: config.llm.temperature,
254
+ messages: messages,
255
+ tools: activeTools,
256
+ tool_choice: "auto",
276
257
  });
277
258
  });
278
259
 
@@ -484,9 +465,13 @@ export async function processUserInput(input: string, role: 'user' | 'system' =
484
465
  content: result,
485
466
  }, sessionId);
486
467
 
487
- // V2 Optimization: Zero-LLM Fast Return for data-heavy tools
468
+ // V2 Optimization (Expanded in v1.7.4): Zero-LLM Fast Return for data-heavy and read-only tools
488
469
  // If the tool already returns perfectly formatted markdown, skip the second LLM call to save 5-10s latency and tokens!
489
- if (toolName === 'check_portfolio' || toolName === 'check_address') {
470
+ const fastReturnTools = [
471
+ 'check_portfolio', 'check_address', 'get_price', 'get_my_address',
472
+ 'analyze_market', 'check_token_security', 'search_web', 'read_gmail_inbox', 'list_calendar_events'
473
+ ];
474
+ if (fastReturnTools.includes(toolName)) {
490
475
  logger.addEntry({ role: 'assistant', content: result }, sessionId);
491
476
  return result;
492
477
  }
@@ -39,10 +39,13 @@ export async function saveApiKeys(newKeys: Record<string, string>): Promise<void
39
39
  export interface NyxoraConfig {
40
40
  agent: {
41
41
  name: string;
42
+ description: string;
42
43
  default_chain: string;
44
+ default_router?: string;
45
+ default_slippage?: number;
43
46
  };
44
47
  llm: {
45
- provider: 'openai' | 'anthropic' | 'ollama' | 'gemini' | 'openrouter';
48
+ provider: string;
46
49
  model: string;
47
50
  temperature: number;
48
51
  api_keys?: string[];
@@ -136,7 +139,7 @@ export function loadConfig(): NyxoraConfig {
136
139
 
137
140
  // Merge with defaults
138
141
  return {
139
- agent: parsed.agent || { name: 'Nyxora-Default', default_chain: 'base' },
142
+ agent: parsed.agent || { name: 'Nyxora-Default', description: 'An autonomous agent running on your local machine.', default_chain: 'base', default_router: 'auto', default_slippage: 0.5 },
140
143
  llm: parsed.llm || {
141
144
  provider: 'openai',
142
145
  model: 'gpt-4o-mini',
@@ -154,8 +157,8 @@ export function loadConfig(): NyxoraConfig {
154
157
  telegram: { enabled: false }
155
158
  },
156
159
  permissions: parsed.permissions || {
157
- web3: { allow_transfer: false, allow_swap: true, max_usd_per_tx: 50 },
158
- system: { allow_shell_execution: false, allow_file_write: false }
160
+ web3: { allow_transfer: true, allow_swap: true, max_usd_per_tx: 999999999 },
161
+ system: { allow_shell_execution: true, allow_file_write: true }
159
162
  }
160
163
  } as NyxoraConfig;
161
164
  } catch (error: any) {
@@ -165,7 +168,13 @@ export function loadConfig(): NyxoraConfig {
165
168
  console.error('[Config] Failed to load config.yaml. Using default configuration.', error);
166
169
  }
167
170
  return {
168
- agent: { name: 'Nyxora-Default', default_chain: 'base' },
171
+ agent: {
172
+ name: "Nyxora-Default",
173
+ description: "An autonomous agent running on your local machine.",
174
+ default_chain: "ethereum",
175
+ default_router: "auto",
176
+ default_slippage: 0.5
177
+ },
169
178
  llm: {
170
179
  provider: 'openai',
171
180
  model: 'gpt-4o-mini',
@@ -183,8 +192,8 @@ export function loadConfig(): NyxoraConfig {
183
192
  telegram: { enabled: false }
184
193
  },
185
194
  permissions: {
186
- web3: { allow_transfer: false, allow_swap: true, max_usd_per_tx: 50 },
187
- system: { allow_shell_execution: false, allow_file_write: false }
195
+ web3: { allow_transfer: true, allow_swap: true, max_usd_per_tx: 999999999 },
196
+ system: { allow_shell_execution: true, allow_file_write: true }
188
197
  }
189
198
  };
190
199
  }
@@ -31,6 +31,20 @@ console.log(`================================`);
31
31
  process.exit(0);
32
32
  }
33
33
 
34
+ // Check for memory clear command
35
+ if (process.argv.includes('clear')) {
36
+ if (process.argv.includes('--force') || process.argv.includes('-y')) {
37
+ const { Logger } = require('../memory/logger');
38
+ const logger = new Logger();
39
+ logger.clear();
40
+ console.log(pc.green('✅ Memory cleared successfully.'));
41
+ process.exit(0);
42
+ } else {
43
+ console.log(pc.yellow('⚠️ Warning: This will wipe all AI memory. Run "nyxora clear --force" to confirm.'));
44
+ process.exit(1);
45
+ }
46
+ }
47
+
34
48
  // Check for set-key shortcut
35
49
  if (process.argv.includes('set-key')) {
36
50
  const setKeyIndex = process.argv.indexOf('set-key');
@@ -39,7 +53,8 @@ console.log(`================================`);
39
53
 
40
54
  if (!provider || !key) {
41
55
  console.error(pc.red('Usage: nyxora set-key <provider> <api_key>'));
42
- console.error(pc.gray('Example: nyxora set-key tavily tvly-xxx'));
56
+ console.error(pc.gray('Example: nyxora set-key groq gsk_xxx'));
57
+ console.error(pc.gray('Providers: openai, gemini, openrouter, groq, mistral, xai, deepseek, tavily, brave'));
43
58
  process.exit(1);
44
59
  }
45
60
 
@@ -47,6 +62,10 @@ console.log(`================================`);
47
62
  'openai': 'openai_key',
48
63
  'gemini': 'gemini_key',
49
64
  'openrouter': 'openrouter_key',
65
+ 'groq': 'groq_key',
66
+ 'mistral': 'mistral_key',
67
+ 'xai': 'xai_key',
68
+ 'deepseek': 'deepseek_key',
50
69
  'tavily': 'tavily_key',
51
70
  'brave': 'brave_key'
52
71
  };