nyxora 26.7.3 → 26.7.5

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 (171) hide show
  1. package/CHANGELOG.md +49 -1
  2. package/README.md +50 -11
  3. package/dist/launcher.js +29 -1
  4. package/dist/packages/core/src/agent/bridgeWatcher.js +1 -1
  5. package/dist/packages/core/src/agent/cronManager.js +1 -1
  6. package/dist/packages/core/src/agent/llmProvider.js +33 -4
  7. package/dist/packages/core/src/agent/nyxDaemon.js +2 -2
  8. package/dist/packages/core/src/agent/osAgent.js +159 -107
  9. package/dist/packages/core/src/agent/promptBuilder.js +452 -0
  10. package/dist/packages/core/src/agent/reasoning.js +66 -184
  11. package/dist/packages/core/src/agent/reasoningScratchpad.js +19 -2
  12. package/dist/packages/core/src/agent/threatPatterns.js +106 -0
  13. package/dist/packages/core/src/agent/web3Agent.js +26 -114
  14. package/dist/packages/core/src/agent/workspaceUtils.js +56 -0
  15. package/dist/packages/core/src/channels/ChannelManager.js +36 -0
  16. package/dist/packages/core/src/channels/discordAdapter.js +81 -0
  17. package/dist/packages/core/src/channels/googlechatAdapter.js +45 -0
  18. package/dist/packages/core/src/channels/imessageAdapter.js +34 -0
  19. package/dist/packages/core/src/channels/index.js +39 -0
  20. package/dist/packages/core/src/channels/ircAdapter.js +34 -0
  21. package/dist/packages/core/src/channels/lineAdapter.js +125 -0
  22. package/dist/packages/core/src/channels/matrixAdapter.js +34 -0
  23. package/dist/packages/core/src/channels/mattermostAdapter.js +45 -0
  24. package/dist/packages/core/src/channels/msteamsAdapter.js +45 -0
  25. package/dist/packages/core/src/channels/nextcloudtalkAdapter.js +45 -0
  26. package/dist/packages/core/src/channels/nostrAdapter.js +34 -0
  27. package/dist/packages/core/src/channels/qqbotAdapter.js +34 -0
  28. package/dist/packages/core/src/channels/slackAdapter.js +74 -0
  29. package/dist/packages/core/src/channels/smsAdapter.js +45 -0
  30. package/dist/packages/core/src/channels/synologychatAdapter.js +45 -0
  31. package/dist/packages/core/src/channels/telegram.js +362 -0
  32. package/dist/packages/core/src/channels/twitchAdapter.js +34 -0
  33. package/dist/packages/core/src/channels/voicecallAdapter.js +45 -0
  34. package/dist/packages/core/src/channels/whatsappAdapter.js +126 -0
  35. package/dist/packages/core/src/channels/zaloAdapter.js +45 -0
  36. package/dist/packages/core/src/config/parser.js +2 -1
  37. package/dist/packages/core/src/gateway/chat.js +10 -2
  38. package/dist/packages/core/src/gateway/cli.js +2 -0
  39. package/dist/packages/core/src/gateway/googleAuthModule.js +112 -12
  40. package/dist/packages/core/src/gateway/server.js +134 -3
  41. package/dist/packages/core/src/gateway/setup-ml.js +65 -2
  42. package/dist/packages/core/src/gateway/setup.js +61 -22
  43. package/dist/packages/core/src/gateway/telegram.js +26 -53
  44. package/dist/packages/core/src/memory/episodic.js +20 -5
  45. package/dist/packages/core/src/memory/logger.js +27 -9
  46. package/dist/packages/core/src/plugin/PluginManager.js +46 -16
  47. package/dist/packages/core/src/system/plugins/GoogleWorkspacePlugin.js +69 -22
  48. package/dist/packages/core/src/system/plugins/SystemNotesPlugin.js +148 -0
  49. package/dist/packages/core/src/system/plugins/SystemSocialPlugin.js +2 -14
  50. package/dist/packages/core/src/system/plugins/SystemWebPlugin.js +0 -5
  51. package/dist/packages/core/src/system/plugins/SystemWorkspacePlugin.js +25 -6
  52. package/dist/packages/core/src/system/skills/analyzeImage.js +82 -0
  53. package/dist/packages/core/src/system/skills/executeShell.js +31 -4
  54. package/dist/packages/core/src/system/skills/fileDownloader.js +45 -0
  55. package/dist/packages/core/src/system/skills/generateExcel.js +1 -1
  56. package/dist/packages/core/src/system/skills/googleWorkspace.js +278 -166
  57. package/dist/packages/core/src/system/skills/playbookManager.js +269 -0
  58. package/dist/packages/core/src/system/skills/searchWeb.js +13 -6
  59. package/dist/packages/core/src/system/skills/telegramUpload.js +25 -0
  60. package/dist/packages/core/src/utils/fileLinker.js +57 -0
  61. package/dist/packages/core/src/utils/historySanitizer.js +5 -1
  62. package/dist/packages/core/src/utils/llmUtils.js +5 -4
  63. package/dist/packages/core/src/utils/skillManager.js +8 -4
  64. package/dist/packages/core/src/utils/streamSimulator.js +14 -8
  65. package/dist/packages/core/src/web3/skills/checkPortfolio.js +7 -1
  66. package/dist/packages/core/src/web3/skills/getPrice.js +1 -1
  67. package/dist/packages/core/src/web3/skills/getTxHistory.js +44 -7
  68. package/dist/packages/core/src/web3/skills/marketAnalysis.js +1 -1
  69. package/launcher.ts +26 -1
  70. package/package.json +5 -8
  71. package/packages/core/package.json +27 -9
  72. package/packages/core/src/agent/bridgeWatcher.ts +1 -1
  73. package/packages/core/src/agent/cronManager.ts +1 -1
  74. package/packages/core/src/agent/llmProvider.ts +34 -5
  75. package/packages/core/src/agent/nyxDaemon.ts +3 -3
  76. package/packages/core/src/agent/osAgent.ts +170 -109
  77. package/packages/core/src/agent/promptBuilder.ts +476 -0
  78. package/packages/core/src/agent/reasoning.ts +60 -189
  79. package/packages/core/src/agent/reasoningScratchpad.ts +21 -2
  80. package/packages/core/src/agent/threatPatterns.ts +115 -0
  81. package/packages/core/src/agent/web3Agent.ts +23 -113
  82. package/packages/core/src/agent/workspaceUtils.ts +53 -0
  83. package/packages/core/src/channels/ChannelManager.ts +45 -0
  84. package/packages/core/src/channels/googlechatAdapter.ts +48 -0
  85. package/packages/core/src/channels/imessageAdapter.ts +37 -0
  86. package/packages/core/src/channels/index.ts +40 -0
  87. package/packages/core/src/channels/ircAdapter.ts +37 -0
  88. package/packages/core/src/channels/lineAdapter.ts +101 -0
  89. package/packages/core/src/channels/matrixAdapter.ts +37 -0
  90. package/packages/core/src/channels/mattermostAdapter.ts +48 -0
  91. package/packages/core/src/channels/msteamsAdapter.ts +48 -0
  92. package/packages/core/src/channels/nextcloudtalkAdapter.ts +48 -0
  93. package/packages/core/src/channels/nostrAdapter.ts +37 -0
  94. package/packages/core/src/channels/qqbotAdapter.ts +37 -0
  95. package/packages/core/src/channels/slackAdapter.ts +83 -0
  96. package/packages/core/src/channels/smsAdapter.ts +48 -0
  97. package/packages/core/src/channels/synologychatAdapter.ts +48 -0
  98. package/packages/core/src/{gateway → channels}/telegram.ts +113 -54
  99. package/packages/core/src/channels/twitchAdapter.ts +37 -0
  100. package/packages/core/src/channels/voicecallAdapter.ts +48 -0
  101. package/packages/core/src/channels/whatsappAdapter.ts +103 -0
  102. package/packages/core/src/channels/zaloAdapter.ts +48 -0
  103. package/packages/core/src/config/parser.ts +7 -1
  104. package/packages/core/src/gateway/chat.ts +10 -2
  105. package/packages/core/src/gateway/cli.ts +2 -0
  106. package/packages/core/src/gateway/googleAuthModule.ts +114 -10
  107. package/packages/core/src/gateway/server.ts +139 -3
  108. package/packages/core/src/gateway/setup-ml.ts +65 -4
  109. package/packages/core/src/gateway/setup.ts +60 -22
  110. package/packages/core/src/memory/episodic.ts +25 -9
  111. package/packages/core/src/memory/logger.ts +26 -9
  112. package/packages/core/src/plugin/PluginManager.ts +78 -16
  113. package/packages/core/src/system/plugins/GoogleWorkspacePlugin.ts +36 -33
  114. package/packages/core/src/system/plugins/SystemNotesPlugin.ts +141 -0
  115. package/packages/core/src/system/plugins/SystemSocialPlugin.ts +2 -14
  116. package/packages/core/src/system/plugins/SystemWebPlugin.ts +0 -5
  117. package/packages/core/src/system/plugins/SystemWorkspacePlugin.ts +25 -6
  118. package/packages/core/src/system/skills/analyzeImage.ts +79 -0
  119. package/packages/core/src/system/skills/executeShell.ts +38 -7
  120. package/packages/core/src/system/skills/fileDownloader.ts +43 -0
  121. package/packages/core/src/system/skills/generateExcel.ts +1 -1
  122. package/packages/core/src/system/skills/googleWorkspace.ts +262 -174
  123. package/packages/core/src/system/skills/playbookManager.ts +285 -0
  124. package/packages/core/src/system/skills/searchWeb.ts +12 -6
  125. package/packages/core/src/system/skills/telegramUpload.ts +23 -0
  126. package/packages/core/src/utils/fileLinker.ts +48 -0
  127. package/packages/core/src/utils/historySanitizer.ts +7 -1
  128. package/packages/core/src/utils/llmUtils.ts +5 -4
  129. package/packages/core/src/utils/skillManager.ts +9 -4
  130. package/packages/core/src/utils/streamSimulator.ts +15 -8
  131. package/packages/core/src/web3/skills/checkPortfolio.ts +8 -1
  132. package/packages/core/src/web3/skills/getPrice.ts +1 -1
  133. package/packages/core/src/web3/skills/getTxHistory.ts +42 -8
  134. package/packages/core/src/web3/skills/marketAnalysis.ts +1 -1
  135. package/packages/dashboard/dist/assets/index-BIXV2TNp.js +26 -0
  136. package/packages/dashboard/dist/assets/index-C2sWcvod.css +1 -0
  137. package/packages/dashboard/dist/index.html +2 -2
  138. package/packages/dashboard/package.json +1 -1
  139. package/packages/mcp-server/package.json +1 -1
  140. package/packages/ml-engine/__pycache__/config.cpython-313.pyc +0 -0
  141. package/packages/ml-engine/__pycache__/main.cpython-313.pyc +0 -0
  142. package/packages/ml-engine/config.py +59 -0
  143. package/packages/ml-engine/main.py +37 -0
  144. package/packages/ml-engine/requirements.txt +22 -0
  145. package/packages/ml-engine/routers/__init__.py +1 -0
  146. package/packages/ml-engine/routers/__pycache__/__init__.cpython-313.pyc +0 -0
  147. package/packages/ml-engine/routers/__pycache__/background_review.cpython-313.pyc +0 -0
  148. package/packages/ml-engine/routers/__pycache__/cognitive.cpython-313.pyc +0 -0
  149. package/packages/ml-engine/routers/__pycache__/critic.cpython-313.pyc +0 -0
  150. package/packages/ml-engine/routers/__pycache__/llm.cpython-313.pyc +0 -0
  151. package/packages/ml-engine/routers/__pycache__/market.cpython-313.pyc +0 -0
  152. package/packages/ml-engine/routers/__pycache__/memory.cpython-313.pyc +0 -0
  153. package/packages/ml-engine/routers/__pycache__/memory_writer.cpython-313.pyc +0 -0
  154. package/packages/ml-engine/routers/__pycache__/skill_manager.cpython-313.pyc +0 -0
  155. package/packages/ml-engine/routers/background_review.py +121 -0
  156. package/packages/ml-engine/routers/cognitive.py +98 -0
  157. package/packages/ml-engine/routers/critic.py +111 -0
  158. package/packages/ml-engine/routers/llm.py +38 -0
  159. package/packages/ml-engine/routers/market.py +332 -0
  160. package/packages/ml-engine/routers/memory.py +125 -0
  161. package/packages/ml-engine/routers/memory_writer.py +72 -0
  162. package/packages/ml-engine/routers/skill_manager.py +123 -0
  163. package/packages/policy/package.json +1 -1
  164. package/packages/signer/package.json +1 -1
  165. package/packages/core/src/system/skills/analyzeDocument.ts +0 -117
  166. package/packages/core/src/system/skills/gitManager.ts +0 -84
  167. package/packages/core/src/system/skills/notionWorkspace.ts +0 -78
  168. package/packages/core/src/system/skills/xManager.ts +0 -76
  169. package/packages/dashboard/dist/assets/index-BTfp141V.js +0 -18
  170. package/packages/dashboard/dist/assets/index-DK2sTU47.css +0 -1
  171. /package/packages/core/src/{gateway → channels}/discordAdapter.ts +0 -0
