nyxora 26.6.13 → 26.6.18
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.
- package/README.md +4 -3
- package/bin/nyxora.mjs +3 -4
- package/dist/launcher.js +18 -7
- package/dist/packages/core/src/agent/reasoning.js +21 -52
- package/dist/packages/core/src/config/parser.js +48 -11
- package/dist/packages/core/src/gateway/server.js +71 -9
- package/dist/packages/core/src/gateway/setup.js +5 -4
- package/dist/packages/core/src/gateway/telegram.js +9 -19
- package/dist/packages/core/src/system/skills/updateSecurityPolicy.js +17 -11
- package/dist/packages/core/src/utils/formatter.js +13 -18
- package/dist/packages/core/src/web3/skills/createMarketWatchAgent.js +51 -0
- package/dist/packages/core/src/web3/skills/getPrice.js +1 -1
- package/dist/packages/core/src/web3/skills/marketAnalysis.js +208 -47
- package/dist/packages/core/src/web3/utils/riskIntelligence.js +110 -0
- package/dist/packages/policy/src/server.js +38 -3
- package/dist/packages/signer/src/server.js +2 -2
- package/launcher.ts +18 -7
- package/package.json +5 -7
- package/packages/core/package.json +1 -2
- package/packages/core/src/agent/reasoning.ts +24 -50
- package/packages/core/src/config/parser.ts +49 -22
- package/packages/core/src/gateway/server.ts +76 -10
- package/packages/core/src/gateway/setup.ts +6 -5
- package/packages/core/src/gateway/telegram.ts +9 -19
- package/packages/core/src/system/skills/updateSecurityPolicy.ts +18 -11
- package/packages/core/src/utils/formatter.ts +13 -17
- package/packages/core/src/web3/skills/createMarketWatchAgent.ts +59 -0
- package/packages/core/src/web3/skills/getPrice.ts +1 -1
- package/packages/core/src/web3/skills/marketAnalysis.ts +209 -49
- package/packages/core/src/web3/utils/riskIntelligence.ts +118 -0
- package/packages/dashboard/dist/assets/index-BAXifdMN.js +16 -0
- package/packages/dashboard/dist/index.html +1 -1
- package/packages/dashboard/package.json +1 -1
- package/packages/mcp-server/dist/server.js +110 -0
- package/packages/mcp-server/package.json +1 -1
- package/packages/policy/package.json +1 -1
- package/packages/policy/src/server.ts +41 -4
- package/packages/signer/package.json +1 -1
- package/packages/signer/src/server.ts +2 -2
- package/packages/core/src/system/pluginManager.ts +0 -106
- package/packages/core/src/system/skills/installSkill.ts +0 -51
- package/packages/dashboard/dist/assets/index-BhKhEfi_.js +0 -13
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ It operates under a **Zero-Trust, Defense-in-Depth Cryptographically Bound Human
|
|
|
25
25
|
* **DeFi Configuration BYOK & UI Masking**: All aggregator and provider API keys are strictly isolated via a Bring Your Own Keys (BYOK) architecture into a heavily guarded `~/.nyxora/defi_keys.yaml` file. The local web Dashboard masks these injected secrets using `***********` and `IS_SET` censorship, completely neutralizing malicious browser extensions from exfiltrating your keys.
|
|
26
26
|
* **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.
|
|
27
27
|
* **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.
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
* **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.
|
|
30
30
|
|
|
31
31
|
### 🌐 Web3 Skills (On-Chain)
|
|
@@ -34,7 +34,8 @@ It operates under a **Zero-Trust, Defense-in-Depth Cryptographically Bound Human
|
|
|
34
34
|
* **6-Engine Meta-Aggregator & Anti-MEV**: The core engine interfaces with a powerful 6-Engine Meta-Aggregator (**1inch, 0x, LI.FI, Relay, OpenOcean, and KyberSwap**) to route tokens cross-chain, ensuring absolute maximum liquidity depth.
|
|
35
35
|
* **Adaptive Auto Slippage Protection**: Nyxora enforces a dynamic and adaptive **'auto' slippage** by default to leverage dynamic MEV-protection from these industry-standard aggregators. However, the user retains absolute control to override this dynamically—either globally via the Dashboard Settings or on a per-transaction basis through NLP chat commands (e.g., *"Swap 1 ETH to PEPE with 10% slippage"*).
|
|
36
36
|
|
|
37
|
-
* **
|
|
37
|
+
* **Dual-Routing Market Intelligence Engine**: Real-time asset tracking utilizing a sophisticated API Waterfall. Symbol queries are routed to CoinGecko/CEXs for global FDV, while Contract Addresses trigger DexScreener for live on-chain liquidity metrics across all networks.
|
|
38
|
+
* **Asynchronous Watchdog Agents**: Seamlessly spawn detached background instances for long-running monitoring tasks (e.g., *"Notify me when $ETH drops below $2500"*), leaving your primary chat session free for other operations.
|
|
38
39
|
* **"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.
|
|
39
40
|
* **Dynamic Portfolio Engine**: Merges standard tokens, your custom Degen CAs, and CoinGecko's daily trending list into a single hyper-fast Multicall scan to deliver a clean, spam-free PnL portfolio report in under 1 second.
|
|
40
41
|
* **Deep Transaction History**: Accurately fetch your 30-day (or custom timeframe) Native and ERC-20 transaction history across all supported EVM chains. Powered by the Unified Etherscan API V2, enabling seamless cross-chain fetching (Mainnets & Testnets) using a single API key.
|
|
@@ -171,7 +172,7 @@ For complete technical deep-dives into our Cryptographic Architecture, please vi
|
|
|
171
172
|
**❤️ Support the Project**
|
|
172
173
|
|
|
173
174
|
Building and maintaining a highly secure, zero-trust architecture takes significant time and resources. If you love what we are building, you can help us keep Nyxora open, secure, and constantly evolving by sending a coffee our way:
|
|
174
|
-
- **EVM:** `
|
|
175
|
+
- **EVM (Multi-Sig Safe):** `0x490717E50D6434C348AA0D2bD5fe682392823708`
|
|
175
176
|
|
|
176
177
|
---
|
|
177
178
|
**License:** MIT License
|
package/bin/nyxora.mjs
CHANGED
|
@@ -15,9 +15,9 @@ const pidFile = path.join(appDir, 'run', 'daemon.pid');
|
|
|
15
15
|
const logFile = path.join(appDir, 'run', 'gateway.log');
|
|
16
16
|
const tokenFile = path.join(appDir, 'auth', 'auth.token');
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
fs.mkdirSync(
|
|
20
|
-
}
|
|
18
|
+
[path.join(appDir, 'run'), path.join(appDir, 'auth')].forEach(dir => {
|
|
19
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
20
|
+
});
|
|
21
21
|
|
|
22
22
|
const command = process.argv[2];
|
|
23
23
|
|
|
@@ -291,7 +291,6 @@ async function unlock() {
|
|
|
291
291
|
} catch (e) {}
|
|
292
292
|
}
|
|
293
293
|
try {
|
|
294
|
-
const fetch = (await import('node-fetch')).default;
|
|
295
294
|
const res = await fetch('http://localhost:3000/api/status/unlock', {
|
|
296
295
|
method: 'POST',
|
|
297
296
|
headers: {
|
package/dist/launcher.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
// @ts-ignore
|
|
6
7
|
const safeLogger_1 = require("./packages/core/src/utils/safeLogger");
|
|
7
8
|
(0, safeLogger_1.initSafeLogger)();
|
|
8
9
|
const child_process_1 = require("child_process");
|
|
@@ -36,7 +37,15 @@ const spawnService = (name, command, args, env, inheritStdio = false) => {
|
|
|
36
37
|
child = (0, child_process_1.spawn)(command, args, { env, stdio: inheritStdio ? 'inherit' : 'pipe' });
|
|
37
38
|
if (!inheritStdio) {
|
|
38
39
|
child.stdout?.on('data', (data) => process.stdout.write(`[${name}] ${data}`));
|
|
39
|
-
child.stderr?.on('data', (data) =>
|
|
40
|
+
child.stderr?.on('data', (data) => {
|
|
41
|
+
const msg = data.toString();
|
|
42
|
+
if (msg.toLowerCase().includes('warn')) {
|
|
43
|
+
process.stderr.write(`[${name}] ${msg}`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
process.stderr.write(`[${name}] ERROR: ${msg}`);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
40
49
|
}
|
|
41
50
|
child.on('close', async (code) => {
|
|
42
51
|
console.log(`[${name}] Exited with code ${code}`);
|
|
@@ -99,19 +108,21 @@ if (fs_1.default.existsSync(socketPath)) {
|
|
|
99
108
|
fs_1.default.unlinkSync(socketPath);
|
|
100
109
|
}
|
|
101
110
|
const children = [];
|
|
102
|
-
const
|
|
111
|
+
const __filenameResolved = __filename;
|
|
112
|
+
const __dirnameResolved = __dirname;
|
|
113
|
+
const isCompiled = __filenameResolved.endsWith('.js');
|
|
103
114
|
const ext = isCompiled ? '.js' : '.ts';
|
|
104
|
-
const cmd = isCompiled ? 'node' : '
|
|
105
|
-
const baseArgs = isCompiled ? [] : ['
|
|
106
|
-
const signerPath = path_1.default.join(
|
|
115
|
+
const cmd = isCompiled ? 'node' : path_1.default.join(__dirnameResolved, 'node_modules', '.bin', 'ts-node');
|
|
116
|
+
const baseArgs = isCompiled ? [] : ['-T'];
|
|
117
|
+
const signerPath = path_1.default.join(__dirnameResolved, `packages/signer/src/server${ext}`);
|
|
107
118
|
const signer = spawnService('Signer', cmd, [...baseArgs, signerPath], env);
|
|
108
119
|
children.push(signer);
|
|
109
120
|
setTimeout(() => {
|
|
110
|
-
const policyPath = path_1.default.join(
|
|
121
|
+
const policyPath = path_1.default.join(__dirnameResolved, `packages/policy/src/server${ext}`);
|
|
111
122
|
const policy = spawnService('Policy', cmd, [...baseArgs, policyPath], env);
|
|
112
123
|
children.push(policy);
|
|
113
124
|
setTimeout(() => {
|
|
114
|
-
const corePath = path_1.default.join(
|
|
125
|
+
const corePath = path_1.default.join(__dirnameResolved, `packages/core/src/gateway/cli${ext}`);
|
|
115
126
|
const args = process.argv.slice(2);
|
|
116
127
|
const core = spawnService('Core', cmd, [...baseArgs, corePath, ...args], env, true);
|
|
117
128
|
children.push(core);
|
|
@@ -22,6 +22,7 @@ const mintNft_1 = require("../web3/skills/mintNft");
|
|
|
22
22
|
const customTx_1 = require("../web3/skills/customTx");
|
|
23
23
|
const checkSecurity_1 = require("../web3/skills/checkSecurity");
|
|
24
24
|
const marketAnalysis_1 = require("../web3/skills/marketAnalysis");
|
|
25
|
+
const createMarketWatchAgent_1 = require("../web3/skills/createMarketWatchAgent");
|
|
25
26
|
const checkPortfolio_1 = require("../web3/skills/checkPortfolio");
|
|
26
27
|
const checkAddress_1 = require("../web3/skills/checkAddress");
|
|
27
28
|
const getMyAddress_1 = require("../web3/skills/getMyAddress");
|
|
@@ -41,7 +42,6 @@ const generateExcel_1 = require("../system/skills/generateExcel");
|
|
|
41
42
|
const executeShell_1 = require("../system/skills/executeShell");
|
|
42
43
|
const browseWeb_1 = require("../system/skills/browseWeb");
|
|
43
44
|
const searchWeb_1 = require("../system/skills/searchWeb");
|
|
44
|
-
const installSkill_1 = require("../system/skills/installSkill");
|
|
45
45
|
const editFile_1 = require("../system/skills/editFile");
|
|
46
46
|
const gitManager_1 = require("../system/skills/gitManager");
|
|
47
47
|
const xManager_1 = require("../system/skills/xManager");
|
|
@@ -49,7 +49,6 @@ const notionWorkspace_1 = require("../system/skills/notionWorkspace");
|
|
|
49
49
|
const audioTranscribe_1 = require("../system/skills/audioTranscribe");
|
|
50
50
|
const summarizeText_1 = require("../system/skills/summarizeText");
|
|
51
51
|
const googleWorkspace_1 = require("../system/skills/googleWorkspace");
|
|
52
|
-
const pluginManager_1 = require("../system/pluginManager");
|
|
53
52
|
const paths_1 = require("../config/paths");
|
|
54
53
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
55
54
|
exports.logger = new logger_1.Logger();
|
|
@@ -134,7 +133,7 @@ IMPORTANT: The <think> block is strictly for your internal hidden monologue. NEV
|
|
|
134
133
|
|
|
135
134
|
[EXECUTION WORKFLOW]
|
|
136
135
|
CRITICAL RULE 1: NEVER expose internal JSON tool calls to the user. Always parse them and explain the outcome naturally.
|
|
137
|
-
CRITICAL RULE 2: STRICT LANGUAGE MATCHING. You MUST strictly reply in the exact same language as the user's LATEST prompt.
|
|
136
|
+
CRITICAL RULE 2: STRICT LANGUAGE MATCHING. You MUST strictly reply in the exact same language as the user's LATEST prompt. Render all output, metric labels, and suggested actions entirely in the language the user initiated the prompt with, while strictly preserving the visual structure of the progress bars.
|
|
138
137
|
CRITICAL RULE 3: FORMATTING & CONCISENESS. Provide concise analytical summaries of data rather than just dumping raw markdown tables. Be analytical but brief. Use commas for thousands.
|
|
139
138
|
CRITICAL RULE 4: TOOL PRIORITIZATION. Web3 tasks must use Web3 Skills exclusively. OS Skills (search, browse) are fallbacks only. Use get_my_address to show wallet address, and check_portfolio to show balances.
|
|
140
139
|
CRITICAL RULE 5: DEFAULT CHAIN HANDLING. Default to: ${config.agent.default_chain} unless specified. If overridden, confirm the chain politely. For 2-chain txs (bridge), default source to ${config.agent.default_chain}.
|
|
@@ -174,16 +173,20 @@ CRITICAL RULE 19: MARKET CONFIDENCE SCORE. When analyzing market data, token sec
|
|
|
174
173
|
catch (error) {
|
|
175
174
|
console.error('Failed to read user.md:', error);
|
|
176
175
|
}
|
|
177
|
-
// Read
|
|
176
|
+
// Read policy.yaml for NLP security constraints
|
|
178
177
|
try {
|
|
179
|
-
const policyPath = (0, paths_1.getPath)('
|
|
178
|
+
const policyPath = (0, paths_1.getPath)('policy.yaml');
|
|
180
179
|
if (fs_1.default.existsSync(policyPath)) {
|
|
181
|
-
const
|
|
182
|
-
|
|
180
|
+
const yaml = require('yaml'); // lazily import if not imported
|
|
181
|
+
const file = fs_1.default.readFileSync(policyPath, 'utf8');
|
|
182
|
+
const parsed = yaml.parse(file) || {};
|
|
183
|
+
if (parsed.custom_llm_rules && Array.isArray(parsed.custom_llm_rules) && parsed.custom_llm_rules.length > 0) {
|
|
184
|
+
basePrompt += `\n\n--- SECURITY POLICY (MANDATORY RULES) ---\n${parsed.custom_llm_rules.map((r) => `* ${r}`).join('\n')}\n\nCRITICAL: If the user asks you to perform an action that violates the Security Policy above, YOU MUST NOT EXECUTE IT DIRECTLY. Instead, ask for their explicit permission first.`;
|
|
185
|
+
}
|
|
183
186
|
}
|
|
184
187
|
}
|
|
185
188
|
catch (error) {
|
|
186
|
-
console.error('Failed to read
|
|
189
|
+
console.error('Failed to read policy.yaml:', error);
|
|
187
190
|
}
|
|
188
191
|
// Inject Episodic Memories (Smart Suggestions Context)
|
|
189
192
|
try {
|
|
@@ -250,19 +253,19 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
250
253
|
const hasGoogleKeyword = /email|gmail|calendar|sheet|doc|form|event/i.test(lowerInput);
|
|
251
254
|
let tools = [];
|
|
252
255
|
if ((0, skillManager_1.isSkillActive)('web3')) {
|
|
253
|
-
tools.push(getBalance_1.getBalanceToolDefinition, transfer_1.transferToolDefinition, getPrice_1.getPriceToolDefinition, swapToken_1.swapTokenToolDefinition, bridgeToken_1.bridgeTokenToolDefinition, mintNft_1.mintNftToolDefinition, customTx_1.customTxToolDefinition, checkSecurity_1.checkSecurityToolDefinition, marketAnalysis_1.marketAnalysisToolDefinition, checkPortfolio_1.checkPortfolioToolDefinition, checkAddress_1.checkAddressToolDefinition, getMyAddress_1.getMyAddressToolDefinition, manageCustomTokens_1.manageCustomTokensDefinition, revokeApprovals_1.revokeApprovalToolDefinition, defiLending_1.aaveSupplyToolDefinition, yieldVault_1.vaultDepositToolDefinition, provideLiquidity_1.provideLiquidityToolDefinition, getTxHistory_1.getTxHistoryToolDefinition, createLimitOrder_1.createLimitOrderToolDefinition);
|
|
256
|
+
tools.push(getBalance_1.getBalanceToolDefinition, transfer_1.transferToolDefinition, getPrice_1.getPriceToolDefinition, swapToken_1.swapTokenToolDefinition, bridgeToken_1.bridgeTokenToolDefinition, mintNft_1.mintNftToolDefinition, customTx_1.customTxToolDefinition, checkSecurity_1.checkSecurityToolDefinition, marketAnalysis_1.marketAnalysisToolDefinition, createMarketWatchAgent_1.createMarketWatchAgentToolDefinition, checkPortfolio_1.checkPortfolioToolDefinition, checkAddress_1.checkAddressToolDefinition, getMyAddress_1.getMyAddressToolDefinition, manageCustomTokens_1.manageCustomTokensDefinition, revokeApprovals_1.revokeApprovalToolDefinition, defiLending_1.aaveSupplyToolDefinition, yieldVault_1.vaultDepositToolDefinition, provideLiquidity_1.provideLiquidityToolDefinition, getTxHistory_1.getTxHistoryToolDefinition, createLimitOrder_1.createLimitOrderToolDefinition);
|
|
254
257
|
}
|
|
255
|
-
const SYSTEM_TOOLS = [updateProfile_1.updateProfileToolDefinition, updateSecurityPolicy_1.updateSecurityPolicyToolDefinition, analyzeDocument_1.analyzeDocumentToolDefinition, readFile_1.readLocalFileToolDefinition, writeFile_1.writeLocalFileToolDefinition, generateExcel_1.generateExcelToolDefinition, executeShell_1.runTerminalCommandToolDefinition, browseWeb_1.browseWebsiteToolDefinition, searchWeb_1.searchWebToolDefinition,
|
|
258
|
+
const SYSTEM_TOOLS = [updateProfile_1.updateProfileToolDefinition, updateSecurityPolicy_1.updateSecurityPolicyToolDefinition, analyzeDocument_1.analyzeDocumentToolDefinition, readFile_1.readLocalFileToolDefinition, writeFile_1.writeLocalFileToolDefinition, generateExcel_1.generateExcelToolDefinition, executeShell_1.runTerminalCommandToolDefinition, browseWeb_1.browseWebsiteToolDefinition, searchWeb_1.searchWebToolDefinition, editFile_1.editLocalFileToolDefinition, gitManager_1.gitManagerToolDefinition, xManager_1.xManagerToolDefinition, notionWorkspace_1.notionWorkspaceToolDefinition, audioTranscribe_1.audioTranscribeToolDefinition, summarizeText_1.summarizeTextToolDefinition];
|
|
256
259
|
const GOOGLE_TOOLS = [googleWorkspace_1.readGmailInboxToolDefinition, googleWorkspace_1.listCalendarEventsToolDefinition, googleWorkspace_1.appendRowToSheetsToolDefinition, googleWorkspace_1.readGoogleDocsToolDefinition, googleWorkspace_1.readGoogleFormResponsesToolDefinition];
|
|
257
260
|
let activeTools = [];
|
|
258
261
|
if (hasGoogleKeyword && !hasWeb3Keyword) {
|
|
259
|
-
activeTools = [...GOOGLE_TOOLS, ...SYSTEM_TOOLS
|
|
262
|
+
activeTools = [...GOOGLE_TOOLS, ...SYSTEM_TOOLS];
|
|
260
263
|
}
|
|
261
264
|
else if (hasWeb3Keyword && !hasGoogleKeyword) {
|
|
262
|
-
activeTools = [...tools, ...SYSTEM_TOOLS
|
|
265
|
+
activeTools = [...tools, ...SYSTEM_TOOLS];
|
|
263
266
|
}
|
|
264
267
|
else {
|
|
265
|
-
activeTools = [...tools, ...SYSTEM_TOOLS, ...GOOGLE_TOOLS
|
|
268
|
+
activeTools = [...tools, ...SYSTEM_TOOLS, ...GOOGLE_TOOLS];
|
|
266
269
|
}
|
|
267
270
|
activeTools = activeTools.filter(t => (0, skillManager_1.isSkillActive)(t.function.name));
|
|
268
271
|
const response = await executeWithRetry(async (client) => {
|
|
@@ -323,10 +326,6 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
323
326
|
}
|
|
324
327
|
case 'transfer_token':
|
|
325
328
|
case 'transfer_native': {
|
|
326
|
-
if (config.permissions?.web3?.allow_transfer === false) {
|
|
327
|
-
result = `[Security Blocked] Runtime Permission Denied: Web3 transfers are disabled. Update config.yaml to allow.`;
|
|
328
|
-
break;
|
|
329
|
-
}
|
|
330
329
|
result = await (0, transfer_1.prepareTransfer)(args.chainName, args.toAddress, args.amountStr || args.amountEth, args.token);
|
|
331
330
|
break;
|
|
332
331
|
}
|
|
@@ -335,18 +334,10 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
335
334
|
break;
|
|
336
335
|
}
|
|
337
336
|
case 'swap_token': {
|
|
338
|
-
if (config.permissions?.web3?.allow_swap === false) {
|
|
339
|
-
result = `[Security Blocked] Runtime Permission Denied: Web3 swaps are disabled. Update config.yaml to allow.`;
|
|
340
|
-
break;
|
|
341
|
-
}
|
|
342
337
|
result = await (0, swapToken_1.prepareSwapToken)(args.chainName, args.fromToken, args.toToken, args.amountStr || args.amount, args.mode, args.providerName);
|
|
343
338
|
break;
|
|
344
339
|
}
|
|
345
340
|
case 'bridge_token': {
|
|
346
|
-
if (config.permissions?.web3?.allow_transfer === false) {
|
|
347
|
-
result = `[Security Blocked] Runtime Permission Denied: Web3 bridging (transfer) is disabled. Update config.yaml to allow.`;
|
|
348
|
-
break;
|
|
349
|
-
}
|
|
350
341
|
result = await (0, bridgeToken_1.prepareBridgeToken)(args.fromChain, args.toChain, args.tokenSymbol, args.amountStr, args.mode, args.providerName);
|
|
351
342
|
break;
|
|
352
343
|
}
|
|
@@ -355,10 +346,6 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
355
346
|
break;
|
|
356
347
|
}
|
|
357
348
|
case 'custom_tx': {
|
|
358
|
-
if (config.permissions?.web3?.allow_transfer === false) {
|
|
359
|
-
result = `[Security Blocked] Runtime Permission Denied: Custom transactions are blocked because transfers are disabled.`;
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
362
349
|
result = await (0, customTx_1.prepareCustomTx)(args.chainName, args.toAddress, args.dataHex, args.valueEth, args.gasLimitStr);
|
|
363
350
|
break;
|
|
364
351
|
}
|
|
@@ -370,6 +357,10 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
370
357
|
result = await (0, marketAnalysis_1.analyzeMarket)(args.chainName, args.tokenAddressOrSymbol);
|
|
371
358
|
break;
|
|
372
359
|
}
|
|
360
|
+
case 'create_market_watch_agent': {
|
|
361
|
+
result = await (0, createMarketWatchAgent_1.createMarketWatchAgent)(args.chainName, args.contractAddress, args.rules, args.durationDays);
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
373
364
|
case 'check_portfolio': {
|
|
374
365
|
result = await (0, checkPortfolio_1.checkPortfolio)(args.chainName, args.address);
|
|
375
366
|
break;
|
|
@@ -451,26 +442,14 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
451
442
|
break;
|
|
452
443
|
}
|
|
453
444
|
case 'write_local_file': {
|
|
454
|
-
if (config.permissions?.system?.allow_file_write === false) {
|
|
455
|
-
result = `[Security Blocked] Runtime Permission Denied: File writing is disabled. Update config.yaml to allow.`;
|
|
456
|
-
break;
|
|
457
|
-
}
|
|
458
445
|
result = (0, writeFile_1.writeLocalFile)(args.filePath, args.content);
|
|
459
446
|
break;
|
|
460
447
|
}
|
|
461
448
|
case 'generate_excel_file': {
|
|
462
|
-
if (config.permissions?.system?.allow_file_write === false) {
|
|
463
|
-
result = `[Security Blocked] Runtime Permission Denied: File writing is disabled. Update config.yaml to allow.`;
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
449
|
result = await (0, generateExcel_1.generateExcelFile)(args.data, args.filePath);
|
|
467
450
|
break;
|
|
468
451
|
}
|
|
469
452
|
case 'run_terminal_command': {
|
|
470
|
-
if (config.permissions?.system?.allow_shell_execution === false) {
|
|
471
|
-
result = `[Security Blocked] Runtime Permission Denied: Shell execution is disabled. Update config.yaml to allow.`;
|
|
472
|
-
break;
|
|
473
|
-
}
|
|
474
453
|
result = await (0, executeShell_1.runTerminalCommand)(args.command);
|
|
475
454
|
break;
|
|
476
455
|
}
|
|
@@ -482,10 +461,6 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
482
461
|
result = await (0, searchWeb_1.searchWeb)(args.query, args.depth);
|
|
483
462
|
break;
|
|
484
463
|
}
|
|
485
|
-
case 'install_external_skill': {
|
|
486
|
-
result = await (0, installSkill_1.installExternalSkill)(args.url);
|
|
487
|
-
break;
|
|
488
|
-
}
|
|
489
464
|
case 'read_gmail_inbox': {
|
|
490
465
|
result = await (0, googleWorkspace_1.readGmailInbox)(args.maxResults);
|
|
491
466
|
break;
|
|
@@ -507,13 +482,7 @@ async function processUserInput(input, role = 'user', onProgress, sessionId) {
|
|
|
507
482
|
break;
|
|
508
483
|
}
|
|
509
484
|
default: {
|
|
510
|
-
|
|
511
|
-
if (externalResult !== null) {
|
|
512
|
-
result = externalResult;
|
|
513
|
-
}
|
|
514
|
-
else {
|
|
515
|
-
result = `Error: Tool ${toolName} is not implemented.`;
|
|
516
|
-
}
|
|
485
|
+
result = `Error: Tool ${toolName} is not implemented.`;
|
|
517
486
|
break;
|
|
518
487
|
}
|
|
519
488
|
}
|
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadRpcConfig = loadRpcConfig;
|
|
7
|
+
exports.saveRpcConfig = saveRpcConfig;
|
|
6
8
|
exports.loadApiKeys = loadApiKeys;
|
|
7
9
|
exports.saveApiKeys = saveApiKeys;
|
|
8
10
|
exports.loadConfig = loadConfig;
|
|
@@ -10,6 +12,27 @@ exports.saveConfig = saveConfig;
|
|
|
10
12
|
const fs_1 = __importDefault(require("fs"));
|
|
11
13
|
const yaml_1 = __importDefault(require("yaml"));
|
|
12
14
|
const paths_1 = require("./paths");
|
|
15
|
+
function loadRpcConfig() {
|
|
16
|
+
const rpcPath = (0, paths_1.getPath)('rpc_key.yaml');
|
|
17
|
+
if (fs_1.default.existsSync(rpcPath)) {
|
|
18
|
+
try {
|
|
19
|
+
return yaml_1.default.parse(fs_1.default.readFileSync(rpcPath, 'utf8')) || {};
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.error('[Config] Failed to parse rpc_key.yaml', e);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
function saveRpcConfig(rpcUrls) {
|
|
28
|
+
const rpcPath = (0, paths_1.getPath)('rpc_key.yaml');
|
|
29
|
+
try {
|
|
30
|
+
fs_1.default.writeFileSync(rpcPath, yaml_1.default.stringify(rpcUrls), 'utf8');
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Failed to save rpc_key.yaml', error);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
13
36
|
async function loadApiKeys() {
|
|
14
37
|
const config = loadConfig();
|
|
15
38
|
return config.credentials || {};
|
|
@@ -23,6 +46,8 @@ async function saveApiKeys(newKeys) {
|
|
|
23
46
|
}
|
|
24
47
|
function loadConfig() {
|
|
25
48
|
const configPath = (0, paths_1.getPath)('config.yaml');
|
|
49
|
+
const rpcPath = (0, paths_1.getPath)('rpc_key.yaml');
|
|
50
|
+
let rpcUrls = loadRpcConfig();
|
|
26
51
|
try {
|
|
27
52
|
const file = fs_1.default.readFileSync(configPath, 'utf8');
|
|
28
53
|
const parsed = yaml_1.default.parse(file);
|
|
@@ -41,6 +66,22 @@ function loadConfig() {
|
|
|
41
66
|
delete parsed.llm.credentials;
|
|
42
67
|
needsSave = true;
|
|
43
68
|
}
|
|
69
|
+
// Ensure we don't accidentally overwrite rpc_key.yaml with old config.yaml data.
|
|
70
|
+
if (parsed.web3 && parsed.web3.rpc_urls) {
|
|
71
|
+
delete parsed.web3.rpc_urls;
|
|
72
|
+
needsSave = true;
|
|
73
|
+
}
|
|
74
|
+
// Auto-migration logic: move permissions to policy.yaml
|
|
75
|
+
const policyPath = (0, paths_1.getPath)('policy.yaml');
|
|
76
|
+
if (!fs_1.default.existsSync(policyPath)) {
|
|
77
|
+
const defaultPolicy = `max_usd_per_tx: ${parsed.permissions?.web3?.max_usd_per_tx || 999999999}\nwhitelist_only: false\nrequire_approval: true\n`;
|
|
78
|
+
fs_1.default.writeFileSync(policyPath, defaultPolicy, 'utf8');
|
|
79
|
+
console.log('[Config] Created default policy.yaml.');
|
|
80
|
+
}
|
|
81
|
+
if (parsed.permissions) {
|
|
82
|
+
delete parsed.permissions;
|
|
83
|
+
needsSave = true;
|
|
84
|
+
}
|
|
44
85
|
if (needsSave) {
|
|
45
86
|
try {
|
|
46
87
|
const yamlStr = yaml_1.default.stringify(parsed);
|
|
@@ -65,13 +106,9 @@ function loadConfig() {
|
|
|
65
106
|
},
|
|
66
107
|
credentials: parsed.credentials || {},
|
|
67
108
|
memory: parsed.memory || { type: 'file', path: './memory.json' },
|
|
68
|
-
web3: parsed.web3
|
|
109
|
+
web3: { ...parsed.web3, rpc_urls: rpcUrls },
|
|
69
110
|
integrations: parsed.integrations || {
|
|
70
111
|
telegram: { enabled: false }
|
|
71
|
-
},
|
|
72
|
-
permissions: parsed.permissions || {
|
|
73
|
-
web3: { allow_transfer: true, allow_swap: true, max_usd_per_tx: 999999999 },
|
|
74
|
-
system: { allow_shell_execution: true, allow_file_write: true }
|
|
75
112
|
}
|
|
76
113
|
};
|
|
77
114
|
}
|
|
@@ -102,13 +139,9 @@ function loadConfig() {
|
|
|
102
139
|
},
|
|
103
140
|
credentials: {},
|
|
104
141
|
memory: { type: 'file', path: './memory.json' },
|
|
105
|
-
web3: { rpc_urls:
|
|
142
|
+
web3: { rpc_urls: rpcUrls },
|
|
106
143
|
integrations: {
|
|
107
144
|
telegram: { enabled: false }
|
|
108
|
-
},
|
|
109
|
-
permissions: {
|
|
110
|
-
web3: { allow_transfer: true, allow_swap: true, max_usd_per_tx: 999999999 },
|
|
111
|
-
system: { allow_shell_execution: true, allow_file_write: true }
|
|
112
145
|
}
|
|
113
146
|
};
|
|
114
147
|
}
|
|
@@ -116,7 +149,11 @@ function loadConfig() {
|
|
|
116
149
|
function saveConfig(newConfig) {
|
|
117
150
|
const configPath = (0, paths_1.getPath)('config.yaml');
|
|
118
151
|
try {
|
|
119
|
-
const
|
|
152
|
+
const configToSave = JSON.parse(JSON.stringify(newConfig));
|
|
153
|
+
if (configToSave.web3 && configToSave.web3.rpc_urls) {
|
|
154
|
+
delete configToSave.web3.rpc_urls;
|
|
155
|
+
}
|
|
156
|
+
const yamlStr = yaml_1.default.stringify(configToSave);
|
|
120
157
|
fs_1.default.writeFileSync(configPath, yamlStr, 'utf8');
|
|
121
158
|
}
|
|
122
159
|
catch (error) {
|
|
@@ -21,6 +21,7 @@ const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
|
|
|
21
21
|
const paths_1 = require("../config/paths");
|
|
22
22
|
const state_1 = require("../utils/state");
|
|
23
23
|
const fs_1 = __importDefault(require("fs"));
|
|
24
|
+
const yaml_1 = __importDefault(require("yaml"));
|
|
24
25
|
const reasoning_1 = require("../agent/reasoning");
|
|
25
26
|
const parser_1 = require("../config/parser");
|
|
26
27
|
const defiConfigManager_1 = require("../config/defiConfigManager");
|
|
@@ -28,7 +29,6 @@ const config_1 = require("../web3/config");
|
|
|
28
29
|
const tokens_1 = require("../web3/utils/tokens");
|
|
29
30
|
const tracker_1 = require("./tracker");
|
|
30
31
|
const transactionManager_1 = require("../agent/transactionManager");
|
|
31
|
-
const pluginManager_1 = require("../system/pluginManager");
|
|
32
32
|
const transfer_1 = require("../web3/skills/transfer");
|
|
33
33
|
const swapToken_1 = require("../web3/skills/swapToken");
|
|
34
34
|
const getBalance_1 = require("../web3/skills/getBalance");
|
|
@@ -55,7 +55,6 @@ const createLimitOrder_1 = require("../web3/skills/createLimitOrder");
|
|
|
55
55
|
// System Skills
|
|
56
56
|
const browseWeb_1 = require("../system/skills/browseWeb");
|
|
57
57
|
const executeShell_1 = require("../system/skills/executeShell");
|
|
58
|
-
const installSkill_1 = require("../system/skills/installSkill");
|
|
59
58
|
const readFile_1 = require("../system/skills/readFile");
|
|
60
59
|
const editFile_1 = require("../system/skills/editFile");
|
|
61
60
|
const gitManager_1 = require("../system/skills/gitManager");
|
|
@@ -264,6 +263,26 @@ app.post('/api/config', (req, res) => {
|
|
|
264
263
|
res.status(500).json({ error: error.message });
|
|
265
264
|
}
|
|
266
265
|
});
|
|
266
|
+
app.get('/api/rpc', (req, res) => {
|
|
267
|
+
try {
|
|
268
|
+
const rpcConfig = (0, parser_1.loadRpcConfig)();
|
|
269
|
+
res.json(rpcConfig);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
res.status(500).json({ error: error.message });
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
app.post('/api/rpc', (req, res) => {
|
|
276
|
+
try {
|
|
277
|
+
const currentRpc = (0, parser_1.loadRpcConfig)();
|
|
278
|
+
const newRpc = { ...currentRpc, ...req.body };
|
|
279
|
+
(0, parser_1.saveRpcConfig)(newRpc);
|
|
280
|
+
res.json({ success: true });
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
res.status(500).json({ error: error.message });
|
|
284
|
+
}
|
|
285
|
+
});
|
|
267
286
|
app.get('/api/defi-keys', (req, res) => {
|
|
268
287
|
try {
|
|
269
288
|
const keys = (0, defiConfigManager_1.loadDefiKeys)();
|
|
@@ -329,7 +348,6 @@ app.get('/api/skills/system', (req, res) => {
|
|
|
329
348
|
generateExcel_1.generateExcelToolDefinition,
|
|
330
349
|
browseWeb_1.browseWebsiteToolDefinition,
|
|
331
350
|
updateSecurityPolicy_1.updateSecurityPolicyToolDefinition,
|
|
332
|
-
installSkill_1.installExternalSkillToolDefinition,
|
|
333
351
|
analyzeDocument_1.analyzeDocumentToolDefinition,
|
|
334
352
|
searchWeb_1.searchWebToolDefinition,
|
|
335
353
|
googleWorkspace_1.readGmailInboxToolDefinition,
|
|
@@ -782,6 +800,46 @@ app.delete('/api/memory/:id', (req, res) => {
|
|
|
782
800
|
res.status(500).json({ error: error.message });
|
|
783
801
|
}
|
|
784
802
|
});
|
|
803
|
+
// --- Policy Engine Endpoints ---
|
|
804
|
+
app.get('/api/policy', (req, res) => {
|
|
805
|
+
try {
|
|
806
|
+
const policyPath = (0, paths_1.getPath)('policy.yaml');
|
|
807
|
+
if (!fs_1.default.existsSync(policyPath)) {
|
|
808
|
+
return res.json({
|
|
809
|
+
max_usd_per_tx: 999999999,
|
|
810
|
+
whitelist_only: false,
|
|
811
|
+
require_approval: true,
|
|
812
|
+
custom_llm_rules: []
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
const file = fs_1.default.readFileSync(policyPath, 'utf8');
|
|
816
|
+
const parsed = yaml_1.default.parse(file) || {};
|
|
817
|
+
res.json({
|
|
818
|
+
max_usd_per_tx: parsed.max_usd_per_tx ?? 999999999,
|
|
819
|
+
whitelist_only: parsed.whitelist_only ?? false,
|
|
820
|
+
require_approval: parsed.require_approval ?? true,
|
|
821
|
+
custom_llm_rules: parsed.custom_llm_rules || []
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
catch (error) {
|
|
825
|
+
res.status(500).json({ error: error.message });
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
app.post('/api/policy', (req, res) => {
|
|
829
|
+
try {
|
|
830
|
+
const policyPath = (0, paths_1.getPath)('policy.yaml');
|
|
831
|
+
let current = {};
|
|
832
|
+
if (fs_1.default.existsSync(policyPath)) {
|
|
833
|
+
current = yaml_1.default.parse(fs_1.default.readFileSync(policyPath, 'utf8')) || {};
|
|
834
|
+
}
|
|
835
|
+
const updated = { ...current, ...req.body };
|
|
836
|
+
fs_1.default.writeFileSync(policyPath, yaml_1.default.stringify(updated), 'utf8');
|
|
837
|
+
res.json({ success: true });
|
|
838
|
+
}
|
|
839
|
+
catch (error) {
|
|
840
|
+
res.status(500).json({ error: error.message });
|
|
841
|
+
}
|
|
842
|
+
});
|
|
785
843
|
// --- User Persona / Risk Profile Endpoints (V3) ---
|
|
786
844
|
app.get('/api/profile', (req, res) => {
|
|
787
845
|
try {
|
|
@@ -842,9 +900,6 @@ async function autoMigrateKeys() {
|
|
|
842
900
|
}
|
|
843
901
|
function startServer() {
|
|
844
902
|
autoMigrateKeys().catch(e => console.error('[Auto-Migrate] Error:', e));
|
|
845
|
-
pluginManager_1.pluginManager.loadPlugins().then(() => {
|
|
846
|
-
console.log(`[PluginManager] Finished loading external skills.`);
|
|
847
|
-
});
|
|
848
903
|
const PORT = Number(process.env.PORT || 3000);
|
|
849
904
|
const server = app.listen(PORT, '127.0.0.1', () => {
|
|
850
905
|
console.log(`🤖 Nyxora API Server running on port ${PORT}`);
|
|
@@ -865,18 +920,25 @@ function startServer() {
|
|
|
865
920
|
process.exit(1);
|
|
866
921
|
}
|
|
867
922
|
});
|
|
923
|
+
let isShuttingDown = false;
|
|
868
924
|
const gracefulShutdown = () => {
|
|
925
|
+
if (isShuttingDown)
|
|
926
|
+
return;
|
|
927
|
+
isShuttingDown = true;
|
|
869
928
|
console.log('[Nyxora Gateway] Received shutdown signal. Closing server...');
|
|
929
|
+
if (server.closeAllConnections) {
|
|
930
|
+
server.closeAllConnections();
|
|
931
|
+
}
|
|
870
932
|
server.close(() => {
|
|
871
933
|
console.log('[Nyxora Gateway] HTTP server closed.');
|
|
872
934
|
reasoning_1.logger.close();
|
|
873
935
|
process.exit(0);
|
|
874
936
|
});
|
|
875
|
-
// Force exit after
|
|
937
|
+
// Force exit after 3s if stuck
|
|
876
938
|
setTimeout(() => {
|
|
877
|
-
console.error('[Nyxora Gateway] Forced shutdown
|
|
939
|
+
console.error('[Nyxora Gateway] Forced shutdown.');
|
|
878
940
|
process.exit(1);
|
|
879
|
-
},
|
|
941
|
+
}, 3000).unref();
|
|
880
942
|
};
|
|
881
943
|
process.on('SIGTERM', gracefulShutdown);
|
|
882
944
|
process.on('SIGINT', gracefulShutdown);
|
|
@@ -289,9 +289,8 @@ Provider: ${config.llm.provider}`;
|
|
|
289
289
|
{ value: 'generateExcel', label: 'Generate Excel Reports' },
|
|
290
290
|
{ value: 'analyzeDocument', label: 'Analyze Docs (PDF/Word)' },
|
|
291
291
|
{ value: 'run_terminal', label: 'Run Terminal Command', hint: '⚠️ UNSAFE' },
|
|
292
|
-
{ value: 'installSkill', label: 'Install External Skills (Plugins)' },
|
|
293
292
|
{ value: 'gitManager', label: 'Git Operations (Commit/Push/Pull)' },
|
|
294
|
-
{ value: 'updateSecurityPolicy', label: 'Update
|
|
293
|
+
{ value: 'updateSecurityPolicy', label: 'Update policy.yaml rules', hint: 'safeguard' },
|
|
295
294
|
{ value: 'browseWeb', label: 'Browse & Scrape Webpages' },
|
|
296
295
|
{ value: 'searchWeb', label: 'Smart Web Search (Tavily/Brave)', hint: 'Requires API Key' },
|
|
297
296
|
{ value: 'googleWorkspace', label: 'Google Workspace (Gmail, Docs, Sheets, Forms)', hint: 'Requires OAuth' },
|
|
@@ -410,7 +409,9 @@ Provider: ${config.llm.provider}`;
|
|
|
410
409
|
config.web_search.enabled = false;
|
|
411
410
|
}
|
|
412
411
|
if (Object.keys(newApiKeys).length > 0) {
|
|
413
|
-
|
|
412
|
+
if (!config.credentials)
|
|
413
|
+
config.credentials = {};
|
|
414
|
+
config.credentials = { ...config.credentials, ...newApiKeys };
|
|
414
415
|
}
|
|
415
416
|
if (!config.integrations)
|
|
416
417
|
config.integrations = {};
|
|
@@ -433,7 +434,7 @@ Provider: ${config.llm.provider}`;
|
|
|
433
434
|
];
|
|
434
435
|
const allOsSkills = [
|
|
435
436
|
'readFile', 'writeFile', 'editFile', 'generateExcel', 'analyzeDocument',
|
|
436
|
-
'run_terminal', '
|
|
437
|
+
'run_terminal', 'gitManager', 'updateSecurityPolicy',
|
|
437
438
|
'browseWeb', 'searchWeb', 'googleWorkspace', 'notionWorkspace', 'xManager',
|
|
438
439
|
'audioTranscribe', 'summarizeText'
|
|
439
440
|
];
|
|
@@ -64,13 +64,13 @@ function startTelegramBot() {
|
|
|
64
64
|
generatedPin = Math.floor(100000 + Math.random() * 900000).toString();
|
|
65
65
|
pinExpiry = Date.now() + 5 * 60 * 1000; // 5 minutes TTL
|
|
66
66
|
console.log(picocolors_1.default.yellow('\n==================================================='));
|
|
67
|
-
console.log(picocolors_1.default.yellow('🔐
|
|
67
|
+
console.log(picocolors_1.default.yellow('🔐 TELEGRAM BOT AUTHORIZATION REQUIRED'));
|
|
68
68
|
console.log(picocolors_1.default.yellow('==================================================='));
|
|
69
|
-
console.log('
|
|
70
|
-
console.log('
|
|
69
|
+
console.log('Your Telegram Bot is currently locked for security.');
|
|
70
|
+
console.log('Open your Telegram app, and send the following command to your bot:\n');
|
|
71
71
|
console.log(picocolors_1.default.cyan(` /auth ${generatedPin}\n`));
|
|
72
|
-
console.log(picocolors_1.default.gray('(
|
|
73
|
-
console.log('⏳
|
|
72
|
+
console.log(picocolors_1.default.gray('(This OTP code will expire in 5 minutes)\n'));
|
|
73
|
+
console.log('⏳ Waiting for incoming message...');
|
|
74
74
|
}
|
|
75
75
|
// Security Middleware (OTP & Authorization)
|
|
76
76
|
bot.use(async (ctx, next) => {
|
|
@@ -100,12 +100,12 @@ function startTelegramBot() {
|
|
|
100
100
|
currentConfig.integrations.telegram = { enabled: true, bot_token: token };
|
|
101
101
|
currentConfig.integrations.telegram.authorized_chat_id = ctx.chat?.id;
|
|
102
102
|
(0, parser_1.saveConfig)(currentConfig);
|
|
103
|
-
await ctx.reply('✅
|
|
103
|
+
await ctx.reply('✅ Authorization Successful! Nyxora Agent will now only obey your commands. Connection secured.');
|
|
104
104
|
console.log(picocolors_1.default.green(`\n[Telegram] Successfully paired with Chat ID: ${ctx.chat?.id}`));
|
|
105
105
|
return; // Done parsing auth, ignore this specific message for further logic
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
108
|
-
await ctx.reply('❌ PIN
|
|
108
|
+
await ctx.reply('❌ Incorrect PIN.');
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
111
|
}
|
|
@@ -115,7 +115,7 @@ function startTelegramBot() {
|
|
|
115
115
|
});
|
|
116
116
|
bot.command('clear', async (ctx) => {
|
|
117
117
|
reasoning_1.logger.clear(ctx.chat?.id.toString());
|
|
118
|
-
await ctx.reply(
|
|
118
|
+
await ctx.reply("✅ AI memory has been cleared. Let's start a new chat!");
|
|
119
119
|
});
|
|
120
120
|
bot.on('text', async (ctx) => {
|
|
121
121
|
const text = ctx.message.text;
|
|
@@ -216,17 +216,7 @@ function startTelegramBot() {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
transactionManager_1.txManager.updateStatus(txId, 'executed', result);
|
|
219
|
-
|
|
220
|
-
const sessionId = ctx.chat?.id.toString() || 'default';
|
|
221
|
-
const history = reasoning_1.logger.getHistory(sessionId);
|
|
222
|
-
let isIndonesian = false;
|
|
223
|
-
if (history.length > 0) {
|
|
224
|
-
const lastMsg = history[history.length - 1].content.toLowerCase();
|
|
225
|
-
const idWords = ['saya', 'kamu', 'aku', 'apa', 'bagaimana', 'kenapa', 'bisa', 'tolong', 'ke', 'di', 'dari', 'yang', 'ini', 'itu', 'buat', 'cek', 'saldo'];
|
|
226
|
-
if (idWords.some(w => lastMsg.includes(w)))
|
|
227
|
-
isIndonesian = true;
|
|
228
|
-
}
|
|
229
|
-
const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result, isIndonesian);
|
|
219
|
+
const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result);
|
|
230
220
|
await ctx.reply(formatToTelegramHTML(`✅ **Transaction processed: Success**\n\n${prettyMsg}`), { parse_mode: 'HTML' });
|
|
231
221
|
(0, reasoning_1.processUserInput)(`Transaction ${txId} was APPROVED via Telegram. Result: ${result}`, 'system', undefined, ctx.chat?.id.toString()).catch(() => { });
|
|
232
222
|
}
|