nyxora 26.7.2 → 26.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -47
- package/README.md +25 -21
- package/bin/nyxora.mjs +4 -6
- package/dist/launcher.js +44 -8
- package/dist/packages/core/src/agent/bridgeWatcher.js +3 -2
- package/dist/packages/core/src/agent/cronManager.js +2 -2
- package/dist/packages/core/src/agent/llmProvider.js +245 -0
- package/dist/packages/core/src/agent/nyxDaemon.js +97 -0
- package/dist/packages/core/src/agent/osAgent.js +351 -29
- package/dist/packages/core/src/agent/reasoning.js +353 -60
- package/dist/packages/core/src/agent/reasoningScratchpad.js +47 -0
- package/dist/packages/core/src/agent/transactionManager.js +36 -31
- package/dist/packages/core/src/agent/web3Agent.js +263 -37
- package/dist/packages/core/src/cognitive/cognitiveManager.js +63 -10
- package/dist/packages/core/src/config/parser.js +10 -4
- package/dist/packages/core/src/gateway/chat.js +56 -13
- package/dist/packages/core/src/gateway/cli.js +3 -0
- package/dist/packages/core/src/gateway/discordAdapter.js +81 -0
- package/dist/packages/core/src/gateway/googleAuthModule.js +2 -0
- package/dist/packages/core/src/gateway/server.js +58 -9
- package/dist/packages/core/src/gateway/setup-ml.js +64 -0
- package/dist/packages/core/src/gateway/setup.js +39 -3
- package/dist/packages/core/src/gateway/telegram.js +123 -27
- package/dist/packages/core/src/memory/episodic.js +58 -3
- package/dist/packages/core/src/memory/logger.js +120 -2
- package/dist/packages/core/src/memory/promotionEngine.js +18 -5
- package/dist/packages/core/src/system/agentskills.js +10 -0
- package/dist/packages/core/src/system/plugins/GoogleWorkspacePlugin.js +10 -2
- package/dist/packages/core/src/system/plugins/SystemCorePlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemExternalPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemPluginInstallerPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemSocialPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemWebPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemWorkspacePlugin.js +3 -3
- package/dist/packages/core/src/system/plugins/createSkill.js +1 -1
- package/dist/packages/core/src/system/skillExtractor.js +16 -5
- package/dist/packages/core/src/system/skills/executeShell.js +31 -4
- package/dist/packages/core/src/system/skills/forgetMemory.js +6 -4
- package/dist/packages/core/src/system/skills/googleWorkspace.js +106 -1
- package/dist/packages/core/src/system/skills/scheduleTask.js +7 -2
- package/dist/packages/core/src/system/skills/searchWeb.js +13 -6
- package/dist/packages/core/src/test_mainnet.js +45 -0
- package/dist/packages/core/src/utils/contextSummarizer.js +82 -0
- package/dist/packages/core/src/utils/skillManager.js +1 -1
- package/dist/packages/core/src/utils/streamSimulator.js +85 -0
- package/dist/packages/core/src/web3/aggregator/providers/ArbitrumBridgeProvider.js +28 -11
- package/dist/packages/core/src/web3/aggregator/providers/OpBridgeProvider.js +41 -27
- package/dist/packages/core/src/web3/aggregator/providers/TestnetSwapProvider.js +65 -0
- package/dist/packages/core/src/web3/aggregator/routeSelector.js +7 -1
- package/dist/packages/core/src/web3/plugins/Web3DefiPlugin.js +1 -1
- package/dist/packages/core/src/web3/plugins/Web3MarketPlugin.js +5 -125
- package/dist/packages/core/src/web3/plugins/Web3SecurityPlugin.js +1 -1
- package/dist/packages/core/src/web3/plugins/Web3WalletPlugin.js +1 -1
- package/dist/packages/core/src/web3/skills/bridgeToken.js +19 -4
- package/dist/packages/core/src/web3/skills/checkAddress.js +2 -0
- package/dist/packages/core/src/web3/skills/checkPortfolio.js +22 -2
- package/dist/packages/core/src/web3/skills/checkSecurity.js +2 -0
- package/dist/packages/core/src/web3/skills/confirmPendingTx.js +1 -1
- package/dist/packages/core/src/web3/skills/createLimitOrder.js +15 -1
- package/dist/packages/core/src/web3/skills/customTx.js +3 -0
- package/dist/packages/core/src/web3/skills/defiLending.js +2 -0
- package/dist/packages/core/src/web3/skills/getBalance.js +2 -0
- package/dist/packages/core/src/web3/skills/getPrice.js +134 -27
- package/dist/packages/core/src/web3/skills/getTxHistory.js +2 -0
- package/dist/packages/core/src/web3/skills/marketAnalysis.js +28 -191
- package/dist/packages/core/src/web3/skills/mintNft.js +3 -0
- package/dist/packages/core/src/web3/skills/provideLiquidity.js +16 -12
- package/dist/packages/core/src/web3/skills/revokeApprovals.js +2 -0
- package/dist/packages/core/src/web3/skills/swapToken.js +20 -2
- package/dist/packages/core/src/web3/skills/transfer.js +2 -0
- package/dist/packages/core/src/web3/skills/yieldVault.js +2 -0
- package/dist/packages/core/src/web3/utils/chains.js +19 -0
- package/dist/packages/core/src/web3/utils/marketEngine.js +26 -33
- package/dist/packages/signer/src/NyxoraSigner.js +181 -0
- package/dist/packages/signer/src/index.js +17 -0
- package/dist/packages/signer/src/server.js +25 -161
- package/launcher.ts +38 -9
- package/package.json +8 -3
- package/packages/core/package.json +21 -10
- package/packages/core/src/agent/bridgeWatcher.ts +3 -2
- package/packages/core/src/agent/cronManager.ts +2 -2
- package/packages/core/src/agent/llmProvider.ts +221 -0
- package/packages/core/src/agent/nyxDaemon.ts +104 -0
- package/packages/core/src/agent/osAgent.ts +381 -32
- package/packages/core/src/agent/reasoning.ts +376 -64
- package/packages/core/src/agent/reasoningScratchpad.ts +45 -0
- package/packages/core/src/agent/transactionManager.ts +36 -28
- package/packages/core/src/agent/web3Agent.ts +291 -40
- package/packages/core/src/cognitive/cognitiveManager.ts +65 -10
- package/packages/core/src/cognitive/prompts/web3/market-analysis.md +24 -0
- package/packages/core/src/cognitive/prompts/web3/portfolio-review.md +29 -0
- package/packages/core/src/cognitive/prompts/web3/risk-assessment.md +28 -0
- package/packages/core/src/cognitive/prompts/web3/trade-planning.md +30 -0
- package/packages/core/src/config/parser.ts +15 -4
- package/packages/core/src/gateway/chat.ts +57 -15
- package/packages/core/src/gateway/cli.ts +4 -0
- package/packages/core/src/gateway/discordAdapter.ts +87 -0
- package/packages/core/src/gateway/googleAuthModule.ts +2 -0
- package/packages/core/src/gateway/server.ts +66 -10
- package/packages/core/src/gateway/setup-ml.ts +68 -0
- package/packages/core/src/gateway/setup.ts +41 -3
- package/packages/core/src/gateway/telegram.ts +141 -30
- package/packages/core/src/memory/episodic.ts +76 -3
- package/packages/core/src/memory/logger.ts +142 -2
- package/packages/core/src/memory/promotionEngine.ts +19 -5
- package/packages/core/src/system/agentskills.ts +10 -0
- package/packages/core/src/system/plugins/GoogleWorkspacePlugin.ts +15 -3
- package/packages/core/src/system/plugins/SystemCorePlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemExternalPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemPluginInstallerPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemSocialPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemWebPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemWorkspacePlugin.ts +3 -3
- package/packages/core/src/system/plugins/createSkill.ts +1 -1
- package/packages/core/src/system/skillExtractor.ts +16 -5
- package/packages/core/src/system/skills/executeShell.ts +38 -7
- package/packages/core/src/system/skills/forgetMemory.ts +7 -4
- package/packages/core/src/system/skills/googleWorkspace.ts +109 -0
- package/packages/core/src/system/skills/scheduleTask.ts +7 -2
- package/packages/core/src/system/skills/searchWeb.ts +12 -6
- package/packages/core/src/utils/contextSummarizer.ts +100 -0
- package/packages/core/src/utils/skillManager.ts +1 -1
- package/packages/core/src/utils/streamSimulator.ts +88 -0
- package/packages/core/src/web3/aggregator/providers/ArbitrumBridgeProvider.ts +30 -11
- package/packages/core/src/web3/aggregator/providers/OpBridgeProvider.ts +43 -29
- package/packages/core/src/web3/aggregator/routeSelector.ts +6 -1
- package/packages/core/src/web3/plugins/Web3DefiPlugin.ts +1 -1
- package/packages/core/src/web3/plugins/Web3MarketPlugin.ts +6 -125
- package/packages/core/src/web3/plugins/Web3SecurityPlugin.ts +1 -1
- package/packages/core/src/web3/plugins/Web3WalletPlugin.ts +1 -1
- package/packages/core/src/web3/skills/bridgeToken.ts +21 -7
- package/packages/core/src/web3/skills/checkAddress.ts +2 -0
- package/packages/core/src/web3/skills/checkPortfolio.ts +23 -2
- package/packages/core/src/web3/skills/checkSecurity.ts +2 -0
- package/packages/core/src/web3/skills/confirmPendingTx.ts +1 -1
- package/packages/core/src/web3/skills/createLimitOrder.ts +17 -2
- package/packages/core/src/web3/skills/customTx.ts +3 -0
- package/packages/core/src/web3/skills/defiLending.ts +2 -0
- package/packages/core/src/web3/skills/getBalance.ts +2 -0
- package/packages/core/src/web3/skills/getPrice.ts +134 -30
- package/packages/core/src/web3/skills/getTxHistory.ts +2 -0
- package/packages/core/src/web3/skills/marketAnalysis.ts +45 -188
- package/packages/core/src/web3/skills/mintNft.ts +3 -0
- package/packages/core/src/web3/skills/provideLiquidity.ts +16 -10
- package/packages/core/src/web3/skills/revokeApprovals.ts +2 -0
- package/packages/core/src/web3/skills/swapToken.ts +20 -3
- package/packages/core/src/web3/skills/transfer.ts +2 -0
- package/packages/core/src/web3/skills/yieldVault.ts +2 -0
- package/packages/core/src/web3/utils/chains.ts +12 -0
- package/packages/core/src/web3/utils/marketEngine.ts +27 -33
- package/packages/dashboard/dist/assets/index-Czxksiao.js +18 -0
- package/packages/dashboard/dist/assets/index-DK2sTU47.css +1 -0
- package/packages/dashboard/dist/index.html +2 -2
- package/packages/dashboard/package.json +10 -10
- package/packages/mcp-server/dist/server.js +5 -1
- package/packages/mcp-server/package.json +6 -6
- package/packages/mcp-server/src/server.ts +11 -7
- package/packages/ml-engine/__pycache__/config.cpython-313.pyc +0 -0
- package/packages/ml-engine/__pycache__/main.cpython-313.pyc +0 -0
- package/packages/ml-engine/config.py +59 -0
- package/packages/ml-engine/main.py +34 -0
- package/packages/ml-engine/requirements.txt +22 -0
- package/packages/ml-engine/routers/__init__.py +1 -0
- package/packages/ml-engine/routers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/packages/ml-engine/routers/__pycache__/cognitive.cpython-313.pyc +0 -0
- package/packages/ml-engine/routers/__pycache__/critic.cpython-313.pyc +0 -0
- package/packages/ml-engine/routers/__pycache__/llm.cpython-313.pyc +0 -0
- package/packages/ml-engine/routers/__pycache__/market.cpython-313.pyc +0 -0
- package/packages/ml-engine/routers/__pycache__/memory.cpython-313.pyc +0 -0
- package/packages/ml-engine/routers/cognitive.py +98 -0
- package/packages/ml-engine/routers/critic.py +111 -0
- package/packages/ml-engine/routers/llm.py +38 -0
- package/packages/ml-engine/routers/market.py +332 -0
- package/packages/ml-engine/routers/memory.py +125 -0
- package/packages/policy/package.json +3 -3
- package/packages/signer/package.json +16 -6
- package/packages/signer/src/NyxoraSigner.ts +161 -0
- package/packages/signer/src/index.ts +1 -0
- package/packages/signer/src/server.ts +25 -135
- package/dist/packages/core/src/agent/honchoDaemon.js +0 -91
- package/dist/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +0 -54
- package/dist/packages/core/src/gateway/test.js +0 -15
- package/dist/packages/core/src/web3/Web3DefiPlugin.js +0 -28
- package/dist/packages/core/src/web3/aggregator/aggregatorMainnet.js +0 -260
- package/dist/packages/core/src/web3/aggregator/aggregatorTestnet.js +0 -119
- package/dist/packages/core/src/web3/skills/nativeOpBridge.js +0 -71
- package/packages/core/src/agent/honchoDaemon.ts +0 -96
- package/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +0 -41
- package/packages/core/src/plugin/registry.test.ts +0 -46
- package/packages/core/src/utils/formatter.test.ts +0 -41
- package/packages/dashboard/dist/assets/index-CSoNa5cx.css +0 -1
- package/packages/dashboard/dist/assets/index-DbRWEoSr.js +0 -16
|
@@ -5,12 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.logger = void 0;
|
|
7
7
|
exports.processOsIntent = processOsIntent;
|
|
8
|
+
exports.processOsIntentStream = processOsIntentStream;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
10
|
const parser_1 = require("../config/parser");
|
|
9
11
|
const logger_1 = require("../memory/logger");
|
|
10
12
|
const tracker_1 = require("../gateway/tracker");
|
|
11
13
|
const episodic_1 = require("../memory/episodic");
|
|
12
14
|
const skillManager_1 = require("../utils/skillManager");
|
|
13
15
|
const cognitiveManager_1 = require("../cognitive/cognitiveManager");
|
|
16
|
+
const reasoningScratchpad_1 = require("./reasoningScratchpad");
|
|
17
|
+
const contextSummarizer_1 = require("../utils/contextSummarizer");
|
|
14
18
|
const EXECUTION_DISCIPLINE = `
|
|
15
19
|
<tool_persistence>
|
|
16
20
|
Use tools whenever they can increase the accuracy, completeness, or factual correctness of your response.
|
|
@@ -26,34 +30,73 @@ NEVER answer the following using only your internal memory — ALWAYS use the re
|
|
|
26
30
|
- Real-world current events
|
|
27
31
|
</mandatory_tool_use>
|
|
28
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
|
+
|
|
29
40
|
<act_dont_ask>
|
|
30
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.
|
|
31
47
|
</act_dont_ask>
|
|
32
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
|
+
|
|
33
57
|
<task_completion>
|
|
34
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.
|
|
35
59
|
NEVER fabricate, hallucinate, or forge tool outputs.
|
|
36
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>
|
|
37
67
|
`;
|
|
38
68
|
const registry_1 = require("../plugin/registry");
|
|
69
|
+
const paths_1 = require("../config/paths");
|
|
39
70
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
40
71
|
exports.logger = new logger_1.Logger();
|
|
41
72
|
const llmUtils_1 = require("../utils/llmUtils");
|
|
42
|
-
function getSystemPrompt(context = 'os', userInput = '') {
|
|
73
|
+
async function getSystemPrompt(context = 'os', userInput = '') {
|
|
43
74
|
const config = (0, parser_1.loadConfig)();
|
|
44
75
|
const currentDateTime = new Date().toLocaleString('en-US');
|
|
45
76
|
let basePrompt = `You are Nyxora's OS Agent (System & Automation Specialist).
|
|
46
77
|
The current real-world date and time is: ${currentDateTime}.
|
|
47
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
|
+
|
|
48
81
|
Reason internally. Never reveal private reasoning. Provide only concise conclusions, assumptions, and actionable steps.
|
|
49
82
|
|
|
50
83
|
[OS EXECUTION WORKFLOW]
|
|
51
84
|
CRITICAL RULE 1: NEVER expose internal JSON tool calls. Explain the outcome naturally.
|
|
52
|
-
CRITICAL RULE 2: STRICT LANGUAGE MATCHING. Reply in the exact same language as the user's LATEST prompt.
|
|
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.
|
|
53
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.
|
|
54
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.
|
|
55
88
|
CRITICAL RULE 5: TOOL CONFIDENCE. NEVER fabricate file contents or command outputs.
|
|
56
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
|
+
|
|
57
100
|
${EXECUTION_DISCIPLINE}
|
|
58
101
|
`;
|
|
59
102
|
// Inject Active Cognitive Skills
|
|
@@ -61,46 +104,108 @@ ${EXECUTION_DISCIPLINE}
|
|
|
61
104
|
if (activeSOP) {
|
|
62
105
|
basePrompt += `\n\n[ACTIVE COGNITIVE SKILLS]\n${activeSOP}\n`;
|
|
63
106
|
}
|
|
64
|
-
// Inject Episodic Memories
|
|
107
|
+
// Inject Episodic Memories via Python RAG
|
|
65
108
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`;
|
|
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
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
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`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
// Ignore error
|
|
137
|
+
}
|
|
138
|
+
// HIGHEST PRIORITY: Inject observed user communication style (NyxDaemon)
|
|
139
|
+
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`;
|
|
75
147
|
});
|
|
76
148
|
}
|
|
77
149
|
}
|
|
78
|
-
catch {
|
|
150
|
+
catch (e) {
|
|
151
|
+
// Ignore
|
|
152
|
+
}
|
|
79
153
|
return basePrompt;
|
|
80
154
|
}
|
|
81
155
|
async function processOsIntent(input, role = 'user', onProgress, sessionId) {
|
|
82
156
|
const config = (0, parser_1.loadConfig)();
|
|
83
157
|
// Add input to memory
|
|
84
158
|
exports.logger.addEntry({ role, content: input }, sessionId);
|
|
85
|
-
|
|
86
|
-
|
|
159
|
+
// --- MULTILINGUAL USER CORRECTION DETECTION ---
|
|
160
|
+
const correctionSignals = [
|
|
161
|
+
// ID
|
|
162
|
+
'salah', 'ngawur', 'keliru', 'bukan', 'tidak benar', 'perbaiki', 'coba lagi',
|
|
163
|
+
// EN
|
|
164
|
+
'wrong', 'incorrect', 'mistake', 'not right', 'false', 'bad', 'fix', 'try again',
|
|
165
|
+
// ES & FR
|
|
166
|
+
'incorrecto', 'mal', 'equivocado', 'error', 'falso', 'faux', 'erreur', 'mauvais',
|
|
167
|
+
// DE & RU
|
|
168
|
+
'falsch', 'inkorrekt', 'fehler', 'ошибка', 'неправильно', 'неверно',
|
|
169
|
+
// JP & ZH
|
|
170
|
+
'違う', '間違い', 'やり直して', '错误', '不对'
|
|
171
|
+
];
|
|
172
|
+
if (role === 'user' && correctionSignals.some(s => input.toLowerCase().includes(s))) {
|
|
173
|
+
exports.logger.addEntry({
|
|
174
|
+
role: 'system',
|
|
175
|
+
content: `[USER CORRECTION DETECTED] The user indicated your previous answer was WRONG, STALE, or INACCURATE.
|
|
176
|
+
CRITICAL INSTRUCTIONS:
|
|
177
|
+
1. Do NOT just apologize and repeat the same data from your memory.
|
|
178
|
+
2. The data in your training memory or previous tool calls is likely stale/incorrect.
|
|
179
|
+
3. You MUST call a tool (like search_web or others) NOW to verify the facts with FRESH data.
|
|
180
|
+
4. Base your new answer strictly on the NEW tool results.`
|
|
181
|
+
}, sessionId);
|
|
182
|
+
}
|
|
87
183
|
let activeTools = [...registry_1.pluginManager.getAllToolDefinitions()];
|
|
88
184
|
activeTools = activeTools.filter(t => (0, skillManager_1.isSkillActive)(t.function.name));
|
|
185
|
+
// P1: Init reasoning scratchpad for this request
|
|
186
|
+
const scratchpad = new reasoningScratchpad_1.ReasoningScratchpad();
|
|
187
|
+
// P3: Build system prompt ONCE per request — not per turn
|
|
188
|
+
const cachedSystemPrompt = await getSystemPrompt('os', input);
|
|
89
189
|
const { sanitizeHistoryForLLM } = require('../utils/historySanitizer');
|
|
90
|
-
const sanitizedHistory = sanitizeHistoryForLLM(history, activeTools, config.llm.provider);
|
|
91
|
-
let messages = [
|
|
92
|
-
{ role: 'system', content: getSystemPrompt('os', input) },
|
|
93
|
-
...sanitizedHistory
|
|
94
|
-
];
|
|
95
190
|
try {
|
|
96
191
|
let turnCount = 0;
|
|
97
192
|
const MAX_TURNS = 10;
|
|
193
|
+
let consecutiveToolErrors = 0;
|
|
194
|
+
let criticHasFired = false; // Critic Pass hanya aktif 1x per request
|
|
98
195
|
while (turnCount < MAX_TURNS) {
|
|
99
196
|
turnCount++;
|
|
100
197
|
const currentHistory = exports.logger.getHistory(sessionId);
|
|
101
|
-
|
|
198
|
+
// P6: Compress history if conversation is too long
|
|
199
|
+
const historyToUse = (0, contextSummarizer_1.needsCompression)(currentHistory)
|
|
200
|
+
? await (0, contextSummarizer_1.compressHistory)(currentHistory)
|
|
201
|
+
: currentHistory;
|
|
202
|
+
const sanitizedHistory = sanitizeHistoryForLLM(historyToUse, activeTools, config.llm.provider);
|
|
203
|
+
// P1: Inject scratchpad into system prompt for turns > 1
|
|
204
|
+
const sysPrompt = turnCount === 1
|
|
205
|
+
? cachedSystemPrompt
|
|
206
|
+
: cachedSystemPrompt + scratchpad.getInjection();
|
|
102
207
|
const messages = [
|
|
103
|
-
{ role: 'system', content:
|
|
208
|
+
{ role: 'system', content: sysPrompt },
|
|
104
209
|
...sanitizedHistory
|
|
105
210
|
];
|
|
106
211
|
const response = await (0, llmUtils_1.executeWithRetry)(async (client) => {
|
|
@@ -119,16 +224,45 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
|
|
|
119
224
|
tracker_1.Tracker.addTokens(response.usage.total_tokens, config.llm.provider);
|
|
120
225
|
}
|
|
121
226
|
tracker_1.Tracker.addEvent('llm.response', { provider: config.llm.provider, tool_calls: responseMessage.tool_calls?.length || 0 });
|
|
227
|
+
// P1: Capture <think> blocks for scratchpad, get clean content
|
|
228
|
+
const cleanedContent = scratchpad.capture(responseMessage.content || '', turnCount);
|
|
122
229
|
exports.logger.addEntry({
|
|
123
230
|
role: 'assistant',
|
|
124
|
-
content:
|
|
231
|
+
content: cleanedContent || '',
|
|
125
232
|
tool_calls: responseMessage.tool_calls,
|
|
126
233
|
}, sessionId);
|
|
127
234
|
if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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 ---
|
|
265
|
+
return cleanedContent || 'No response generated.';
|
|
132
266
|
}
|
|
133
267
|
let canFastReturnAll = true;
|
|
134
268
|
let accumulatedResults = [];
|
|
@@ -205,8 +339,26 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
|
|
|
205
339
|
canFastReturnAll = false;
|
|
206
340
|
}
|
|
207
341
|
}
|
|
208
|
-
//
|
|
209
|
-
|
|
342
|
+
// P4: Self-reflection — if ALL tools failed, inject reflection before next turn
|
|
343
|
+
const allFailed = accumulatedResults.length > 0 && accumulatedResults.every(r => r.startsWith('Error') || r.includes('[System Error]') || r.includes('[Security Blocked]'));
|
|
344
|
+
if (allFailed) {
|
|
345
|
+
consecutiveToolErrors++;
|
|
346
|
+
const reflection = `[SELF-REFLECTION] All ${accumulatedResults.length} tool call(s) failed (attempt ${consecutiveToolErrors}). ` +
|
|
347
|
+
`Errors: ${accumulatedResults.join(' | ')}. ` +
|
|
348
|
+
`Analyze WHY each failed. Options: (1) retry with corrected params, (2) use alternative tool, (3) inform user clearly. ` +
|
|
349
|
+
`Do NOT repeat the exact same failed call.`;
|
|
350
|
+
exports.logger.addEntry({ role: 'system', content: reflection }, sessionId);
|
|
351
|
+
console.log(picocolors_1.default.magenta(`[Self-Reflection] Turn ${turnCount}: all tools failed, injecting reflection.`));
|
|
352
|
+
if (consecutiveToolErrors >= 2) {
|
|
353
|
+
const errorSummary = `⚠️ Unable to complete this request after multiple attempts.\n${accumulatedResults.join('\n')}`;
|
|
354
|
+
exports.logger.addEntry({ role: 'assistant', content: errorSummary }, sessionId);
|
|
355
|
+
return errorSummary;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
consecutiveToolErrors = 0;
|
|
360
|
+
}
|
|
361
|
+
// V2 Optimization: Zero-LLM Fast Return for transaction tools
|
|
210
362
|
if (canFastReturnAll && accumulatedResults.length > 0) {
|
|
211
363
|
const finalContent = accumulatedResults.join('\n\n---\n\n');
|
|
212
364
|
exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
|
|
@@ -229,3 +381,173 @@ async function processOsIntent(input, role = 'user', onProgress, sessionId) {
|
|
|
229
381
|
return errorMsg;
|
|
230
382
|
}
|
|
231
383
|
}
|
|
384
|
+
async function processOsIntentStream(input, onChunk, onProgress, sessionId) {
|
|
385
|
+
const config = (0, parser_1.loadConfig)();
|
|
386
|
+
exports.logger.addEntry({ role: 'user', content: input }, sessionId);
|
|
387
|
+
// --- MULTILINGUAL USER CORRECTION DETECTION ---
|
|
388
|
+
const correctionSignals = [
|
|
389
|
+
// ID
|
|
390
|
+
'salah', 'ngawur', 'keliru', 'bukan', 'tidak benar', 'perbaiki', 'coba lagi',
|
|
391
|
+
// EN
|
|
392
|
+
'wrong', 'incorrect', 'mistake', 'not right', 'false', 'bad', 'fix', 'try again',
|
|
393
|
+
// ES & FR
|
|
394
|
+
'incorrecto', 'mal', 'equivocado', 'error', 'falso', 'faux', 'erreur', 'mauvais',
|
|
395
|
+
// DE & RU
|
|
396
|
+
'falsch', 'inkorrekt', 'fehler', 'ошибка', 'неправильно', 'неверно',
|
|
397
|
+
// JP & ZH
|
|
398
|
+
'違う', '間違い', 'やり直して', '错误', '不对'
|
|
399
|
+
];
|
|
400
|
+
if (correctionSignals.some(s => input.toLowerCase().includes(s))) {
|
|
401
|
+
exports.logger.addEntry({
|
|
402
|
+
role: 'system',
|
|
403
|
+
content: `[USER CORRECTION DETECTED] The user indicated your previous answer was WRONG, STALE, or INACCURATE.
|
|
404
|
+
CRITICAL INSTRUCTIONS:
|
|
405
|
+
1. Do NOT just apologize and repeat the same data from your memory.
|
|
406
|
+
2. The data in your training memory or previous tool calls is likely stale/incorrect.
|
|
407
|
+
3. You MUST call a tool (like search_web or others) NOW to verify the facts with FRESH data.
|
|
408
|
+
4. Base your new answer strictly on the NEW tool results.`
|
|
409
|
+
}, sessionId);
|
|
410
|
+
}
|
|
411
|
+
const pluginTools = registry_1.pluginManager.getAllToolDefinitions();
|
|
412
|
+
let activeTools = [...pluginTools].filter(t => (0, skillManager_1.isSkillActive)(t.function.name));
|
|
413
|
+
const { sanitizeHistoryForLLM } = require('../utils/historySanitizer');
|
|
414
|
+
try {
|
|
415
|
+
let turnCount = 0;
|
|
416
|
+
const MAX_TURNS = 10;
|
|
417
|
+
let fullResponse = '';
|
|
418
|
+
let criticHasFiredStream = false; // Critic Pass hanya aktif 1x per request
|
|
419
|
+
while (turnCount < MAX_TURNS) {
|
|
420
|
+
turnCount++;
|
|
421
|
+
const currentHistory = exports.logger.getHistory(sessionId);
|
|
422
|
+
const sanitizedHistory = sanitizeHistoryForLLM(currentHistory, activeTools, config.llm.provider);
|
|
423
|
+
const messages = [
|
|
424
|
+
{ role: 'system', content: await getSystemPrompt('os', input) },
|
|
425
|
+
...sanitizedHistory
|
|
426
|
+
];
|
|
427
|
+
let streamedContent = '';
|
|
428
|
+
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) => {
|
|
430
|
+
streamedContent += chunk;
|
|
431
|
+
onChunk(chunk);
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
const responseMessage = response.message;
|
|
435
|
+
if (turnCount === 1)
|
|
436
|
+
tracker_1.Tracker.addMessage();
|
|
437
|
+
if (response.usage?.total_tokens)
|
|
438
|
+
tracker_1.Tracker.addTokens(response.usage.total_tokens, config.llm.provider);
|
|
439
|
+
tracker_1.Tracker.addEvent('llm.response', { provider: config.llm.provider, tool_calls: responseMessage.tool_calls?.length || 0 });
|
|
440
|
+
exports.logger.addEntry({
|
|
441
|
+
role: 'assistant',
|
|
442
|
+
content: responseMessage.content || '',
|
|
443
|
+
tool_calls: responseMessage.tool_calls,
|
|
444
|
+
}, sessionId);
|
|
445
|
+
if (!responseMessage.tool_calls || responseMessage.tool_calls.length === 0) {
|
|
446
|
+
let finalContent = responseMessage.content || 'No response generated.';
|
|
447
|
+
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 ---
|
|
478
|
+
fullResponse = finalContent;
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
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;
|
|
484
|
+
const accumulatedResults = [];
|
|
485
|
+
for (const _toolCall of responseMessage.tool_calls) {
|
|
486
|
+
const toolCall = _toolCall;
|
|
487
|
+
const toolName = toolCall.function.name;
|
|
488
|
+
let result = '';
|
|
489
|
+
let args = {};
|
|
490
|
+
console.log(picocolors_1.default.yellow(`[⚡ Tool Execution] AI is calling ${toolName}...`));
|
|
491
|
+
if (onProgress)
|
|
492
|
+
onProgress(`_⚡ Running tool: ${toolName}..._`);
|
|
493
|
+
try {
|
|
494
|
+
let argStr = toolCall.function.arguments;
|
|
495
|
+
if (argStr && !argStr.trim().endsWith('}'))
|
|
496
|
+
argStr += '}';
|
|
497
|
+
args = JSON.parse(argStr);
|
|
498
|
+
}
|
|
499
|
+
catch (parseError) {
|
|
500
|
+
result = `[System Error] Arguments for ${toolName} must be valid JSON. Error: ${parseError.message}`;
|
|
501
|
+
exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
if (!(0, skillManager_1.isSkillActive)(toolName)) {
|
|
505
|
+
result = `[System Error] Access denied: Skill '${toolName}' is currently disabled.`;
|
|
506
|
+
exports.logger.addEntry({ role: 'tool', tool_call_id: toolCall.id, content: result }, sessionId);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
const pluginResult = await registry_1.pluginManager.executeTool(toolName, args, { sessionId });
|
|
511
|
+
result = pluginResult !== null ? pluginResult : `Error: Tool ${toolName} is not implemented.`;
|
|
512
|
+
if (result.includes('[Security Blocked]') || result.startsWith('Error:')) {
|
|
513
|
+
console.log(picocolors_1.default.red(`[❌ Failed] Tool ${toolName} returned an error or was blocked.`));
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
console.log(picocolors_1.default.green(`[✅ Success] Tool ${toolName} executed successfully.`));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
catch (toolError) {
|
|
520
|
+
result = `Error executing ${toolName}: ${toolError.message}`;
|
|
521
|
+
console.error(picocolors_1.default.red(`[❌ Error Crash] Execution of ${toolName} failed: ${toolError.message}`));
|
|
522
|
+
}
|
|
523
|
+
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) {
|
|
529
|
+
const finalContent = accumulatedResults.join('\n\n---\n\n');
|
|
530
|
+
exports.logger.addEntry({ role: 'assistant', content: finalContent }, sessionId);
|
|
531
|
+
onChunk(finalContent);
|
|
532
|
+
fullResponse = finalContent;
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (!fullResponse) {
|
|
537
|
+
const maxTurnMsg = '⚠️ Reached maximum interaction limit (10 turns). Please be more specific.';
|
|
538
|
+
exports.logger.addEntry({ role: 'assistant', content: maxTurnMsg }, sessionId);
|
|
539
|
+
fullResponse = maxTurnMsg;
|
|
540
|
+
}
|
|
541
|
+
return fullResponse;
|
|
542
|
+
}
|
|
543
|
+
catch (error) {
|
|
544
|
+
console.error('LLM Stream Error:', error);
|
|
545
|
+
const status = error?.status || error?.response?.status;
|
|
546
|
+
let errorMsg = '⚠️ All models are temporarily rate-limited. Please try again in a few minutes.';
|
|
547
|
+
if (status === 400 || (error.message && error.message.toLowerCase().includes('invalid'))) {
|
|
548
|
+
errorMsg = '⚠️ Failed to parse instruction. Please describe your command more specifically.';
|
|
549
|
+
}
|
|
550
|
+
exports.logger.addEntry({ role: 'assistant', content: errorMsg }, sessionId);
|
|
551
|
+
return errorMsg;
|
|
552
|
+
}
|
|
553
|
+
}
|