nyxora 26.7.1 → 26.7.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.
Files changed (100) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/README.md +14 -2
  3. package/dist/packages/core/src/agent/honchoDaemon.js +91 -0
  4. package/dist/packages/core/src/agent/osAgent.js +82 -60
  5. package/dist/packages/core/src/agent/reasoning.js +25 -14
  6. package/dist/packages/core/src/agent/updateProfile.js +13 -16
  7. package/dist/packages/core/src/agent/web3Agent.js +82 -62
  8. package/dist/packages/core/src/cognitive/cognitiveManager.js +52 -0
  9. package/dist/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +54 -0
  10. package/dist/packages/core/src/config/parser.js +1 -0
  11. package/dist/packages/core/src/config/paths.js +14 -4
  12. package/dist/packages/core/src/gateway/server.js +54 -2
  13. package/dist/packages/core/src/gateway/telegram.js +3 -104
  14. package/dist/packages/core/src/memory/episodic.js +47 -6
  15. package/dist/packages/core/src/memory/promotionEngine.js +4 -1
  16. package/dist/packages/core/src/plugin/PluginManager.js +18 -3
  17. package/dist/packages/core/src/plugin/registry.js +1 -0
  18. package/dist/packages/core/src/system/agentskills.js +184 -0
  19. package/dist/packages/core/src/system/plugins/SystemCorePlugin.js +6 -1
  20. package/dist/packages/core/src/system/plugins/SystemExternalPlugin.js +18 -0
  21. package/dist/packages/core/src/system/plugins/SystemWorkspacePlugin.js +6 -1
  22. package/dist/packages/core/src/system/plugins/createSkill.js +41 -0
  23. package/dist/packages/core/src/system/skillExtractor.js +94 -0
  24. package/dist/packages/core/src/system/skills/createAgentSkill.js +84 -0
  25. package/dist/packages/core/src/system/skills/createCognitiveSkill.js +53 -0
  26. package/dist/packages/core/src/system/skills/forgetMemory.js +38 -0
  27. package/dist/packages/core/src/utils/llmUtils.js +4 -3
  28. package/dist/packages/core/src/utils/skillManager.js +5 -1
  29. package/dist/packages/core/src/web3/plugins/Web3DefiPlugin.js +6 -1
  30. package/dist/packages/core/src/web3/plugins/Web3MarketPlugin.js +239 -0
  31. package/dist/packages/core/src/web3/plugins/Web3SecurityPlugin.js +4 -4
  32. package/dist/packages/core/src/web3/skills/bridgeToken.js +9 -1
  33. package/dist/packages/core/src/web3/skills/checkRegistryStatus.js +1 -1
  34. package/dist/packages/core/src/web3/skills/confirmPendingTx.js +134 -0
  35. package/dist/packages/core/src/web3/skills/customTx.js +44 -1
  36. package/dist/packages/core/src/web3/skills/defiLending.js +42 -2
  37. package/dist/packages/core/src/web3/skills/getTrendingTokens.js +67 -0
  38. package/dist/packages/core/src/web3/skills/mintNft.js +42 -1
  39. package/dist/packages/core/src/web3/skills/provideLiquidity.js +45 -3
  40. package/dist/packages/core/src/web3/skills/revokeApprovals.js +41 -1
  41. package/dist/packages/core/src/web3/skills/swapToken.js +18 -2
  42. package/dist/packages/core/src/web3/skills/transfer.js +46 -1
  43. package/dist/packages/core/src/web3/skills/yieldVault.js +42 -2
  44. package/dist/packages/core/src/web3/utils/balanceChecker.js +59 -0
  45. package/package.json +1 -2
  46. package/packages/core/package.json +1 -1
  47. package/packages/core/src/agent/honchoDaemon.ts +96 -0
  48. package/packages/core/src/agent/osAgent.ts +90 -69
  49. package/packages/core/src/agent/reasoning.ts +28 -14
  50. package/packages/core/src/agent/updateProfile.ts +17 -16
  51. package/packages/core/src/agent/web3Agent.ts +89 -71
  52. package/packages/core/src/cognitive/cognitiveManager.ts +53 -0
  53. package/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +41 -0
  54. package/packages/core/src/cognitive/prompts/software-development/plan.md +15 -0
  55. package/packages/core/src/cognitive/prompts/software-development/systematic-debugging.md +14 -0
  56. package/packages/core/src/cognitive/prompts/software-development/test-driven-development.md +14 -0
  57. package/packages/core/src/config/parser.ts +4 -0
  58. package/packages/core/src/config/paths.ts +13 -4
  59. package/packages/core/src/gateway/server.ts +63 -2
  60. package/packages/core/src/gateway/telegram.ts +3 -95
  61. package/packages/core/src/memory/episodic.ts +52 -6
  62. package/packages/core/src/memory/promotionEngine.ts +5 -1
  63. package/packages/core/src/plugin/PluginManager.ts +21 -3
  64. package/packages/core/src/plugin/registry.ts +2 -0
  65. package/packages/core/src/system/agentskills.ts +175 -0
  66. package/packages/core/src/system/plugins/SystemCorePlugin.ts +6 -1
  67. package/packages/core/src/system/plugins/SystemExternalPlugin.ts +18 -0
  68. package/packages/core/src/system/plugins/SystemWorkspacePlugin.ts +6 -1
  69. package/packages/core/src/system/plugins/createSkill.ts +41 -0
  70. package/packages/core/src/system/skillExtractor.ts +101 -0
  71. package/packages/core/src/system/skills/createAgentSkill.ts +85 -0
  72. package/packages/core/src/system/skills/createCognitiveSkill.ts +50 -0
  73. package/packages/core/src/system/skills/forgetMemory.ts +34 -0
  74. package/packages/core/src/utils/llmUtils.ts +4 -3
  75. package/packages/core/src/utils/skillManager.ts +5 -1
  76. package/packages/core/src/web3/plugins/Web3DefiPlugin.ts +6 -1
  77. package/packages/core/src/web3/plugins/Web3MarketPlugin.ts +231 -0
  78. package/packages/core/src/web3/plugins/Web3SecurityPlugin.ts +4 -4
  79. package/packages/core/src/web3/skills/bridgeToken.ts +12 -2
  80. package/packages/core/src/web3/skills/checkRegistryStatus.ts +1 -1
  81. package/packages/core/src/web3/skills/confirmPendingTx.ts +94 -0
  82. package/packages/core/src/web3/skills/customTx.ts +13 -1
  83. package/packages/core/src/web3/skills/defiLending.ts +10 -2
  84. package/packages/core/src/web3/skills/getTrendingTokens.ts +89 -0
  85. package/packages/core/src/web3/skills/mintNft.ts +10 -1
  86. package/packages/core/src/web3/skills/provideLiquidity.ts +12 -3
  87. package/packages/core/src/web3/skills/revokeApprovals.ts +8 -1
  88. package/packages/core/src/web3/skills/swapToken.ts +20 -3
  89. package/packages/core/src/web3/skills/transfer.ts +13 -1
  90. package/packages/core/src/web3/skills/yieldVault.ts +10 -2
  91. package/packages/core/src/web3/utils/balanceChecker.ts +68 -0
  92. package/packages/dashboard/dist/assets/index-CSoNa5cx.css +1 -0
  93. package/packages/dashboard/dist/assets/index-DbRWEoSr.js +16 -0
  94. package/packages/dashboard/dist/index.html +2 -2
  95. package/packages/dashboard/package.json +1 -1
  96. package/packages/mcp-server/package.json +1 -1
  97. package/packages/policy/package.json +1 -1
  98. package/packages/signer/package.json +1 -1
  99. package/packages/dashboard/dist/assets/index-Djg8yTDk.js +0 -16
  100. package/packages/dashboard/dist/assets/index-VEis1hNq.css +0 -1
