fluxflow-cli 1.8.9 → 1.8.11
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/TOOLS.md +2 -0
- package/dist/fluxflow.js +405 -219
- package/package.json +1 -1
package/TOOLS.md
CHANGED
|
@@ -14,6 +14,7 @@ Flux Flow provides a robust set of tools that allow the AI to interact with the
|
|
|
14
14
|
| **View/Read Files** | ✅ | ❌ |
|
|
15
15
|
| **Write/Update Files** | ✅ | ❌ |
|
|
16
16
|
| **Execute Commands** | ✅ | ❌ |
|
|
17
|
+
| **Search Keyword** | ✅ | ❌ |
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
@@ -37,6 +38,7 @@ Flux Flow provides a robust set of tools that allow the AI to interact with the
|
|
|
37
38
|
- **`view_file`**: Reads the content of a file.
|
|
38
39
|
- **Native Multimodality**: Supports analyzing images (JPG, PNG, WEBP) and PDF documents. The tool automatically detects binary formats and encodes them for AI analysis.
|
|
39
40
|
- **Text Reading**: Supports specific line ranges (`start_line`, `end_line`) to manage context size efficiently.
|
|
41
|
+
- **`search_keyword`**: Performs a global project search for a specific string or keyword. Returns file paths and line numbers where matches are found, making it essential for navigation and impact analysis.
|
|
40
42
|
|
|
41
43
|
### ✍️ Code Editing
|
|
42
44
|
- **`write_file`**: Creates a new file or completely overwrites an existing one with new content.
|
package/dist/fluxflow.js
CHANGED
|
@@ -721,7 +721,7 @@ Prefer write_file tool to write code instead of chat by default.
|
|
|
721
721
|
- DEV & FILE TOOLS ARE NOT AVAILABLE IN FLOW MODE. If you need to access files, tell the user to switch to FLUX MODE (manually by user).`.trim()}
|
|
722
722
|
-----------------
|
|
723
723
|
|
|
724
|
-
Results will be provided in the next loop as: [TOOL_RESULT]: [content]
|
|
724
|
+
Results will be provided in the next loop as: [TOOL_RESULT]: [content] under <user> tag. Treat them as SYSTEM MESSAGES. True user messages will be prefixed as 'USER_PROMPT' by the system.
|
|
725
725
|
WHEN CALLING TOOLS, YOU **MUST** end your response with '[turn: continue]'. NEVER use '[turn: finish]' in the same turn as a tool call. After receiving the [TOOL_RESULT], acknowledge the output and verify if the goal is met; only then may you use '[turn: finish]', otherwise use '[turn: continue]'.
|
|
726
726
|
Do NOT over-use tools. Use them only when strictly necessary for the user's objective. You can stack multiple tool calls 1-by-1.
|
|
727
727
|
Distinguish clearly between tool discussion and execution. Use the 'tool:' prefix ONLY when calling a function. When discussing tools with the user, refer to them by name as nouns (e.g., 'write_file', 'list_files') to avoid accidental triggers and context bloat. Even in your <think> ... </think> tags, do not use the 'tool:' prefix when planning to select a tool.
|
|
@@ -2430,7 +2430,7 @@ var init_terminal = __esm({
|
|
|
2430
2430
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
2431
2431
|
import path16 from "path";
|
|
2432
2432
|
import fs16 from "fs";
|
|
2433
|
-
var client, TERMINATION_SIGNAL, signalTermination, detectToolCalls, initAI, getAIStream;
|
|
2433
|
+
var client, TERMINATION_SIGNAL, signalTermination, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
|
|
2434
2434
|
var init_ai = __esm({
|
|
2435
2435
|
"src/utils/ai.js"() {
|
|
2436
2436
|
init_prompts();
|
|
@@ -2446,6 +2446,138 @@ var init_ai = __esm({
|
|
|
2446
2446
|
signalTermination = () => {
|
|
2447
2447
|
TERMINATION_SIGNAL = true;
|
|
2448
2448
|
};
|
|
2449
|
+
getActiveToolContext = (text) => {
|
|
2450
|
+
const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
|
|
2451
|
+
let match;
|
|
2452
|
+
while ((match = toolRegex.exec(text)) !== null) {
|
|
2453
|
+
const startIdx = match.index + match[0].length - 1;
|
|
2454
|
+
let balance = 0;
|
|
2455
|
+
let inString = null;
|
|
2456
|
+
let isEscaped = false;
|
|
2457
|
+
let closed = false;
|
|
2458
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
2459
|
+
const char = text[i];
|
|
2460
|
+
if (!inString && (char === '"' || char === "'" || char === "`")) {
|
|
2461
|
+
inString = char;
|
|
2462
|
+
isEscaped = false;
|
|
2463
|
+
} else if (inString && char === inString && !isEscaped) {
|
|
2464
|
+
inString = null;
|
|
2465
|
+
}
|
|
2466
|
+
if (!inString) {
|
|
2467
|
+
if (char === "(") balance++;
|
|
2468
|
+
else if (char === ")") balance--;
|
|
2469
|
+
if (balance === 0) {
|
|
2470
|
+
closed = true;
|
|
2471
|
+
toolRegex.lastIndex = i + 1;
|
|
2472
|
+
break;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
if (char === "\\") isEscaped = !isEscaped;
|
|
2476
|
+
else isEscaped = false;
|
|
2477
|
+
}
|
|
2478
|
+
if (!closed) {
|
|
2479
|
+
return { inside: true, toolName: match[1], startIndex: match.index };
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
return { inside: false };
|
|
2483
|
+
};
|
|
2484
|
+
getContextSafeText = (text, stripThoughts = true) => {
|
|
2485
|
+
const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
|
|
2486
|
+
let result = "";
|
|
2487
|
+
let lastIdx = 0;
|
|
2488
|
+
let match;
|
|
2489
|
+
while ((match = toolRegex.exec(text)) !== null) {
|
|
2490
|
+
const before = text.substring(lastIdx, match.index);
|
|
2491
|
+
result += stripThoughts ? before.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "") : before;
|
|
2492
|
+
const startIdx = match.index + match[0].length - 1;
|
|
2493
|
+
let balance = 0;
|
|
2494
|
+
let inString = null;
|
|
2495
|
+
let isEscaped = false;
|
|
2496
|
+
let endIdx = -1;
|
|
2497
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
2498
|
+
const char = text[i];
|
|
2499
|
+
if (!inString && (char === '"' || char === "'" || char === "`")) {
|
|
2500
|
+
inString = char;
|
|
2501
|
+
isEscaped = false;
|
|
2502
|
+
} else if (inString && char === inString && !isEscaped) {
|
|
2503
|
+
inString = null;
|
|
2504
|
+
}
|
|
2505
|
+
if (!inString) {
|
|
2506
|
+
if (char === "(") balance++;
|
|
2507
|
+
else if (char === ")") balance--;
|
|
2508
|
+
if (balance === 0) {
|
|
2509
|
+
endIdx = i;
|
|
2510
|
+
break;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
if (char === "\\") isEscaped = !isEscaped;
|
|
2514
|
+
else isEscaped = false;
|
|
2515
|
+
}
|
|
2516
|
+
if (endIdx !== -1) {
|
|
2517
|
+
result += "tool:functions." + match[1] + "()";
|
|
2518
|
+
lastIdx = endIdx + 1;
|
|
2519
|
+
toolRegex.lastIndex = lastIdx;
|
|
2520
|
+
} else {
|
|
2521
|
+
result += "tool:functions." + match[1] + "(";
|
|
2522
|
+
lastIdx = text.length;
|
|
2523
|
+
break;
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
if (lastIdx < text.length) {
|
|
2527
|
+
result += stripThoughts ? text.substring(lastIdx).replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "") : text.substring(lastIdx);
|
|
2528
|
+
}
|
|
2529
|
+
return result;
|
|
2530
|
+
};
|
|
2531
|
+
contextSafeReplace = (text, regex, replacement) => {
|
|
2532
|
+
const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
|
|
2533
|
+
let result = "";
|
|
2534
|
+
let lastIdx = 0;
|
|
2535
|
+
let match;
|
|
2536
|
+
while ((match = toolRegex.exec(text)) !== null) {
|
|
2537
|
+
const before = text.substring(lastIdx, match.index);
|
|
2538
|
+
result += before.replace(regex, replacement);
|
|
2539
|
+
const startIdx = match.index + match[0].length - 1;
|
|
2540
|
+
let balance = 0;
|
|
2541
|
+
let inString = null;
|
|
2542
|
+
let isEscaped = false;
|
|
2543
|
+
let endIdx = -1;
|
|
2544
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
2545
|
+
const char = text[i];
|
|
2546
|
+
if (!inString && (char === '"' || char === "'" || char === "`")) {
|
|
2547
|
+
inString = char;
|
|
2548
|
+
isEscaped = false;
|
|
2549
|
+
} else if (inString && char === inString && !isEscaped) {
|
|
2550
|
+
inString = null;
|
|
2551
|
+
}
|
|
2552
|
+
if (!inString) {
|
|
2553
|
+
if (char === "(") balance++;
|
|
2554
|
+
else if (char === ")") balance--;
|
|
2555
|
+
if (balance === 0) {
|
|
2556
|
+
endIdx = i;
|
|
2557
|
+
break;
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
if (char === "\\") isEscaped = !isEscaped;
|
|
2561
|
+
else isEscaped = false;
|
|
2562
|
+
}
|
|
2563
|
+
if (endIdx !== -1) {
|
|
2564
|
+
result += text.substring(match.index, endIdx + 1);
|
|
2565
|
+
lastIdx = endIdx + 1;
|
|
2566
|
+
toolRegex.lastIndex = lastIdx;
|
|
2567
|
+
} else {
|
|
2568
|
+
result += text.substring(match.index);
|
|
2569
|
+
lastIdx = text.length;
|
|
2570
|
+
break;
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
if (lastIdx < text.length) {
|
|
2574
|
+
result += text.substring(lastIdx).replace(regex, replacement);
|
|
2575
|
+
}
|
|
2576
|
+
return result;
|
|
2577
|
+
};
|
|
2578
|
+
getSanitizedText = (text) => {
|
|
2579
|
+
return getContextSafeText(text, true);
|
|
2580
|
+
};
|
|
2449
2581
|
detectToolCalls = (text) => {
|
|
2450
2582
|
const results = [];
|
|
2451
2583
|
const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
|
|
@@ -2550,22 +2682,34 @@ var init_ai = __esm({
|
|
|
2550
2682
|
yield { type: "status", content: "Steering Hint Injected." };
|
|
2551
2683
|
}
|
|
2552
2684
|
}
|
|
2553
|
-
yield { type: "turn_reset", content: true };
|
|
2554
|
-
const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => {
|
|
2555
|
-
const parts = [{ text: msg.text }];
|
|
2556
|
-
if (msg.binaryPart) {
|
|
2557
|
-
parts.push(msg.binaryPart);
|
|
2558
|
-
}
|
|
2559
|
-
return {
|
|
2560
|
-
role: msg.role === "user" || msg.role === "system" ? "user" : "model",
|
|
2561
|
-
parts
|
|
2562
|
-
};
|
|
2563
|
-
});
|
|
2564
2685
|
let stream;
|
|
2565
2686
|
let success = false;
|
|
2566
2687
|
let retryCount = 0;
|
|
2567
|
-
|
|
2688
|
+
let turnText = "";
|
|
2689
|
+
let lastToolSniffed = null;
|
|
2690
|
+
let lastToolEventTime = null;
|
|
2691
|
+
let toolResults = [];
|
|
2692
|
+
let toolCallPointer = 0;
|
|
2693
|
+
let isThinkingLoop = false;
|
|
2694
|
+
let isInitialAttempt = true;
|
|
2695
|
+
let accumulatedContext = "";
|
|
2696
|
+
while (retryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
|
|
2568
2697
|
try {
|
|
2698
|
+
if (isInitialAttempt) {
|
|
2699
|
+
yield { type: "turn_reset", content: true };
|
|
2700
|
+
isInitialAttempt = false;
|
|
2701
|
+
accumulatedContext = "";
|
|
2702
|
+
}
|
|
2703
|
+
const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => {
|
|
2704
|
+
const parts = [{ text: msg.text }];
|
|
2705
|
+
if (msg.binaryPart) {
|
|
2706
|
+
parts.push(msg.binaryPart);
|
|
2707
|
+
}
|
|
2708
|
+
return {
|
|
2709
|
+
role: msg.role === "user" || msg.role === "system" ? "user" : "model",
|
|
2710
|
+
parts
|
|
2711
|
+
};
|
|
2712
|
+
});
|
|
2569
2713
|
if (!await checkQuota("agent", settings)) {
|
|
2570
2714
|
throw new Error("Error: Daily Quota Exausted for Agent");
|
|
2571
2715
|
}
|
|
@@ -2613,226 +2757,266 @@ var init_ai = __esm({
|
|
|
2613
2757
|
}
|
|
2614
2758
|
}
|
|
2615
2759
|
});
|
|
2616
|
-
|
|
2760
|
+
turnText = "";
|
|
2761
|
+
lastToolSniffed = null;
|
|
2762
|
+
lastToolEventTime = null;
|
|
2763
|
+
toolResults = [];
|
|
2764
|
+
toolCallPointer = 0;
|
|
2617
2765
|
yield { type: "model_update", content: null };
|
|
2618
2766
|
yield { type: "status", content: "Working..." };
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
const
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
`);
|
|
2627
|
-
if (retryCount < MAX_RETRIES) {
|
|
2628
|
-
retryCount++;
|
|
2629
|
-
const waitTime = Math.floor(Math.random() * (2e3 - 800 + 1)) + 800;
|
|
2630
|
-
yield { type: "status", content: `Retrying (${retryCount}/${MAX_RETRIES + 1})...` };
|
|
2631
|
-
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
2632
|
-
} else {
|
|
2633
|
-
throw new Error(`Model cannot be reached: ${errMsg}. (Failed ${MAX_RETRIES + 1} times)`);
|
|
2634
|
-
}
|
|
2635
|
-
}
|
|
2636
|
-
}
|
|
2637
|
-
let turnText = "";
|
|
2638
|
-
let lastToolSniffed = null;
|
|
2639
|
-
let lastToolEventTime = null;
|
|
2640
|
-
let toolResults = [];
|
|
2641
|
-
let toolCallPointer = 0;
|
|
2642
|
-
for await (const chunk of stream) {
|
|
2643
|
-
if (TERMINATION_SIGNAL) break;
|
|
2644
|
-
if (chunk.text) {
|
|
2645
|
-
turnText += chunk.text;
|
|
2646
|
-
yield { type: "text", content: chunk.text };
|
|
2647
|
-
if (turnText.includes("tool:functions.")) {
|
|
2648
|
-
if (!lastToolEventTime) lastToolEventTime = Date.now();
|
|
2649
|
-
const parts = turnText.split("tool:functions.");
|
|
2650
|
-
const potentialTool = parts[parts.length - 1].split("(")[0].trim();
|
|
2651
|
-
if (potentialTool && /^[a-z_]+$/.test(potentialTool) && potentialTool !== lastToolSniffed) {
|
|
2652
|
-
lastToolSniffed = potentialTool;
|
|
2653
|
-
yield { type: "status", content: `Working (${potentialTool})...` };
|
|
2767
|
+
let dedupeBuffer = "";
|
|
2768
|
+
let isDedupeActive = accumulatedContext.length > 0;
|
|
2769
|
+
for await (const chunk of stream) {
|
|
2770
|
+
if (TERMINATION_SIGNAL) {
|
|
2771
|
+
yield { type: "status", content: "Termination Signal Received." };
|
|
2772
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
2773
|
+
break;
|
|
2654
2774
|
}
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
while (allToolsFound.length > toolCallPointer) {
|
|
2672
|
-
const toolCall = allToolsFound[toolCallPointer];
|
|
2673
|
-
yield { type: "status", content: `Working (${toolCall.toolName})...` };
|
|
2674
|
-
let label = "";
|
|
2675
|
-
if (toolCall.toolName === "web_search") {
|
|
2676
|
-
const { query, limit = 10 } = parseArgs(toolCall.args);
|
|
2677
|
-
label = `\u{1F50D} SEARCHING: "${query}" (${limit})`.toUpperCase();
|
|
2678
|
-
} else if (toolCall.toolName === "web_scrape") {
|
|
2679
|
-
const url = parseArgs(toolCall.args).url || "...";
|
|
2680
|
-
label = `\u{1F4D6} READING SITE: ${url}`.toUpperCase();
|
|
2681
|
-
} else if (toolCall.toolName === "view_file") {
|
|
2682
|
-
const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
|
|
2683
|
-
const rawStart = StartLine || start_line;
|
|
2684
|
-
const rawEnd = EndLine || end_line;
|
|
2685
|
-
const sLine = parseInt(rawStart) || 1;
|
|
2686
|
-
const eLine = parseInt(rawEnd) || (rawStart ? sLine + 800 : 800);
|
|
2687
|
-
let totalLines = "...";
|
|
2688
|
-
let actualEndLine = eLine;
|
|
2689
|
-
try {
|
|
2690
|
-
const absPath = path16.resolve(process.cwd(), targetPath2);
|
|
2691
|
-
if (fs16.existsSync(absPath)) {
|
|
2692
|
-
const content = fs16.readFileSync(absPath, "utf8");
|
|
2693
|
-
const lines = content.split("\n").length;
|
|
2694
|
-
totalLines = lines;
|
|
2695
|
-
actualEndLine = Math.min(eLine, lines);
|
|
2775
|
+
if (chunk.text) {
|
|
2776
|
+
if (isDedupeActive) {
|
|
2777
|
+
dedupeBuffer += chunk.text;
|
|
2778
|
+
if (dedupeBuffer.length >= accumulatedContext.length) {
|
|
2779
|
+
if (dedupeBuffer.startsWith(accumulatedContext)) {
|
|
2780
|
+
const newText = dedupeBuffer.substring(accumulatedContext.length);
|
|
2781
|
+
if (newText) {
|
|
2782
|
+
turnText += newText;
|
|
2783
|
+
yield { type: "text", content: newText };
|
|
2784
|
+
}
|
|
2785
|
+
isDedupeActive = false;
|
|
2786
|
+
} else {
|
|
2787
|
+
turnText += dedupeBuffer;
|
|
2788
|
+
yield { type: "text", content: dedupeBuffer };
|
|
2789
|
+
isDedupeActive = false;
|
|
2790
|
+
}
|
|
2696
2791
|
}
|
|
2697
|
-
} catch (e) {
|
|
2698
|
-
}
|
|
2699
|
-
const pathLower = targetPath2.toLowerCase();
|
|
2700
|
-
const isPdf = pathLower.endsWith(".pdf");
|
|
2701
|
-
const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
|
|
2702
|
-
if (isPdf) {
|
|
2703
|
-
label = `\u{1F4C4} ANALYZING PDF: ${targetPath2}`.toUpperCase();
|
|
2704
|
-
} else if (isImage) {
|
|
2705
|
-
label = `\u{1F4F8} ANALYZING IMAGE: ${targetPath2}`.toUpperCase();
|
|
2706
2792
|
} else {
|
|
2707
|
-
|
|
2793
|
+
turnText += chunk.text;
|
|
2794
|
+
yield { type: "text", content: chunk.text };
|
|
2708
2795
|
}
|
|
2709
|
-
|
|
2710
|
-
const
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
const
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2796
|
+
const signalSafeText2 = getSanitizedText(turnText);
|
|
2797
|
+
const toolContext = getActiveToolContext(turnText);
|
|
2798
|
+
if (toolContext.inside) {
|
|
2799
|
+
if (!lastToolEventTime) lastToolEventTime = Date.now();
|
|
2800
|
+
const potentialTool = toolContext.toolName;
|
|
2801
|
+
if (potentialTool && /^[a-z_]+$/.test(potentialTool) && potentialTool !== lastToolSniffed) {
|
|
2802
|
+
lastToolSniffed = potentialTool;
|
|
2803
|
+
yield { type: "status", content: `Working (${potentialTool})...` };
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
const contextSafeText = getContextSafeText(turnText, false);
|
|
2807
|
+
const thinkBlocks = contextSafeText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
|
|
2808
|
+
const thinkContent = thinkBlocks.join("").trim();
|
|
2809
|
+
const sentences = thinkContent.split(/[.!?]\s+/);
|
|
2810
|
+
const uniqueSentences = new Set(sentences);
|
|
2811
|
+
const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
|
|
2812
|
+
const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
|
|
2813
|
+
let repetitionThreshold = 0.4;
|
|
2814
|
+
let isOverVerbose = wordCount > 2500;
|
|
2815
|
+
if (repetitionRatio > repetitionThreshold || isOverVerbose) {
|
|
2816
|
+
const reason = repetitionRatio > repetitionThreshold ? "Thinking Loop Detected" : "Rambling Detected";
|
|
2817
|
+
yield { type: "status", content: `${reason}. Re-centering...` };
|
|
2818
|
+
isThinkingLoop = true;
|
|
2819
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
2820
|
+
break;
|
|
2821
|
+
}
|
|
2822
|
+
const toolActionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
|
|
2823
|
+
const allToolsFound = detectToolCalls(toolActionableText);
|
|
2824
|
+
while (allToolsFound.length > toolCallPointer) {
|
|
2825
|
+
const toolCall = allToolsFound[toolCallPointer];
|
|
2826
|
+
yield { type: "status", content: `Working (${toolCall.toolName})...` };
|
|
2827
|
+
let label = "";
|
|
2828
|
+
if (toolCall.toolName === "web_search") {
|
|
2829
|
+
const { query, limit = 10 } = parseArgs(toolCall.args);
|
|
2830
|
+
label = `\u{1F50D} SEARCHING: "${query}" (${limit})`.toUpperCase();
|
|
2831
|
+
} else if (toolCall.toolName === "web_scrape") {
|
|
2832
|
+
const url = parseArgs(toolCall.args).url || "...";
|
|
2833
|
+
label = `\u{1F4D6} READING SITE: ${url}`.toUpperCase();
|
|
2834
|
+
} else if (toolCall.toolName === "view_file") {
|
|
2835
|
+
const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
|
|
2836
|
+
const rawStart = StartLine || start_line;
|
|
2837
|
+
const rawEnd = EndLine || end_line;
|
|
2838
|
+
const sLine = parseInt(rawStart) || 1;
|
|
2839
|
+
const eLine = parseInt(rawEnd) || (rawStart ? sLine + 800 : 800);
|
|
2840
|
+
let totalLines = "...";
|
|
2841
|
+
let actualEndLine = eLine;
|
|
2842
|
+
try {
|
|
2843
|
+
const absPath = path16.resolve(process.cwd(), targetPath2);
|
|
2844
|
+
if (fs16.existsSync(absPath)) {
|
|
2845
|
+
const content = fs16.readFileSync(absPath, "utf8");
|
|
2846
|
+
const lines = content.split("\n").length;
|
|
2847
|
+
totalLines = lines;
|
|
2848
|
+
actualEndLine = Math.min(eLine, lines);
|
|
2849
|
+
}
|
|
2850
|
+
} catch (e) {
|
|
2851
|
+
}
|
|
2852
|
+
const pathLower = targetPath2.toLowerCase();
|
|
2853
|
+
const isPdf = pathLower.endsWith(".pdf");
|
|
2854
|
+
const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
|
|
2855
|
+
if (isPdf) {
|
|
2856
|
+
label = `\u{1F4C4} ANALYZING PDF: ${targetPath2}`.toUpperCase();
|
|
2857
|
+
} else if (isImage) {
|
|
2858
|
+
label = `\u{1F4F8} ANALYZING IMAGE: ${targetPath2}`.toUpperCase();
|
|
2859
|
+
} else {
|
|
2860
|
+
label = `\u{1F4C4} READING FILE: ${targetPath2}. LINES ${sLine} - ${actualEndLine} FROM ${totalLines}`.toUpperCase();
|
|
2861
|
+
}
|
|
2862
|
+
} else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
|
|
2863
|
+
const action = toolCall.toolName === "list_files" ? "LISTING" : "DISCOVERING";
|
|
2864
|
+
label = `\u{1F4C2} ${action} DIRECTORY: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
|
|
2865
|
+
} else if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
|
|
2866
|
+
const action = toolCall.toolName === "write_file" ? "WRITING" : "PATCHING";
|
|
2867
|
+
label = `\u{1F4BE} ${action} FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
2868
|
+
} else if (toolCall.toolName === "write_pdf") {
|
|
2869
|
+
label = `\u{1F4D1} GENERATING PDF: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
2870
|
+
} else if (toolCall.toolName === "write_docx") {
|
|
2871
|
+
label = `\u{1F4DD} GENERATING DOCX: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
2872
|
+
} else if (toolCall.toolName === "write_pptx") {
|
|
2873
|
+
label = `\u{1F4CA} GENERATING PPTX: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
2874
|
+
} else if (toolCall.toolName === "search_keyword") {
|
|
2875
|
+
const { keyword } = parseArgs(toolCall.args);
|
|
2876
|
+
label = `\u{1F50E} SEARCHING KEYWORD: "${keyword}"`.toUpperCase();
|
|
2877
|
+
} else if (toolCall.toolName === "exec_command" || toolCall.toolName === "ask") {
|
|
2878
|
+
label = "";
|
|
2879
|
+
} else {
|
|
2880
|
+
label = `EXECUTING ${toolCall.toolName}`.toUpperCase();
|
|
2881
|
+
}
|
|
2882
|
+
if (label) {
|
|
2883
|
+
const boxWidth = Math.min(label.length + 4, 115);
|
|
2884
|
+
const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
|
|
2885
|
+
const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
|
|
2886
|
+
const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
|
|
2887
|
+
yield { type: "visual_feedback", content: `
|
|
2735
2888
|
|
|
2736
2889
|
${boxTop}
|
|
2737
2890
|
${boxMid}
|
|
2738
2891
|
${boxBottom}
|
|
2739
2892
|
` };
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2893
|
+
}
|
|
2894
|
+
if (toolCall.toolName === "exec_command") {
|
|
2895
|
+
const { command } = parseArgs(toolCall.args);
|
|
2896
|
+
if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
|
|
2897
|
+
const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
|
|
2898
|
+
const currentDrive = path16.resolve(process.cwd()).substring(0, 3).toLowerCase();
|
|
2899
|
+
const isViolating = riskyPatterns.some((pattern) => {
|
|
2900
|
+
if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
|
|
2901
|
+
const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
|
|
2902
|
+
return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
|
|
2903
|
+
}
|
|
2904
|
+
return pattern.test(command);
|
|
2905
|
+
});
|
|
2906
|
+
if (isViolating) {
|
|
2907
|
+
const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
|
|
2908
|
+
toolResults.push({ role: "user", text: `[TOOL_RESULT]: ERROR: ${denyMsg}` });
|
|
2909
|
+
yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
|
|
2910
|
+
toolCallPointer++;
|
|
2911
|
+
continue;
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
if (settings.onExecStart) settings.onExecStart(command || "Unknown");
|
|
2915
|
+
yield { type: "exec_start" };
|
|
2916
|
+
}
|
|
2917
|
+
const parsedArgs = parseArgs(toolCall.args);
|
|
2918
|
+
const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
|
|
2919
|
+
if (targetPath) {
|
|
2920
|
+
const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
|
|
2921
|
+
const absoluteTarget = path16.resolve(targetPath);
|
|
2922
|
+
const absoluteCwd = path16.resolve(process.cwd());
|
|
2923
|
+
if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
|
|
2924
|
+
const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
|
|
2925
|
+
toolResults.push({ role: "user", text: `[TOOL_RESULT]: ERROR: ${denyMsg}` });
|
|
2926
|
+
yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
|
|
2927
|
+
toolCallPointer++;
|
|
2928
|
+
continue;
|
|
2750
2929
|
}
|
|
2751
|
-
|
|
2930
|
+
}
|
|
2931
|
+
if (settings.onToolApproval) {
|
|
2932
|
+
let shouldPrompt = toolCall.toolName === "write_file" || toolCall.toolName === "update_file" || toolCall.toolName === "exec_command";
|
|
2933
|
+
if (shouldPrompt) {
|
|
2934
|
+
const approval = await settings.onToolApproval(toolCall.toolName, toolCall.args);
|
|
2935
|
+
if (approval === "deny") {
|
|
2936
|
+
if (toolCall.toolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
|
|
2937
|
+
const denyMsg = `Permission Denied: User rejected the ${toolCall.toolName === "exec_command" ? "terminal execution" : "file edit"}.`;
|
|
2938
|
+
toolResults.push({ role: "user", text: `[TOOL_RESULT]: ERROR: ${denyMsg}` });
|
|
2939
|
+
yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
|
|
2940
|
+
toolCallPointer++;
|
|
2941
|
+
continue;
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
const effectiveStart = lastToolEventTime || Date.now();
|
|
2946
|
+
let result = await dispatchTool(toolCall.toolName, toolCall.args, {
|
|
2947
|
+
chatId,
|
|
2948
|
+
history,
|
|
2949
|
+
onChunk: (chunk2) => settings.onExecChunk ? settings.onExecChunk(chunk2) : null,
|
|
2950
|
+
onAskUser: settings.onAskUser
|
|
2752
2951
|
});
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2952
|
+
const toolEnd = Date.now();
|
|
2953
|
+
yield { type: "tool_time", content: toolEnd - effectiveStart };
|
|
2954
|
+
lastToolEventTime = toolEnd;
|
|
2955
|
+
let binaryPart = null;
|
|
2956
|
+
if (typeof result === "object" && result.binaryPart) {
|
|
2957
|
+
binaryPart = result.binaryPart;
|
|
2958
|
+
result = result.text;
|
|
2759
2959
|
}
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
}
|
|
2778
|
-
if (settings.onToolApproval) {
|
|
2779
|
-
let shouldPrompt = toolCall.toolName === "write_file" || toolCall.toolName === "update_file" || toolCall.toolName === "exec_command";
|
|
2780
|
-
if (shouldPrompt) {
|
|
2781
|
-
const approval = await settings.onToolApproval(toolCall.toolName, toolCall.args);
|
|
2782
|
-
if (approval === "deny") {
|
|
2783
|
-
if (toolCall.toolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
|
|
2784
|
-
const denyMsg = `Permission Denied: User rejected the ${toolCall.toolName === "exec_command" ? "terminal execution" : "file edit"}.`;
|
|
2785
|
-
toolResults.push({ role: "user", text: `[TOOL_RESULT]: ERROR: ${denyMsg}` });
|
|
2786
|
-
yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
|
|
2787
|
-
toolCallPointer++;
|
|
2788
|
-
continue;
|
|
2960
|
+
if (toolCall.toolName === "exec_command" && settings.onExecEnd) {
|
|
2961
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
2962
|
+
settings.onExecEnd();
|
|
2963
|
+
}
|
|
2964
|
+
const isSuccess = result && !result.startsWith("ERROR:");
|
|
2965
|
+
if (isSuccess) {
|
|
2966
|
+
await incrementUsage("toolSuccess");
|
|
2967
|
+
if (settings.onToolResult) settings.onToolResult("success");
|
|
2968
|
+
} else {
|
|
2969
|
+
await incrementUsage("toolFailure");
|
|
2970
|
+
if (settings.onToolResult) settings.onToolResult("failure");
|
|
2971
|
+
}
|
|
2972
|
+
const aiContent = `[TOOL_RESULT]: ${result.split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
|
|
2973
|
+
toolResults.push({ role: "user", text: aiContent, binaryPart });
|
|
2974
|
+
let uiContent = `[TOOL_RESULT]: ${result}`;
|
|
2975
|
+
if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
|
|
2976
|
+
uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
|
|
2789
2977
|
}
|
|
2978
|
+
yield { type: "tool_result", content: uiContent, aiContent, binaryPart, toolName: toolCall.toolName };
|
|
2979
|
+
if (toolCall.toolName === "memory" && result.includes("SUCCESS")) yield { type: "memory_updated" };
|
|
2980
|
+
toolCallPointer++;
|
|
2790
2981
|
}
|
|
2791
2982
|
}
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
history,
|
|
2796
|
-
onChunk: (chunk2) => settings.onExecChunk ? settings.onExecChunk(chunk2) : null,
|
|
2797
|
-
onAskUser: settings.onAskUser
|
|
2798
|
-
});
|
|
2799
|
-
const toolEnd = Date.now();
|
|
2800
|
-
yield { type: "tool_time", content: toolEnd - effectiveStart };
|
|
2801
|
-
lastToolEventTime = toolEnd;
|
|
2802
|
-
let binaryPart = null;
|
|
2803
|
-
if (typeof result === "object" && result.binaryPart) {
|
|
2804
|
-
binaryPart = result.binaryPart;
|
|
2805
|
-
result = result.text;
|
|
2806
|
-
}
|
|
2807
|
-
if (toolCall.toolName === "exec_command" && settings.onExecEnd) {
|
|
2808
|
-
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
2809
|
-
settings.onExecEnd();
|
|
2983
|
+
lastUsage = chunk.usageMetadata;
|
|
2984
|
+
if (lastUsage) {
|
|
2985
|
+
yield { type: "liveTokens", content: lastUsage.totalTokenCount };
|
|
2810
2986
|
}
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2987
|
+
}
|
|
2988
|
+
if (TERMINATION_SIGNAL) break;
|
|
2989
|
+
success = true;
|
|
2990
|
+
await incrementUsage("agent");
|
|
2991
|
+
} catch (err) {
|
|
2992
|
+
const errMsg = err.status || err.error && err.error.message || String(err);
|
|
2993
|
+
const errLog = String(err);
|
|
2994
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2995
|
+
const agentErrDir = path16.join(LOGS_DIR, "agent");
|
|
2996
|
+
if (!fs16.existsSync(agentErrDir)) fs16.mkdirSync(agentErrDir, { recursive: true });
|
|
2997
|
+
fs16.appendFileSync(path16.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
|
|
2998
|
+
`);
|
|
2999
|
+
if (retryCount < MAX_RETRIES) {
|
|
3000
|
+
retryCount++;
|
|
3001
|
+
const waitTime = Math.floor(Math.random() * (2e3 - 800 + 1)) + 800;
|
|
3002
|
+
if (turnText.trim().length > 0) {
|
|
3003
|
+
modifiedHistory.push({ role: "agent", text: turnText });
|
|
3004
|
+
if (toolResults.length > 0) {
|
|
3005
|
+
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
3006
|
+
}
|
|
3007
|
+
modifiedHistory.push({ role: "user", text: "[SYSTEM] Response got cut for internal error, continue from checkpoint seamlessly and DON'T repeat what you already said!" });
|
|
3008
|
+
accumulatedContext += turnText;
|
|
3009
|
+
yield { type: "status", content: `Recovering & Continuing (${retryCount}/${MAX_RETRIES + 1})...` };
|
|
2815
3010
|
} else {
|
|
2816
|
-
|
|
2817
|
-
|
|
3011
|
+
isInitialAttempt = true;
|
|
3012
|
+
yield { type: "status", content: `Retrying (${retryCount}/${MAX_RETRIES + 1})...` };
|
|
2818
3013
|
}
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
|
|
2823
|
-
uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
|
|
2824
|
-
}
|
|
2825
|
-
yield { type: "tool_result", content: uiContent, aiContent, binaryPart, toolName: toolCall.toolName };
|
|
2826
|
-
if (toolCall.toolName === "memory" && result.includes("SUCCESS")) yield { type: "memory_updated" };
|
|
2827
|
-
toolCallPointer++;
|
|
3014
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
3015
|
+
} else {
|
|
3016
|
+
throw new Error(`Model cannot be reached: ${errMsg}. (Failed ${MAX_RETRIES + 1} times)`);
|
|
2828
3017
|
}
|
|
2829
3018
|
}
|
|
2830
|
-
lastUsage = chunk.usageMetadata;
|
|
2831
|
-
if (lastUsage) {
|
|
2832
|
-
yield { type: "liveTokens", content: lastUsage.totalTokenCount };
|
|
2833
|
-
}
|
|
2834
3019
|
}
|
|
2835
|
-
await incrementUsage("agent");
|
|
2836
3020
|
if (lastUsage) {
|
|
2837
3021
|
await addToUsage("tokens", lastUsage.totalTokenCount || 0);
|
|
2838
3022
|
yield { type: "usage", content: lastUsage };
|
|
@@ -2843,10 +3027,11 @@ ${boxBottom}
|
|
|
2843
3027
|
if (thinkMatch) {
|
|
2844
3028
|
textToProcess = turnText.replace(/<think>[\s\S]*?<\/think>/i, "");
|
|
2845
3029
|
}
|
|
2846
|
-
const
|
|
3030
|
+
const signalSafeText = getSanitizedText(turnText);
|
|
3031
|
+
const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText.toLowerCase());
|
|
2847
3032
|
const shouldContinue = toolCallPointer > 0;
|
|
2848
3033
|
yield { type: "status", content: "Working..." };
|
|
2849
|
-
const cleanedTurnText = turnText
|
|
3034
|
+
const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
|
|
2850
3035
|
let isActuallyFinished = hasFinish && !shouldContinue;
|
|
2851
3036
|
if (isActuallyFinished) {
|
|
2852
3037
|
yield { type: "status", content: "Finalizing..." };
|
|
@@ -2956,7 +3141,8 @@ ${timestamp}`;
|
|
|
2956
3141
|
if (toolResults.length > 0) {
|
|
2957
3142
|
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
2958
3143
|
} else {
|
|
2959
|
-
modifiedHistory.push({ role: "user", text:
|
|
3144
|
+
modifiedHistory.push({ role: "user", text: `[SYSTEM]: ${isThinkingLoop ? "OVER-THINKING " : ""}LOOP DETECTED by Internal System. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}` });
|
|
3145
|
+
isThinkingLoop = false;
|
|
2960
3146
|
}
|
|
2961
3147
|
}
|
|
2962
3148
|
yield { type: "status", content: null };
|
|
@@ -4641,7 +4827,7 @@ Selection: ${val}`,
|
|
|
4641
4827
|
}
|
|
4642
4828
|
));
|
|
4643
4829
|
case "approval":
|
|
4644
|
-
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u{
|
|
4830
|
+
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u{1F510} SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
|
|
4645
4831
|
const args = parseArgs(pendingApproval?.args || "{}");
|
|
4646
4832
|
const oldVal = args.TargetContent || args.content_to_replace || null;
|
|
4647
4833
|
const newVal = args.content || args.ReplacementContent || args.content_to_add || args.replacementContent || null;
|
|
@@ -4655,7 +4841,7 @@ Selection: ${val}`,
|
|
|
4655
4841
|
title: "Action Required",
|
|
4656
4842
|
items: [
|
|
4657
4843
|
{ label: "\u2705 Accept this time", value: "allow" },
|
|
4658
|
-
{ label: "\u{
|
|
4844
|
+
{ label: "\u{1F510} Accept for this session", value: "always" },
|
|
4659
4845
|
{ label: "\u274C Don't accept", value: "deny" }
|
|
4660
4846
|
],
|
|
4661
4847
|
onSelect: (item) => {
|
|
@@ -4731,7 +4917,7 @@ Selection: ${val}`,
|
|
|
4731
4917
|
}
|
|
4732
4918
|
);
|
|
4733
4919
|
case "terminalApproval":
|
|
4734
|
-
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u{
|
|
4920
|
+
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u{1F510} SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "Agent requested to run: ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
|
|
4735
4921
|
CommandMenu,
|
|
4736
4922
|
{
|
|
4737
4923
|
title: "Risk Assessment Required",
|
|
@@ -4869,8 +5055,8 @@ var init_app = __esm({
|
|
|
4869
5055
|
init_text();
|
|
4870
5056
|
SESSION_START_TIME = Date.now();
|
|
4871
5057
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
4872
|
-
versionFluxflow = "1.8.
|
|
4873
|
-
updatedOn = "2026-05-
|
|
5058
|
+
versionFluxflow = "1.8.11";
|
|
5059
|
+
updatedOn = "2026-05-09";
|
|
4874
5060
|
ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent already finished the task before your hint was consumed."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
|
|
4875
5061
|
CommandMenu,
|
|
4876
5062
|
{
|