nyxora 26.7.4 → 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 (148) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +48 -9
  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 +29 -3
  7. package/dist/packages/core/src/agent/nyxDaemon.js +1 -1
  8. package/dist/packages/core/src/agent/osAgent.js +109 -205
  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 +111 -13
  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 +21 -48
  44. package/dist/packages/core/src/memory/episodic.js +4 -0
  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 -30
  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/fileDownloader.js +45 -0
  54. package/dist/packages/core/src/system/skills/generateExcel.js +1 -1
  55. package/dist/packages/core/src/system/skills/googleWorkspace.js +278 -271
  56. package/dist/packages/core/src/system/skills/playbookManager.js +269 -0
  57. package/dist/packages/core/src/system/skills/telegramUpload.js +25 -0
  58. package/dist/packages/core/src/utils/fileLinker.js +57 -0
  59. package/dist/packages/core/src/utils/historySanitizer.js +5 -1
  60. package/dist/packages/core/src/utils/llmUtils.js +5 -4
  61. package/dist/packages/core/src/utils/skillManager.js +8 -4
  62. package/dist/packages/core/src/utils/streamSimulator.js +14 -8
  63. package/dist/packages/core/src/web3/skills/checkPortfolio.js +7 -1
  64. package/dist/packages/core/src/web3/skills/getTxHistory.js +44 -7
  65. package/launcher.ts +26 -1
  66. package/package.json +3 -7
  67. package/packages/core/package.json +27 -9
  68. package/packages/core/src/agent/bridgeWatcher.ts +1 -1
  69. package/packages/core/src/agent/cronManager.ts +1 -1
  70. package/packages/core/src/agent/llmProvider.ts +30 -3
  71. package/packages/core/src/agent/nyxDaemon.ts +2 -2
  72. package/packages/core/src/agent/osAgent.ts +116 -206
  73. package/packages/core/src/agent/promptBuilder.ts +476 -0
  74. package/packages/core/src/agent/reasoning.ts +60 -189
  75. package/packages/core/src/agent/reasoningScratchpad.ts +21 -2
  76. package/packages/core/src/agent/threatPatterns.ts +115 -0
  77. package/packages/core/src/agent/web3Agent.ts +23 -113
  78. package/packages/core/src/agent/workspaceUtils.ts +53 -0
  79. package/packages/core/src/channels/ChannelManager.ts +45 -0
  80. package/packages/core/src/channels/googlechatAdapter.ts +48 -0
  81. package/packages/core/src/channels/imessageAdapter.ts +37 -0
  82. package/packages/core/src/channels/index.ts +40 -0
  83. package/packages/core/src/channels/ircAdapter.ts +37 -0
  84. package/packages/core/src/channels/lineAdapter.ts +101 -0
  85. package/packages/core/src/channels/matrixAdapter.ts +37 -0
  86. package/packages/core/src/channels/mattermostAdapter.ts +48 -0
  87. package/packages/core/src/channels/msteamsAdapter.ts +48 -0
  88. package/packages/core/src/channels/nextcloudtalkAdapter.ts +48 -0
  89. package/packages/core/src/channels/nostrAdapter.ts +37 -0
  90. package/packages/core/src/channels/qqbotAdapter.ts +37 -0
  91. package/packages/core/src/channels/slackAdapter.ts +83 -0
  92. package/packages/core/src/channels/smsAdapter.ts +48 -0
  93. package/packages/core/src/channels/synologychatAdapter.ts +48 -0
  94. package/packages/core/src/{gateway → channels}/telegram.ts +108 -49
  95. package/packages/core/src/channels/twitchAdapter.ts +37 -0
  96. package/packages/core/src/channels/voicecallAdapter.ts +48 -0
  97. package/packages/core/src/channels/whatsappAdapter.ts +103 -0
  98. package/packages/core/src/channels/zaloAdapter.ts +48 -0
  99. package/packages/core/src/config/parser.ts +7 -1
  100. package/packages/core/src/gateway/chat.ts +10 -2
  101. package/packages/core/src/gateway/cli.ts +2 -0
  102. package/packages/core/src/gateway/googleAuthModule.ts +113 -11
  103. package/packages/core/src/gateway/server.ts +139 -3
  104. package/packages/core/src/gateway/setup-ml.ts +65 -4
  105. package/packages/core/src/gateway/setup.ts +60 -22
  106. package/packages/core/src/memory/episodic.ts +4 -0
  107. package/packages/core/src/memory/logger.ts +26 -9
  108. package/packages/core/src/plugin/PluginManager.ts +78 -16
  109. package/packages/core/src/system/plugins/GoogleWorkspacePlugin.ts +36 -45
  110. package/packages/core/src/system/plugins/SystemNotesPlugin.ts +141 -0
  111. package/packages/core/src/system/plugins/SystemSocialPlugin.ts +2 -14
  112. package/packages/core/src/system/plugins/SystemWebPlugin.ts +0 -5
  113. package/packages/core/src/system/plugins/SystemWorkspacePlugin.ts +25 -6
  114. package/packages/core/src/system/skills/analyzeImage.ts +79 -0
  115. package/packages/core/src/system/skills/fileDownloader.ts +43 -0
  116. package/packages/core/src/system/skills/generateExcel.ts +1 -1
  117. package/packages/core/src/system/skills/googleWorkspace.ts +262 -283
  118. package/packages/core/src/system/skills/playbookManager.ts +285 -0
  119. package/packages/core/src/system/skills/telegramUpload.ts +23 -0
  120. package/packages/core/src/utils/fileLinker.ts +48 -0
  121. package/packages/core/src/utils/historySanitizer.ts +7 -1
  122. package/packages/core/src/utils/llmUtils.ts +5 -4
  123. package/packages/core/src/utils/skillManager.ts +9 -4
  124. package/packages/core/src/utils/streamSimulator.ts +15 -8
  125. package/packages/core/src/web3/skills/checkPortfolio.ts +8 -1
  126. package/packages/core/src/web3/skills/getTxHistory.ts +42 -8
  127. package/packages/dashboard/dist/assets/index-BIXV2TNp.js +26 -0
  128. package/packages/dashboard/dist/assets/index-C2sWcvod.css +1 -0
  129. package/packages/dashboard/dist/index.html +2 -2
  130. package/packages/dashboard/package.json +1 -1
  131. package/packages/mcp-server/package.json +1 -1
  132. package/packages/ml-engine/__pycache__/main.cpython-313.pyc +0 -0
  133. package/packages/ml-engine/main.py +4 -1
  134. package/packages/ml-engine/routers/__pycache__/background_review.cpython-313.pyc +0 -0
  135. package/packages/ml-engine/routers/__pycache__/memory_writer.cpython-313.pyc +0 -0
  136. package/packages/ml-engine/routers/__pycache__/skill_manager.cpython-313.pyc +0 -0
  137. package/packages/ml-engine/routers/background_review.py +121 -0
  138. package/packages/ml-engine/routers/memory_writer.py +72 -0
  139. package/packages/ml-engine/routers/skill_manager.py +123 -0
  140. package/packages/policy/package.json +1 -1
  141. package/packages/signer/package.json +1 -1
  142. package/packages/core/src/system/skills/analyzeDocument.ts +0 -117
  143. package/packages/core/src/system/skills/gitManager.ts +0 -84
  144. package/packages/core/src/system/skills/notionWorkspace.ts +0 -78
  145. package/packages/core/src/system/skills/xManager.ts +0 -76
  146. package/packages/dashboard/dist/assets/index-Czxksiao.js +0 -18
  147. package/packages/dashboard/dist/assets/index-DK2sTU47.css +0 -1
  148. /package/packages/core/src/{gateway → channels}/discordAdapter.ts +0 -0
