nyxora 26.6.7 → 26.6.9

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 (114) hide show
  1. package/.dockerignore +9 -0
  2. package/CHANGELOG.md +27 -3
  3. package/README.md +18 -10
  4. package/SECURITY.md +16 -4
  5. package/bin/nyxora.mjs +43 -5
  6. package/dist/launcher.js +137 -0
  7. package/dist/packages/core/src/agent/reasoning.js +5 -21
  8. package/dist/packages/core/src/agent/transactionManager.js +2 -0
  9. package/dist/packages/core/src/config/parser.js +7 -45
  10. package/dist/packages/core/src/config/paths.js +39 -1
  11. package/dist/packages/core/src/gateway/cli.js +5 -5
  12. package/dist/packages/core/src/gateway/doctor.js +3 -5
  13. package/dist/packages/core/src/gateway/googleAuthModule.js +13 -32
  14. package/dist/packages/core/src/gateway/legalGenerator.js +88 -0
  15. package/dist/packages/core/src/gateway/server.js +115 -5
  16. package/dist/packages/core/src/gateway/setup.js +4 -2
  17. package/dist/packages/core/src/memory/logger.js +15 -3
  18. package/dist/packages/core/src/system/pluginManager.js +2 -1
  19. package/dist/packages/core/src/system/skills/installSkill.js +2 -1
  20. package/dist/packages/core/src/utils/state.js +24 -7
  21. package/dist/packages/core/src/web3/config.js +11 -1
  22. package/dist/packages/core/src/web3/skills/bridgeToken.js +30 -2
  23. package/dist/packages/core/src/web3/skills/checkSecurity.js +2 -0
  24. package/dist/packages/core/src/web3/skills/customTx.js +1 -1
  25. package/dist/packages/core/src/web3/skills/manageCustomTokens.js +1 -2
  26. package/dist/packages/core/src/web3/skills/mintNft.js +1 -1
  27. package/dist/packages/core/src/web3/skills/swapToken.js +1 -1
  28. package/dist/packages/core/src/web3/skills/transfer.js +1 -1
  29. package/dist/packages/core/src/web3/utils/tokens.js +6 -0
  30. package/dist/packages/policy/src/server.js +21 -4
  31. package/dist/packages/signer/src/server.js +7 -0
  32. package/package.json +4 -3
  33. package/packages/core/package.json +1 -1
  34. package/packages/core/src/agent/reasoning.ts +7 -24
  35. package/packages/core/src/agent/transactionManager.ts +3 -0
  36. package/packages/core/src/config/parser.ts +7 -41
  37. package/packages/core/src/config/paths.ts +42 -1
  38. package/packages/core/src/gateway/cli.ts +21 -21
  39. package/packages/core/src/gateway/doctor.ts +4 -5
  40. package/packages/core/src/gateway/googleAuthModule.ts +12 -27
  41. package/packages/core/src/gateway/legalGenerator.ts +85 -0
  42. package/packages/core/src/gateway/server.ts +138 -7
  43. package/packages/core/src/gateway/setup.ts +5 -2
  44. package/packages/core/src/memory/logger.ts +15 -2
  45. package/packages/core/src/system/pluginManager.ts +2 -1
  46. package/packages/core/src/system/skills/installSkill.ts +2 -2
  47. package/packages/core/src/utils/state.ts +23 -6
  48. package/packages/core/src/web3/config.ts +10 -2
  49. package/packages/core/src/web3/skills/bridgeToken.ts +29 -3
  50. package/packages/core/src/web3/skills/checkSecurity.ts +2 -0
  51. package/packages/core/src/web3/skills/customTx.ts +1 -1
  52. package/packages/core/src/web3/skills/manageCustomTokens.ts +2 -2
  53. package/packages/core/src/web3/skills/mintNft.ts +1 -1
  54. package/packages/core/src/web3/skills/swapToken.ts +1 -1
  55. package/packages/core/src/web3/skills/transfer.ts +1 -1
  56. package/packages/core/src/web3/utils/tokens.ts +6 -0
  57. package/packages/dashboard/dist/assets/index-BT9WzHpr.js +326 -0
  58. package/packages/dashboard/dist/index.html +1 -1
  59. package/packages/dashboard/package.json +1 -1
  60. package/packages/mcp-server/package.json +1 -1
  61. package/packages/policy/package.json +1 -1
  62. package/packages/policy/src/server.ts +23 -3
  63. package/packages/registry-contract/artifacts/@openzeppelin/contracts/access/Ownable.sol/Ownable.dbg.json +4 -0
  64. package/packages/registry-contract/artifacts/@openzeppelin/contracts/access/Ownable.sol/Ownable.json +85 -0
  65. package/packages/registry-contract/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +4 -0
  66. package/packages/registry-contract/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json +10 -0
  67. package/packages/registry-contract/artifacts/@openzeppelin/contracts/utils/Pausable.sol/Pausable.dbg.json +4 -0
  68. package/packages/registry-contract/artifacts/@openzeppelin/contracts/utils/Pausable.sol/Pausable.json +60 -0
  69. package/packages/registry-contract/artifacts/build-info/1a74d547ba64d2f3b7adbff726f3d048.json +1 -0
  70. package/packages/registry-contract/artifacts/contracts/NyxoraAgentRegistry.sol/NyxoraAgentRegistry.dbg.json +4 -0
  71. package/packages/registry-contract/artifacts/contracts/NyxoraAgentRegistry.sol/NyxoraAgentRegistry.json +316 -0
  72. package/packages/registry-contract/cache/solidity-files-cache.json +156 -0
  73. package/packages/registry-contract/contracts/NyxoraAgentRegistry.sol +93 -0
  74. package/packages/registry-contract/hardhat.config.ts +32 -0
  75. package/packages/registry-contract/ignition/deployments/chain-421614/artifacts/RegistryModule#NyxoraAgentRegistry.dbg.json +4 -0
  76. package/packages/registry-contract/ignition/deployments/chain-421614/artifacts/RegistryModule#NyxoraAgentRegistry.json +316 -0
  77. package/packages/registry-contract/ignition/deployments/chain-421614/build-info/1a74d547ba64d2f3b7adbff726f3d048.json +12064 -0
  78. package/packages/registry-contract/ignition/deployments/chain-421614/deployed_addresses.json +3 -0
  79. package/packages/registry-contract/ignition/deployments/chain-421614/journal.jsonl +8 -0
  80. package/packages/registry-contract/ignition/modules/Registry.ts +9 -0
  81. package/packages/registry-contract/package.json +23 -0
  82. package/packages/registry-contract/typechain-types/@openzeppelin/contracts/access/Ownable.ts +153 -0
  83. package/packages/registry-contract/typechain-types/@openzeppelin/contracts/access/index.ts +4 -0
  84. package/packages/registry-contract/typechain-types/@openzeppelin/contracts/index.ts +7 -0
  85. package/packages/registry-contract/typechain-types/@openzeppelin/contracts/utils/Pausable.ts +150 -0
  86. package/packages/registry-contract/typechain-types/@openzeppelin/contracts/utils/index.ts +4 -0
  87. package/packages/registry-contract/typechain-types/@openzeppelin/index.ts +5 -0
  88. package/packages/registry-contract/typechain-types/common.ts +131 -0
  89. package/packages/registry-contract/typechain-types/contracts/NyxoraAgentRegistry.ts +416 -0
  90. package/packages/registry-contract/typechain-types/contracts/index.ts +4 -0
  91. package/packages/registry-contract/typechain-types/factories/@openzeppelin/contracts/access/Ownable__factory.ts +96 -0
  92. package/packages/registry-contract/typechain-types/factories/@openzeppelin/contracts/access/index.ts +4 -0
  93. package/packages/registry-contract/typechain-types/factories/@openzeppelin/contracts/index.ts +5 -0
  94. package/packages/registry-contract/typechain-types/factories/@openzeppelin/contracts/utils/Pausable__factory.ts +71 -0
  95. package/packages/registry-contract/typechain-types/factories/@openzeppelin/contracts/utils/index.ts +4 -0
  96. package/packages/registry-contract/typechain-types/factories/@openzeppelin/index.ts +4 -0
  97. package/packages/registry-contract/typechain-types/factories/contracts/NyxoraAgentRegistry__factory.ts +378 -0
  98. package/packages/registry-contract/typechain-types/factories/contracts/index.ts +4 -0
  99. package/packages/registry-contract/typechain-types/factories/index.ts +5 -0
  100. package/packages/registry-contract/typechain-types/hardhat.d.ts +99 -0
  101. package/packages/registry-contract/typechain-types/index.ts +14 -0
  102. package/packages/signer/package.json +1 -1
  103. package/packages/signer/src/server.ts +9 -0
  104. package/test_state.mjs +1 -0
  105. package/test_state.ts +20 -0
  106. package/test_updates.mjs +76 -0
  107. package/DOCKER.md +0 -68
  108. package/Dockerfile +0 -43
  109. package/assets/architecture.png +0 -0
  110. package/assets/architecture.svg +0 -1
  111. package/assets/raw-diagram.png +0 -0
  112. package/assets/security-flow.png +0 -0
  113. package/launcher.ts +0 -98
  114. package/packages/dashboard/dist/assets/index-whRRjJKK.js +0 -306