@@ -6,118 +6,110 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.logger = void 0;
7
7
  exports.processOsIntent = processOsIntent;
8
8
  exports.processOsIntentStream = processOsIntentStream;
9
- const fs_1 = __importDefault(require("fs"));
10
9
  const parser_1 = require("../config/parser");
11
10
  const logger_1 = require("../memory/logger");
12
11
  const tracker_1 = require("../gateway/tracker");
13
- const episodic_1 = require("../memory/episodic");
14
12
  const skillManager_1 = require("../utils/skillManager");
15
- const cognitiveManager_1 = require("../cognitive/cognitiveManager");
16
13
  const reasoningScratchpad_1 = require("./reasoningScratchpad");
17
14
  const contextSummarizer_1 = require("../utils/contextSummarizer");
18
- const EXECUTION_DISCIPLINE = `
19
- <tool_persistence>
20
- Use tools whenever they can increase the accuracy, completeness, or factual correctness of your response.
21
- Do NOT stop early if another tool call would materially improve the result.
22
- Continue using tools until the task is completely finished and verified.
23
- </tool_persistence>
24
-
25
- <mandatory_tool_use>
26
- NEVER answer the following using only your internal memory — ALWAYS use the relevant tool:
27
- - Arithmetic, math, calculations
28
- - System State: OS version, RAM, processes
29
- - File contents, file sizes
30
- - Real-world current events
31
- </mandatory_tool_use>
32
-
33
- <act_dont_ask>
34
- When a user's request has a clear, standard interpretation, take immediate ACTION instead of asking for clarification.
35
- </act_dont_ask>
36
-
37
- <task_completion>
38
- 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.
39
- NEVER fabricate, hallucinate, or forge tool outputs.
40
- </task_completion>
41
- `;
15
+ const promptBuilder_1 = require("./promptBuilder");
42
16
  const registry_1 = require("../plugin/registry");