@@ -6,151 +6,81 @@ 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
- <web_search_accuracy>
34
- When using the search_web tool to look up news, current events, or factual data:
35
- 1. NEVER pass casual, conversational, or highly localized queries directly to the tool (e.g. do not pass "hasil piala dunia tadi pagi").
36
- 2. ALWAYS translate and optimize the query into an absolute, highly specific, and globally-understood English search query (e.g. "World Cup 2026 match results June 25 2026").
37
- 3. Use depth: 2 (deep research) for anything that requires high factual accuracy, such as sports scores, news, or complex topics.
38
- </web_search_accuracy>
39
-
40
- <act_dont_ask>
41
- When a user's request has a clear, standard interpretation, take immediate ACTION instead of asking for clarification.
42
- NEVER show a command as a markdown code block and wait. CALL the tool directly.
43
- NEVER ask "do you want me to run this?" — just run it.
44
- NEVER say "you need to run this yourself" — you have direct shell access.
45
- If a command requires sudo and may need a password, just run it and report what happens.
46
- Only report failure AFTER actually attempting the tool call and receiving an error.
47
- </act_dont_ask>
48
-
49
- <anti_hallucination_execution>
50
- CRITICAL: It is STRICTLY FORBIDDEN to write a bash/shell command in a markdown code block (e.g. \`\`\`bash ... \`\`\`) as a substitute for calling the run_terminal_command tool.
51
- Writing a code block does NOT execute anything. It is a lie to the user.
52
- If you write \`\`\`bash\nsudo apt install steam\n\`\`\` instead of calling run_terminal_command, you are hallucinating execution.
53
- The ONLY way to run a command is to emit a proper tool_call for run_terminal_command.
54
- If the tool is available, USE IT. Do not simulate or describe running it.
55
- </anti_hallucination_execution>
56
-
57
- <task_completion>
58
- 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.
59
- NEVER fabricate, hallucinate, or forge tool outputs.
60
- </task_completion>
61
-
62
- <self_correction>
63
- Before providing a final answer to the user (especially regarding dates, events, news, or factual data), you MUST evaluate your tool results inside a <think> block.
64
- Ask yourself: "Is my answer based on absolute facts, or circumstantial evidence (e.g., guessing a registration date based on a video upload date)?"
65
- If the evidence is circumstantial or incomplete, you MUST NOT answer the user. Instead, call the search_web tool again with a highly optimized query and depth=2.
66
- </self_correction>
67
- `;
15
+ const promptBuilder_1 = require("./promptBuilder");
68
16
  const registry_1 = require("../plugin/registry");
69
- const paths_1 = require("../config/paths");
70
17
  const picocolors_1 = __importDefault(require("picocolors"));
71
- exports.logger = new logger_1.Logger();
72
- const llmUtils_1 = require("../utils/llmUtils");
73
- async function getSystemPrompt(context = 'os', userInput = '') {
74
- const config = (0, parser_1.loadConfig)();
75
- const currentDateTime = new Date().toLocaleString('en-US');
76
- let basePrompt = `You are Nyxora's OS Agent (System & Automation Specialist).
77
- The current real-world date and time is: ${currentDateTime}.
78
-
79
- You are running LOCALLY on the user's own computer — NOT on a remote cloud server. The 'run_terminal_command' tool executes shell commands directly on this machine, the same physical machine the user is sitting at. You have FULL local shell access. When asked to install software, manage files, or perform any OS task, you MUST use run_terminal_command immediately. NEVER claim you cannot access the user's system.
80
-
81
- Reason internally. Never reveal private reasoning. Provide only concise conclusions, assumptions, and actionable steps.
82
-
83
- [OS EXECUTION WORKFLOW]
84
- CRITICAL RULE 1: NEVER expose internal JSON tool calls. Explain the outcome naturally.
85
- 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.
86
- 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.
87
- 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.
88
- CRITICAL RULE 5: TOOL CONFIDENCE. NEVER fabricate file contents or command outputs.
89
-
90
- [SUDO & PACKAGE INSTALL STRATEGY]
91
- This tool runs in a NON-INTERACTIVE shell (no TTY). Therefore:
92
- - ALWAYS prefix apt/apt-get commands with: DEBIAN_FRONTEND=noninteractive
93
- - ALWAYS use the -y flag for package installations to auto-confirm.
94
- - If a command fails with "sudo: a password is required" or similar, DO NOT promise to retry without actually retrying. Instead:
95
- 1. First retry with: echo 'USER_PASSWORD' | sudo -S <command> — but since you don't know the password, skip this.
96
- 2. Instead, try running the command WITHOUT sudo if possible (e.g. for user-space tools).
97
- 3. If sudo is truly required and unavailable, clearly tell the user EXACTLY what command to run manually in their terminal, with a copy-paste ready command. Do not just say it failed without providing a solution.
98
- - NEVER promise to retry ("let me try again", "I'll run it again", etc.) without immediately making another tool_call in the same response.
99
-
100
- ${EXECUTION_DISCIPLINE}
101
- `;
102
- // Inject Active Cognitive Skills
103
- const activeSOP = cognitiveManager_1.cognitiveManager.loadActiveCognitiveSkills(userInput);
104
- if (activeSOP) {
105
- basePrompt += `\n\n[ACTIVE COGNITIVE SKILLS]\n${activeSOP}\n`;
106
- }
107
- // Inject Episodic Memories via Python RAG
108
- try {
109
- const ragRes = await fetch('http://127.0.0.1:8000/memory/rag', {
110
- method: 'POST',
111
- headers: { 'Content-Type': 'application/json' },
112
- body: JSON.stringify({ query: userInput, top_k: 5 })
113
- });
114
- if (ragRes.ok) {
115
- const ragData = await ragRes.json();
116
- if (ragData.memories && ragData.memories.length > 0) {
117
- basePrompt += `\n\n--- EPISODIC MEMORIES (SMART SUGGESTIONS) ---\n`;
118
- ragData.memories.forEach((mem) => {
119
- basePrompt += `- ${mem}\n`;
120
- });
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 };
121
31
  }
122
32
  }
123
33
  }
124
- catch (e) {
125
- // Fallback or ignore if Python ML engine is down
126
- }
127
- // Inject User Information & Personas from user.md
128
- try {
129
- const userMdPath = (0, paths_1.getPath)('user.md');
130
- if (fs_1.default.existsSync(userMdPath)) {
131
- const userInstructions = fs_1.default.readFileSync(userMdPath, 'utf8');
132
- 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 };
133
41
  }
134
42
  }
