nyxora 1.0.9 → 1.1.2

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.
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Nyxora Dashboard</title>
8
- <script type="module" crossorigin src="/assets/index-DR9Ii-ZU.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-CKUbyknW.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-33NxKAJt.css">
10
10
  </head>
11
11
  <body>
@@ -103,10 +103,10 @@ If the user doesn't specify a chain, default to: ${config.agent.default_chain}.`
103
103
  }
104
104
  return basePrompt;
105
105
  }
106
- async function processUserInput(input) {
106
+ async function processUserInput(input, role = 'user') {
107
107
  const config = (0, parser_1.loadConfig)();
108
- // Add user input to memory
109
- exports.logger.addEntry({ role: 'user', content: input });
108
+ // Add input to memory
109
+ exports.logger.addEntry({ role, content: input });
110
110
  const history = exports.logger.getHistory();
111
111
  // Format messages for OpenAI
112
112
  const messages = [
@@ -30,23 +30,12 @@ async function main() {
30
30
  // 2. Setup boilerplate files if in global mode and they don't exist
31
31
  let isFirstBoot = false;
32
32
  if (isGlobalMode) {
33
- const globalEnvPath = path_1.default.join(appDir, '.env');
34
33
  const globalConfigPath = path_1.default.join(appDir, 'config.yaml');
35
34
  const globalUserMdPath = path_1.default.join(appDir, 'user.md');
36
35
  const globalIdentityMdPath = path_1.default.join(appDir, 'IDENTITY.md');
37
- // Copy .env.example to ~/.nyxora/.env if it doesn't exist
38
- if (!fs_1.default.existsSync(globalEnvPath)) {
39
- isFirstBoot = true;
40
- const exampleEnvPath = path_1.default.resolve(__dirname, '../../../.env.example');
41
- if (fs_1.default.existsSync(exampleEnvPath)) {
42
- fs_1.default.copyFileSync(exampleEnvPath, globalEnvPath);
43
- }
44
- else {
45
- fs_1.default.writeFileSync(globalEnvPath, '# Nyxora Environment Variables\nPRIVATE_KEY=\n');
46
- }
47
- }
48
36
  // Copy default config.yaml
49
37
  if (!fs_1.default.existsSync(globalConfigPath)) {
38
+ isFirstBoot = true;
50
39
  const exampleConfigPath = path_1.default.resolve(__dirname, '../../../config.yaml');
51
40
  if (fs_1.default.existsSync(exampleConfigPath)) {
52
41
  fs_1.default.copyFileSync(exampleConfigPath, globalConfigPath);
@@ -56,39 +45,39 @@ async function main() {
56
45
  }
57
46
  }
58
47
  if (!fs_1.default.existsSync(globalUserMdPath)) {
59
- fs_1.default.writeFileSync(globalUserMdPath, 'Tuliskan instruksi kustom, aturan khusus, profil pengguna, atau persona yang Anda inginkan untuk Nyxora AI di file ini.\n');
48
+ fs_1.default.writeFileSync(globalUserMdPath, 'Write custom instructions, special rules, user profiles, or the persona you want for Nyxora AI in this file.\n');
60
49
  }
61
50
  if (!fs_1.default.existsSync(globalIdentityMdPath)) {
62
- fs_1.default.writeFileSync(globalIdentityMdPath, 'Kamu adalah Nyxora, asisten Web3 pintar.\n');
51
+ fs_1.default.writeFileSync(globalIdentityMdPath, 'You are a Web3 AI assistant named Nyxora.\n');
63
52
  }
64
53
  }
65
54
  if (isFirstBoot) {
66
- console.log('[Setup] Instalasi baru terdeteksi. Memulai Setup Wizard...');
55
+ console.log('[Setup] New installation detected. Starting Setup Wizard...');
67
56
  await (0, setup_1.runSetupWizard)();
68
57
  }
69
58
  // 3. Load Private Key into Memory
70
59
  const keystorePath = path_1.default.join(appDir, 'keystore.json');
71
60
  if (fs_1.default.existsSync(keystorePath)) {
72
61
  const masterPassword = await (0, prompts_1.password)({
73
- message: '🔒 Brankas terkunci! Masukkan Master Password untuk mengakses Nyxora:',
62
+ message: '🔒 Vault locked! Enter Master Password to access Nyxora:',
74
63
  });
75
64
  if ((0, prompts_1.isCancel)(masterPassword) || !masterPassword) {
76
- console.log(picocolors_1.default.red('Akses ditolak. Keluar dari Nyxora.'));
65
+ console.log(picocolors_1.default.red('Access denied. Exiting Nyxora.'));
77
66
  return process.exit(0);
78
67
  }
79
68
  try {
80
69
  const keystore = JSON.parse(fs_1.default.readFileSync(keystorePath, 'utf8'));
81
70
  const privateKey = (0, crypto_1.decryptKey)(keystore, masterPassword);
82
71
  (0, state_1.setPrivateKey)(privateKey);
83
- console.log(picocolors_1.default.green('✅ Kunci Privat berhasil didekripsi ke dalam memori.'));
72
+ console.log(picocolors_1.default.green('✅ Private Key successfully decrypted into memory.'));
84
73
  }
85
74
  catch (error) {
86
- console.log(picocolors_1.default.red('❌ Master Password salah atau keystore rusak. Keluar dari Nyxora.'));
75
+ console.log(picocolors_1.default.red('❌ Invalid Master Password or corrupted keystore. Exiting Nyxora.'));
87
76
  return process.exit(1);
88
77
  }
89
78
  }
90
79
  else {
91
- console.log(picocolors_1.default.yellow('⚠️ Keystore tidak ditemukan. Fitur Web3 akan dinonaktifkan kecuali Anda menjalankan `nyxora setup`.'));
80
+ console.log(picocolors_1.default.yellow('⚠️ Keystore not found. Web3 features will be disabled unless you run `nyxora setup`.'));
92
81
  }
93
82
  // 4. Start the Express API Server (which also serves the static dashboard and Telegram bot)
94
83
  (0, server_1.startServer)();
@@ -19,6 +19,7 @@ const transfer_2 = require("../web3/skills/transfer");
19
19
  const getPrice_1 = require("../web3/skills/getPrice");
20
20
  const swapToken_2 = require("../web3/skills/swapToken");
21
21
  const telegram_1 = require("./telegram");
22
+ const formatter_1 = require("../utils/formatter");
22
23
  // Intercept console.log and console.error
23
24
  const originalLog = console.log;
24
25
  const originalError = console.error;
@@ -115,13 +116,19 @@ app.post('/api/transactions/:id/approve', async (req, res) => {
115
116
  result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details.fromToken, tx.details.toToken, tx.details.amount);
116
117
  }
117
118
  transactionManager_1.txManager.updateStatus(id, 'executed', result);
118
- // Tell the LLM that the transaction was executed
119
- (0, reasoning_1.processUserInput)(`[SYSTEM]: Transaction ${id} was APPROVED and EXECUTED by the user. Result: ${result}`);
119
+ // Add programmatic beautiful message directly to chat
120
+ const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result);
121
+ reasoning_1.logger.addEntry({ role: 'assistant', content: `✅ Transaction processed:\n\n${prettyMsg}` });
122
+ // Background update to LLM
123
+ (0, reasoning_1.processUserInput)(`Transaction ${id} was APPROVED and EXECUTED by the user via Dashboard. Result: ${result}`, 'system').catch(() => { });
120
124
  res.json({ success: true, result });
121
125
  }
122
126
  catch (err) {
123
127
  transactionManager_1.txManager.updateStatus(id, 'failed', err.message);
124
- (0, reasoning_1.processUserInput)(`[SYSTEM]: Transaction ${id} was APPROVED but FAILED to execute. Error: ${err.message}`);
128
+ // Add programmatic beautiful error message directly to chat
129
+ const prettyError = (0, formatter_1.formatTransactionError)(tx, err.message);
130
+ reasoning_1.logger.addEntry({ role: 'assistant', content: prettyError });
131
+ (0, reasoning_1.processUserInput)(`Transaction ${id} was APPROVED but FAILED to execute. Error: ${err.message}`, 'system').catch(() => { });
125
132
  res.status(500).json({ error: err.message });
126
133
  }
127
134
  });
@@ -129,9 +136,9 @@ app.post('/api/transactions/:id/reject', (req, res) => {
129
136
  const id = req.params.id;
130
137
  const tx = transactionManager_1.txManager.getTransaction(id);
131
138
  if (!tx || tx.status !== 'pending')
132
- return res.status(404).json({ error: 'Transaction not found' });
139
+ return res.status(404).json({ error: 'Transaction not found or not pending' });
133
140
  transactionManager_1.txManager.updateStatus(id, 'rejected');
134
- (0, reasoning_1.processUserInput)(`[SYSTEM]: Transaction ${id} was REJECTED by the user.`);
141
+ (0, reasoning_1.processUserInput)(`Transaction ${id} was REJECTED by the user via Dashboard. Acknowledge this briefly.`, 'system').catch(() => { });
135
142
  res.json({ success: true });
136
143
  });
137
144
  app.post('/api/chat', async (req, res) => {
@@ -22,62 +22,62 @@ async function runSetupWizard() {
22
22
  ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
23
23
  `;
24
24
  console.log(picocolors_1.default.cyan(logo));
25
- (0, prompts_1.intro)(picocolors_1.default.inverse(' Pengaturan Nyxora CLI '));
25
+ (0, prompts_1.intro)(picocolors_1.default.inverse(' Nyxora CLI Setup '));
26
26
  const appDir = (0, paths_1.getAppDir)();
27
27
  const config = (0, parser_1.loadConfig)();
28
- const disclaimer = `Nyxora adalah Asisten Web3 yang beroperasi dengan akses penuh atas kendali anda.
28
+ const disclaimer = `Nyxora is a Web3 Assistant that operates with full access under your control.
29
29
 
30
- Tindakan Pencegahan Kritis:
31
- - Private Key Anda adalah nyawa aset Anda. JANGAN PERNAH menyalin atau membagikan file keystore.json.
32
- - Segala instruksi yang Anda berikan via Telegram atau Dashboard dapat memicu transaksi on-chain.
33
- - Disarankan menggunakan model AI yang cerdas untuk akurasi maksimal.
30
+ Critical Precautions:
31
+ - Your Private Key is the lifeblood of your assets. NEVER copy or share the keystore.json file.
32
+ - Any instructions you provide via Telegram or Dashboard can trigger on-chain transactions.
33
+ - It is recommended to use a smart AI model for maximum accuracy.
34
34
 
35
- Dengan menggunakan Nyxora, Anda sepenuhnya memegang kendali atas kunci Anda sendiri.`;
36
- (0, prompts_1.note)(disclaimer, 'Peringatan Keamanan');
35
+ By using Nyxora, you retain full control over your own keys.`;
36
+ (0, prompts_1.note)(disclaimer, 'Security Warning');
37
37
  const understand = await (0, prompts_1.confirm)({
38
- message: 'Saya mengerti bahwa keamanan Private Key adalah tanggung jawab saya. Lanjutkan?',
38
+ message: 'I understand that Private Key security is my responsibility. Continue?',
39
39
  initialValue: true,
40
40
  });
41
41
  if ((0, prompts_1.isCancel)(understand) || !understand) {
42
- (0, prompts_1.cancel)('Pengaturan dibatalkan.');
42
+ (0, prompts_1.cancel)('Setup cancelled.');
43
43
  return process.exit(0);
44
44
  }
45
45
  const existingConfigNote = `Workspace: ${appDir}
46
- Model Saat Ini: ${config.llm.model}
46
+ Current Model: ${config.llm.model}
47
47
  Provider: ${config.llm.provider}`;
48
- (0, prompts_1.note)(existingConfigNote, 'Konfigurasi Terdeteksi');
48
+ (0, prompts_1.note)(existingConfigNote, 'Configuration Detected');
49
49
  const action = await (0, prompts_1.select)({
50
- message: 'Apa yang ingin Anda lakukan?',
50
+ message: 'What would you like to do?',
51
51
  options: [
52
- { value: 'keep', label: 'Pertahankan nilai saat ini' },
53
- { value: 'update', label: 'Tinjau dan perbarui pengaturan' },
52
+ { value: 'keep', label: 'Keep current values' },
53
+ { value: 'update', label: 'Review and update settings' },
54
54
  ],
55
55
  });
56
56
  if ((0, prompts_1.isCancel)(action)) {
57
- (0, prompts_1.cancel)('Pengaturan dibatalkan.');
57
+ (0, prompts_1.cancel)('Setup cancelled.');
58
58
  return process.exit(0);
59
59
  }
60
60
  if (action === 'keep') {
61
- (0, prompts_1.outro)(picocolors_1.default.green('Selesai! Konfigurasi tidak diubah. Menjalankan Nyxora...'));
61
+ (0, prompts_1.outro)(picocolors_1.default.green('Done! Configuration unchanged. Starting Nyxora...'));
62
62
  return;
63
63
  }
64
64
  // --- WIZARD FORM ---
65
65
  // 1. LLM Provider
66
66
  const provider = await (0, prompts_1.select)({
67
- message: 'Pilih Mesin AI (Provider):',
67
+ message: 'Select AI Engine (Provider):',
68
68
  initialValue: config.llm.provider,
69
69
  options: [
70
- { value: 'openai', label: 'OpenAI (Rekomendasi)' },
70
+ { value: 'openai', label: 'OpenAI (Recommended)' },
71
71
  { value: 'gemini', label: 'Google Gemini' },
72
- { value: 'openrouter', label: 'OpenRouter (Banyak Model)' },
73
- { value: 'ollama', label: 'Ollama (Lokal)' },
72
+ { value: 'openrouter', label: 'OpenRouter (Many Models)' },
73
+ { value: 'ollama', label: 'Ollama (Local)' },
74
74
  ],
75
75
  });
76
76
  if ((0, prompts_1.isCancel)(provider))
77
77
  return process.exit(0);
78
78
  // 2. Model Name
79
79
  const model = await (0, prompts_1.text)({
80
- message: 'Masukkan nama model AI (contoh: gpt-4o, gemini-2.5-flash):',
80
+ message: 'Enter AI model name (e.g. gpt-4o, gemini-2.5-flash):',
81
81
  initialValue: config.llm.model,
82
82
  });
83
83
  if ((0, prompts_1.isCancel)(model))
@@ -86,14 +86,14 @@ Provider: ${config.llm.provider}`;
86
86
  let apiKey = '';
87
87
  if (provider !== 'ollama') {
88
88
  apiKey = (await (0, prompts_1.password)({
89
- message: `Masukkan API Key untuk ${provider} (Biarkan kosong jika sudah ada):`,
89
+ message: `Enter API Key for ${provider} (Leave empty if already set):`,
90
90
  }));
91
91
  if ((0, prompts_1.isCancel)(apiKey))
92
92
  return process.exit(0);
93
93
  }
94
94
  // 4. Default Chain
95
95
  const defaultChain = await (0, prompts_1.select)({
96
- message: 'Pilih Jaringan Utama (Default Chain):',
96
+ message: 'Select Default Chain:',
97
97
  initialValue: config.agent.default_chain,
98
98
  options: [
99
99
  { value: 'sepolia', label: 'Sepolia (Testnet)' },
@@ -108,7 +108,7 @@ Provider: ${config.llm.provider}`;
108
108
  return process.exit(0);
109
109
  // 5. Telegram Bot
110
110
  const setupTelegram = await (0, prompts_1.confirm)({
111
- message: 'Apakah Anda ingin memasang Bot Telegram?',
111
+ message: 'Do you want to setup the Telegram Bot?',
112
112
  initialValue: config.integrations?.telegram?.enabled || false,
113
113
  });
114
114
  if ((0, prompts_1.isCancel)(setupTelegram))
@@ -116,21 +116,21 @@ Provider: ${config.llm.provider}`;
116
116
  let telegramToken = '';
117
117
  if (setupTelegram) {
118
118
  telegramToken = (await (0, prompts_1.password)({
119
- message: 'Masukkan Telegram Bot Token dari @BotFather (Biarkan kosong jika sudah ada):',
119
+ message: 'Enter Telegram Bot Token from @BotFather (Leave empty if already set):',
120
120
  }));
121
121
  if ((0, prompts_1.isCancel)(telegramToken))
122
122
  return process.exit(0);
123
123
  }
124
124
  // 6. Wallet Private Key (keystore.json)
125
125
  const privateKey = await (0, prompts_1.password)({
126
- message: 'Masukkan Wallet Private Key (0x...)\n (Akan dienkripsi AES-256-GCM. Biarkan kosong jika tidak ingin mengubah):',
126
+ message: 'Enter Wallet Private Key (0x...)\n (Will be AES-256-GCM encrypted. Leave empty to keep current):',
127
127
  });
128
128
  if ((0, prompts_1.isCancel)(privateKey))
129
129
  return process.exit(0);
130
130
  let masterPassword = '';
131
131
  if (privateKey) {
132
132
  masterPassword = (await (0, prompts_1.password)({
133
- message: 'Masukkan MASTER PASSWORD untuk mengenkripsi brankas kunci Anda:',
133
+ message: 'Enter MASTER PASSWORD to encrypt your key vault:',
134
134
  }));
135
135
  if ((0, prompts_1.isCancel)(masterPassword) || !masterPassword)
136
136
  return process.exit(0);
@@ -169,12 +169,12 @@ Provider: ${config.llm.provider}`;
169
169
  const envPath = path_1.default.join(appDir, '.env');
170
170
  if (fs_1.default.existsSync(envPath)) {
171
171
  fs_1.default.unlinkSync(envPath);
172
- console.log(picocolors_1.default.yellow('File .env lama telah dihapus demi keamanan.'));
172
+ console.log(picocolors_1.default.yellow('Legacy .env file has been deleted for security.'));
173
173
  }
174
174
  }
175
175
  catch (error) {
176
- console.error('Gagal menyimpan keystore.json:', error);
176
+ console.error('Failed to save keystore.json:', error);
177
177
  }
178
178
  }
179
- (0, prompts_1.outro)(picocolors_1.default.green('✨ Setup Berhasil! Semua konfigurasi telah disimpan dengan aman.'));
179
+ (0, prompts_1.outro)(picocolors_1.default.green('✨ Setup Successful! All configurations have been securely saved.'));
180
180
  }
@@ -10,6 +10,7 @@ const parser_1 = require("../config/parser");
10
10
  const transactionManager_1 = require("../agent/transactionManager");
11
11
  const transfer_1 = require("../web3/skills/transfer");
12
12
  const swapToken_1 = require("../web3/skills/swapToken");
13
+ const formatter_1 = require("../utils/formatter");
13
14
  function startTelegramBot() {
14
15
  const config = (0, parser_1.loadConfig)();
15
16
  const token = config.integrations?.telegram?.bot_token;
@@ -32,17 +33,17 @@ function startTelegramBot() {
32
33
  // Feed the message to the AI agent
33
34
  const response = await (0, reasoning_1.processUserInput)(text);
34
35
  // Send the AI's response back to Telegram
35
- // Extract pending TX ID if present
36
- const txMatch = response.match(/Transaction ID: ([a-z0-9-]+)/i);
37
- if (txMatch) {
38
- const txId = txMatch[1];
39
- const tx = transactionManager_1.txManager.getTransaction(txId);
40
- if (tx && tx.status === 'pending') {
36
+ // Check for newly created pending transactions
37
+ const pendingTxs = transactionManager_1.txManager.getPending();
38
+ if (pendingTxs.length > 0) {
39
+ const latestTx = pendingTxs[pendingTxs.length - 1];
40
+ // If the transaction was created within the last 2 minutes, show the inline keyboard
41
+ if (Date.now() - latestTx.createdAt < 120000) {
41
42
  bot.sendMessage(chatId, response, {
42
43
  reply_markup: {
43
44
  inline_keyboard: [[
44
- { text: '✅ Approve', callback_data: `approve_${txId}` },
45
- { text: '❌ Reject', callback_data: `reject_${txId}` }
45
+ { text: '✅ Approve', callback_data: `approve_${latestTx.id}` },
46
+ { text: '❌ Reject', callback_data: `reject_${latestTx.id}` }
46
47
  ]]
47
48
  }
48
49
  });
@@ -53,7 +54,7 @@ function startTelegramBot() {
53
54
  }
54
55
  catch (error) {
55
56
  console.error('[Telegram] Error processing message:', error);
56
- bot.sendMessage(chatId, '❌ Maaf, saya mengalami gangguan saat memproses pesan Anda.');
57
+ bot.sendMessage(chatId, '❌ Sorry, I encountered an error while processing your message.');
57
58
  }
58
59
  });
59
60
  bot.on('callback_query', async (query) => {
@@ -63,12 +64,12 @@ function startTelegramBot() {
63
64
  const [action, txId] = query.data.split('_');
64
65
  const tx = transactionManager_1.txManager.getTransaction(txId);
65
66
  if (!tx || tx.status !== 'pending') {
66
- bot.answerCallbackQuery(query.id, { text: 'Transaksi tidak ditemukan atau sudah diproses.', show_alert: true });
67
+ bot.answerCallbackQuery(query.id, { text: 'Transaction not found or already processed.', show_alert: true });
67
68
  return;
68
69
  }
69
70
  if (action === 'approve') {
70
- bot.answerCallbackQuery(query.id, { text: 'Memproses transaksi...' });
71
- bot.sendMessage(chatId, `⏳ Memproses transaksi ${txId}...`);
71
+ bot.answerCallbackQuery(query.id, { text: 'Processing transaction...' });
72
+ bot.sendMessage(chatId, `⏳ Processing transaction ${txId}...`);
72
73
  try {
73
74
  let result = '';
74
75
  if (tx.type === 'transfer') {
@@ -78,20 +79,24 @@ function startTelegramBot() {
78
79
  result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details.fromToken, tx.details.toToken, tx.details.amount);
79
80
  }
80
81
  transactionManager_1.txManager.updateStatus(txId, 'executed', result);
81
- (0, reasoning_1.processUserInput)(`[SYSTEM]: Transaction ${txId} was APPROVED via Telegram. Result: ${result}`);
82
- bot.sendMessage(chatId, `✅ Transaksi berhasil!\n${result}`);
82
+ const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result);
83
+ bot.sendMessage(chatId, `✅ Transaction processed:\n\n${prettyMsg}`);
84
+ // Background update to LLM
85
+ (0, reasoning_1.processUserInput)(`Transaction ${txId} was APPROVED via Telegram. Result: ${result}`, 'system').catch(() => { });
83
86
  }
84
87
  catch (err) {
85
88
  transactionManager_1.txManager.updateStatus(txId, 'failed', err.message);
86
- (0, reasoning_1.processUserInput)(`[SYSTEM]: Transaction ${txId} FAILED via Telegram. Error: ${err.message}`);
87
- bot.sendMessage(chatId, `❌ Transaksi gagal!\n${err.message}`);
89
+ const prettyError = (0, formatter_1.formatTransactionError)(tx, err.message);
90
+ bot.sendMessage(chatId, prettyError);
91
+ // Background update to LLM
92
+ (0, reasoning_1.processUserInput)(`Transaction ${txId} FAILED via Telegram. Error: ${err.message}`, 'system').catch(() => { });
88
93
  }
89
94
  }
90
95
  else if (action === 'reject') {
91
96
  transactionManager_1.txManager.updateStatus(txId, 'rejected');
92
- (0, reasoning_1.processUserInput)(`[SYSTEM]: Transaction ${txId} was REJECTED via Telegram.`);
93
- bot.answerCallbackQuery(query.id, { text: 'Transaksi dibatalkan.' });
94
- bot.sendMessage(chatId, `❌ Transaksi ${txId} telah dibatalkan.`);
97
+ (0, reasoning_1.processUserInput)(`Transaction ${txId} was REJECTED via Telegram. Acknowledge this briefly.`, 'system').catch(() => { });
98
+ bot.answerCallbackQuery(query.id, { text: 'Transaction cancelled.' });
99
+ bot.sendMessage(chatId, `❌ Transaction cancelled.`);
95
100
  }
96
101
  // Remove inline keyboard
97
102
  bot.editMessageReplyMarkup({ inline_keyboard: [] }, { chat_id: chatId, message_id: query.message?.message_id });
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatTransactionSuccess = formatTransactionSuccess;
4
+ exports.formatTransactionError = formatTransactionError;
5
+ function formatTransactionSuccess(tx, rawResult) {
6
+ let txHash = 'N/A';
7
+ try {
8
+ const parsed = JSON.parse(rawResult);
9
+ if (parsed.txHash)
10
+ txHash = parsed.txHash;
11
+ }
12
+ catch (e) {
13
+ const hashMatch = rawResult.match(/Hash: (0x[a-fA-F0-9]+)/);
14
+ if (hashMatch) {
15
+ txHash = hashMatch[1];
16
+ }
17
+ }
18
+ const chainFormatted = tx.chainName.charAt(0).toUpperCase() + tx.chainName.slice(1);
19
+ if (tx.type === 'swap') {
20
+ return `Alright, I have completed the swap from ${tx.details.amount} ${tx.details.fromToken.toUpperCase()} to ${tx.details.toToken.toUpperCase()}.\n\nChain: ${chainFormatted}\nTx Hash:\n${txHash}`;
21
+ }
22
+ else if (tx.type === 'transfer') {
23
+ return `Alright, I have completed the transfer of ${tx.details.amountEth} tokens to ${tx.details.toAddress}.\n\nChain: ${chainFormatted}\nTx Hash:\n${txHash}`;
24
+ }
25
+ return `Transaction successful!\n\nChain: ${chainFormatted}\nTx Hash:\n${txHash}`;
26
+ }
27
+ function formatTransactionError(tx, errorMsg) {
28
+ const chainFormatted = tx.chainName.charAt(0).toUpperCase() + tx.chainName.slice(1);
29
+ return `❌ Failed to process transaction on ${chainFormatted}.\n\nError: ${errorMsg}`;
30
+ }
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "nyxora",
3
- "version": "1.0.9",
3
+ "version": "1.1.2",
4
4
  "description": "",
5
5
  "main": "dist/gateway/cli.js",
6
6
  "files": [
7
7
  "dist",
8
8
  "dashboard/dist",
9
- "config.yaml",
10
9
  "user.md",
11
10
  "IDENTITY.md",
12
11
  "SECURITY.md",
@@ -20,7 +19,7 @@
20
19
  "start": "node dist/gateway/cli.js",
21
20
  "dashboard": "npm run build && node dist/gateway/cli.js",
22
21
  "test": "echo \"Error: no test specified\" && exit 1",
23
- "deploy": "npm run build && git add . && git commit -m \"chore: auto-deploy new feature\" && git push && npm publish"
22
+ "deploy": "npm run build && git add . && git commit -m \"chore: auto-deploy new feature\" && git push && git push --tags && npm publish"
24
23
  },
25
24
  "keywords": [],
26
25
  "author": "",
package/user.md CHANGED
@@ -1,10 +1,9 @@
1
- Tuliskan instruksi kustom, aturan khusus, profil pengguna, atau persona yang Anda inginkan untuk Nyxora AI di file ini.
1
+ Write custom instructions, special rules, user profiles, or the persona you want for Nyxora AI in this file.
2
2
 
3
- Setiap kali agen membaca pesan Anda, ia akan membaca file ini terlebih dahulu sebagai pedoman utama.
3
+ Every time the agent reads your messages, it will read this file first as its primary guideline.
4
4
 
5
- Contoh:
6
-
7
- * "Panggil saya dengan sebutan Yudha"
8
- * "Gunakan gaya bahasa santai dan gaul"
9
- * "Fokuskan analisis pada sudut pandang teknikal trading"
5
+ Examples:
10
6
 
7
+ * "Call me Yudha"
8
+ * "Use casual and slang language"
9
+ * "Focus analysis from a technical trading perspective"
package/config.yaml DELETED
@@ -1,15 +0,0 @@
1
- agent:
2
- name: Nyxora-EVM-Agent
3
- default_chain: sepolia
4
- llm:
5
- provider: gemini
6
- model: gemini-2.5-flash
7
- temperature: 0.2
8
- credentials:
9
- gemini_key: AIzaSyDBlde1SSp_kbTweW1QXHknwzRTYHp98IQ
10
- memory:
11
- type: file
12
- path: ./memory.json
13
- integrations:
14
- telegram:
15
- enabled: false