43
- const paths_1 = require("../config/paths");
44
17
  const picocolors_1 = __importDefault(require("picocolors"));
45
- exports.logger = new logger_1.Logger();
46
- const llmUtils_1 = require("../utils/llmUtils");
47
- async function getSystemPrompt(context = 'os', userInput = '') {
48
- const config = (0, parser_1.loadConfig)();
49
- const currentDateTime = new Date().toLocaleString('en-US');
50
- let basePrompt = `You are Nyxora's OS Agent (System & Automation Specialist).
51
- The current real-world date and time is: ${currentDateTime}.
52
-
53
- Reason internally. Never reveal private reasoning. Provide only concise conclusions, assumptions, and actionable steps.
54
-
55
- [OS EXECUTION WORKFLOW]
56
- CRITICAL RULE 1: NEVER expose internal JSON tool calls. Explain the outcome naturally.
57
- CRITICAL RULE 2: STRICT LANGUAGE MATCHING. Reply in the exact same language as the user's LATEST prompt, UNLESS the Episodic Memories or Cognitive Skills specify a strict language preference.
58
- CRITICAL RULE 3: FILE SYSTEM SAFETY. You are STRICTLY FORBIDDEN from modifying config.yaml, rpc_key.yaml, or policy.yaml using terminal commands like sed or echo.
59
- CRITICAL RULE 4: CRON JOBS VS LIMIT ORDERS. Do NOT use schedule_task for price-based trading triggers. Use schedule_task for time-based recurring tasks.
60
- CRITICAL RULE 5: TOOL CONFIDENCE. NEVER fabricate file contents or command outputs.
61
-
62
- ${EXECUTION_DISCIPLINE}
63
- `;
64
- // Inject Active Cognitive Skills
65
- const activeSOP = cognitiveManager_1.cognitiveManager.loadActiveCognitiveSkills(userInput);
66
- if (activeSOP) {
67
- basePrompt += `\n\n[ACTIVE COGNITIVE SKILLS]\n${activeSOP}\n`;
68
- }
69
- // Inject Episodic Memories via Python RAG
70
- try {
71
- const ragRes = await fetch('http://localhost:8000/memory/rag', {
72
- method: 'POST',
73
- headers: { 'Content-Type': 'application/json' },
74
- body: JSON.stringify({ query: userInput, top_k: 5 })
75
- });
76
- if (ragRes.ok) {
77
- const ragData = await ragRes.json();
78
- if (ragData.memories && ragData.memories.length > 0) {
79
- basePrompt += `\n\n--- EPISODIC MEMORIES (SMART SUGGESTIONS) ---\n`;
80
- ragData.memories.forEach((mem) => {
81
- basePrompt += `- ${mem}\n`;
82
- });
18
+ // --- REGISTER LIFECYCLE HOOKS ---
19
+ registry_1.pluginManager.registerHook({
20
+ name: 'ReasoningGate',
21
+ beforeToolCall: async (toolName, args, context) => {
22
+ const toolsRequiringReasoning = ['run_command', 'write_to_file', 'replace_file_content', 'multi_replace_file_content', 'execute_script'];
23
+ if (toolsRequiringReasoning.includes(toolName)) {
24
+ const responseMessage = context.responseMessage || {};
25
+ const hasThinkingTag = /<(think|thought|thinking|reasoning|analysis|reflection)>[\s\S]*?<\/\1>/i.test(responseMessage.content || '');
26
+ const hasNativeReasoning = !!responseMessage.reasoning_content;
27
+ if (!hasThinkingTag && !hasNativeReasoning) {
28
+ const msg = `[System Error] BLOCKED BY REASONING GATE: You MUST output a <think>...</think> block to plan your actions BEFORE calling the '${toolName}' tool. Please rethink and try again.`;
29
+ console.log(picocolors_1.default.red(`[❌ Blocked] Tool ${toolName} blocked by Reasoning Gate.`));
30
+ return { block: true, reason: msg };
83
31
  }
84
32
  }
85
33
  }
86
- catch (e) {
87
- // Fallback or ignore if Python ML engine is down
88
- }
89
- // Inject User Information & Personas from user.md
90
- try {
91
- const userMdPath = (0, paths_1.getPath)('user.md');
92
- if (fs_1.default.existsSync(userMdPath)) {
93
- const userInstructions = fs_1.default.readFileSync(userMdPath, 'utf8');
94
- basePrompt += `\n\n--- USER INFORMATION & PREFERENCES ---\n${userInstructions}\n`;
34
+ });
35
+ registry_1.pluginManager.registerHook({
36
+ name: 'Web3FastReturn',
37
+ afterToolCall: async (toolName, args, result, context) => {
38
+ const fastReturnTools = ['transfer_token', 'transfer_native', 'swap_token', 'bridge_token', 'mint_nft', 'custom_tx', 'revoke_approval', 'supply_aave', 'deposit_yield_vault', 'provide_liquidity_v3', 'send_telegram_file'];
39
+ if (fastReturnTools.includes(toolName)) {
40
+ return { terminate: true };
95
41
  }
96
42
  }
97
- catch (e) {
98
- // Ignore error
99
- }
100
- // HIGHEST PRIORITY: Inject observed user communication style (NyxDaemon)
43
+ });
44
+ // --- END LIFECYCLE HOOKS ---
45
+ exports.logger = new logger_1.Logger();
46
+ // Helper to trigger background review async
47
+ const triggerBackgroundReview = async (sessionId) => {
101
48
  try {
102
- const strongPersonas = episodic_1.episodicDB.getStrongPersonas(0.5);
103
- if (strongPersonas.length > 0) {
104
- basePrompt += `\n\n--- ⚡ OVERRIDE: USER COMMUNICATION STYLE (HIGHEST PRIORITY — OVERRIDES ALL RULES ABOVE) ---\n`;
105
- basePrompt += `CRITICAL: These are CONFIRMED user preferences observed across multiple conversations. You MUST apply them IMMEDIATELY and CONSISTENTLY, overriding any default tone or style instructions above.\n\n`;
106
- strongPersonas.forEach(p => {
107
- const label = p.category ? `[${p.category.toUpperCase()}]` : '[PREFERENCE]';
108
- basePrompt += `${label} ${p.trait}\n`;
109
- });
110
- }
49
+ const history = exports.logger.getHistory(sessionId, 30);
50
+ fetch('http://127.0.0.1:8000/cognitive/review', {
51
+ method: 'POST',
52
+ headers: { 'Content-Type': 'application/json' },
53
+ body: JSON.stringify({
54
+ messages: history,
55
+ session_id: sessionId || 'default',
56
+ trigger: 'turn_end'
57
+ })
58
+ }).catch(() => { });
111
59
  }
112
60
  catch (e) {
113
- // Ignore
61
+ // silently fail
114
62
  }
115
- return basePrompt;
63
+ };
64
+ const llmUtils_1 = require("../utils/llmUtils");
65
+ async function getSystemPrompt(context = 'os', userInput = '') {
66
+ const config = (0, parser_1.loadConfig)();
67
+ // Safely deduce model family from config
68
+ const provider = (config?.llm?.provider || '').toLowerCase();
69
+ let modelFamily = 'unknown';
70
+ if (provider.includes('openai'))
71
+ modelFamily = 'openai';
72
+ else if (provider.includes('gemini') || provider.includes('google'))
73
+ modelFamily = 'google';
74
+ else if (provider.includes('anthropic') || provider.includes('claude'))
75
+ modelFamily = 'anthropic';
76
+ else if (provider.includes('grok') || provider.includes('xai'))
77
+ modelFamily = 'grok';
78
+ return await promptBuilder_1.promptBuilder.buildSystemPrompt({
79
+ agentType: context,
80
+ userInput,
81
+ config,
82
+ modelFamily
83
+ });
116
84
  }
117
85
  async function processOsIntent(input, role = 'user', onProgress, sessionId) {
118
86
  const config = (0, parser_1.loadConfig)();
119
87
  // Add input to memory
120
88
  exports.logger.addEntry({ role, content: input }, sessionId);
89
+ // --- MULTILINGUAL USER CORRECTION DETECTION ---
90
+ const correctionSignals = [
91
+ // ID
92
+ 'salah', 'ngawur', 'keliru', 'bukan', 'tidak benar', 'perbaiki', 'coba lagi',
93
+ // EN
94
+ 'wrong', 'incorrect', 'mistake', 'not right', 'false', 'bad', 'fix', 'try again',
95
+ // ES & FR
96
+ 'incorrecto', 'mal', 'equivocado', 'error', 'falso', 'faux', 'erreur', 'mauvais',
97
+ // DE & RU
98
+ 'falsch', 'inkorrekt', 'fehler', 'ошибка', 'неправильно', 'неверно',
99
+ // JP & ZH
100
+ '違う', '間違い', 'やり直して', '错误', '不对'
101
+ ];
102
+ if (role === 'user' && correctionSignals.some(s => input.toLowerCase().includes(s))) {
103
+ exports.logger.addEntry({
104
+ role: 'system',
105
+ content: `[USER CORRECTION DETECTED] The user indicated your previous answer was WRONG, STALE, or INACCURATE.
106
+ CRITICAL INSTRUCTIONS:
107
+ 1. Do NOT just apologize and repeat the same data from your memory.
108
+ 2. The data in your training memory or previous tool calls is likely stale/incorrect.
109
+ 3. You MUST call a tool (like search_web or others) NOW to verify the facts with FRESH data.
110
+ 4. Base your new answer strictly on the NEW tool results.`
111
+ }, sessionId);
112
+ }
121
113
  let activeTools = [...registry_1.pluginManager.getAllToolDefinitions()];
122
114
  activeTools = activeTools.filter(t => (0, skillManager_1.isSkillActive)(t.function.name));
123
115
  // P1: Init reasoning scratchpad for this request
@@ -129,6 +121,7 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
129
121
  let turnCount = 0;
130
122
  const MAX_TURNS = 10;
131
123
  let consecutiveToolErrors = 0;
124
+ let criticHasFired = false; // Critic Pass hanya aktif 1x per request
132
125
  while (turnCount < MAX_TURNS) {
133
126
  turnCount++;
134
127
  const currentHistory = exports.logger.getHistory(sessionId);
@@ -150,7 +143,8 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
150
143
  model: config.llm.model,
151
144
  temperature: config.llm.temperature,
152
145
  messages: messages,
153
- tools: activeTools
146
+ tools: activeTools,
147
+ reasoning_effort: (!config.llm.reasoning_effort || config.llm.reasoning_effort === 'none') ? undefined : config.llm.reasoning_effort
154
148
  });
155
149
  });
156
150
  const responseMessage = response.message;
@@ -169,6 +163,10 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
169
163
  tool_calls: responseMessage.tool_calls,
170
164
  }, sessionId);
171
165
  if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
166
+ // --- CRITIC PASS REMOVED ---
167
+ // The new PromptBuilder handles robust reasoning. Post-generation critic
168
+ // causes aggressive loops and UI artifacts.
169
+ triggerBackgroundReview(sessionId);
172
170
  return cleanedContent || 'No response generated.';
173
171
  }
174
172
  let canFastReturnAll = true;
@@ -177,7 +175,7 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
177
175
  const fastReturnTools = [
178
176
  'transfer_token', 'transfer_native', 'swap_token', 'bridge_token',
179
177
  'mint_nft', 'custom_tx', 'revoke_approval', 'supply_aave',
180
- 'deposit_yield_vault', 'provide_liquidity_v3'
178
+ 'deposit_yield_vault', 'provide_liquidity_v3', 'send_telegram_file'
181
179
  ];
182
180
  for (const _toolCall of responseMessage.tool_calls) {
183
181
  const toolCall = _toolCall;
@@ -242,7 +240,7 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
242
240
  content: result,
243
241
  }, sessionId);