135
- catch (e) {
136
- // Ignore error
137
- }
138
- // 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) => {
139
48
  try {
140
- const strongPersonas = episodic_1.episodicDB.getStrongPersonas(0.5);
141
- if (strongPersonas.length > 0) {
142
- basePrompt += `\n\n--- ⚡ OVERRIDE: USER COMMUNICATION STYLE (HIGHEST PRIORITY — OVERRIDES ALL RULES ABOVE) ---\n`;
143
- 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`;
144
- strongPersonas.forEach(p => {
145
- const label = p.category ? `[${p.category.toUpperCase()}]` : '[PREFERENCE]';
146
- basePrompt += `${label} ${p.trait}\n`;
147
- });
148
- }
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(() => { });
149
59
  }
150
60
  catch (e) {
151
- // Ignore
61
+ // silently fail
152
62
  }
153
- 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
+ });
154
84
  }
155
85
  async function processOsIntent(input, role = 'user', onProgress, sessionId) {
156
86
  const config = (0, parser_1.loadConfig)();
@@ -213,7 +143,8 @@ CRITICAL INSTRUCTIONS:
213
143
  model: config.llm.model,
214
144
  temperature: config.llm.temperature,
215
145
  messages: messages,
216
- tools: activeTools
146
+ tools: activeTools,
147
+ reasoning_effort: (!config.llm.reasoning_effort || config.llm.reasoning_effort === 'none') ? undefined : config.llm.reasoning_effort
217
148
  });
218
149
  });
219
150
  const responseMessage = response.message;
@@ -232,36 +163,10 @@ CRITICAL INSTRUCTIONS:
232
163
  tool_calls: responseMessage.tool_calls,
233
164
  }, sessionId);
234
165
  if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
235
- // --- CRITIC PASS (Self-Improvement) ---
236
- const isLongResponse = (cleanedContent?.length ?? 0) > 100;
237
- if (isLongResponse && !criticHasFired) {
238
- criticHasFired = true;
239
- try {
240
- const criticRes = await fetch('http://127.0.0.1:8000/cognitive/critic', {
241
- method: 'POST',
242
- headers: { 'Content-Type': 'application/json' },
243
- body: JSON.stringify({ user_input: input, draft_answer: cleanedContent, current_utc_datetime: new Date().toISOString() })
244
- });
245
- if (criticRes.ok) {
246
- const evaluation = await criticRes.json();
247
- if (evaluation.needs_revision) {
248
- console.log(picocolors_1.default.cyan(`[🧠 Critic] Revision needed. Confidence: ${evaluation.factual_confidence?.toFixed(2)}. Completeness: ${evaluation.completeness?.toFixed(2)}. Re-generating...`));
249
- exports.logger.addEntry({
250
- role: 'system',
251
- content: `[SELF-CRITIQUE — MANDATORY REVISION] Your previous answer was REJECTED. Issues:\n${evaluation.revision_instructions}\n\nCRITICAL REVISION RULES:\n1. Look at the tool results (search_web, etc.) ALREADY in this conversation history above.\n2. Base your revised answer EXCLUSIVELY on those tool results — NEVER use training data memory for facts, dates, or events.\n3. If tool results contain the answer, state it directly and confidently. Do NOT say an event hasn't happened if the tool results show it has.\n4. Do NOT call any tools again — the results are already in your history. USE THEM NOW.`
252
- }, sessionId);
253
- continue; // Loop kembali ke Generator untuk revisi
254
- }
255
- else {
256
- console.log(picocolors_1.default.green(`[🧠 Critic] Passed. Confidence: ${evaluation.factual_confidence?.toFixed(2)}, Completeness: ${evaluation.completeness?.toFixed(2)}.`));
257
- }
258
- }
259
- }
260
- catch {
261
- // Python ML Engine tidak aktif — skip Critic, lanjut seperti biasa
262
- }
263
- }
264
- // --- END CRITIC PASS ---
166
+ // --- CRITIC PASS REMOVED ---
167
+ // The new PromptBuilder handles robust reasoning. Post-generation critic
168
+ // causes aggressive loops and UI artifacts.
169
+ triggerBackgroundReview(sessionId);
265
170
  return cleanedContent || 'No response generated.';