@@ -11,10 +11,35 @@ const tracker_1 = require("../gateway/tracker");
11
11
  const episodic_1 = require("../memory/episodic");
12
12
  const skillManager_1 = require("../utils/skillManager");
13
13
  const registry_1 = require("../plugin/registry");
14
+ const cognitiveManager_1 = require("../cognitive/cognitiveManager");
15
+ const EXECUTION_DISCIPLINE = `
16
+ <tool_persistence>
17
+ Use tools whenever they can increase the accuracy, completeness, or factual correctness of your response.
18
+ Do NOT stop early if another tool call would materially improve the result.
19
+ Continue using tools until the task is completely finished and verified.
20
+ </tool_persistence>
21
+
22
+ <mandatory_tool_use>
23
+ NEVER answer the following using only your internal memory — ALWAYS use the relevant tool:
24
+ - Arithmetic, math, calculations
25
+ - System State: OS version, RAM, processes
26
+ - File contents, file sizes
27
+ - Real-world current events
28
+ </mandatory_tool_use>
29
+
30
+ <act_dont_ask>
31
+ When a user's request has a clear, standard interpretation, take immediate ACTION instead of asking for clarification.
32
+ </act_dont_ask>
33
+
34
+ <task_completion>
35
+ The deliverable must be a working artifact backed by real tool output — not just a description or a plan of how you would do it.
36
+ NEVER fabricate, hallucinate, or forge tool outputs.
37
+ </task_completion>
38
+ `;
14
39
  const picocolors_1 = __importDefault(require("picocolors"));
15
40
  exports.logger = new logger_1.Logger();
16
41
  const llmUtils_1 = require("../utils/llmUtils");