244
242
  accumulatedResults.push(result);
245
- if (!fastReturnTools.includes(toolName)) {
243
+ if (!['transfer_token', 'transfer_native', 'swap_token', 'bridge_token', 'mint_nft', 'custom_tx', 'revoke_approval', 'supply_aave', 'deposit_yield_vault', 'provide_liquidity_v3', 'send_telegram_file'].includes(toolName)) {
246
244
  canFastReturnAll = false;
247
245
  }
248
246
  }
@@ -259,6 +257,7 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
259
257
  if (consecutiveToolErrors >= 2) {
260
258
  const errorSummary = `⚠️ Unable to complete this request after multiple attempts.\n${accumulatedResults.join('\n')}`;
261
259
  exports.logger.addEntry({ role: 'assistant', content: errorSummary }, sessionId);
260
+ triggerBackgroundReview(sessionId);
262
261
  return errorSummary;
263
262
  }
264
263
  }
@@ -269,12 +268,14 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
269
268
  if (canFastReturnAll && accumulatedResults.length > 0) {
270
269
  const finalContent = accumulatedResults.join('\n\n---\n\n');
271
270
  exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
271
+ triggerBackgroundReview(sessionId);
272
272
  return finalContent;
273
273
  }
274
274
  // Loop continues, sending tool results in the next turn