266
171
  }
267
172
  let canFastReturnAll = true;
@@ -270,7 +175,7 @@ CRITICAL INSTRUCTIONS:
270
175
  const fastReturnTools = [
271
176
  'transfer_token', 'transfer_native', 'swap_token', 'bridge_token',
272
177
  'mint_nft', 'custom_tx', 'revoke_approval', 'supply_aave',
273
- 'deposit_yield_vault', 'provide_liquidity_v3'
178
+ 'deposit_yield_vault', 'provide_liquidity_v3', 'send_telegram_file'
274
179
  ];
275
180
  for (const _toolCall of responseMessage.tool_calls) {
276
181
  const toolCall = _toolCall;
@@ -335,7 +240,7 @@ CRITICAL INSTRUCTIONS:
335
240
  content: result,
336
241
  }, sessionId);
337
242
  accumulatedResults.push(result);
338
- 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)) {
339
244
  canFastReturnAll = false;
340
245
  }
341
246
  }
@@ -352,6 +257,7 @@ CRITICAL INSTRUCTIONS:
352
257
  if (consecutiveToolErrors >= 2) {
353
258
  const errorSummary = `⚠️ Unable to complete this request after multiple attempts.\n${accumulatedResults.join('\n')}`;
354
259
  exports.logger.addEntry({ role: 'assistant', content: errorSummary }, sessionId);
260
+ triggerBackgroundReview(sessionId);
355
261
  return errorSummary;
356
262
  }