package/.dockerignore CHANGED
@@ -10,3 +10,12 @@ build
10
10
  .nyxora
11
11
  vault.key
12
12
  api_vault.key
13
+ keystore.json
14
+ memory.json
15
+ memory.db*
16
+ credentials.json
17
+ google-*.json
18
+ *.token
19
+ config.yaml
20
+ custom_tokens.json
21
+ dynamic_tokens.json
package/CHANGELOG.md CHANGED
@@ -5,7 +5,32 @@ All notable changes to this project will be documented in this file.
5
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
- ## [26.6.7] - Unreleased
8
+ ## [26.6.9] - 2026-06-08
9
+ ### Security & UX Hardening
10
+ - **Zero-Trust Auto-Lock (Passwordless)**: Implemented a robust idle timeout mechanism in the React Dashboard with an elegant glassmorphism blur overlay. The dashboard securely locks after periods of inactivity, requiring the user to authorize unlock directly via the CLI (`nyxora unlock`) to prevent unauthorized local access.
11
+ - **Approval Replay Protection (Nonce Guard)**: Hardened the `transactionManager` to cryptographically sign all pending transaction payloads with a randomized 16-byte Nonce. The `/api/transactions/:id/approve` endpoint now strictly enforces Nonce matching and immediately marks it as `used_` upon first validation, completely eliminating double-spending and Replay Attack vectors.
12
+ - **Graceful Shutdown (SQLite WAL Guard)**: Integrated deep `SIGTERM` and `SIGINT` signal listeners within the Gateway server. When the daemon is halted, the system now safely terminates active incoming requests and explicitly invokes `logger.close()` to securely flush SQLite Write-Ahead Logs (WAL) before exiting, completely eliminating the risk of database corruption.
13
+ - **Resilient UI (Reconnect Overlay)**: Engineered a global network interceptor inside the Dashboard's React `apiFetch` utility. If the daemon goes offline unexpectedly or is restarting, the UI instantly pauses and deploys a transparent, pulsing "Nyxora Daemon Offline" screen. Once the daemon is revived, the overlay automatically lifts, preserving the user's workflow seamlessly.
14
+
15
+ ### Architecture & Production Readiness
16
+ - **Dynamic Port Anti-Collision**: Replaced the hardcoded `3001` Policy Server port with a dynamic `process.env.POLICY_PORT` fallback. All Web3 Agents (Bridge, Swap, Transfer, etc.) are now dynamically linked to this environment variable, completely eliminating `ECONNREFUSED` crashes when port 3001 is occupied by other local developer applications.
17
+ - **Production-Ready Path Resolution**: Eliminated hardcoded `process.cwd()` dependencies across the Gateway, Dashboard, and Plugin Manager. The CLI now utilizes robust absolute `__dirname` and `getAppDir()` traversal, guaranteeing the Dashboard UI and External Skills load flawlessly regardless of where the global CLI command is executed from.
18
+
19
+
20
+ ## [26.6.8] - 2026-06-08
21
+ ### Enterprise Features & Web3 Enhancements
22
+ - **Zero-Downtime Directory Migration**: Restructured the root `~/.nyxora` local data directory into a strict `config/`, `data/`, `auth/`, and `run/` subdirectory architecture. Implemented a Lazy Auto-Migration Engine (`getPath()`) that seamlessly relocates legacy files to their new secure zones instantly upon access, ensuring zero-downtime and zero-data-loss upgrades for existing users.
23
+ ### Security & UX Updates
24
+ - **Proactive Anti-Crash Engine**: Implemented `Max Retry` & `Exponential Backoff` auto-respawn logic inside the Monorepo Launcher. The daemon now features robust global `unhandledRejection` and `uncaughtException` guards across the Core, Policy, and Signer subsystems, ensuring sporadic Web3 network timeouts can no longer crash the main reasoning engine.
25
+ - **Death Loop Telegram Alerts**: Integrated a critical emergency monitoring system into the Launcher. If a core microservice crashes catastrophically (5 times within 1 minute), the daemon will autonomously initiate an emergency lock-down to protect the system state and immediately broadcast a high-priority alert directly to the administrator's Telegram.
26
+ - **Unix Socket Anti-EADDRINUSE Guard**: Implemented aggressive pre-flight cleanup routines for the `nyxora-signer.sock` IPC channel. The system now guarantees secure file unlinking before rebinding, eliminating recurring `EADDRINUSE` daemon failures upon rapid restart commands.
27
+
28
+ ### Bug Fixes & Optimizations
29
+ - **NPM Package Optimization**: Added `assets/` to `.npmignore` to exclude large architectural diagrams and images from the NPM registry tarball, reducing the total package download size by over 11 MB.
30
+ - **Docker Multi-Stage Build**: Radically refactored `Dockerfile` to a Multi-Stage architecture. The production image now exclusively installs runtime dependencies (`--omit=dev`) and leaves behind heavy build tools (`python3`, `make`, `g++`), dramatically shrinking the final container image size.
31
+ - **Docker Security Patch**: Hardened `.dockerignore` to explicitly block local keystores (`keystore.json`), persistent memory (`memory.db`), and local credentials from accidentally leaking into Docker image layers during local builds.
32
+
33
+ ## [26.6.7] - 2026-06-07
9
34
  ### Enterprise Features & Web3 Enhancements