275
275
  }
276
276
  const maxTurnMsg = "⚠️ Reached maximum interaction limit (10 turns). Please be more specific.";
277
277
  exports.logger.addEntry({ role: 'assistant', content: maxTurnMsg }, sessionId);
278
+ triggerBackgroundReview(sessionId);
278
279
  return maxTurnMsg;
279
280
  }
280
281
  catch (error) {
@@ -291,6 +292,30 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
291
292
  async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
292
293
  const config = (0, parser_1.loadConfig)();
293
294
  exports.logger.addEntry({ role: 'user', content: input }, sessionId);
295
+ // --- MULTILINGUAL USER CORRECTION DETECTION ---
296
+ const correctionSignals = [
297
+ // ID
298
+ 'salah', 'ngawur', 'keliru', 'bukan', 'tidak benar', 'perbaiki', 'coba lagi',
299
+ // EN
300
+ 'wrong', 'incorrect', 'mistake', 'not right', 'false', 'bad', 'fix', 'try again',
301
+ // ES & FR
302
+ 'incorrecto', 'mal', 'equivocado', 'error', 'falso', 'faux', 'erreur', 'mauvais',
303
+ // DE & RU
304
+ 'falsch', 'inkorrekt', 'fehler', 'ошибка', 'неправильно', 'неверно',
305
+ // JP & ZH
306
+ '違う', '間違い', 'やり直して', '错误', '不对'
307
+ ];
308
+ if (correctionSignals.some(s => input.toLowerCase().includes(s))) {
309
+ exports.logger.addEntry({
310
+ role: 'system',
311
+ content: `[USER CORRECTION DETECTED] The user indicated your previous answer was WRONG, STALE, or INACCURATE.
312
+ CRITICAL INSTRUCTIONS:
313
+ 1. Do NOT just apologize and repeat the same data from your memory.
314
+ 2. The data in your training memory or previous tool calls is likely stale/incorrect.
315
+ 3. You MUST call a tool (like search_web or others) NOW to verify the facts with FRESH data.
316
+ 4. Base your new answer strictly on the NEW tool results.`
317
+ }, sessionId);
318
+ }
294
319
  const pluginTools = registry_1.pluginManager.getAllToolDefinitions();
295
320
  let activeTools = [...pluginTools].filter(t => (0, skillManager_1.isSkillActive)(t.function.name));
296
321
  const { sanitizeHistoryForLLM } = require('../utils/historySanitizer');
@@ -298,6 +323,7 @@ async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
298
323
  let turnCount = 0;
299
324
  const MAX_TURNS = 10;
300
325
  let fullResponse = '';
326
+ let criticHasFiredStream = false; // Critic Pass hanya aktif 1x per request
301
327
  while (turnCount < MAX_TURNS) {
302
328
  turnCount++;
303
329
  const currentHistory = exports.logger.getHistory(sessionId);
@@ -308,7 +334,9 @@ async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
308
334
  ];
309
335
  let streamedContent = '';
310
336
  const response = await (0, llmUtils_1.executeWithRetry)(async (client) => {
311
- return await client.stream({ model: config.llm.model, temperature: config.llm.temperature, messages, tools: activeTools }, (chunk) => {
337
+ streamedContent = '';
338
+ onChunk('[CLEAR_STREAM]');
339
+ return await client.stream({ model: config.llm.model, temperature: config.llm.temperature, messages, tools: activeTools, reasoning_effort: (!config.llm.reasoning_effort || config.llm.reasoning_effort === 'none') ? undefined : config.llm.reasoning_effort }, (chunk) => {
312
340
  streamedContent += chunk;
313
341
  onChunk(chunk);
314
342
  });
@@ -322,23 +350,28 @@ async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
322
350
  exports.logger.addEntry({
323
351
  role: 'assistant',
324
352
  content: responseMessage.content || '',
353
+ reasoning_content: responseMessage.reasoning_content,
325
354
  tool_calls: responseMessage.tool_calls,
326
355
  }, sessionId);
327
356
  if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
328
357
  let finalContent = responseMessage.content || 'No response generated.';
329
358
  finalContent = finalContent.replace(/<(think|thought|thinking|reasoning|analysis|reflection)[\s\S]*?<\/\1>\n?/gi, '').trim();
359
+ finalContent = finalContent.replace(/^\s*(?:\*\*)?(?:think|thought|thinking|reasoning|analysis|reflection)(?:\*\*)?\s*?\n[\s\S]*?\n\n/i, '').trim();
360
+ // --- CRITIC PASS REMOVED ---
361
+ // Prevents leaking internal reasoning into the stream and confusing the user.
330
362
  fullResponse = finalContent;
363
+ triggerBackgroundReview(sessionId);
331
364
  break;
332
365
  }
333
- // Tool calls detected — pause stream visually and execute tools
334
- const fastReturnTools = ['transfer_token', 'transfer_native', 'swap_token', 'bridge_token', 'mint_nft', 'custom_tx', 'revoke_approval', 'supply_aave', 'deposit_yield_vault', 'provide_liquidity_v3'];
335
- let canFastReturnAll = true;
366
+ // Tool calls detected — pause stream visually and execute tools concurrently
367
+ let shouldFastReturn = false;
336
368
  const accumulatedResults = [];
337
- for (const _toolCall of responseMessage.tool_calls) {
369
+ const promises = responseMessage.tool_calls.map(async (_toolCall) => {
338
370
  const toolCall = _toolCall;
339
371
  const toolName = toolCall.function.name;
340
372
  let result = '';
341
373
  let args = {};
374
+ const context = { sessionId, toolCallId: toolCall.id, responseMessage };
342
375
  console.log(picocolors_1.default.yellow(`[⚡ Tool Execution] AI is calling ${toolName}...`));
343
376
  if (onProgress)
344
377
  onProgress(`_⚡ Running tool: ${toolName}..._`);
@@ -351,17 +384,28 @@ async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
351
384
  catch (parseError) {
352
385
  result = `[System Error] Arguments for ${toolName} must be valid JSON. Error: ${parseError.message}`;
353
386
  exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
354
- continue;
387
+ return { toolName, result };
355
388
  }
356
389
  if (!(0, skillManager_1.isSkillActive)(toolName)) {
357
390
  result = `[System Error] Access denied: Skill '${toolName}' is currently disabled.`;
358
391
  exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
359
- continue;
392
+ return { toolName, result };
393
+ }
394
+ // --- LIFECYCLE: BEFORE TOOL CALL ---
395
+ const beforeRes = await registry_1.pluginManager.triggerBeforeHooks(toolName, args, context);
396
+ if (beforeRes && beforeRes.block) {
397
+ result = beforeRes.reason || `[System Error] Blocked by hook for ${toolName}`;
398
+ exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
399
+ return { toolName, result };
360
400
  }
361
401
  try {
362
- const pluginResult = await registry_1.pluginManager.executeTool(toolName, args, { sessionId });
402
+ const pluginResult = await registry_1.pluginManager.executeTool(toolName, args, context, (partialResult) => {
403
+ // Partial Streaming callback
404
+ if (onProgress)
405
+ onProgress(`_⏳ [${toolName}] ${partialResult}..._`);
406
+ });
363
407
  result = pluginResult !== null ? pluginResult : `Error: Tool ${toolName} is not implemented.`;
364
- if (result.includes('[Security Blocked]') || result.startsWith('Error:')) {
408
+ if (typeof result === 'string' && (result.includes('[Security Blocked]') || result.startsWith('Error:'))) {
365
409
  console.log(picocolors_1.default.red(`[❌ Failed] Tool ${toolName} returned an error or was blocked.`));
366
410
  }
367
411
  else {
@@ -372,16 +416,23 @@ async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
372
416
  result = `Error executing ${toolName}: ${toolError.message}`;
373
417
  console.error(picocolors_1.default.red(`[❌ Error Crash] Execution of ${toolName} failed: ${toolError.message}`));
374
418
  }
419
+ // --- LIFECYCLE: AFTER TOOL CALL ---
420
+ const afterRes = await registry_1.pluginManager.triggerAfterHooks(toolName, args, result, context);
421
+ result = afterRes.content || result;
422
+ if (afterRes.terminate) {
423
+ shouldFastReturn = true;
424
+ }
375
425
  exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, name: toolName, content: result }, sessionId);
376
- accumulatedResults.push(result);
377
- if (!fastReturnTools.includes(toolName))
378
- canFastReturnAll = false;
379
- }
380
- if (canFastReturnAll && accumulatedResults.length > 0) {
426
+ return { toolName, result };
427
+ });
428
+ const results = await Promise.all(promises);
429
+ results.forEach(r => accumulatedResults.push(r.result));
430
+ if (shouldFastReturn && accumulatedResults.length > 0) {
381
431
  const finalContent = accumulatedResults.join('\n\n---\n\n');
382
432
  exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
383
433
  onChunk(finalContent);
384
434
  fullResponse = finalContent;
435
+ triggerBackgroundReview(sessionId);
385
436
  break;
386
437
  }
387
438
  }
@@ -389,6 +440,7 @@ async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
389
440
  const maxTurnMsg = '⚠️ Reached maximum interaction limit (10 turns). Please be more specific.';
390
441
  exports.logger.addEntry({ role: 'assistant', content: maxTurnMsg }, sessionId);
391
442
  fullResponse = maxTurnMsg;
443
+ triggerBackgroundReview(sessionId);
392
444
  }
393
445
  return fullResponse;
394
446
  }