357
263
  }
@@ -362,12 +268,14 @@ CRITICAL INSTRUCTIONS:
362
268
  if (canFastReturnAll && accumulatedResults.length > 0) {
363
269
  const finalContent = accumulatedResults.join('\n\n---\n\n');
364
270
  exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
271
+ triggerBackgroundReview(sessionId);
365
272
  return finalContent;
366
273
  }
367
274
  // Loop continues, sending tool results in the next turn
368
275
  }
369
276
  const maxTurnMsg = "⚠️ Reached maximum interaction limit (10 turns). Please be more specific.";
370
277
  exports.logger.addEntry({ role: 'assistant', content: maxTurnMsg }, sessionId);
278
+ triggerBackgroundReview(sessionId);
371
279
  return maxTurnMsg;
372
280
  }
373
281
  catch (error) {
@@ -426,7 +334,9 @@ CRITICAL INSTRUCTIONS:
426
334
  ];
427
335
  let streamedContent = '';
428
336
  const response = await (0, llmUtils_1.executeWithRetry)(async (client) => {
429
- 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) => {
430
340
  streamedContent += chunk;
431
341
  onChunk(chunk);
432
342
  });
@@ -440,53 +350,28 @@ CRITICAL INSTRUCTIONS:
440
350
  exports.logger.addEntry({
441
351
  role: 'assistant',
442
352
  content: responseMessage.content || '',
353
+ reasoning_content: responseMessage.reasoning_content,
443
354
  tool_calls: responseMessage.tool_calls,
444
355
  }, sessionId);