10
35
  - **Enterprise Portfolio Scanner**: Integrated a fully decentralized, real-time Dashboard UI (Nord Theme) to scan all native and ERC-20 token balances across 8 EVM chains natively, without relying on centralized third-party APIs.
11
36
  - **Real-Time USD Valuation**: Integrated DexScreener API into the Portfolio Scanner backend to actively compute and display USD portfolio values in real-time. Features an adaptive 2-minute memory cache system to ensure complete immunity against API rate-limits and eliminate LLM token consumption.
@@ -121,8 +146,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
121
146
  - **Fast CLI Shortcuts**: Added the `nyxora set-key <provider> <key>` global command shortcut allowing developers to quickly inject or override any API Key (OpenAI, Gemini, OpenRouter, Tavily, Brave) directly into the secure vault without traversing the wizard.
122
147
 
123
148
  ### AI Engine Optimizations
124
- - **Hybrid API Vault (Security)**: API Keys are no longer stored in plain text inside `config.yaml`. Nyxora now encrypts and stores them via `@napi-rs/keyring` utilizing OS-native credential management. For Headless/VPS Linux environments lacking DBUS/Secret Service, it automatically falls back to an isolated `api_vault.key` with strict `0600` permissions.
125
- - **Root-Level Config Auto-Migration**: Restructured `config.yaml` to move all API keys out of the nested `llm.credentials` into a logical, root-level `credentials` object. Implemented a silent auto-migration routine in `parser.ts` that safely upgrades legacy config files on boot without breaking existing setups.
149
+
126
150
  - **Web Search Smart Memory Cache**: Embedded a local Memory Cache (`Map`) into the `searchWeb` skill with a 5-minute (300,000ms) TTL. Exact duplicate queries now execute in 0ms and consume 0 API quota, dramatically improving conversation flow.
127
151
  - **Deep Research Mode**: The `search_web` tool definition now accepts a dynamic `depth` parameter (1 to 3). If users instruct the AI to conduct comprehensive research, Nyxora will automatically trigger `advanced` API payloads and extract up to 15 top web snippets simultaneously.
128
152
  - **Strict Skill Prioritization**: Added CRITICAL RULE 7 to the core NLP System Prompt. The AI is now hard-coded to prioritize native Web3 Skills (e.g. `get_price`, `analyze_market`, `check_security`) for all crypto-related queries, using `search_web` exclusively as a fallback mechanism.
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  Nyxora is a **secure, non-custodial runtime infrastructure for autonomous onchain agents** built with a robust Monorepo architecture (Node.js & React). Designed for autonomous workflows with a premium Utility-Centric dark-themed UI and strict client-side key isolation.
12
12
 
13
- **Nyxora now natively supports the Model Context Protocol (MCP)**. You can transform your external AI agents (like Claude Desktop and Cursor) into secure Web3 actors that execute swaps and fetch balances using Nyxora's secure signer vault. [View the MCP Integration Guide](https://nyxoraAI.github.io/Nyxora/guide/mcp-integration)
13
+ **Nyxora now natively supports the Model Context Protocol (MCP)**. You can transform your external AI agents (like Claude Desktop and Cursor) into secure Web3 actors that execute swaps and fetch balances using Nyxora's secure signer vault. [View the MCP Integration Guide](https://nyxoraai.github.io/Nyxora/guide/mcp-integration)
14
14
 
15
15
  It operates under an institutional-grade **Cryptographically Bound Human-in-the-Loop** execution model, ensuring that Remote AIs (LLMs) never have unilateral access to your funds.
16
16
 
@@ -20,10 +20,10 @@ It operates under an institutional-grade **Cryptographically Bound Human-in-the-
20
20
 
21
21
  ### Advanced Security Architecture