17
- function getSystemPrompt(context = 'web3') {
42
+ function getSystemPrompt(context = 'web3', userInput = '') {
18
43
  const config = (0, parser_1.loadConfig)();
19
44
  const currentDateTime = new Date().toLocaleString('en-US');
20
45
  let basePrompt = `You are Nyxora's Web3 Agent (DeFi Specialist).
@@ -31,7 +56,11 @@ CRITICAL RULE 4: CONDITIONAL PARALLEL EXECUTION. Parallel tool execution is ONLY
31
56
  CRITICAL RULE 5: TRANSACTION EXECUTION. For ALL state-changing transactions (swap, bridge, transfer), execute IMMEDIATELY. It will trigger a secure popup.
32
57
  CRITICAL RULE 6: NETWORK SAFETY VALIDATION. NEVER GUESS chains or tokens. Ask for confirmation if ambiguous.
33
58
  CRITICAL RULE 7: TOOL CONFIDENCE & HALUCINATION PREVENTION. NEVER fabricate blockchain data.
34
- CRITICAL RULE 8: AMOUNT PRECISION. Use 6 decimal places for precision, or 2 if >$10,000.`;
59
+ CRITICAL RULE 8: AMOUNT PRECISION. Use 6 decimal places for precision, or 2 if >$10,000.
60
+ CRITICAL RULE 9: MARKET CONFIDENCE SCORE. Declare a 'Confidence Score (0-100%)' inside <think>. Warn if < 40%.
61
+
62
+ ${EXECUTION_DISCIPLINE}
63
+ `;
35
64
  // Inject Episodic Memories
36
65
  try {
37
66
  const recentMemories = episodic_1.episodicDB.getMemories().slice(0, 10);
@@ -47,6 +76,11 @@ CRITICAL RULE 8: AMOUNT PRECISION. Use 6 decimal places for precision, or 2 if >
47
76
  }
48
77
  }
49
78
  catch { }
79
+ // Inject Active Cognitive Skills
80
+ const activeSOP = cognitiveManager_1.cognitiveManager.loadActiveCognitiveSkills(userInput);
81
+ if (activeSOP) {
82
+ basePrompt += `\n\n[ACTIVE COGNITIVE SKILLS]\n${activeSOP}\n`;
83
+ }
50
84
  return basePrompt;
51
85
  }
52
86
  async function processWeb3Intent(input, role = 'user', onProgress, sessionId) {
@@ -62,33 +96,48 @@ async function processWeb3Intent(input, role = 'user', onProgress, sessionId) {
62
96
  const { sanitizeHistoryForLLM } = require('../utils/historySanitizer');
63
97
  const sanitizedHistory = sanitizeHistoryForLLM(history, activeTools, config.llm.provider);
64
98
  let messages = [
65
- { role: 'system', content: getSystemPrompt('web3') },
99
+ { role: 'system', content: getSystemPrompt('web3', input) },
66
100
  ...sanitizedHistory
67
101
  ];
68
102
  try {
69
103
  const context = 'web3';
70
- const response = await (0, llmUtils_1.executeWithRetry)(async (client) => {
71
- // Debug log to find out why Gemini 400 error happens
72
- // console.log(`[LLM Debug] Sending ${messages.length} messages to LLM.`);
73
- return await client.chat({
74
- model: config.llm.model,
75
- temperature: config.llm.temperature,
76
- messages: messages,
77
- tools: activeTools
104
+ let turnCount = 0;
105
+ const MAX_TURNS = 10;
106
+ while (turnCount < MAX_TURNS) {
107
+ turnCount++;
108
+ const currentHistory = exports.logger.getHistory(sessionId);
109
+ const sanitizedHistory = sanitizeHistoryForLLM(currentHistory, activeTools, config.llm.provider);
110
+ const messages = [
111
+ { role: 'system', content: getSystemPrompt('web3', input) },
112
+ ...sanitizedHistory
113
+ ];
114
+ const response = await (0, llmUtils_1.executeWithRetry)(async (client) => {
115
+ return await client.chat({
116
+ model: config.llm.model,
117
+ temperature: config.llm.temperature,
118
+ messages: messages,
119
+ tools: activeTools
120
+ });
78
121
  });
79
- });
80
- const responseMessage = response.message;
81
- tracker_1.Tracker.addMessage();
82
- if (response.usage?.total_tokens) {
83
- tracker_1.Tracker.addTokens(response.usage.total_tokens, config.llm.provider);
84
- }
85
- tracker_1.Tracker.addEvent('llm.response', { provider: config.llm.provider, tool_calls: responseMessage.tool_calls?.length || 0 });
86
- exports.logger.addEntry({
87
- role: 'assistant',
88
- content: responseMessage.content || "",
89
- tool_calls: responseMessage.tool_calls,
90
- }, sessionId);
91
- if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
122
+ const responseMessage = response.message;
123
+ if (turnCount === 1) {
124
+ tracker_1.Tracker.addMessage();
125
+ }
126
+ if (response.usage?.total_tokens) {
127
+ tracker_1.Tracker.addTokens(response.usage.total_tokens, config.llm.provider);
128
+ }
129
+ tracker_1.Tracker.addEvent('llm.response', { provider: config.llm.provider, tool_calls: responseMessage.tool_calls?.length || 0 });
130
+ exports.logger.addEntry({
131
+ role: 'assistant',
132
+ content: responseMessage.content || "",
133
+ tool_calls: responseMessage.tool_calls,
134
+ }, sessionId);
135
+ if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
136
+ let finalContent = responseMessage.content || "No response generated.";
137
+ finalContent = finalContent.replace(/<(think|thought|thinking|reasoning|analysis|reflection)>[\s\S]*?<\/\1>\n?/gi, '');
138
+ finalContent = finalContent.trim();
139
+ return finalContent;
140
+ }
92
141
  let canFastReturnAll = true;
93
142
  let accumulatedResults = [];
94
143
  // Enabled fastReturnTools to eliminate 2nd LLM latency for transaction popups
@@ -106,7 +155,11 @@ async function processWeb3Intent(input, role = 'user', onProgress, sessionId) {
106
155
  if (onProgress)
107
156
  onProgress(`_⚡ Running tool: ${toolName}..._`);
108
157
  try {
109
- args = JSON.parse(toolCall.function.arguments);
158
+ let argStr = toolCall.function.arguments;
159
+ if (argStr && !argStr.trim().endsWith('}')) {
160
+ argStr += '}';
161
+ }
162
+ args = JSON.parse(argStr);
110
163
  }
111
164
  catch (parseError) {
112
165
  console.error(picocolors_1.default.red(`[LLM Validation Error] Invalid JSON arguments for ${toolName}: ${parseError.message}`));
@@ -166,44 +219,11 @@ async function processWeb3Intent(input, role = 'user', onProgress, sessionId) {
166
219
  exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
167
220
  return finalContent;
168
221
  }
169
- // Second call to get the final answer after tool execution
170
- const secondSanitized = sanitizeHistoryForLLM(exports.logger.getHistory(sessionId), activeTools, config.llm.provider);
171
- const secondMessages = [
172
- { role: 'system', content: getSystemPrompt('web3') },
173
- ...secondSanitized
174
- ];
175
- const secondResponse = await (0, llmUtils_1.executeWithRetry)(async (client) => {
176
- return await client.chat({
177
- model: config.llm.model,
178
- messages: secondMessages,
179
- });
180
- });
181
- if (secondResponse.usage?.total_tokens) {
182
- tracker_1.Tracker.addTokens(secondResponse.usage.total_tokens, config.llm.provider);
183
- }
184
- tracker_1.Tracker.addEvent('llm.final_response', { provider: config.llm.provider });
185
- let finalContent = secondResponse.message.content || "";
186
- // Clean up orphaned <think> blocks that forgot to output </think>
187
- finalContent = finalContent.replace(/<thought>[\s\S]*?<\/thought>\n?/gi, '');
188
- finalContent = finalContent.replace(/<think>[\s\S]*?<\/think>\n?/gi, '');
189
- if (finalContent.includes('<think>')) {
190
- finalContent = finalContent.replace(/<think>[\s\S]*?\n\n/i, '');
191
- finalContent = finalContent.replace(/<think>[\s\S]*$/i, '');
192
- }
193
- finalContent = finalContent.trim();
194
- exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
195
- return finalContent;
196
- }
197
- let finalContent = responseMessage.content || "No response generated.";
198
- // Clean up orphaned <think> blocks that forgot to output </think>
199
- finalContent = finalContent.replace(/<thought>[\s\S]*?<\/thought>\n?/gi, '');
200
- finalContent = finalContent.replace(/<think>[\s\S]*?<\/think>\n?/gi, '');
201
- if (finalContent.includes('<think>')) {
202
- finalContent = finalContent.replace(/<think>[\s\S]*?\n\n/i, '');
203
- finalContent = finalContent.replace(/<think>[\s\S]*$/i, '');
222
+ // Loop continues, sending tool results in the next turn
204
223
  }
205
- finalContent = finalContent.trim();
206
- return finalContent;
224
+ const maxTurnMsg = "⚠️ Reached maximum interaction limit (10 turns). Please be more specific.";
225
+ exports.logger.addEntry({ role: 'assistant', content: maxTurnMsg }, sessionId);
226
+ return maxTurnMsg;
207
227
  }
208
228
  catch (error) {
209
229
  console.error("LLM Error:", error);
@@ -0,0 +1,52 @@
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
+ exports.cognitiveManager = exports.CognitiveManager = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ class CognitiveManager {
10
+ promptsPath;
11
+ constructor() {
12
+ this.promptsPath = path_1.default.join(__dirname, 'prompts');
13
+ }
14
+ loadActiveCognitiveSkills(intent) {
15
+ const activeSOPs = [];
16
+ const lowerIntent = intent.toLowerCase();
17
+ // Mapping of keywords to SOP paths
18
+ const skillMappings = [
19
+ {
20
+ keywords: ['debug', 'error', 'bug', 'fix', 'crash', 'fail', 'trace'],
21
+ file: 'software-development/systematic-debugging.md'
22
+ },
23
+ {
24
+ keywords: ['tdd', 'test', 'red green', 'unit test', 'jest', 'mocha'],
25
+ file: 'software-development/test-driven-development.md'
26
+ },
27
+ {
28
+ keywords: ['plan', 'architecture', 'design', 'structure', 'blueprint'],
29
+ file: 'software-development/plan.md'
30
+ },
31
+ {
32
+ keywords: ['binance', 'spot trading', 'exchange trading', 'cex trading', 'api key'],
33
+ file: 'autonomous/binance-trading-integration.md'
34
+ }
35
+ ];
36
+ for (const mapping of skillMappings) {
37
+ if (mapping.keywords.some(kw => lowerIntent.includes(kw))) {
38
+ const fullPath = path_1.default.join(this.promptsPath, mapping.file);
39
+ if (fs_1.default.existsSync(fullPath)) {
40
+ const content = fs_1.default.readFileSync(fullPath, 'utf8');
41
+ activeSOPs.push(`--- COGNITIVE SKILL: ${path_1.default.basename(mapping.file, '.md').toUpperCase()} ---\n${content}`);
42
+ }
43
+ }
44
+ }
45
+ if (activeSOPs.length === 0) {
46
+ return '';
47
+ }
48
+ return activeSOPs.join('\n\n');
49
+ }
50
+ }
51
+ exports.CognitiveManager = CognitiveManager;
52
+ exports.cognitiveManager = new CognitiveManager();
@@ -0,0 +1,54 @@
1
+ # Binance Trading Integration SOP
2
+
3
+ ## Tujuan
4
+ Membantu Nyxora menyiapkan alur kerja aman untuk analisis, simulasi, dan eksekusi trading Binance melalui API/plugin/tool yang tersedia atau yang akan dibuat.
5
+
6
+ ## Prinsip Keamanan Wajib
7
+ 1. Jangan pernah meminta atau menyimpan API Secret secara plaintext di chat.
8
+ 2. Jangan pernah mengaktifkan permission withdrawal pada API Binance.
9
+ 3. Default mode harus read-only atau paper/simulation kecuali user secara eksplisit meminta eksekusi live.
10
+ 4. Semua order live wajib membutuhkan konfirmasi eksplisit user sebelum dieksekusi.
11
+ 5. Terapkan batas risiko: max notional per trade, max daily loss, allowed symbols, dan allowed order types.
12
+ 6. Validasi registry/status agent sebelum transaksi jika eksekusi melibatkan sistem transaksi.
13
+
14
+ ## Data yang Harus Dikumpulkan
15
+ - Tipe market: Spot atau Futures.
16
+ - Mode: read-only, paper trading, atau live trading dengan confirmation.
17
+ - Pair yang diizinkan, contoh BTCUSDT, ETHUSDT.
18
+ - Maksimal nilai per trade.
19
+ - Maksimal kerugian harian.
20
+ - Jenis order yang diizinkan: market, limit, stop-limit, OCO.
21
+ - Preferensi strategi: manual, grid, DCA, breakout, mean reversion, atau signal-based.
22
+
23
+ ## Alur Setup Aman
24
+ 1. Jelaskan bahwa API key/secret tidak boleh dikirim langsung di chat.
25
+ 2. Minta user membuat Binance API key dengan permission minimal.
26
+ 3. Pastikan withdrawal permission nonaktif.
27
+ 4. Simpan credential hanya melalui secret manager/env file terenkripsi, bukan profile/memory/chat.
28
+ 5. Jika belum ada tool Binance, tawarkan membuat plugin/tool integrasi Binance dengan approval user.
29
+ 6. Uji koneksi dengan endpoint read-only terlebih dahulu.
30
+ 7. Uji paper trading/simulasi order.
31
+ 8. Baru aktifkan live trading setelah user menyetujui batas risiko.
32
+
33
+ ## Alur Trading
34
+ 1. Ambil saldo, pair info, ticker, order book, dan fee.
35
+ 2. Validasi pair termasuk whitelist user.
36
+ 3. Hitung quantity sesuai step size/min notional Binance.
37
+ 4. Buat rencana order berisi: pair, side, type, quantity, estimated price, max cost, fee estimate, risiko, dan alasan.
38
+ 5. Minta konfirmasi user untuk live order.
39
+ 6. Setelah konfirmasi, kirim order.
40
+ 7. Verifikasi status order.
41
+ 8. Laporkan hasil eksekusi beserta orderId, filled qty, average price, fee, dan status.
42
+
43
+ ## Risk Guardrails
44
+ - Tolak order jika pair tidak masuk whitelist.
45
+ - Tolak order jika nilai melebihi max notional per trade.
46
+ - Tolak order jika daily loss limit tercapai.
47
+ - Tolak futures leverage tinggi kecuali user eksplisit menyetujui dan batas risiko jelas.
48
+ - Jangan melakukan revenge trading atau trading beruntun tanpa instruksi.
49
+
50
+ ## Format Jawaban ke User
51
+ Gunakan bahasa Indonesia. Ringkas, jelas, dan actionable. Untuk order live, tampilkan ringkasan order dan minta konfirmasi eksplisit sebelum eksekusi.
52
+
53
+ ## Disclaimer
54
+ Selalu tekankan bahwa analisis/trading bukan nasihat keuangan dan user bertanggung jawab atas keputusan akhir.
@@ -205,6 +205,7 @@ function loadConfig() {
205
205
  integrations: parsed.integrations || {
206
206
  telegram: { enabled: false }
207
207
  },
208
+ security: parsed.security || { dashboard_password: '123456' },
208
209
  skills: parsed.skills
209
210
  };
210
211
  cachedNyxoraConfig = validatedConfig;
@@ -25,10 +25,13 @@ function getPath(filename) {
25
25
  // Determine subdirectory based on filename
26
26
  let subDir = '';
27
27
  const lowerFile = filename.toLowerCase();
28
- if (lowerFile.endsWith('.db') || lowerFile.endsWith('.db-wal') || lowerFile.endsWith('.db-shm') || lowerFile.endsWith('.json') && lowerFile.includes('memory') || lowerFile.endsWith('.md') || lowerFile.includes('orders')) {
28
+ if (filename === 'skills' || lowerFile.startsWith('skills/')) {
29
+ subDir = 'skills';
30
+ }
31
+ else if (lowerFile.endsWith('.db') || lowerFile.endsWith('.db-wal') || lowerFile.endsWith('.db-shm') || (lowerFile.endsWith('.json') && lowerFile.includes('memory')) || lowerFile.endsWith('.md') || lowerFile.includes('orders')) {
29
32
  subDir = 'data';
30
33
  }
31
- else if (lowerFile.endsWith('.yaml') || lowerFile.includes('config') || lowerFile.includes('skills') || lowerFile.includes('whitelist') || lowerFile.includes('tokens')) {
34
+ else if (lowerFile.endsWith('.yaml') || lowerFile.includes('config') || lowerFile.includes('whitelist') || lowerFile.includes('tokens')) {
32
35
  subDir = 'config';
33
36
  }
34
37
  else if (lowerFile.endsWith('.token') || lowerFile.includes('vault') || lowerFile.includes('credentials')) {
@@ -39,10 +42,17 @@ function getPath(filename) {
39
42
  }
40
43
  const targetDir = path_1.default.join(baseDir, subDir);
41
44
  ensureDir(targetDir);
42
- const fullPath = path_1.default.join(targetDir, filename);
45
+ let fullPath = path_1.default.join(targetDir, filename);
46
+ // Prevent duplicating the subdirectory name if the filename already includes it
47
+ if (filename === subDir) {
48
+ fullPath = targetDir;
49
+ }
50
+ else if (filename.startsWith(subDir + '/') || filename.startsWith(subDir + '\\')) {
51
+ fullPath = path_1.default.join(baseDir, filename);
52
+ }
43
53
  // AUTO-MIGRATION: If file exists in root but not in subdir, move it
44
54
  const oldRootPath = path_1.default.join(baseDir, filename);
45
- if (subDir !== '') {
55
+ if (subDir !== '' && fullPath !== oldRootPath) {
46
56
  if (fs_1.default.existsSync(oldRootPath) && !fs_1.default.existsSync(fullPath)) {
47
57
  try {
48
58
  fs_1.default.renameSync(oldRootPath, fullPath);
@@ -57,8 +57,11 @@ const googleAuthModule_1 = require("./googleAuthModule");
57
57
  const legalGenerator_1 = require("./legalGenerator");
58
58
  const episodic_1 = require("../memory/episodic");
59
59
  const reflection_1 = require("../memory/reflection");
60
+ const honchoDaemon_1 = require("../agent/honchoDaemon");
60
61
  // Initialize Google Auth
61
62
  (0, googleAuthModule_1.initGoogleAuth)();
63
+ // Start Background Honcho Daemon
64
+ honchoDaemon_1.honchoDaemon.start();
62
65
  // Synchronize all active skills to config.yaml on startup
63
66
  (0, skillManager_1.syncAllSkillsToConfig)();
64
67
  const util_1 = __importDefault(require("util"));
@@ -404,6 +407,9 @@ const getWeb3Skills = () => {
404
407
  .filter(p => p.name.startsWith('Web3'))
405
408
  .flatMap(p => p.tools);
406
409
  };
410
+ const getExternalSkills = () => {
411
+ return registry_1.pluginManager.agentSkills ? registry_1.pluginManager.agentSkills.getToolSchemas() : [];
412
+ };
407
413
  const getSystemSkills = () => {
408
414
  return registry_1.pluginManager.getPlugins()
409
415
  .filter(p => !p.name.startsWith('Web3'))
@@ -414,10 +420,12 @@ app.get('/api/stats', (req, res) => {
414
420
  const dbPath = (0, paths_1.getPath)('memory.db');
415
421
  const allSkills = getWeb3Skills();
416
422
  const systemSkills = getSystemSkills();
423
+ const externalSkills = getExternalSkills();
417
424
  const activeWeb3 = allSkills.filter(s => (0, skillManager_1.isSkillActive)(s.function.name)).length;
418
425
  const activeSystem = systemSkills.filter(s => (0, skillManager_1.isSkillActive)(s.function.name)).length;
419
- const totalSkills = allSkills.length + systemSkills.length;
420
- const activeSkills = activeWeb3 + activeSystem;
426
+ const activeExternal = externalSkills.filter(s => (0, skillManager_1.isSkillActive)(s.function.name)).length;
427
+ const totalSkills = allSkills.length + systemSkills.length + externalSkills.length;
428
+ const activeSkills = activeWeb3 + activeSystem + activeExternal;
421
429
  res.json({ ...stats, memoryPath: dbPath, totalSkills, activeSkills });
422
430
  });
423
431
  app.get('/api/logs', (req, res) => {
@@ -437,6 +445,14 @@ app.get('/api/skills', (req, res) => {
437
445
  }));
438
446
  res.json(skillsWithStatus);
439
447
  });
448
+ app.get('/api/skills/external', (req, res) => {
449
+ const externalSkills = getExternalSkills();
450
+ const skillsWithStatus = externalSkills.map(skill => ({
451
+ ...skill,
452
+ isActive: (0, skillManager_1.isSkillActive)(skill.function.name)
453
+ }));
454
+ res.json(skillsWithStatus);
455
+ });
440
456
  app.get('/api/skills/system', (req, res) => {
441
457
  const systemSkills = getSystemSkills();
442
458
  const skillsWithStatus = systemSkills.map(skill => ({
@@ -488,6 +504,42 @@ app.get('/api/portfolio/token-metadata', async (req, res) => {
488
504
  res.status(500).json({ error: err.message });
489
505
  }
490
506
  });
507
+ // Dashboard Auth Routes
508
+ app.post('/api/auth', (req, res) => {
509
+ try {
510
+ const config = (0, parser_1.loadConfig)();
511
+ const currentPass = config.security?.dashboard_password || '123456';
512
+ if (req.body?.password === currentPass) {
513
+ res.json({ success: true });
514
+ }
515
+ else {
516
+ res.status(401).json({ error: 'Invalid password' });
517
+ }
518
+ }
519
+ catch (err) {
520
+ res.status(500).json({ error: err.message });
521
+ }
522
+ });
523
+ app.post('/api/auth/update', (req, res) => {
524
+ try {
525
+ const { oldPassword, newPassword } = req.body;
526
+ const config = (0, parser_1.loadConfig)();
527
+ const currentPass = config.security?.dashboard_password || '123456';
528
+ if (oldPassword !== currentPass) {
529
+ return res.status(401).json({ error: 'Invalid old password' });
530
+ }
531
+ if (!newPassword || newPassword.length < 4) {
532
+ return res.status(400).json({ error: 'New password must be at least 4 characters' });
533
+ }
534
+ config.security = config.security || {};
535
+ config.security.dashboard_password = newPassword;
536
+ (0, parser_1.saveConfig)(config);
537
+ res.json({ success: true });
538
+ }
539
+ catch (err) {
540
+ res.status(500).json({ error: err.message });
541
+ }
542
+ });
491
543
  // Google Workspace Auth Routes
492
544
  app.get('/api/auth/google/url', (req, res) => {
493
545
  const url = (0, googleAuthModule_1.getAuthUrl)();
@@ -11,16 +11,6 @@ const runner_1 = require("@grammyjs/runner");
11
11
  const transformer_throttler_1 = require("@grammyjs/transformer-throttler");
12
12
  const reasoning_1 = require("../agent/reasoning");
13
13
  const parser_1 = require("../config/parser");
14
- const transactionManager_1 = require("../agent/transactionManager");
15
- const transfer_1 = require("../web3/skills/transfer");
16
- const swapToken_1 = require("../web3/skills/swapToken");
17
- const bridgeToken_1 = require("../web3/skills/bridgeToken");
18
- const mintNft_1 = require("../web3/skills/mintNft");
19
- const customTx_1 = require("../web3/skills/customTx");
20
- const executeDefi_1 = require("../web3/skills/executeDefi");
21
- const revokeApprovals_1 = require("../web3/skills/revokeApprovals");
22
- const checkRegistryStatus_1 = require("../web3/skills/checkRegistryStatus");
23
- const formatter_1 = require("../utils/formatter");
24
14
  const picocolors_1 = __importDefault(require("picocolors"));
25
15
  const fs_1 = __importDefault(require("fs"));
26
16
  const path_1 = __importDefault(require("path"));
@@ -140,19 +130,7 @@ function startTelegramBot() {
140
130
  if (progressMsgId) {
141
131
  await ctx.api.deleteMessage(ctx.chat.id, progressMsgId).catch(() => { });
142
132
  }
143
- const pendingTxs = transactionManager_1.txManager.getPending();
144
- const recentPendingTxs = pendingTxs.filter((tx) => Date.now() - tx.createdAt < 120000);
145
- if (recentPendingTxs.length > 0) {
146
- const keyboard = new grammy_1.InlineKeyboard();
147
- recentPendingTxs.forEach((tx) => {
148
- keyboard.text(`✅ Approve ${tx.type}`, `approve_${tx.id}`).text(`❌ Reject`, `reject_${tx.id}`).row();
149
- });
150
- await ctx.reply(formatToTelegramHTML(response), {
151
- parse_mode: 'HTML',
152
- reply_markup: keyboard
153
- });
154
- return;
155
- }
133
+ // Transactions will now use conversational approval (Zero-Latency text prompts) instead of InlineKeyboards.
156
134
  await ctx.reply(formatToTelegramHTML(response), { parse_mode: 'HTML' });
157
135
  }
158
136
  catch (error) {
@@ -176,7 +154,7 @@ function startTelegramBot() {
176
154
  const res = await fetch(fileLink);
177
155
  const buffer = await res.arrayBuffer();
178
156
  fs_1.default.writeFileSync(localFilePath, Buffer.from(buffer));
179
- const prompt = `Tolong analisis dokumen ini: ${localFilePath}\n\n${caption}`;
157
+ const prompt = `Please analyze this document: ${localFilePath}\n\n${caption}`;
180
158
  let progressMsgId = null;
181
159
  const onProgress = async (progressText) => {
182
160
  try {
@@ -201,86 +179,7 @@ function startTelegramBot() {
201
179
  await ctx.reply('❌ Sorry, I failed to download or analyze the document.');
202
180
  }
203
181
  });
204
- bot.callbackQuery(/^approve_(.+)$/, async (ctx) => {
205
- const txId = ctx.match[1];
206
- const tx = transactionManager_1.txManager.getTransaction(txId);
207
- if (!tx || tx.status !== 'pending') {
208
- await ctx.answerCallbackQuery({ text: 'Transaction not found or already processed.', show_alert: true });
209
- return;
210
- }
211
- await ctx.answerCallbackQuery('Processing transaction...');
212
- await ctx.reply(`⏳ Processing transaction ${txId}...`);
213
- await ctx.api.editMessageReplyMarkup(ctx.chat.id, ctx.msg.message_id, { reply_markup: { inline_keyboard: [] } }).catch(() => { });
214
- try {
215
- // --- Arbitrum Registry Kill-Switch Interceptor ---
216
- const registryCheck = await (0, checkRegistryStatus_1.checkRegistryStatus)();
217
- if (!registryCheck.isActive) {
218
- transactionManager_1.txManager.updateStatus(txId, 'failed', registryCheck.reason);
219
- reasoning_1.logger.addEntry({ role: 'assistant', content: `❌ **Security Blocked:** ${registryCheck.reason}` }, `telegram_${ctx.chat?.id}`);
220
- await ctx.reply(formatToTelegramHTML(`❌ **Security Blocked:** ${registryCheck.reason}`), { parse_mode: 'HTML' });
221
- return;
222
- }
223
- // ------------------------------------------------
224
- let result = '';
225
- if (tx.type === 'transfer') {
226
- result = await (0, transfer_1.executeTransfer)(tx.chainName, tx.details, true);
227
- }
228
- else if (tx.type === 'swap') {
229
- result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details, true);
230
- }
231
- else if (tx.type === 'bridge') {
232
- result = await (0, bridgeToken_1.executeBridge)(tx.chainName, tx.details, true);
233
- }
234
- else if (tx.type === 'mint') {
235
- result = await (0, mintNft_1.executeMintNft)(tx.chainName, tx.details, true);
236
- }
237
- else if (tx.type === 'custom') {
238
- result = await (0, customTx_1.executeCustomTx)(tx.chainName, tx.details, true);
239
- }
240
- else if (tx.type === 'approve') {
241
- result = await (0, executeDefi_1.executeApprove)(tx.chainName, tx.details);
242
- }
243
- else if (tx.type === 'aaveSupply') {
244
- result = await (0, executeDefi_1.executeAaveSupply)(tx.chainName, tx.details);
245
- }
246
- else if (tx.type === 'vaultDeposit') {
247
- result = await (0, executeDefi_1.executeVaultDeposit)(tx.chainName, tx.details);
248
- }
249
- else if (tx.type === 'univ3Mint') {
250
- result = await (0, executeDefi_1.executeUniv3Mint)(tx.chainName, tx.details);
251
- }
252
- else if (tx.type === 'revokeApproval') {
253
- result = await (0, revokeApprovals_1.executeRevokeApproval)(tx.chainName, tx.details, true);
254
- }
255
- else if (tx.type === 'limit_order') {
256
- const success = reasoning_1.logger.activateLimitOrder(tx.details.orderId);
257
- if (success) {
258
- result = `Limit Order ${tx.details.orderId} is now ACTIVE. The Event-Driven Engine is monitoring the market.`;
259
- }
260
- else {
261
- throw new Error(`Failed to activate Limit Order. ID not found in database.`);
262
- }
263
- }
264
- transactionManager_1.txManager.updateStatus(txId, 'executed', result);
265
- const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result);
266
- await ctx.reply(formatToTelegramHTML(`✅ **Transaction processed: Success**\n\n${prettyMsg}`), { parse_mode: 'HTML' });
267
- (0, reasoning_1.processUserInput)(`Transaction ${txId} was APPROVED via Telegram. Result: ${result}`, 'system', undefined, `telegram_${ctx.chat?.id}`).catch(() => { });
268
- }
269
- catch (err) {
270
- transactionManager_1.txManager.updateStatus(txId, 'failed', err.message);
271
- const prettyError = (0, formatter_1.formatTransactionError)(tx, err.message);
272
- await ctx.reply(prettyError);
273
- (0, reasoning_1.processUserInput)(`Transaction ${txId} FAILED via Telegram. Error: ${err.message}`, 'system', undefined, `telegram_${ctx.chat?.id}`).catch(() => { });
274
- }
275
- });
276
- bot.callbackQuery(/^reject_(.+)$/, async (ctx) => {
277
- const txId = ctx.match[1];
278
- transactionManager_1.txManager.updateStatus(txId, 'rejected');
279
- (0, reasoning_1.processUserInput)(`Transaction ${txId} was REJECTED via Telegram. CRITICAL: DO NOT retry or recreate this transaction. Acknowledge this cancellation to the user and stop.`, 'system', undefined, `telegram_${ctx.chat?.id}`).catch(() => { });
280
- await ctx.answerCallbackQuery('Transaction cancelled.');
281
- await ctx.reply(`❌ Transaction cancelled.`);
282
- await ctx.api.editMessageReplyMarkup(ctx.chat.id, ctx.msg.message_id, { reply_markup: { inline_keyboard: [] } }).catch(() => { });
283
- });
182
+ // Transaction approval and rejection are now handled conversationally via the LLM and the confirm_pending_tx tool.
284
183
  bot.catch((err) => {
285
184
  console.error('[Telegram] Grammy error:', err);
286
185
  });