445
356
  if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
446
357
  let finalContent = responseMessage.content || 'No response generated.';
447
358
  finalContent = finalContent.replace(/<(think|thought|thinking|reasoning|analysis|reflection)[\s\S]*?<\/\1>\n?/gi, '').trim();
448
- // --- CRITIC PASS (Self-Improvement) ---
449
- const isLongResponseStream = finalContent.length > 100;
450
- if (isLongResponseStream && !criticHasFiredStream) {
451
- criticHasFiredStream = true;
452
- try {
453
- const criticRes = await fetch('http://127.0.0.1:8000/cognitive/critic', {
454
- method: 'POST',
455
- headers: { 'Content-Type': 'application/json' },
456
- body: JSON.stringify({ user_input: input, draft_answer: finalContent, current_utc_datetime: new Date().toISOString() })
457
- });
458
- if (criticRes.ok) {
459
- const evaluation = await criticRes.json();
460
- if (evaluation.needs_revision) {
461
- console.log(picocolors_1.default.cyan(`[🧠 Critic] Revision needed. Confidence: ${evaluation.factual_confidence?.toFixed(2)}. Completeness: ${evaluation.completeness?.toFixed(2)}. Re-generating...`));
462
- exports.logger.addEntry({
463
- role: 'system',
464
- content: `[SELF-CRITIQUE — MANDATORY REVISION] Your previous answer was REJECTED. Issues:\n${evaluation.revision_instructions}\n\nCRITICAL REVISION RULES:\n1. Look at the tool results (search_web, etc.) ALREADY in this conversation history above.\n2. Base your revised answer EXCLUSIVELY on those tool results — NEVER use training data memory for facts, dates, or events.\n3. If tool results contain the answer, state it directly and confidently. Do NOT say an event hasn't happened if the tool results show it has.\n4. Do NOT call any tools again — the results are already in your history. USE THEM NOW.`
465
- }, sessionId);
466
- continue; // Loop kembali ke Generator untuk revisi
467
- }
468
- else {
469
- console.log(picocolors_1.default.green(`[🧠 Critic] Passed. Confidence: ${evaluation.factual_confidence?.toFixed(2)}, Completeness: ${evaluation.completeness?.toFixed(2)}.`));
470
- }
471
- }
472
- }
473
- catch {
474
- // Python ML Engine tidak aktif — skip Critic, lanjut seperti biasa
475
- }
476
- }
477
- // --- END CRITIC PASS ---
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.
478
362
  fullResponse = finalContent;