22
22
  * **3-Tier IPC Architecture**: Nyxora is split into isolated processes: **Core** (LLM Runtime), **Policy Engine** (Guardrails on port 3001), and **Signer Vault** (Isolated Key Manager on Unix Sockets).
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.
23
+ * **Approval Replay Protection (Nonce Guard)**: Transactions requested by the AI are drafted as hashes and signed with a randomized 16-byte Nonce. The `/api/transactions/:id/approve` endpoint strictly enforces Nonce matching to completely eliminate double-spending and Replay 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
+ * **Graceful SQLite WAL Shutdown**: Integrated `SIGTERM`/`SIGINT` interceptors ensure that when the daemon stops, active requests are safely terminated and SQLite Write-Ahead Logs (WAL) are securely flushed, preventing database corruption.
27
27
 
28
28
  ### 🌐 Web3 Skills (On-Chain)
29
29
  * **Security Scanner**: Nyxora can scan smart contracts via GoPlus Labs to detect Honeypots, Hidden Taxes, and malicious proxy upgrades before you buy.
@@ -39,8 +39,9 @@ It operates under an institutional-grade **Cryptographically Bound Human-in-the-
39
39
  * **Unstoppable Synergy**: Combine both engines with a single prompt. Example: *"Read the latest presale token email from my Gmail, automatically set a Take Profit limit order on Uniswap, and log the execution result to my Google Sheets."*
40
40
 
41
41
  ### AI & UI Customization
42
+ * **Zero-Trust Auto-Lock (Passwordless)**: A sleek glassmorphism blur overlay automatically locks the dashboard during inactivity. Unlocking requires physical local execution via the CLI (`nyxora unlock`), preventing unauthorized local access.
43
+ * **Resilient UI (Reconnect Overlay)**: Built-in global network interceptors ensure that if the daemon restarts or crashes, the UI immediately pauses with a transparent "Offline" overlay and seamlessly resumes your workflow once revived.
42
44
  * **Zero-Click Multi-Session**: Instantly create isolated chat sessions with smart auto-naming triggered by your first prompt, exactly like ChatGPT.
43
- * **Dynamic Trending Tokens**: Live top 5 crypto assets feed directly injected into the dashboard, completely clickable for instant AI market analysis.
44
45
  * **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
46
  * **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
47
  * **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.
@@ -66,7 +67,7 @@ The following diagram illustrates Nyxora's **3-Tier Monorepo Architecture**, sho
66
67
 
67
68
  ## 🛡️ Advanced Security & Threat Model
68
69
 