363
+ triggerBackgroundReview(sessionId);
479
364
  break;
480
365
  }
481
- // Tool calls detected — pause stream visually and execute tools
482
- const fastReturnTools = ['transfer_token', 'transfer_native', 'swap_token', 'bridge_token', 'mint_nft', 'custom_tx', 'revoke_approval', 'supply_aave', 'deposit_yield_vault', 'provide_liquidity_v3'];
483
- let canFastReturnAll = true;
366
+ // Tool calls detected — pause stream visually and execute tools concurrently
367
+ let shouldFastReturn = false;
484
368
  const accumulatedResults = [];
485
- for (const _toolCall of responseMessage.tool_calls) {
369
+ const promises = responseMessage.tool_calls.map(async (_toolCall) => {
486
370
  const toolCall = _toolCall;
487
371
  const toolName = toolCall.function.name;
488
372
  let result = '';
489
373
  let args = {};
374
+ const context = { sessionId, toolCallId: toolCall.id, responseMessage };
490
375
  console.log(picocolors_1.default.yellow(`[⚡ Tool Execution] AI is calling ${toolName}...`));
491
376
  if (onProgress)
492
377
  onProgress(`_⚡ Running tool: ${toolName}..._`);
@@ -499,17 +384,28 @@ CRITICAL INSTRUCTIONS:
499
384
  catch (parseError) {
500
385
  result = `[System Error] Arguments for ${toolName} must be valid JSON. Error: ${parseError.message}`;
501
386
  exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
502
- continue;
387
+ return { toolName, result };
503
388
  }
504
389
  if (!(0, skillManager_1.isSkillActive)(toolName)) {
505
390
  result = `[System Error] Access denied: Skill '${toolName}' is currently disabled.`;
506
391
  exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
507
- 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 };
508
400
  }
509
401
  try {
510
- 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
+ });
511
407
  result = pluginResult !== null ? pluginResult : `Error: Tool ${toolName} is not implemented.`;
512
- if (result.includes('[Security Blocked]') || result.startsWith('Error:')) {
408
+ if (typeof result === 'string' && (result.includes('[Security Blocked]') || result.startsWith('Error:'))) {
513
409
  console.log(picocolors_1.default.red(`[❌ Failed] Tool ${toolName} returned an error or was blocked.`));
514
410
  }
515
411
  else {
@@ -520,16 +416,23 @@ CRITICAL INSTRUCTIONS:
520
416
  result = `Error executing ${toolName}: ${toolError.message}`;
521
417
  console.error(picocolors_1.default.red(`[❌ Error Crash] Execution of ${toolName} failed: ${toolError.message}`));
522
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
+ }
523
425
  exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, name: toolName, content: result }, sessionId);
524
- accumulatedResults.push(result);
525
- if (!fastReturnTools.includes(toolName))
526
- canFastReturnAll = false;
527
- }
528
- 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) {
529
431
  const finalContent = accumulatedResults.join('\n\n---\n\n');
530
432
  exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
531
433
  onChunk(finalContent);
532
434
  fullResponse = finalContent;
435
+ triggerBackgroundReview(sessionId);
533
436
  break;
534
437
  }
535
438
  }
@@ -537,6 +440,7 @@ CRITICAL INSTRUCTIONS:
537
440
  const maxTurnMsg = '⚠️ Reached maximum interaction limit (10 turns). Please be more specific.';
538
441
  exports.logger.addEntry({ role: 'assistant', content: maxTurnMsg }, sessionId);
539
442
  fullResponse = maxTurnMsg;
443
+ triggerBackgroundReview(sessionId);
540
444
  }
541
445
  return fullResponse;
542
446
  }