69
- To dive deeper into the technical details of our Zero-Knowledge security architecture, please visit the [Nyxora Security Blueprint](https://nyxoraAI.github.io/Nyxora/).
70
+ To dive deeper into the technical details of our Zero-Knowledge security architecture, please visit the [Nyxora Security Blueprint](https://nyxoraai.github.io/Nyxora/).
70
71
 
71
72
  ---
72
73
 
@@ -93,16 +94,23 @@ Alternatively, you can install it manually on any operating system using NPM:
93
94
  npm install -g nyxora@latest
94
95
  ```
95
96
 
96
- # 2. Run the Interactive Setup Wizard (API Keys, Wallet, Telegram)
97
+ ### 2. Run the Interactive Setup Wizard (API Keys, Wallet, Telegram)
98
+ ```bash
97
99
  nyxora setup
100
+ ```
98
101
 
99
- # 3. Start the Nyxora background daemon
102
+ ### 3. Start the Nyxora background daemon
103
+ ```bash
100
104
  nyxora start
105
+ ```
101
106
 
102
- # 4. Open the Web Dashboard
107
+ ### 4. Open the Web Dashboard
108
+ ```bash
103
109
  nyxora dashboard
110
+ ```
104
111
 
105
- # Utility: Atomically clear the AI's short-term and long-term memory
112
+ ### Utility: Atomically clear the AI's short-term and long-term memory
113
+ ```bash
106
114
  nyxora clear --force
107
115
  ```
108
116
  > **⚠️ 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.
@@ -135,7 +143,7 @@ npm start
135
143
 
136
144
  For complete technical deep-dives into our Cryptographic Architecture, please visit our official VitePress Documentation Site!
137
145
 
138
- > **🔗 [Read the Full Nyxora Documentation Here](https://nyxoraAI.github.io/Nyxora/)**
146
+ > **🔗 [Read the Full Nyxora Documentation Here](https://nyxoraai.github.io/Nyxora/)**
139
147
 
140
148
  *(Includes guides on Secure Wallet Imports, Architecture Blueprints, Troubleshooting, and Custom Skill Development).*
141
149
 
package/SECURITY.md CHANGED
@@ -38,7 +38,9 @@ Nyxora completely eliminates the need for manual "Master Passwords" or custom AE
38
38
  When the background daemon boots via `nyxora start`, the Signer Vault process reads the Private Key directly from the OS Keyring without requiring human intervention. This ensures the daemon can safely persist across reboots while maintaining institutional-grade encryption at rest.
39
39
 
40
40
  ### Secure Fallback Storage
41
- In headless server environments (e.g., VPS, Docker) where a GUI Keyring is unavailable, Nyxora gracefully falls back to a strictly permissioned `.env` / `vault.key` file mechanism. This file is programmatically enforced with `chmod 0600` permissions (Read/Write for owner only), preventing access by other system users.
41
+ In headless server environments (e.g., VPS, Docker) where a GUI Keyring is unavailable, Nyxora gracefully falls back to a strictly permissioned `vault.key` file mechanism. This file is programmatically enforced with `chmod 0600` permissions (Read/Write for owner only), preventing access by other system users.
42
+
43
+ > **Note:** This OS-level keyring protection is strictly reserved for your Web3 Wallet Private Keys. Standard integration credentials (like LLM API Keys or Telegram tokens) are managed separately via the `config.yaml` file for transparent developer access.
42
44
 
43
45
  ---
44
46
 
@@ -64,12 +66,22 @@ approval_hash = sha256(policy_diff + timestamp + user_id)
64
66
  ```
65
67
  This ensures that what the human saw on the UI matches exactly what is being executed, preventing the LLM from secretly modifying the payload in transit.
66
68
 
67
- ### Anti-Replay Challenge Nonce
68
- Every approval UI prompt utilizes a **Single-Use Challenge Nonce** with a strict expiry time. This mitigates *XSS Token Leaks* and *Replay Attacks*, ensuring that an old approval token cannot be stolen and reused for a malicious transaction later.
69
+ ### Anti-Replay Challenge Nonce (Nonce Guard)
70
+ Every approval UI prompt utilizes a **Single-Use Challenge Nonce** (a randomized 16-byte cryptographic string). The `transactionManager` signs all pending payloads with this Nonce. The `/api/transactions/:id/approve` endpoint strictly enforces matching and immediately marks the Nonce as `used_` upon first validation. This completely eliminates *XSS Token Leaks*, *Double-Spending*, and *Replay Attacks*, ensuring that an old approval token cannot be stolen and reused for a malicious transaction later.
71
+
72
+ ---
73
+
74
+ ## 4. Physical Access & Data Integrity
75
+
76
+ ### Zero-Trust Auto-Lock (Physical Protection)
77
+ To protect against unauthorized physical access (e.g., leaving a laptop unattended), the Dashboard implements a **Zero-Trust Auto-Lock** mechanism. After a period of inactivity, the UI aggressively blurs and locks all state. Unlocking the interface requires the user to execute `nyxora unlock` directly from the host operating system's CLI. This guarantees that anyone physically sitting at the unlocked dashboard cannot execute transactions without also possessing SSH or direct terminal access to the host machine.
78
+
79
+ ### SQLite WAL Graceful Shutdown (Data Integrity)
80
+ To prevent database corruption during abrupt terminations, the Gateway daemon employs deep `SIGTERM` and `SIGINT` interceptors. When a halt is requested, the system safely terminates active incoming API requests and explicitly flushes the SQLite Write-Ahead Logs (WAL) before fully exiting, ensuring enterprise-grade state stability.
69
81
 
70
82
  ---
71
83
 
72
- ## 4. Plugin Sandboxing (Node.js VM Isolation)
84
+ ## 5. Plugin Sandboxing (Node.js VM Isolation)
73
85
 
74
86
  Community plugins and custom skills are NEVER executed directly at the OS level. Instead, Nyxora creates an airtight **Virtual Machine (VM) Sandbox** in memory.
75
87
 
package/bin/nyxora.mjs CHANGED
@@ -11,9 +11,9 @@ const __dirname = path.dirname(__filename);
11
11
  const projectRoot = path.join(__dirname, '..');
12
12
 
13
13
  const appDir = path.join(os.homedir(), '.nyxora');
14
- const pidFile = path.join(appDir, 'daemon.pid');
15
- const logFile = path.join(appDir, 'gateway.log');
16
- const tokenFile = path.join(appDir, 'auth.token');
14
+ const pidFile = path.join(appDir, 'run', 'daemon.pid');
15
+ const logFile = path.join(appDir, 'run', 'gateway.log');
16
+ const tokenFile = path.join(appDir, 'auth', 'auth.token');
17
17
 
18
18
  if (!fs.existsSync(appDir)) {
19
19
  fs.mkdirSync(appDir, { recursive: true });
@@ -117,7 +117,13 @@ async function dashboard() {
117
117
  }
118
118
 
119
119
  if (fs.existsSync(tokenFile)) {
120
- const token = fs.readFileSync(tokenFile, 'utf8').trim();
120
+ let token = fs.readFileSync(tokenFile, 'utf8').trim();
121
+ if (token.startsWith('{')) {
122
+ try {
123
+ const parsed = JSON.parse(token);
124
+ token = parsed.token;
125
+ } catch (e) {}
126
+ }
121
127
  const url = `http://localhost:3000?token=${token}`;
122
128
  console.log(`Opening Dashboard at ${url}`);
123
129
  try {
@@ -275,8 +281,38 @@ async function runDoctor() {
275
281
  await new Promise(resolve => child.on('close', resolve));
276
282
  }
277
283
 
284
+ async function unlock() {
285
+ if (fs.existsSync(tokenFile)) {
286
+ let token = fs.readFileSync(tokenFile, 'utf8').trim();
287
+ if (token.startsWith('{')) {
288
+ try {
289
+ const parsed = JSON.parse(token);
290
+ token = parsed.token;
291
+ } catch (e) {}
292
+ }
293
+ try {
294
+ const fetch = (await import('node-fetch')).default;
295
+ const res = await fetch('http://localhost:3000/api/status/unlock', {
296
+ method: 'POST',
297
+ headers: {
298
+ 'x-nyxora-token': token
299
+ }
300
+ });
301
+ if (res.ok) {
302
+ console.log('✅ Dashboard unlocked successfully.');
303
+ } else {
304
+ console.log('❌ Failed to unlock dashboard. Is the daemon running?');
305
+ }
306
+ } catch (e) {
307
+ console.log('❌ Failed to communicate with the daemon. Is it running?');
308
+ }
309
+ } else {
310
+ console.log('❌ Authentication token not found.');
311
+ }
312
+ }
313
+
278
314
  async function main() {
279
- switch (command) {
315
+ switch(command) {
280
316
  case 'doctor': await runDoctor(); break;
281
317
  case 'setup': await setup(); break;
282
318
  case 'clear': await clearMemory(process.argv.slice(3)); break;
@@ -286,6 +322,7 @@ async function main() {
286
322
  case 'stop': await stop(); break;
287
323
  case 'restart': await restart(); break;
288
324
  case 'dashboard': await dashboard(); break;
325
+ case 'unlock': await unlock(); break;
289
326
  case 'clean-logs': await cleanLogs(); break;
290
327
  case 'autostart': await autostart(process.argv[3]); break;
291
328
  case '-v':
@@ -307,6 +344,7 @@ Commands:
307
344
  restart Restart the daemon
308
345
  setup Run the interactive Setup Wizard
309
346
  dashboard Open the dashboard in your browser
347
+ unlock Unlock an inactive dashboard session
310
348
  doctor Run system diagnostics and check requirements
311
349
  clear Atomically clear the AI's short/long-term memory SQLite database
312
350
  clean-logs Clear the daemon logs
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const safeLogger_1 = require("./packages/core/src/utils/safeLogger");
7
+ (0, safeLogger_1.initSafeLogger)();
8
+ const child_process_1 = require("child_process");
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const INTERNAL_AUTH_TOKEN = crypto_1.default.randomBytes(64).toString('hex');
13
+ console.log(`[Launcher] Generated Internal Auth Token: ${INTERNAL_AUTH_TOKEN.substring(0, 8)}...`);
14
+ const nyxoraDir = path_1.default.join(process.env.HOME || process.env.USERPROFILE || '', '.nyxora');
15
+ const authDir = path_1.default.join(nyxoraDir, 'auth');
16
+ if (!fs_1.default.existsSync(authDir))
17
+ fs_1.default.mkdirSync(authDir, { recursive: true, mode: 0o700 });
18
+ const tokenPath = path_1.default.join(authDir, 'runtime.token');
19
+ fs_1.default.writeFileSync(tokenPath, INTERNAL_AUTH_TOKEN, { mode: 0o600 });
20
+ console.log(`[Launcher] Secured runtime token at ${tokenPath} (0600)`);
21
+ const env = {
22
+ ...process.env,
23
+ INTERNAL_AUTH_TOKEN,
24
+ SIGNER_SOCKET_PATH: '/tmp/nyxora-signer.sock',
25
+ TS_NODE_CACHE: 'false'
26
+ };
27
+ const spawnService = (name, command, args, env, inheritStdio = false) => {
28
+ let child;
29
+ let crashCount = 0;
30
+ let crashWindowStart = Date.now();
31
+ let isShuttingDown = false;
32
+ const startProcess = () => {
33
+ child = (0, child_process_1.spawn)(command, args, { env, stdio: inheritStdio ? 'inherit' : 'pipe' });
34
+ if (!inheritStdio) {
35
+ child.stdout?.on('data', (data) => process.stdout.write(`[${name}] ${data}`));
36
+ child.stderr?.on('data', (data) => process.stderr.write(`[${name}] ERROR: ${data}`));
37
+ }
38
+ child.on('close', async (code) => {
39
+ console.log(`[${name}] Exited with code ${code}`);
40
+ if (isShuttingDown)
41
+ return;
42
+ const now = Date.now();
43
+ if (now - crashWindowStart > 60000) {
44
+ crashCount = 0;
45
+ crashWindowStart = now;
46
+ }
47
+ crashCount++;
48
+ if (crashCount > 5) {
49
+ console.error(`[Launcher] FATAL: ${name} crashed 5 times in 1 minute. Initiating emergency shutdown.`);
50
+ isShuttingDown = true;
51
+ try {
52
+ const yaml = require('yaml');
53
+ const configPath = path_1.default.join(process.env.HOME || process.env.USERPROFILE || '', '.nyxora', 'config', 'config.yaml');
54
+ // Fallback check just in case it hasn't migrated yet
55
+ const actualConfigPath = fs_1.default.existsSync(configPath) ? configPath : path_1.default.join(process.env.HOME || process.env.USERPROFILE || '', '.nyxora', 'config.yaml');
56
+ if (fs_1.default.existsSync(actualConfigPath)) {
57
+ const configStr = fs_1.default.readFileSync(actualConfigPath, 'utf8');
58
+ const config = yaml.parse(configStr);
59
+ const tgToken = config?.telegram?.bot_token;
60
+ const tgChatId = config?.telegram?.admin_chat_id;
61
+ if (tgToken && tgChatId) {
62
+ const alertText = config?.alerts?.emergency_text || "🚨 FATAL ERROR: A critical process has crashed repeatedly. Nyxora is executing an emergency auto-shutdown to protect your system. Please check the server logs.";
63
+ await fetch(`https://api.telegram.org/bot${tgToken}/sendMessage`, {
64
+ method: 'POST',
65
+ headers: { 'Content-Type': 'application/json' },
66
+ body: JSON.stringify({ chat_id: tgChatId, text: alertText })
67
+ }).catch(() => { });
68
+ }
69
+ }
70
+ }
71
+ catch (e) { }
72
+ process.exit(1);
73
+ return;
74
+ }
75
+ console.log(`[Launcher] Restarting ${name} in 3 seconds... (Attempt ${crashCount}/5)`);
76
+ setTimeout(startProcess, 3000);
77
+ });
78
+ };
79
+ startProcess();
80
+ return {
81
+ kill: () => {
82
+ isShuttingDown = true;
83
+ if (child && !child.killed && child.pid) {
84
+ try {
85
+ process.kill(child.pid, 'SIGTERM');
86
+ }
87
+ catch (e) { }
88
+ }
89
+ }
90
+ };
91
+ };
92
+ console.log('[Launcher] Starting Monorepo Services...');
93
+ const socketPath = env.SIGNER_SOCKET_PATH;
94
+ if (fs_1.default.existsSync(socketPath)) {
95
+ console.log(`[Launcher] Removing stale unix socket at ${socketPath}`);
96
+ fs_1.default.unlinkSync(socketPath);
97
+ }
98
+ const children = [];
99
+ const isCompiled = __filename.endsWith('.js');
100
+ const ext = isCompiled ? '.js' : '.ts';
101
+ const cmd = isCompiled ? 'node' : 'npx';
102
+ const baseArgs = isCompiled ? [] : ['ts-node', '-T'];
103
+ const signerPath = path_1.default.join(__dirname, `packages/signer/src/server${ext}`);
104
+ const signer = spawnService('Signer', cmd, [...baseArgs, signerPath], env);
105
+ children.push(signer);
106
+ setTimeout(() => {
107
+ const policyPath = path_1.default.join(__dirname, `packages/policy/src/server${ext}`);
108
+ const policy = spawnService('Policy', cmd, [...baseArgs, policyPath], env);
109
+ children.push(policy);
110
+ setTimeout(() => {
111
+ const corePath = path_1.default.join(__dirname, `packages/core/src/gateway/cli${ext}`);
112
+ const args = process.argv.slice(2);
113
+ const core = spawnService('Core', cmd, [...baseArgs, corePath, ...args], env, true);
114
+ children.push(core);
115
+ }, 1000);
116
+ }, 1000);
117
+ // Ensure all child processes are killed when launcher exits
118
+ let isCleaningUp = false;
119
+ const cleanup = () => {
120
+ if (isCleaningUp)
121
+ return;
122
+ isCleaningUp = true;
123
+ console.log('\n[Launcher] Shutting down all services...');
124
+ children.forEach(c => c.kill());
125
+ // Give them a moment to cleanup
126
+ setTimeout(() => {
127
+ try {
128
+ require('child_process').execSync('pkill -f ts-node');
129
+ }
130
+ catch (e) { }
131
+ process.exit(0);
132
+ }, 1000);
133
+ };
134
+ process.on('SIGINT', cleanup);
135
+ process.on('SIGTERM', cleanup);
136
+ process.on('SIGTERM', cleanup);
137
+ process.on('exit', cleanup);
@@ -40,7 +40,6 @@ const pluginManager_1 = require("../system/pluginManager");
40
40
  const paths_1 = require("../config/paths");
41
41
  const picocolors_1 = __importDefault(require("picocolors"));
42
42
  exports.logger = new logger_1.Logger();
43
- let currentKeyIndex = 0;
44
43
  const PROVIDER_CONFIGS = {
45
44
  ollama: { baseURL: process.env.OLLAMA_BASE_URL ? `${process.env.OLLAMA_BASE_URL}/v1` : 'http://localhost:11434/v1', requiresApiKey: false },
46
45
  gemini: { baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/', requiresApiKey: true },
@@ -59,27 +58,12 @@ async function getOpenAI() {
59
58
  let apiKey = 'local';
60
59
  if (providerConf.requiresApiKey) {
61
60
  apiKey = '';
62
- let configuredKeys = config.llm.api_keys;
63
- if (typeof configuredKeys === 'string') {
64
- configuredKeys = [configuredKeys];
65
- }
66
- if (Array.isArray(configuredKeys) && configuredKeys.length > 0) {
67
- const keys = configuredKeys.filter(k => typeof k === 'string' && k.trim() !== '');
68
- if (keys.length > 0) {
69
- currentKeyIndex = currentKeyIndex % keys.length;
70
- apiKey = keys[currentKeyIndex];
71
- console.log(`[LLM] Using rotated API Key (${currentKeyIndex + 1}/${keys.length}): ${apiKey.substring(0, 4)}...`);
72
- currentKeyIndex++;
73
- }
74
- }
61
+ const keyName = `${providerName}_key`;
62
+ apiKey = vaultKeys[keyName] || config.credentials?.[keyName] || '';
75
63
  if (!apiKey) {
76
- const fallbackKeyName = `${providerName}_key`;
77
- apiKey = vaultKeys[fallbackKeyName] || config.credentials?.[fallbackKeyName] || '';
78
- if (!apiKey) {
79
- throw new Error(`No API Key found for ${providerName}. Please run 'nyxora setup' to configure it.`);
80
- }
81
- console.log(`[LLM] Using API Key from secure vault`);
64
+ throw new Error(`[Security] No API Key found for ${providerName} in OS Keyring. Please run 'nyxora set-key ${providerName} <key>' or 'nyxora setup'.`);
82
65
  }
66
+ console.log(`[LLM] Using API Key securely unlocked from OS Keyring vault.`);
83
67
  }
84
68
  return new openai_1.OpenAI({
85
69
  baseURL: providerConf.baseURL,
@@ -130,7 +114,7 @@ function getSystemPrompt() {
130
114
  You are equipped with a native wallet.
131
115
  The current real-world date and time is: ${currentDateTime}. Use this for any time-related questions.
132
116
 
133
- 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.
117
+ CRITICAL RULE 1: NEVER expose internal JSON tool calls to the user. Always parse them and explain the outcome naturally.
134
118
  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.
135
119
  CRITICAL RULE 3: FORMATTING & CONCISENESS.
136
120
  - Your responses MUST be concise and to the point. Do not add unnecessary fluff or overly long explanations unless explicitly asked.
@@ -9,6 +9,7 @@ class TransactionManager {
9
9
  transactions = new Map();
10
10
  createPendingTransaction(type, chainName, details) {
11
11
  const id = crypto_1.default.randomUUID();
12
+ const nonce = crypto_1.default.randomBytes(16).toString('hex');
12
13
  const tx = {
13
14
  id,
14
15
  type,
@@ -16,6 +17,7 @@ class TransactionManager {
16
17
  details,
17
18
  status: 'pending',
18
19
  createdAt: Date.now(),
20
+ nonce,
19
21
  };
20
22
  this.transactions.set(id, tx);
21
23
  return tx;
@@ -11,38 +11,15 @@ const fs_1 = __importDefault(require("fs"));
11
11
  const yaml_1 = __importDefault(require("yaml"));
12
12
  const paths_1 = require("./paths");
13
13
  async function loadApiKeys() {
14
- const vaultPath = (0, paths_1.getPath)('api_vault.key');
15
- try {
16
- const { Entry } = require('@napi-rs/keyring');
17
- const entry = new Entry('nyxora', 'api_keys');
18
- const data = await entry.getPassword();
19
- if (data)
20
- return JSON.parse(data);
21
- }
22
- catch (e) {
23
- if (fs_1.default.existsSync(vaultPath)) {
24
- try {
25
- const file = fs_1.default.readFileSync(vaultPath, 'utf8');
26
- return JSON.parse(file);
27
- }
28
- catch (err) { }
29
- }
30
- }
31
- return {};
14
+ const config = loadConfig();
15
+ return config.credentials || {};
32
16
  }
33
17
  async function saveApiKeys(newKeys) {
34
- const vaultPath = (0, paths_1.getPath)('api_vault.key');
35
- const currentKeys = await loadApiKeys();
36
- const mergedKeys = { ...currentKeys, ...newKeys };
37
- const dataString = JSON.stringify(mergedKeys);
38
- try {
39
- const { Entry } = require('@napi-rs/keyring');
40
- const entry = new Entry('nyxora', 'api_keys');
41
- await entry.setPassword(dataString);
42
- }
43
- catch (e) {
44
- fs_1.default.writeFileSync(vaultPath, dataString, { mode: 0o600 });
45
- }
18
+ const config = loadConfig();
19
+ if (!config.credentials)
20
+ config.credentials = {};
21
+ config.credentials = { ...config.credentials, ...newKeys };
22
+ saveConfig(config);
46
23
  }
47
24
  function loadConfig() {
48
25
  const configPath = (0, paths_1.getPath)('config.yaml');
@@ -74,21 +51,6 @@ function loadConfig() {
74
51
  console.error('[Config] Failed to auto-migrate config file', e);
75
52
  }
76
53
  }
77
- // Auto-migrate from config.yaml to Keyring/Vault
78
- if (parsed.credentials && Object.keys(parsed.credentials).length > 0) {
79
- const credsToMigrate = { ...parsed.credentials };
80
- saveApiKeys(credsToMigrate).then(() => {
81
- console.log('[Config] Auto-migrated API keys to secure vault.');
82
- delete parsed.credentials;
83
- try {
84
- const yamlStr = yaml_1.default.stringify(parsed);
85
- fs_1.default.writeFileSync(configPath, yamlStr, 'utf8');
86
- }
87
- catch (e) { }
88
- }).catch(e => {
89
- console.error('[Config] Failed to migrate API keys to secure vault', e);
90
- });
91
- }
92
54
  return {
93
55
  agent: parsed.agent || { name: 'Nyxora-Default', description: 'Your Personal Web3 Assistant.', default_chain: 'base', default_router: 'auto', default_slippage: 0.5 },
94
56
  llm: parsed.llm || {
@@ -30,6 +30,44 @@ function getAppDir() {
30
30
  }
31
31
  return process.cwd();
32
32
  }
33
+ function ensureDir(dir) {
34
+ if (!fs_1.default.existsSync(dir)) {
35
+ fs_1.default.mkdirSync(dir, { recursive: true });
36
+ }
37
+ }
33
38
  function getPath(filename) {
34
- return path_1.default.join(getAppDir(), filename);
39
+ const baseDir = getAppDir();
40
+ // Determine subdirectory based on filename
41
+ let subDir = '';
42
+ const lowerFile = filename.toLowerCase();
43
+ if (lowerFile.endsWith('.db') || lowerFile.endsWith('.db-wal') || lowerFile.endsWith('.db-shm') || lowerFile.endsWith('.json') && lowerFile.includes('memory') || lowerFile.endsWith('.md') || lowerFile.includes('orders')) {
44
+ subDir = 'data';
45
+ }
46
+ else if (lowerFile.endsWith('.yaml') || lowerFile.includes('config') || lowerFile.includes('skills') || lowerFile.includes('whitelist') || lowerFile.includes('tokens')) {
47
+ subDir = 'config';
48
+ }
49
+ else if (lowerFile.endsWith('.token') || lowerFile.includes('vault') || lowerFile.includes('credentials')) {
50
+ subDir = 'auth';
51
+ }
52
+ else if (lowerFile.endsWith('.log') || lowerFile.includes('pid')) {
53
+ subDir = 'run';
54
+ }
55
+ const targetDir = path_1.default.join(baseDir, subDir);
56
+ ensureDir(targetDir);
57
+ const fullPath = path_1.default.join(targetDir, filename);
58
+ // AUTO-MIGRATION: If file exists in root but not in subdir, move it
59
+ const oldRootPath = path_1.default.join(baseDir, filename);
60
+ if (subDir !== '') {
61
+ if (fs_1.default.existsSync(oldRootPath) && !fs_1.default.existsSync(fullPath)) {
62
+ try {
63
+ fs_1.default.renameSync(oldRootPath, fullPath);
64
+ console.log(`[Migration] Moved ${filename} to ${subDir}/ directory.`);
65
+ }
66
+ catch (err) {
67
+ console.warn(`[Migration] Failed to move ${filename} to ${subDir}/`, err);
68
+ return oldRootPath; // fallback to root if migration fails
69
+ }
70
+ }
71
+ }
72
+ return fullPath;
35
73
  }
@@ -106,7 +106,7 @@ async function main() {
106
106
  };
107
107
  const mappedKey = keyMap[provider.toLowerCase()] || `${provider.toLowerCase()}_key`;
108
108
  await (0, parser_1.saveApiKeys)({ [mappedKey]: key });
109
- console.log(picocolors_1.default.green(`✅ API Key for ${provider} saved securely to vault.`));
109
+ console.log(picocolors_1.default.green(`✅ API Key for ${provider} saved successfully.`));
110
110
  process.exit(0);
111
111
  }
112
112
  // Check for wallet command
@@ -146,9 +146,9 @@ async function main() {
146
146
  // 2. Setup boilerplate files if in global mode and they don't exist
147
147
  let isFirstBoot = false;
148
148
  if (isGlobalMode) {
149
- const globalConfigPath = path_1.default.join(appDir, 'config.yaml');
150
- const globalUserMdPath = path_1.default.join(appDir, 'user.md');
151
- const globalIdentityMdPath = path_1.default.join(appDir, 'IDENTITY.md');
149
+ const globalConfigPath = (0, paths_1.getPath)('config.yaml');
150
+ const globalUserMdPath = (0, paths_1.getPath)('user.md');
151
+ const globalIdentityMdPath = (0, paths_1.getPath)('IDENTITY.md');
152
152
  // Copy default config.yaml
153
153
  if (!fs_1.default.existsSync(globalConfigPath)) {
154
154
  isFirstBoot = true;
@@ -157,7 +157,7 @@ async function main() {
157
157
  fs_1.default.copyFileSync(exampleConfigPath, globalConfigPath);
158
158
  }
159
159
  else {
160
- fs_1.default.writeFileSync(globalConfigPath, 'agent:\n name: Nyxora-Agent\n default_chain: base\nllm:\n provider: openai\n model: gpt-4o-mini\n temperature: 0.2\n api_keys: []\nmemory:\n type: file\n path: memory.json\n');
160
+ fs_1.default.writeFileSync(globalConfigPath, 'agent:\n name: Nyxora-Agent\n default_chain: base\nllm:\n provider: openai\n model: gpt-4\n temperature: 0.7\nmemory:\n type: file\n path: memory.json\n');
161
161
  }
162
162
  }
163
163
  if (!fs_1.default.existsSync(globalUserMdPath)) {