fluxflow-cli 2.16.9 → 3.0.0
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/ARCHITECTURE.md +12 -0
- package/README.md +3 -0
- package/dist/fluxflow.js +564 -113
- package/package.json +2 -2
package/ARCHITECTURE.md
CHANGED
|
@@ -61,6 +61,18 @@ To maintain a fast, snappy UI while still performing complex data management, Fl
|
|
|
61
61
|
- **Behavior**: After the Main Agent finishes its loop, the entire context (User Prompt + Agent Raws) is sent to the Janitor model.
|
|
62
62
|
- **Headless Operation**: The Janitor is explicitly instructed to be a "silent background system process" with "no mouth." It *only* outputs valid tool calls (e.g., updating the chat title or saving a new user preference to the persistent memory vault).
|
|
63
63
|
|
|
64
|
+
## The Subagent System
|
|
65
|
+
|
|
66
|
+
Flux Flow provides a robust, multi-agent execution system to delegate sub-tasks and run parallel operations without blocking the main workflow:
|
|
67
|
+
|
|
68
|
+
- **Sync/Async Execution Modes**:
|
|
69
|
+
- **`invokeSync`**: Spawns a blocking subagent. The main loop waits for the subagent to complete its assignment before continuing. Best used for immediate, sequential task delegations.
|
|
70
|
+
- **`invoke`**: Spawns an asynchronous background subagent. The main agent receives a unique Task ID and can continue working or poll for progress asynchronously.
|
|
71
|
+
- **Isolated System Context**: Subagents operate independently and have no direct context of the main conversation chat. They only receive the custom system instructions and the specific task query assigned by the main agent.
|
|
72
|
+
- **Permanent Tool Suite**: Subagents are equipped with a permanent suite of 10 system tools (ReadFile, ReadFolder, FileMap, PatchFile, WriteFile, SearchKeyword, WritePDF, WriteDoc, WebSearch, and WebScrape), but are restricted from executing commands or prompt prompts (`Run`, `Ask`, and `Todo` are disabled for safety).
|
|
73
|
+
- **Silent Logging and Telemetry**: Background subagent operations are logged quietly and report status updates to the CLI's active subagents UI block.
|
|
74
|
+
- **Transaction-Safe Reversion**: All file modifications made by asynchronous background subagents are logged chronologically under the session's active transaction. This ensures that any subagent modifications can be fully reverted/undone by the user at any point.
|
|
75
|
+
|
|
64
76
|
## Data Persistence & Safety
|
|
65
77
|
|
|
66
78
|
- **High-Fidelity Lock**: Because both the UI and the Janitor model may attempt to write to the `history.json` file simultaneously, a Promise-based `WRITE_LOCK` (`src/utils/history.js`) is utilized. This prevents race conditions and ensures data integrity.
|
package/README.md
CHANGED
|
@@ -85,6 +85,9 @@ Security isn't an afterthought; it's a boundary.
|
|
|
85
85
|
### 🧹 **The Background Janitor**
|
|
86
86
|
While you move at high speed, the Janitor follows behind—refining session titles, compressing data, and ensuring your context window remains at absolute peak performance.
|
|
87
87
|
|
|
88
|
+
### 🤖 **Autonomous Subagent System**
|
|
89
|
+
Delegate complex tasks to subagents. Spawns blocking subagents (`invokeSync`) or asynchronous background subagents (`invoke`) with distinct telemetry and silent background logging. Built-in transaction-safe reversion logs all subagent changes under the active turn, preserving rollback security.
|
|
90
|
+
|
|
88
91
|
---
|
|
89
92
|
|
|
90
93
|
## 🛠️ Key Capabilities
|
package/dist/fluxflow.js
CHANGED
|
@@ -2846,7 +2846,7 @@ var init_text = __esm({
|
|
|
2846
2846
|
"GenerateImage": "GenerateImage"
|
|
2847
2847
|
};
|
|
2848
2848
|
REGEX_INITIAL_THINK = /<\/think>(\r?\n){2}/gi;
|
|
2849
|
-
REGEX_INITIAL_TOOL = /(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|\s*turn\s*:))/gi;
|
|
2849
|
+
REGEX_INITIAL_TOOL = /(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|agent:generalist|agent\.generalist|\s*turn\s*:))/gi;
|
|
2850
2850
|
REGEX_CLEAN_SIGNALS = /\[SYSTEM\][\s\S]*?\[\/SYSTEM\]|<(think|thought)>[\s\S]*?(?:<\/(think|thought)>|$)|\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)|\[TOOL RESULT\]:?\s*|^\s*(SUCCESS|ERROR):.*(\r?\n)?|\[\s*turn\s*:\s*(continue|finish)\s*\]|\[\[END\]\]|\[\s*turn\s*:?.*?$|\n\s*turn\s*:?.*?$|\[\s*$|\n\nResponded on .*|\n\n\[Prompted on: .*\]|@\[TerminalName:.*?, ProcessId:.*?\]/gmi;
|
|
2851
2851
|
REGEX_ARROWS_ALL = /(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)|(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)|(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)|(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)|(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi;
|
|
2852
2852
|
REGEX_TOOLS = /\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_docx|generate_image)\b/gi;
|
|
@@ -2854,14 +2854,22 @@ var init_text = __esm({
|
|
|
2854
2854
|
if (!text) return text;
|
|
2855
2855
|
let result = text.replace(REGEX_INITIAL_THINK, "</think>").replace(REGEX_INITIAL_TOOL, "");
|
|
2856
2856
|
const trigger = "tool:functions.";
|
|
2857
|
-
|
|
2857
|
+
const subagentTrigger = "agent:generalist.";
|
|
2858
|
+
if (result.toLowerCase().includes(trigger) || result.toLowerCase().includes(subagentTrigger)) {
|
|
2858
2859
|
while (true) {
|
|
2859
2860
|
const lowerResult = result.toLowerCase();
|
|
2860
2861
|
let triggerIdx = lowerResult.indexOf(trigger);
|
|
2861
|
-
|
|
2862
|
-
let
|
|
2862
|
+
let subagentIdx = lowerResult.indexOf(subagentTrigger);
|
|
2863
|
+
let currentTrigger = trigger;
|
|
2864
|
+
let triggerIdxToUse = triggerIdx;
|
|
2865
|
+
if (triggerIdx === -1 || subagentIdx !== -1 && subagentIdx < triggerIdx) {
|
|
2866
|
+
currentTrigger = subagentTrigger;
|
|
2867
|
+
triggerIdxToUse = subagentIdx;
|
|
2868
|
+
}
|
|
2869
|
+
if (triggerIdxToUse === -1) break;
|
|
2870
|
+
let startIdx = triggerIdxToUse;
|
|
2863
2871
|
let hasOuterBracket = false;
|
|
2864
|
-
let k =
|
|
2872
|
+
let k = triggerIdxToUse - 1;
|
|
2865
2873
|
while (k >= 0 && /\s/.test(result[k])) k--;
|
|
2866
2874
|
if (k >= 0 && result[k] === "[") {
|
|
2867
2875
|
startIdx = k;
|
|
@@ -2870,7 +2878,7 @@ var init_text = __esm({
|
|
|
2870
2878
|
let balance = 0;
|
|
2871
2879
|
let foundStart = false;
|
|
2872
2880
|
let inString = null;
|
|
2873
|
-
let j =
|
|
2881
|
+
let j = triggerIdxToUse;
|
|
2874
2882
|
while (j < result.length) {
|
|
2875
2883
|
const char = result[j];
|
|
2876
2884
|
if (!inString && (char === "'" || char === '"' || char === "`")) {
|
|
@@ -5116,7 +5124,13 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
|
|
|
5116
5124
|
5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
|
|
5117
5125
|
6. [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit
|
|
5118
5126
|
7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
|
|
5119
|
-
8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, NO Markdown IN ARRAY. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed. **EVERY TURN UPDATE POLICY
|
|
5127
|
+
8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, NO Markdown IN ARRAY. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed. **EVERY TURN UPDATE POLICY**
|
|
5128
|
+
|
|
5129
|
+
-- SUB AGENTS --
|
|
5130
|
+
IN NEW LINE, use when needed
|
|
5131
|
+
- Invocation Types: invoke (async, background worker for parallel tasks), invokeSync (sync, blocking main agent loop, usage: task delegation, repeatetive work)
|
|
5132
|
+
1. [agent:generalist.invocationType(title="...", task="...")]. Usage: delegate repeatative task or work in background, Task must me detailed, with file paths & required folder structure provided
|
|
5133
|
+
2. [agent:generalist.getProgress(id="...")]. Usage: Check progress of async subagent task, dont spam`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
|
|
5120
5134
|
1. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout
|
|
5121
5135
|
2. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document
|
|
5122
5136
|
- WORKSPACE TOOLS ARE NOT AVAILABLE IN FLOW`.trim()}
|
|
@@ -6559,15 +6573,17 @@ async function restoreWithRetry(change, tx, maxAttempts = 7) {
|
|
|
6559
6573
|
}
|
|
6560
6574
|
return false;
|
|
6561
6575
|
}
|
|
6562
|
-
var currentTransaction, RevertManager;
|
|
6576
|
+
var currentTransaction, lastChatId, RevertManager;
|
|
6563
6577
|
var init_revert = __esm({
|
|
6564
6578
|
"src/utils/revert.js"() {
|
|
6565
6579
|
init_paths();
|
|
6566
6580
|
init_crypto();
|
|
6567
6581
|
fs6.ensureDirSync(BACKUPS_DIR);
|
|
6568
6582
|
currentTransaction = null;
|
|
6583
|
+
lastChatId = null;
|
|
6569
6584
|
RevertManager = {
|
|
6570
6585
|
async startTransaction(chatId, promptText) {
|
|
6586
|
+
lastChatId = chatId;
|
|
6571
6587
|
currentTransaction = {
|
|
6572
6588
|
id: `tx_prompt_${Date.now()}`,
|
|
6573
6589
|
chatId,
|
|
@@ -6579,8 +6595,37 @@ var init_revert = __esm({
|
|
|
6579
6595
|
writeEncryptedJson(ACTIVE_TX_FILE, currentTransaction);
|
|
6580
6596
|
},
|
|
6581
6597
|
async recordFileChange(absolutePath, forcedContent = null) {
|
|
6582
|
-
if (!currentTransaction) return;
|
|
6583
6598
|
try {
|
|
6599
|
+
if (!currentTransaction) {
|
|
6600
|
+
if (lastChatId) {
|
|
6601
|
+
const ledger = readEncryptedJson(LEDGER_FILE, []);
|
|
6602
|
+
const lastTx = [...ledger].reverse().find((tx) => tx.chatId === lastChatId);
|
|
6603
|
+
if (lastTx) {
|
|
6604
|
+
const alreadyBackedUp2 = lastTx.changes.some((c) => c.filePath === absolutePath);
|
|
6605
|
+
if (alreadyBackedUp2) return;
|
|
6606
|
+
const fileExists2 = await fs6.pathExists(absolutePath);
|
|
6607
|
+
let type2 = fileExists2 || forcedContent ? "update" : "create";
|
|
6608
|
+
let backupFile2 = null;
|
|
6609
|
+
if (type2 === "update") {
|
|
6610
|
+
const fileName = path5.basename(absolutePath);
|
|
6611
|
+
backupFile2 = `${lastTx.id}_${fileName}.bak`;
|
|
6612
|
+
const chatBackupDir = path5.join(BACKUPS_DIR, lastTx.chatId);
|
|
6613
|
+
await fs6.ensureDir(chatBackupDir);
|
|
6614
|
+
const backupPath = path5.join(chatBackupDir, backupFile2);
|
|
6615
|
+
let content = forcedContent !== null ? forcedContent : await fs6.readFile(absolutePath, "utf8").catch(() => null);
|
|
6616
|
+
if (content !== null) {
|
|
6617
|
+
writeEncryptedJson(backupPath, { data: encryptAes(content) });
|
|
6618
|
+
} else {
|
|
6619
|
+
type2 = "create";
|
|
6620
|
+
backupFile2 = null;
|
|
6621
|
+
}
|
|
6622
|
+
}
|
|
6623
|
+
lastTx.changes.push({ filePath: absolutePath, type: type2, backupFile: backupFile2 });
|
|
6624
|
+
writeEncryptedJson(LEDGER_FILE, ledger);
|
|
6625
|
+
}
|
|
6626
|
+
}
|
|
6627
|
+
return;
|
|
6628
|
+
}
|
|
6584
6629
|
const alreadyBackedUp = currentTransaction.changes.some((c) => c.filePath === absolutePath);
|
|
6585
6630
|
if (alreadyBackedUp) return;
|
|
6586
6631
|
const fileExists = await fs6.pathExists(absolutePath);
|
|
@@ -8666,7 +8711,7 @@ var init_search_keyword = __esm({
|
|
|
8666
8711
|
const fileGroups = [];
|
|
8667
8712
|
let totalMatches = 0;
|
|
8668
8713
|
for (const result of settledResults) {
|
|
8669
|
-
if (!result) continue;
|
|
8714
|
+
if (!result || !result.matches) continue;
|
|
8670
8715
|
if (totalMatches >= maxMatches) break;
|
|
8671
8716
|
const remaining = maxMatches - totalMatches;
|
|
8672
8717
|
const trimmedMatches = result.matches.slice(0, remaining);
|
|
@@ -9462,6 +9507,193 @@ ${content}`;
|
|
|
9462
9507
|
}
|
|
9463
9508
|
});
|
|
9464
9509
|
|
|
9510
|
+
// src/tools/invokeSync.js
|
|
9511
|
+
var invokeSync;
|
|
9512
|
+
var init_invokeSync = __esm({
|
|
9513
|
+
"src/tools/invokeSync.js"() {
|
|
9514
|
+
init_arg_parser();
|
|
9515
|
+
invokeSync = async (args, context = {}) => {
|
|
9516
|
+
const { runSubagent: runSubagent2 } = await init_ai().then(() => ai_exports);
|
|
9517
|
+
const parsed = parseArgs(args);
|
|
9518
|
+
const task = parsed.task || parsed.instruction || parsed.prompt;
|
|
9519
|
+
const model = parsed.model || null;
|
|
9520
|
+
const toolsRaw = parsed.tools || null;
|
|
9521
|
+
if (!task) {
|
|
9522
|
+
return 'ERROR: Missing "task" argument for invokeSync.';
|
|
9523
|
+
}
|
|
9524
|
+
let allowedTools = null;
|
|
9525
|
+
if (toolsRaw) {
|
|
9526
|
+
try {
|
|
9527
|
+
let cleaned = toolsRaw.trim();
|
|
9528
|
+
if (cleaned.startsWith("[") && cleaned.endsWith("]")) {
|
|
9529
|
+
cleaned = cleaned.substring(1, cleaned.length - 1);
|
|
9530
|
+
}
|
|
9531
|
+
allowedTools = cleaned.split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
9532
|
+
} catch (e) {
|
|
9533
|
+
}
|
|
9534
|
+
}
|
|
9535
|
+
const title = parsed.title || task.substring(0, 30);
|
|
9536
|
+
try {
|
|
9537
|
+
if (context.onVisualFeedback) {
|
|
9538
|
+
context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title}`);
|
|
9539
|
+
}
|
|
9540
|
+
const result = await runSubagent2(task, context, model, allowedTools, 20);
|
|
9541
|
+
if (context.onVisualFeedback) {
|
|
9542
|
+
context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} [COMPLETED]
|
|
9543
|
+
`);
|
|
9544
|
+
}
|
|
9545
|
+
return result;
|
|
9546
|
+
} catch (err) {
|
|
9547
|
+
if (context.onVisualFeedback) {
|
|
9548
|
+
context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} [FAILED]
|
|
9549
|
+
`);
|
|
9550
|
+
}
|
|
9551
|
+
return `ERROR: Subagent execution failed: ${err.message}`;
|
|
9552
|
+
}
|
|
9553
|
+
};
|
|
9554
|
+
}
|
|
9555
|
+
});
|
|
9556
|
+
|
|
9557
|
+
// src/utils/subagent_state.js
|
|
9558
|
+
var subagentProgress;
|
|
9559
|
+
var init_subagent_state = __esm({
|
|
9560
|
+
"src/utils/subagent_state.js"() {
|
|
9561
|
+
subagentProgress = [];
|
|
9562
|
+
}
|
|
9563
|
+
});
|
|
9564
|
+
|
|
9565
|
+
// src/tools/invoke.js
|
|
9566
|
+
var invoke;
|
|
9567
|
+
var init_invoke = __esm({
|
|
9568
|
+
"src/tools/invoke.js"() {
|
|
9569
|
+
init_subagent_state();
|
|
9570
|
+
init_arg_parser();
|
|
9571
|
+
invoke = async (args, context = {}) => {
|
|
9572
|
+
const { runSubagent: runSubagent2 } = await init_ai().then(() => ai_exports);
|
|
9573
|
+
const parsed = parseArgs(args);
|
|
9574
|
+
const task = parsed.task || parsed.instruction || parsed.prompt;
|
|
9575
|
+
const model = parsed.model || null;
|
|
9576
|
+
const title = parsed.title || null;
|
|
9577
|
+
const toolsRaw = parsed.tools || null;
|
|
9578
|
+
if (!task) {
|
|
9579
|
+
return 'ERROR: Missing "task" argument for invoke.';
|
|
9580
|
+
}
|
|
9581
|
+
let allowedTools = null;
|
|
9582
|
+
if (toolsRaw) {
|
|
9583
|
+
try {
|
|
9584
|
+
let cleaned = toolsRaw.trim();
|
|
9585
|
+
if (cleaned.startsWith("[") && cleaned.endsWith("]")) {
|
|
9586
|
+
cleaned = cleaned.substring(1, cleaned.length - 1);
|
|
9587
|
+
}
|
|
9588
|
+
allowedTools = cleaned.split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
9589
|
+
} catch (e) {
|
|
9590
|
+
}
|
|
9591
|
+
}
|
|
9592
|
+
const taskId = `subagent-${Date.now()}-${Math.floor(Math.random() * 1e3)}`;
|
|
9593
|
+
const taskEntry = {
|
|
9594
|
+
id: taskId,
|
|
9595
|
+
title: title || task.substring(0, 30),
|
|
9596
|
+
task,
|
|
9597
|
+
status: "running",
|
|
9598
|
+
progress: []
|
|
9599
|
+
// Array of arrays containing logs for each turn
|
|
9600
|
+
};
|
|
9601
|
+
subagentProgress.push(taskEntry);
|
|
9602
|
+
if (context.onSubagentUpdate) {
|
|
9603
|
+
context.onSubagentUpdate();
|
|
9604
|
+
}
|
|
9605
|
+
let currentTurnLogs = [];
|
|
9606
|
+
const subagentContext = { ...context, onVisualFeedback: null };
|
|
9607
|
+
runSubagent2(task, subagentContext, model, allowedTools, 20, (logMessage) => {
|
|
9608
|
+
if (logMessage.startsWith("[Subagent Turn")) {
|
|
9609
|
+
if (currentTurnLogs.length > 0) {
|
|
9610
|
+
taskEntry.progress.push([...currentTurnLogs]);
|
|
9611
|
+
currentTurnLogs = [];
|
|
9612
|
+
}
|
|
9613
|
+
}
|
|
9614
|
+
if (logMessage.includes("[Executing Tool]")) {
|
|
9615
|
+
const m = logMessage.match(/\[Executing Tool\]\s*([a-zA-Z0-9_]+)/);
|
|
9616
|
+
if (m) {
|
|
9617
|
+
taskEntry.currentTool = m[1];
|
|
9618
|
+
}
|
|
9619
|
+
}
|
|
9620
|
+
let displayLog = logMessage;
|
|
9621
|
+
if (displayLog.startsWith("[Tool Result]")) {
|
|
9622
|
+
const lines = displayLog.split("\n");
|
|
9623
|
+
if (lines.length > 5) {
|
|
9624
|
+
displayLog = lines.slice(0, 4).join("\n") + "\n... [Content/Diff Truncated from Logs] ...";
|
|
9625
|
+
}
|
|
9626
|
+
}
|
|
9627
|
+
currentTurnLogs.push(displayLog);
|
|
9628
|
+
if (context.onSubagentUpdate) {
|
|
9629
|
+
context.onSubagentUpdate();
|
|
9630
|
+
}
|
|
9631
|
+
}).then((finalAnswer) => {
|
|
9632
|
+
currentTurnLogs.push(`[SUBAGENT SUCCESS] Final Answer:
|
|
9633
|
+
${finalAnswer}`);
|
|
9634
|
+
taskEntry.progress.push([...currentTurnLogs]);
|
|
9635
|
+
taskEntry.status = "completed";
|
|
9636
|
+
taskEntry.finalAnswer = finalAnswer;
|
|
9637
|
+
if (context.onSubagentUpdate) {
|
|
9638
|
+
context.onSubagentUpdate();
|
|
9639
|
+
}
|
|
9640
|
+
}).catch((err) => {
|
|
9641
|
+
currentTurnLogs.push(`[SUBAGENT FAILURE] Error: ${err.message}`);
|
|
9642
|
+
taskEntry.progress.push([...currentTurnLogs]);
|
|
9643
|
+
taskEntry.status = "failed";
|
|
9644
|
+
taskEntry.error = err.message;
|
|
9645
|
+
if (context.onSubagentUpdate) {
|
|
9646
|
+
context.onSubagentUpdate();
|
|
9647
|
+
}
|
|
9648
|
+
});
|
|
9649
|
+
return `SUCCESS: Background subagent started. Task ID: ${taskId}`;
|
|
9650
|
+
};
|
|
9651
|
+
}
|
|
9652
|
+
});
|
|
9653
|
+
|
|
9654
|
+
// src/tools/getProgress.js
|
|
9655
|
+
var getProgress;
|
|
9656
|
+
var init_getProgress = __esm({
|
|
9657
|
+
"src/tools/getProgress.js"() {
|
|
9658
|
+
init_subagent_state();
|
|
9659
|
+
init_arg_parser();
|
|
9660
|
+
getProgress = async (args, context = {}) => {
|
|
9661
|
+
const parsed = parseArgs(args);
|
|
9662
|
+
const id = parsed.id;
|
|
9663
|
+
if (!id) {
|
|
9664
|
+
return 'ERROR: Missing "id" argument for getProgress.';
|
|
9665
|
+
}
|
|
9666
|
+
const task = subagentProgress.find((t) => t.id === id);
|
|
9667
|
+
if (!task) {
|
|
9668
|
+
return `ERROR: Subagent task with ID [${id}] not found.`;
|
|
9669
|
+
}
|
|
9670
|
+
let output = `Subagent Task Status: ${task.status.toUpperCase()}
|
|
9671
|
+
`;
|
|
9672
|
+
output += `Title: ${task.title}
|
|
9673
|
+
`;
|
|
9674
|
+
output += `Task: ${task.task}
|
|
9675
|
+
|
|
9676
|
+
`;
|
|
9677
|
+
output += `Progress Log:
|
|
9678
|
+
`;
|
|
9679
|
+
task.progress.forEach((turnLogs, index) => {
|
|
9680
|
+
output += `--- Turn ${index + 1} ---
|
|
9681
|
+
`;
|
|
9682
|
+
output += turnLogs.join("\n") + "\n\n";
|
|
9683
|
+
});
|
|
9684
|
+
if (task.status === "completed" && task.finalAnswer) {
|
|
9685
|
+
output += `Final Answer:
|
|
9686
|
+
${task.finalAnswer}
|
|
9687
|
+
`;
|
|
9688
|
+
} else if (task.status === "failed" && task.error) {
|
|
9689
|
+
output += `Failure Error: ${task.error}
|
|
9690
|
+
`;
|
|
9691
|
+
}
|
|
9692
|
+
return output.trim();
|
|
9693
|
+
};
|
|
9694
|
+
}
|
|
9695
|
+
});
|
|
9696
|
+
|
|
9465
9697
|
// src/utils/tools.js
|
|
9466
9698
|
var TOOL_MAP, dispatchTool;
|
|
9467
9699
|
var init_tools = __esm({
|
|
@@ -9484,6 +9716,9 @@ var init_tools = __esm({
|
|
|
9484
9716
|
init_addMemScore();
|
|
9485
9717
|
init_file_map();
|
|
9486
9718
|
init_todo();
|
|
9719
|
+
init_invokeSync();
|
|
9720
|
+
init_invoke();
|
|
9721
|
+
init_getProgress();
|
|
9487
9722
|
TOOL_MAP = {
|
|
9488
9723
|
web_search,
|
|
9489
9724
|
web_scrape,
|
|
@@ -9502,6 +9737,11 @@ var init_tools = __esm({
|
|
|
9502
9737
|
addMemScore,
|
|
9503
9738
|
file_map,
|
|
9504
9739
|
todo,
|
|
9740
|
+
invokeSync,
|
|
9741
|
+
invoke,
|
|
9742
|
+
getProgress,
|
|
9743
|
+
invoke_sync: invokeSync,
|
|
9744
|
+
get_progress: getProgress,
|
|
9505
9745
|
ask: ask_user,
|
|
9506
9746
|
// PascalCase Normalizations for Token Efficiency
|
|
9507
9747
|
Ask: ask_user,
|
|
@@ -9527,7 +9767,10 @@ var init_tools = __esm({
|
|
|
9527
9767
|
AddMemoryScore: addMemScore,
|
|
9528
9768
|
FileMap: file_map,
|
|
9529
9769
|
Todo: todo,
|
|
9530
|
-
TODO: todo
|
|
9770
|
+
TODO: todo,
|
|
9771
|
+
InvokeSync: invokeSync,
|
|
9772
|
+
Invoke: invoke,
|
|
9773
|
+
GetProgress: getProgress
|
|
9531
9774
|
};
|
|
9532
9775
|
dispatchTool = async (toolName, args, context = {}) => {
|
|
9533
9776
|
const mode = context.mode ? context.mode.toLowerCase() : "flux";
|
|
@@ -9664,10 +9907,22 @@ var init_editor = __esm({
|
|
|
9664
9907
|
});
|
|
9665
9908
|
|
|
9666
9909
|
// src/utils/ai.js
|
|
9910
|
+
var ai_exports = {};
|
|
9911
|
+
__export(ai_exports, {
|
|
9912
|
+
compressHistory: () => compressHistory,
|
|
9913
|
+
deleteChatSummary: () => deleteChatSummary,
|
|
9914
|
+
getAIStream: () => getAIStream,
|
|
9915
|
+
getCleanGroupedLength: () => getCleanGroupedLength,
|
|
9916
|
+
initAI: () => initAI,
|
|
9917
|
+
isModelMultimodal: () => isModelMultimodal,
|
|
9918
|
+
runJanitorTask: () => runJanitorTask,
|
|
9919
|
+
runSubagent: () => runSubagent,
|
|
9920
|
+
signalTermination: () => signalTermination
|
|
9921
|
+
});
|
|
9667
9922
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
9668
9923
|
import path19 from "path";
|
|
9669
9924
|
import fs20 from "fs";
|
|
9670
|
-
var client, globalSettings, colorMainWords, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream;
|
|
9925
|
+
var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
|
|
9671
9926
|
var init_ai = __esm({
|
|
9672
9927
|
async "src/utils/ai.js"() {
|
|
9673
9928
|
await init_prompts();
|
|
@@ -9679,6 +9934,7 @@ var init_ai = __esm({
|
|
|
9679
9934
|
init_view_file();
|
|
9680
9935
|
init_terminal();
|
|
9681
9936
|
init_text();
|
|
9937
|
+
init_settings();
|
|
9682
9938
|
init_paths();
|
|
9683
9939
|
init_revert();
|
|
9684
9940
|
init_editor();
|
|
@@ -9686,10 +9942,39 @@ var init_ai = __esm({
|
|
|
9686
9942
|
globalSettings = {};
|
|
9687
9943
|
colorMainWords = (label2) => {
|
|
9688
9944
|
if (!label2) return label2;
|
|
9689
|
-
return label2.replace(/(?:(\x1b\[\d+m))?([✔✗✖🔍📖→➕↻•])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
|
|
9945
|
+
return label2.replace(/(?:(\x1b\[\d+m))?([✔✗✖🔍📖→➕↻•])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Elevating SubAgent|Checking SubAgent Work)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
|
|
9690
9946
|
return `${ansiBefore || ""}${icon}${ansiAfter || ""} \x1B[95m${word}\x1B[0m`;
|
|
9691
9947
|
});
|
|
9692
9948
|
};
|
|
9949
|
+
withRetry = async (fn, maxRetries = 8, initialDelayMs = 1e3, maxDelayMs = 8e3, signal = null) => {
|
|
9950
|
+
let attempt = 0;
|
|
9951
|
+
while (true) {
|
|
9952
|
+
if (signal?.aborted) {
|
|
9953
|
+
throw new DOMException("The user aborted a request.", "AbortError");
|
|
9954
|
+
}
|
|
9955
|
+
try {
|
|
9956
|
+
return await fn();
|
|
9957
|
+
} catch (error) {
|
|
9958
|
+
if (signal?.aborted || error?.name === "AbortError") {
|
|
9959
|
+
throw error;
|
|
9960
|
+
}
|
|
9961
|
+
attempt++;
|
|
9962
|
+
if (attempt >= maxRetries) {
|
|
9963
|
+
throw error;
|
|
9964
|
+
}
|
|
9965
|
+
const delay = Math.min(initialDelayMs * Math.pow(2, attempt - 1), maxDelayMs);
|
|
9966
|
+
await new Promise((resolve, reject) => {
|
|
9967
|
+
const timer = setTimeout(resolve, delay);
|
|
9968
|
+
if (signal) {
|
|
9969
|
+
signal.addEventListener("abort", () => {
|
|
9970
|
+
clearTimeout(timer);
|
|
9971
|
+
reject(new DOMException("The user aborted a request.", "AbortError"));
|
|
9972
|
+
});
|
|
9973
|
+
}
|
|
9974
|
+
});
|
|
9975
|
+
}
|
|
9976
|
+
}
|
|
9977
|
+
};
|
|
9693
9978
|
TERMINATION_SIGNAL = false;
|
|
9694
9979
|
MULTIMODAL_MODELS = [
|
|
9695
9980
|
// OpenRouter models
|
|
@@ -10242,11 +10527,21 @@ var init_ai = __esm({
|
|
|
10242
10527
|
"write_docx": "Creating",
|
|
10243
10528
|
"generate_image": "Generating",
|
|
10244
10529
|
"todo": "Planning",
|
|
10245
|
-
"Todo": "Planning"
|
|
10530
|
+
"Todo": "Planning",
|
|
10531
|
+
"invoke_sync": "Spawning SubAgent",
|
|
10532
|
+
"invoke": "Spawning SubAgent",
|
|
10533
|
+
"get_progress": "Checking SubAgent"
|
|
10246
10534
|
};
|
|
10247
10535
|
getToolDetail = (toolName, argsStr) => {
|
|
10248
10536
|
try {
|
|
10249
10537
|
const pArgs = parseArgs(argsStr);
|
|
10538
|
+
const normToolName = toolName.toLowerCase().replace(/_/g, "");
|
|
10539
|
+
if (normToolName === "invokesync" || normToolName === "invoke") {
|
|
10540
|
+
return pArgs.title || (pArgs.task ? pArgs.task.substring(0, 30) : null);
|
|
10541
|
+
}
|
|
10542
|
+
if (normToolName === "getprogress") {
|
|
10543
|
+
return pArgs.id || pArgs.taskId;
|
|
10544
|
+
}
|
|
10250
10545
|
const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
|
|
10251
10546
|
return filePath ? path19.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
|
|
10252
10547
|
} catch (e) {
|
|
@@ -10736,7 +11031,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
10736
11031
|
const translatedText = translateKimiToolCalls(text);
|
|
10737
11032
|
const cleanText = translatedText.replace(/(?:<(think|thought|thoughts)>|\[(think|thought|thoughts)\])[\s\S]*?(?:<\/(think|thought|thoughts)>|\[\/(think|thought|thoughts)\]|$)/gi, "");
|
|
10738
11033
|
const results = [];
|
|
10739
|
-
const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
|
|
11034
|
+
const toolRegex = /\[\s*(?:tool:functions\.|agent:generalist\.)([a-z0-9_]+)\s*\(/gi;
|
|
10740
11035
|
let match;
|
|
10741
11036
|
while ((match = toolRegex.exec(cleanText)) !== null) {
|
|
10742
11037
|
const toolName = match[1];
|
|
@@ -10795,39 +11090,61 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
10795
11090
|
client = new GoogleGenAI({ apiKey });
|
|
10796
11091
|
return client;
|
|
10797
11092
|
};
|
|
10798
|
-
generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75) => {
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
11093
|
+
generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75, usageKey = "agent") => {
|
|
11094
|
+
return withRetry(async () => {
|
|
11095
|
+
const { aiProvider = "Google", apiKey, mode } = settings;
|
|
11096
|
+
let fullText = "";
|
|
11097
|
+
let usageMetadata = null;
|
|
11098
|
+
const normalizedContents = typeof contents === "string" ? [{ role: "user", parts: [{ text: contents }] }] : contents;
|
|
11099
|
+
let stream;
|
|
11100
|
+
if (aiProvider === "OpenRouter") {
|
|
11101
|
+
stream = getOpenRouterStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
|
|
11102
|
+
} else if (aiProvider === "DeepSeek") {
|
|
11103
|
+
stream = getDeepSeekStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
|
|
11104
|
+
} else if (aiProvider === "NVIDIA") {
|
|
11105
|
+
stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
|
|
11106
|
+
} else {
|
|
11107
|
+
const genStream = await client.models.generateContentStream({
|
|
11108
|
+
model,
|
|
11109
|
+
contents: normalizedContents,
|
|
11110
|
+
config: {
|
|
11111
|
+
systemInstruction,
|
|
11112
|
+
temperature,
|
|
11113
|
+
thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL }
|
|
11114
|
+
}
|
|
11115
|
+
});
|
|
11116
|
+
stream = genStream;
|
|
11117
|
+
}
|
|
11118
|
+
for await (const chunk of stream) {
|
|
11119
|
+
if (chunk.candidates?.[0]?.content?.parts) {
|
|
11120
|
+
for (const part of chunk.candidates[0].content.parts) {
|
|
11121
|
+
if (part.text && !part.thought) fullText += part.text;
|
|
11122
|
+
}
|
|
10818
11123
|
}
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
11124
|
+
if (chunk.usageMetadata) usageMetadata = chunk.usageMetadata;
|
|
11125
|
+
}
|
|
11126
|
+
if (usageMetadata) {
|
|
11127
|
+
const total = usageMetadata.totalTokenCount || 0;
|
|
11128
|
+
const cached = usageMetadata.cachedContentTokenCount || 0;
|
|
11129
|
+
const candidates = (usageMetadata.candidatesTokenCount || 0) + (usageMetadata.thoughtsTokenCount || 0);
|
|
11130
|
+
await addToUsage("tokens", total, aiProvider, model);
|
|
11131
|
+
if (cached > 0) {
|
|
11132
|
+
await addToUsage("cachedTokens", cached, aiProvider, model);
|
|
11133
|
+
}
|
|
11134
|
+
if (candidates > 0) {
|
|
11135
|
+
await addToUsage("candidateTokens", candidates, aiProvider, model);
|
|
11136
|
+
}
|
|
11137
|
+
if (settings && typeof settings.onUsage === "function") {
|
|
11138
|
+
settings.onUsage({
|
|
11139
|
+
totalTokenCount: total,
|
|
11140
|
+
cachedContentTokenCount: cached,
|
|
11141
|
+
candidatesTokenCount: candidates
|
|
11142
|
+
});
|
|
10826
11143
|
}
|
|
10827
11144
|
}
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
|
|
11145
|
+
await incrementUsage(usageKey, aiProvider);
|
|
11146
|
+
return { text: fullText, usageMetadata };
|
|
11147
|
+
});
|
|
10831
11148
|
};
|
|
10832
11149
|
consolidatePastMemories = async (currentChatId, settings) => {
|
|
10833
11150
|
try {
|
|
@@ -10885,7 +11202,7 @@ ${newMemoryListStr}
|
|
|
10885
11202
|
while (attempts <= maxAttempts && !success) {
|
|
10886
11203
|
attempts++;
|
|
10887
11204
|
try {
|
|
10888
|
-
const response = await generateSimpleContent(settings, targetModel, prompt, null, "Fast");
|
|
11205
|
+
const response = await generateSimpleContent(settings, targetModel, prompt, null, "Fast", 0.75, "background");
|
|
10889
11206
|
const responseText = response.text || "";
|
|
10890
11207
|
const janitorToolCalls = detectToolCalls(responseText);
|
|
10891
11208
|
if (janitorToolCalls.length === 0) {
|
|
@@ -10897,19 +11214,6 @@ ${newMemoryListStr}
|
|
|
10897
11214
|
await dispatchTool(toolName, janitorToolCall.args, { chatId: currentChatId });
|
|
10898
11215
|
}
|
|
10899
11216
|
}
|
|
10900
|
-
if (response.usageMetadata) {
|
|
10901
|
-
const meta = response.usageMetadata;
|
|
10902
|
-
const total = meta.totalTokenCount || 0;
|
|
10903
|
-
const cached = meta.cachedContentTokenCount || 0;
|
|
10904
|
-
const candidates = (meta.candidatesTokenCount || 0) + (meta.thoughtsTokenCount || 0);
|
|
10905
|
-
await addToUsage("tokens", total, aiProvider, targetModel);
|
|
10906
|
-
if (cached > 0) {
|
|
10907
|
-
await addToUsage("cachedTokens", cached, aiProvider, targetModel);
|
|
10908
|
-
}
|
|
10909
|
-
if (candidates > 0) {
|
|
10910
|
-
await addToUsage("candidateTokens", candidates, aiProvider, targetModel);
|
|
10911
|
-
}
|
|
10912
|
-
}
|
|
10913
11217
|
success = true;
|
|
10914
11218
|
} catch (err) {
|
|
10915
11219
|
if (attempts >= maxAttempts) {
|
|
@@ -10969,19 +11273,6 @@ Provide a consolidated summary of the entire session.`;
|
|
|
10969
11273
|
attempts++;
|
|
10970
11274
|
try {
|
|
10971
11275
|
response = await generateSimpleContent(settings, targetModel, prompt, systemInstruction, "Fast");
|
|
10972
|
-
if (response && response.usageMetadata) {
|
|
10973
|
-
const meta = response.usageMetadata;
|
|
10974
|
-
const total = meta.totalTokenCount || 0;
|
|
10975
|
-
const cached = meta.cachedContentTokenCount || 0;
|
|
10976
|
-
const candidates = (meta.candidatesTokenCount || 0) + (meta.thoughtsTokenCount || 0);
|
|
10977
|
-
await addToUsage("tokens", total, aiProvider, targetModel);
|
|
10978
|
-
if (cached > 0) {
|
|
10979
|
-
await addToUsage("cachedTokens", cached, aiProvider, targetModel);
|
|
10980
|
-
}
|
|
10981
|
-
if (candidates > 0) {
|
|
10982
|
-
await addToUsage("candidateTokens", candidates, aiProvider, targetModel);
|
|
10983
|
-
}
|
|
10984
|
-
}
|
|
10985
11276
|
success = true;
|
|
10986
11277
|
} catch (err) {
|
|
10987
11278
|
if (attempts > 3) {
|
|
@@ -10989,19 +11280,6 @@ Provide a consolidated summary of the entire session.`;
|
|
|
10989
11280
|
try {
|
|
10990
11281
|
const fallbackModel = "gemini-3.1-flash-lite";
|
|
10991
11282
|
const fallback = await generateSimpleContent(settings, fallbackModel, prompt, systemInstruction, "Fast");
|
|
10992
|
-
if (fallback && fallback.usageMetadata) {
|
|
10993
|
-
const meta = fallback.usageMetadata;
|
|
10994
|
-
const total = meta.totalTokenCount || 0;
|
|
10995
|
-
const cached = meta.cachedContentTokenCount || 0;
|
|
10996
|
-
const candidates = (meta.candidatesTokenCount || 0) + (meta.thoughtsTokenCount || 0);
|
|
10997
|
-
await addToUsage("tokens", total, aiProvider, fallbackModel);
|
|
10998
|
-
if (cached > 0) {
|
|
10999
|
-
await addToUsage("cachedTokens", cached, aiProvider, fallbackModel);
|
|
11000
|
-
}
|
|
11001
|
-
if (candidates > 0) {
|
|
11002
|
-
await addToUsage("candidateTokens", candidates, aiProvider, fallbackModel);
|
|
11003
|
-
}
|
|
11004
|
-
}
|
|
11005
11283
|
return fallback.text || "";
|
|
11006
11284
|
} catch (e) {
|
|
11007
11285
|
return "";
|
|
@@ -12006,11 +12284,13 @@ ${ideErr} [/ERROR]`;
|
|
|
12006
12284
|
while (remaining.length > 0) {
|
|
12007
12285
|
if (!isBufferingToolCall) {
|
|
12008
12286
|
const toolIdx = remaining.indexOf("[tool");
|
|
12287
|
+
const agentIdx = remaining.indexOf("[agent");
|
|
12009
12288
|
const endIdx = remaining.indexOf("[[END]]");
|
|
12010
12289
|
const kimiSectionIdx = remaining.indexOf("<|tool_calls_section_begin|>");
|
|
12011
12290
|
const kimiCallIdx = remaining.indexOf("<|tool_call_begin|>");
|
|
12012
12291
|
const indices = [
|
|
12013
12292
|
{ type: "tool", idx: toolIdx, start: "[tool", end: "]" },
|
|
12293
|
+
{ type: "agent", idx: agentIdx, start: "[agent", end: "]" },
|
|
12014
12294
|
{ type: "end", idx: endIdx, start: "[[END]]", end: "[[END]]" },
|
|
12015
12295
|
{ type: "kimi_section", idx: kimiSectionIdx, start: "<|tool_calls_section_begin|>", end: "<|tool_calls_section_end|>" },
|
|
12016
12296
|
{ type: "kimi_call", idx: kimiCallIdx, start: "<|tool_call_begin|>", end: "<|tool_call_end|>" }
|
|
@@ -12025,7 +12305,7 @@ ${ideErr} [/ERROR]`;
|
|
|
12025
12305
|
toolCallBuffer = "";
|
|
12026
12306
|
remaining = remaining.substring(match2.idx);
|
|
12027
12307
|
} else {
|
|
12028
|
-
const potentialStarts = ["[tool", "[[END]]", "<|tool_calls_section_begin|>", "<|tool_call_begin|>"];
|
|
12308
|
+
const potentialStarts = ["[tool", "[agent", "[[END]]", "<|tool_calls_section_begin|>", "<|tool_call_begin|>"];
|
|
12029
12309
|
let splitPoint = -1;
|
|
12030
12310
|
for (const start of potentialStarts) {
|
|
12031
12311
|
for (let len = start.length - 1; len > 0; len--) {
|
|
@@ -12033,8 +12313,9 @@ ${ideErr} [/ERROR]`;
|
|
|
12033
12313
|
splitPoint = remaining.length - len;
|
|
12034
12314
|
const idx = potentialStarts.indexOf(start);
|
|
12035
12315
|
if (idx === 0) activeBufferType = "tool";
|
|
12036
|
-
else if (idx === 1) activeBufferType = "
|
|
12037
|
-
else if (idx === 2) activeBufferType = "
|
|
12316
|
+
else if (idx === 1) activeBufferType = "agent";
|
|
12317
|
+
else if (idx === 2) activeBufferType = "end";
|
|
12318
|
+
else if (idx === 3) activeBufferType = "kimi_section";
|
|
12038
12319
|
else activeBufferType = "kimi_call";
|
|
12039
12320
|
break;
|
|
12040
12321
|
}
|
|
@@ -12055,9 +12336,10 @@ ${ideErr} [/ERROR]`;
|
|
|
12055
12336
|
}
|
|
12056
12337
|
} else {
|
|
12057
12338
|
const combined = toolCallBuffer + remaining;
|
|
12058
|
-
if (activeBufferType === "tool") {
|
|
12059
|
-
const protocolPrefix = "[tool:functions.";
|
|
12060
|
-
|
|
12339
|
+
if (activeBufferType === "tool" || activeBufferType === "agent") {
|
|
12340
|
+
const protocolPrefix = activeBufferType === "tool" ? "[tool:functions." : "[agent:generalist.";
|
|
12341
|
+
const startPrefix = activeBufferType === "tool" ? "[tool" : "[agent";
|
|
12342
|
+
if (!combined.startsWith(startPrefix) || combined.length >= protocolPrefix.length && !combined.startsWith(protocolPrefix)) {
|
|
12061
12343
|
msgs.push({ type: "text", content: combined });
|
|
12062
12344
|
toolCallBuffer = "";
|
|
12063
12345
|
isBufferingToolCall = false;
|
|
@@ -12068,7 +12350,7 @@ ${ideErr} [/ERROR]`;
|
|
|
12068
12350
|
}
|
|
12069
12351
|
let endIdx = -1;
|
|
12070
12352
|
let endTag = "]";
|
|
12071
|
-
if (activeBufferType === "tool") {
|
|
12353
|
+
if (activeBufferType === "tool" || activeBufferType === "agent") {
|
|
12072
12354
|
let balance = 0;
|
|
12073
12355
|
let inString = null;
|
|
12074
12356
|
let bracketBalance = 0;
|
|
@@ -12226,7 +12508,6 @@ ${ideErr} [/ERROR]`;
|
|
|
12226
12508
|
const toolContext = getActiveToolContext(turnText);
|
|
12227
12509
|
if (toolContext.inside) {
|
|
12228
12510
|
if (!lastToolEventTime) lastToolEventTime = Date.now();
|
|
12229
|
-
const rawToolName = toolContext.toolName;
|
|
12230
12511
|
const NORMALIZE_MAP = {
|
|
12231
12512
|
"Ask": "ask",
|
|
12232
12513
|
"WebSearch": "web_search",
|
|
@@ -12245,24 +12526,39 @@ ${ideErr} [/ERROR]`;
|
|
|
12245
12526
|
"Chat": "chat",
|
|
12246
12527
|
"chat": "chat",
|
|
12247
12528
|
"GenerateImage": "generate_image",
|
|
12248
|
-
"generate_image": "generate_image"
|
|
12529
|
+
"generate_image": "generate_image",
|
|
12530
|
+
"todo": "todo",
|
|
12531
|
+
"Todo": "todo",
|
|
12532
|
+
"invoke": "invoke",
|
|
12533
|
+
"invokeSync": "invoke_sync",
|
|
12534
|
+
"getProgress": "get_progress"
|
|
12249
12535
|
};
|
|
12250
|
-
const potentialTool = NORMALIZE_MAP[
|
|
12536
|
+
const potentialTool = NORMALIZE_MAP[toolContext.toolName] || toolContext.toolName;
|
|
12251
12537
|
const partialArgs = toolContext.args || "";
|
|
12252
12538
|
let detail = null;
|
|
12253
|
-
if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image", "file_map"].includes(potentialTool)) {
|
|
12539
|
+
if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image", "file_map", "invoke", "invoke_sync", "get_progress"].includes(potentialTool)) {
|
|
12254
12540
|
const pArgs = parseArgs(partialArgs);
|
|
12255
12541
|
const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
|
|
12256
12542
|
const keyword = pArgs.keyword;
|
|
12543
|
+
const title = pArgs.title || pArgs.task;
|
|
12544
|
+
const id = pArgs.id || pArgs.taskId;
|
|
12257
12545
|
if (keyword) {
|
|
12258
12546
|
detail = keyword.replace(/["']/g, "");
|
|
12259
12547
|
} else if (filePath) {
|
|
12260
12548
|
detail = path19.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
|
|
12549
|
+
} else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
|
|
12550
|
+
detail = title.replace(/["']/g, "").substring(0, 30);
|
|
12551
|
+
} else if (id && potentialTool === "get_progress") {
|
|
12552
|
+
detail = id.replace(/["']/g, "");
|
|
12261
12553
|
} else {
|
|
12262
|
-
const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
|
|
12554
|
+
const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword|id|taskId|title|task)\s*=\s*\\?["']?([^\\"' \),]+)/);
|
|
12263
12555
|
if (m) {
|
|
12264
12556
|
const val = m[1].replace(/["']/g, "");
|
|
12265
|
-
|
|
12557
|
+
if (potentialTool === "invoke" || potentialTool === "invoke_sync" || potentialTool === "get_progress") {
|
|
12558
|
+
detail = val.substring(0, 30);
|
|
12559
|
+
} else {
|
|
12560
|
+
detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path19.basename(val.replace(/\\/g, "/"));
|
|
12561
|
+
}
|
|
12266
12562
|
}
|
|
12267
12563
|
}
|
|
12268
12564
|
}
|
|
@@ -12413,7 +12709,10 @@ ${ideErr} [/ERROR]`;
|
|
|
12413
12709
|
"GenerateImage": "generate_image",
|
|
12414
12710
|
"generate_image": "generate_image",
|
|
12415
12711
|
"todo": "todo",
|
|
12416
|
-
"Todo": "todo"
|
|
12712
|
+
"Todo": "todo",
|
|
12713
|
+
"invoke": "invoke",
|
|
12714
|
+
"invokeSync": "invoke_sync",
|
|
12715
|
+
"getProgress": "get_progress"
|
|
12417
12716
|
};
|
|
12418
12717
|
const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
|
|
12419
12718
|
const displayLabel = TOOL_LABELS2[normToolName] || toolCall.toolName;
|
|
@@ -12422,7 +12721,7 @@ ${ideErr} [/ERROR]`;
|
|
|
12422
12721
|
let label2 = "";
|
|
12423
12722
|
if (normToolName === "web_search") {
|
|
12424
12723
|
const { query, limit = 10 } = parseArgs(toolCall.args);
|
|
12425
|
-
label2 = `\u2714 Searched: ${query}`;
|
|
12724
|
+
label2 = `\u2714 Searched: ${query} \u2192 ${limit}`;
|
|
12426
12725
|
} else if (normToolName === "web_scrape") {
|
|
12427
12726
|
const url = parseArgs(toolCall.args).url || "...";
|
|
12428
12727
|
label2 = `\u2714 Visited: ${url}`;
|
|
@@ -12453,7 +12752,7 @@ ${ideErr} [/ERROR]`;
|
|
|
12453
12752
|
} else if (isImage) {
|
|
12454
12753
|
label2 = `\u2714 Viewed: ${targetPath2}`;
|
|
12455
12754
|
} else {
|
|
12456
|
-
label2 =
|
|
12755
|
+
label2 = `${totalLines !== "..." ? "\u2714" : "\u2717"} Read: ${targetPath2} \u2192 ${totalLines !== "..." ? `Lines ${sLine} - ${actualEndLine} of ${totalLines}` : "File Not Found"}`;
|
|
12457
12756
|
}
|
|
12458
12757
|
} else if (normToolName === "list_files" || normToolName === "read_folder") {
|
|
12459
12758
|
const action = normToolName === "list_files" ? "List" : "Viewed";
|
|
@@ -12473,7 +12772,13 @@ ${ideErr} [/ERROR]`;
|
|
|
12473
12772
|
} else if (normToolName.toLowerCase() === "generate_image") {
|
|
12474
12773
|
const { path: argPath, outputPath, output } = parseArgs(toolCall.args);
|
|
12475
12774
|
label2 = `\u2714 Generated: ${argPath || outputPath || output || "generated_image.png"}`;
|
|
12476
|
-
} else if (normToolName
|
|
12775
|
+
} else if (normToolName === "invoke_sync" || normToolName === "invoke") {
|
|
12776
|
+
const detail2 = getToolDetail(normToolName, toolCall.args);
|
|
12777
|
+
label2 = `\u2714 Elevating SubAgent${detail2 ? `: ${detail2}` : ""}`;
|
|
12778
|
+
} else if (normToolName === "get_progress") {
|
|
12779
|
+
const detail2 = getToolDetail(normToolName, toolCall.args);
|
|
12780
|
+
label2 = `\u2714 Checked${detail2 ? `: ${detail2}` : ""}`;
|
|
12781
|
+
} else if (normToolName === "exec_command" || normToolName === "ask") {
|
|
12477
12782
|
label2 = "";
|
|
12478
12783
|
} else {
|
|
12479
12784
|
label2 = `Executed: ${toolCall.toolName}`;
|
|
@@ -12994,7 +13299,7 @@ ${snippet2}
|
|
|
12994
13299
|
[SYSTEM] Check the content preview for verification [/SYSTEM]`;
|
|
12995
13300
|
}
|
|
12996
13301
|
const action = normToolName === "write_file" ? "Created" : "Edited";
|
|
12997
|
-
const feedbackLabel = `\u2714
|
|
13302
|
+
const feedbackLabel = `\u2714 ${action}: ${filePath || "..."}`;
|
|
12998
13303
|
let terminalWidth = 115;
|
|
12999
13304
|
if (process.stdout.isTTY) {
|
|
13000
13305
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -13028,7 +13333,7 @@ ${boxMid}`) };
|
|
|
13028
13333
|
}
|
|
13029
13334
|
if (normToolName === "write_file" || normToolName === "update_file") {
|
|
13030
13335
|
const action = normToolName === "write_file" ? "Write Cancelled" : "Edit Denied";
|
|
13031
|
-
const deniedLabel = `\
|
|
13336
|
+
const deniedLabel = `\u2717 ${action}: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
13032
13337
|
let terminalWidth = 115;
|
|
13033
13338
|
if (process.stdout.isTTY) {
|
|
13034
13339
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -13080,7 +13385,13 @@ ${boxBottom}`}`) };
|
|
|
13080
13385
|
onAskUser: settings.onAskUser,
|
|
13081
13386
|
systemSettings: settings.systemSettings,
|
|
13082
13387
|
mode,
|
|
13083
|
-
isMultiModal: isModelMultimodal(targetModel)
|
|
13388
|
+
isMultiModal: isModelMultimodal(targetModel),
|
|
13389
|
+
onVisualFeedback: settings.onVisualFeedback,
|
|
13390
|
+
onSubagentUpdate: settings.onSubagentUpdate,
|
|
13391
|
+
modelName: targetModel,
|
|
13392
|
+
aiProvider: settings.aiProvider,
|
|
13393
|
+
apiKey: settings.apiKey,
|
|
13394
|
+
onUsage: settings.onUsage
|
|
13084
13395
|
};
|
|
13085
13396
|
if (normToolName === "write_file" || normToolName === "update_file") {
|
|
13086
13397
|
try {
|
|
@@ -13134,7 +13445,8 @@ ${boxBottom}`}`) };
|
|
|
13134
13445
|
const boxMid = `${postLabel.padEnd(boxWidth - 2).substring(0, boxWidth - 2)}`;
|
|
13135
13446
|
const boxBottom = ` ${" ".repeat(boxWidth)} `;
|
|
13136
13447
|
yield { type: "visual_feedback", content: colorMainWords(`${boxBottom}
|
|
13137
|
-
${boxMid}
|
|
13448
|
+
${boxMid}
|
|
13449
|
+
`) };
|
|
13138
13450
|
}
|
|
13139
13451
|
if (normToolName === "todo") {
|
|
13140
13452
|
const { method, tasks, markDone } = parseArgs(toolCall.args);
|
|
@@ -13534,6 +13846,120 @@ Error Log can be found in ${path19.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
13534
13846
|
}
|
|
13535
13847
|
yield { type: "status", content: null };
|
|
13536
13848
|
};
|
|
13849
|
+
runSubagent = async (task, settings, model = null, allowedTools = null, maxTurns = 20, logCallback = null) => {
|
|
13850
|
+
const savedSettings = await loadSettings();
|
|
13851
|
+
const mergedSettings = { ...savedSettings, ...settings };
|
|
13852
|
+
const targetModel = model || settings?.modelName || settings?.activeModel || savedSettings.activeModel;
|
|
13853
|
+
const SUBAGENT_TOOL_DEFINITIONS = {
|
|
13854
|
+
"readfile": '- [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. View files, supports images/docs.',
|
|
13855
|
+
"readfolder": '- [tool:functions.ReadFolder(path="...")]. Detailed folder contents and stats.',
|
|
13856
|
+
"filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, classes, imports/exports.',
|
|
13857
|
+
"patchfile": '- [tool:functions.PatchFile(path="...", replaceContent1="...", newContent1="...")]. Surgical block replacement for editing files.',
|
|
13858
|
+
"writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates or overwrites a file.',
|
|
13859
|
+
"searchkeyword": '- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false")]. Global project text search.',
|
|
13860
|
+
"writepdf": '- [tool:functions.WritePDF(path="...", content="...", orientation="...")]. Generates PDF documents.',
|
|
13861
|
+
"writedoc": '- [tool:functions.WriteDoc(path="...", content="...")]. Generates Word documents.',
|
|
13862
|
+
"websearch": '- [tool:functions.WebSearch(query="...", limit=number)]. Web Search.',
|
|
13863
|
+
"webscrape": '- [tool:functions.WebScrape(url="...")]. Web Scrape.'
|
|
13864
|
+
};
|
|
13865
|
+
const providedToolsSection = `
|
|
13866
|
+
|
|
13867
|
+
-- Provided Tools --
|
|
13868
|
+
${Object.values(SUBAGENT_TOOL_DEFINITIONS).join("\n")}`;
|
|
13869
|
+
const systemInstruction = `You are a subagent helping the main FluxFlow CLI agent.
|
|
13870
|
+
Your task is: "${task}"
|
|
13871
|
+
You have access to the same tools as the main agent. Execute tools as needed using the [tool:functions.ToolName(args)] syntax${providedToolsSection}
|
|
13872
|
+
Your main focus should be on tools and task, not chatting. Your Chat won't be visible to user
|
|
13873
|
+
Once you have fully completed the task, provide a concise final structured summary preferebly in Tables/Bullet Points. Current Time: ${(/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: true }).replace(/(\d+)\/(\d+)\/(\d+),/, "$3-$1-$2").replace(":", "-")}`;
|
|
13874
|
+
const subagentHistory = [
|
|
13875
|
+
{ role: "user", text: `Please execute this task: ${task}` }
|
|
13876
|
+
];
|
|
13877
|
+
let turn = 0;
|
|
13878
|
+
let finalAnswer = "";
|
|
13879
|
+
while (turn < maxTurns) {
|
|
13880
|
+
const contents = subagentHistory.map((m) => ({
|
|
13881
|
+
role: m.role === "user" ? "user" : "model",
|
|
13882
|
+
parts: [{ text: m.text }]
|
|
13883
|
+
}));
|
|
13884
|
+
if (logCallback) logCallback(`[Subagent Turn ${turn + 1}] Invoking model ${targetModel}...`);
|
|
13885
|
+
const response = await generateSimpleContent(mergedSettings, targetModel, contents, systemInstruction, "Fast");
|
|
13886
|
+
const responseText = response.text || "";
|
|
13887
|
+
const cleanResponse = responseText.replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\])/gi, "").trim();
|
|
13888
|
+
finalAnswer = cleanResponse;
|
|
13889
|
+
if (logCallback) logCallback(`[Subagent Response]
|
|
13890
|
+
${cleanResponse}
|
|
13891
|
+
`);
|
|
13892
|
+
subagentHistory.push({ role: "agent", text: cleanResponse });
|
|
13893
|
+
const toolCalls = detectToolCalls(cleanResponse);
|
|
13894
|
+
if (toolCalls.length === 0) {
|
|
13895
|
+
break;
|
|
13896
|
+
}
|
|
13897
|
+
let toolResultsStr = "";
|
|
13898
|
+
for (const toolCall of toolCalls) {
|
|
13899
|
+
const normalizedToolName = toolCall.toolName.toLowerCase();
|
|
13900
|
+
const allowed = allowedTools ? allowedTools.some((t) => t.toLowerCase() === normalizedToolName) : true;
|
|
13901
|
+
if (!allowed) {
|
|
13902
|
+
const errorMsg = `ERROR: Tool [${toolCall.toolName}] is not in the allowed tools list for this subagent.`;
|
|
13903
|
+
if (logCallback) logCallback(`[Blocked Tool Call] ${toolCall.toolName} - not allowed
|
|
13904
|
+
`);
|
|
13905
|
+
toolResultsStr += `${errorMsg}
|
|
13906
|
+
|
|
13907
|
+
`;
|
|
13908
|
+
continue;
|
|
13909
|
+
}
|
|
13910
|
+
let label2 = "";
|
|
13911
|
+
if (normalizedToolName === "web_search") {
|
|
13912
|
+
const { query, limit = 10 } = parseArgs(toolCall.args);
|
|
13913
|
+
label2 = `\u2714 \x1B[95mSearched\x1B[0m: ${query} \u2192 ${limit}`;
|
|
13914
|
+
} else if (normalizedToolName === "web_scrape") {
|
|
13915
|
+
const url = parseArgs(toolCall.args).url || "...";
|
|
13916
|
+
label2 = `\u2714 \x1B[95mVisited\x1B[0m: ${url}`;
|
|
13917
|
+
} else if (normalizedToolName === "view_file") {
|
|
13918
|
+
const { path: targetPath } = parseArgs(toolCall.args);
|
|
13919
|
+
label2 = `\u2714 \x1B[95mRead\x1B[0m: ${targetPath}`;
|
|
13920
|
+
} else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder") {
|
|
13921
|
+
const path21 = parseArgs(toolCall.args).path || "...";
|
|
13922
|
+
label2 = `\u2714 \x1B[95mViewed\x1B[0m: ${path21}`;
|
|
13923
|
+
} else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
|
|
13924
|
+
const path21 = parseArgs(toolCall.args).path || "...";
|
|
13925
|
+
label2 = `\u2714 \x1B[95mCreated\x1B[0m: ${path21}`;
|
|
13926
|
+
} else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file") {
|
|
13927
|
+
const path21 = parseArgs(toolCall.args).path || "...";
|
|
13928
|
+
label2 = `\u2714 \x1B[95mEdited\x1B[0m: ${path21}`;
|
|
13929
|
+
} else if (normalizedToolName === "file_map") {
|
|
13930
|
+
const path21 = parseArgs(toolCall.args).path || "...";
|
|
13931
|
+
label2 = `\u2714 \x1B[95mGet Map\x1B[0m: ${path21}`;
|
|
13932
|
+
} else {
|
|
13933
|
+
const displayLabel = TOOL_LABELS2[normalizedToolName] || toolCall.toolName;
|
|
13934
|
+
const detail = getToolDetail(normalizedToolName, toolCall.args);
|
|
13935
|
+
label2 = `\u2714 \x1B[95m${displayLabel}\x1B[0m${detail ? `: ${detail}` : ""}`;
|
|
13936
|
+
}
|
|
13937
|
+
if (settings.onVisualFeedback && label2) {
|
|
13938
|
+
settings.onVisualFeedback(label2);
|
|
13939
|
+
}
|
|
13940
|
+
if (logCallback) logCallback(`[Executing Tool] ${toolCall.toolName}(${toolCall.args})...`);
|
|
13941
|
+
try {
|
|
13942
|
+
const result = await dispatchTool(toolCall.toolName, toolCall.args, { ...settings, mode: "Flux" });
|
|
13943
|
+
if (logCallback) logCallback(`[Tool Result]
|
|
13944
|
+
${result}
|
|
13945
|
+
`);
|
|
13946
|
+
toolResultsStr += `[TOOL RESULT for ${toolCall.toolName}]: ${result}
|
|
13947
|
+
|
|
13948
|
+
`;
|
|
13949
|
+
} catch (e) {
|
|
13950
|
+
const errorMsg = `ERROR: Execution failed for [${toolCall.toolName}]: ${e.message}`;
|
|
13951
|
+
if (logCallback) logCallback(`[Tool Error] ${errorMsg}
|
|
13952
|
+
`);
|
|
13953
|
+
toolResultsStr += `${errorMsg}
|
|
13954
|
+
|
|
13955
|
+
`;
|
|
13956
|
+
}
|
|
13957
|
+
}
|
|
13958
|
+
subagentHistory.push({ role: "user", text: toolResultsStr.trim() });
|
|
13959
|
+
turn++;
|
|
13960
|
+
}
|
|
13961
|
+
return finalAnswer;
|
|
13962
|
+
};
|
|
13537
13963
|
}
|
|
13538
13964
|
});
|
|
13539
13965
|
|
|
@@ -14743,6 +15169,7 @@ function App({ args = [] }) {
|
|
|
14743
15169
|
const [activeCommand, setActiveCommand] = useState14(null);
|
|
14744
15170
|
const [execOutput, setExecOutput] = useState14("");
|
|
14745
15171
|
const [isTerminalFocused, setIsTerminalFocused] = useState14(false);
|
|
15172
|
+
const [activeSubagents, setActiveSubagents] = useState14([]);
|
|
14746
15173
|
const [tick, setTick] = useState14(0);
|
|
14747
15174
|
const isFirstRender = useRef3(true);
|
|
14748
15175
|
const isSecondRender = useRef3(true);
|
|
@@ -15830,7 +16257,7 @@ function App({ args = [] }) {
|
|
|
15830
16257
|
// --- GLM (Zhipu AI) ---
|
|
15831
16258
|
{
|
|
15832
16259
|
cmd: "z-ai/glm-5.1",
|
|
15833
|
-
desc: "Text Only"
|
|
16260
|
+
desc: "Text Only [DEPRICATED]"
|
|
15834
16261
|
},
|
|
15835
16262
|
// --- MiniMax Family ---
|
|
15836
16263
|
{
|
|
@@ -16822,7 +17249,7 @@ ${timestamp}` };
|
|
|
16822
17249
|
id: "cancel-" + Date.now(),
|
|
16823
17250
|
role: "system",
|
|
16824
17251
|
text: "\n\n\x1B[33m\u24D8 Request Cancelled\x1B[0m",
|
|
16825
|
-
isMeta:
|
|
17252
|
+
isMeta: false
|
|
16826
17253
|
}];
|
|
16827
17254
|
setCompletedIndex(newMsgs.length);
|
|
16828
17255
|
return newMsgs;
|
|
@@ -16882,6 +17309,15 @@ ${timestamp}` };
|
|
|
16882
17309
|
apiTier,
|
|
16883
17310
|
cols: terminalSize.columns - 6,
|
|
16884
17311
|
rows: 30,
|
|
17312
|
+
onVisualFeedback: (content) => {
|
|
17313
|
+
setMessages((prev) => {
|
|
17314
|
+
const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
|
|
17315
|
+
return [...updatedPrev, { id: "visual-" + Date.now(), role: "system", text: content, isVisualFeedback: true }];
|
|
17316
|
+
});
|
|
17317
|
+
},
|
|
17318
|
+
onSubagentUpdate: () => {
|
|
17319
|
+
setActiveSubagents([...subagentProgress]);
|
|
17320
|
+
},
|
|
16885
17321
|
onExecStart: (cmd) => {
|
|
16886
17322
|
setActiveCommand(cmd);
|
|
16887
17323
|
setExecOutput("");
|
|
@@ -16977,6 +17413,20 @@ Selection: ${val}`,
|
|
|
16977
17413
|
});
|
|
16978
17414
|
setActiveView("ask");
|
|
16979
17415
|
});
|
|
17416
|
+
},
|
|
17417
|
+
onUsage: (usage) => {
|
|
17418
|
+
const total = usage.totalTokenCount || 0;
|
|
17419
|
+
const cached = usage.cachedContentTokenCount || 0;
|
|
17420
|
+
const candidates = usage.candidatesTokenCount || 0;
|
|
17421
|
+
setSessionStats({ tokens: total });
|
|
17422
|
+
setSessionTotalTokens((prev) => prev + total);
|
|
17423
|
+
if (cached > 0) {
|
|
17424
|
+
setSessionTotalCachedTokens((prev) => prev + cached);
|
|
17425
|
+
}
|
|
17426
|
+
if (candidates > 0) {
|
|
17427
|
+
setSessionTotalCandidateTokens((prev) => prev + candidates);
|
|
17428
|
+
}
|
|
17429
|
+
setSessionAgentCalls((prev) => prev + 1);
|
|
16980
17430
|
}
|
|
16981
17431
|
},
|
|
16982
17432
|
async () => {
|
|
@@ -17255,11 +17705,11 @@ Selection: ${val}`,
|
|
|
17255
17705
|
}
|
|
17256
17706
|
const chunkLower = chunkText.toLowerCase();
|
|
17257
17707
|
if (chunkText.includes("```")) inCodeBlock = !inCodeBlock;
|
|
17258
|
-
if (chunkLower.includes("tool:functions.")) {
|
|
17708
|
+
if (chunkLower.includes("tool:functions.") || chunkLower.includes("agent:generalist.")) {
|
|
17259
17709
|
inToolCall = true;
|
|
17260
17710
|
toolCallBalance = 0;
|
|
17261
17711
|
inToolCallString = null;
|
|
17262
|
-
if (chunkText.includes("[tool:functions.")) toolCallBalance = 0;
|
|
17712
|
+
if (chunkText.includes("[tool:functions.") || chunkText.includes("[agent:generalist.")) toolCallBalance = 0;
|
|
17263
17713
|
}
|
|
17264
17714
|
if (inToolCall) {
|
|
17265
17715
|
for (let j = 0; j < chunkText.length; j++) {
|
|
@@ -17351,7 +17801,7 @@ Selection: ${val}`,
|
|
|
17351
17801
|
});
|
|
17352
17802
|
} else if (!inThinkMode) {
|
|
17353
17803
|
const chunkLower2 = chunkText.toLowerCase();
|
|
17354
|
-
if (!toolCallEncounteredInTurn && chunkLower2.includes("tool:functions.")) {
|
|
17804
|
+
if (!toolCallEncounteredInTurn && (chunkLower2.includes("tool:functions.") || chunkLower2.includes("agent:generalist."))) {
|
|
17355
17805
|
toolCallEncounteredInTurn = true;
|
|
17356
17806
|
}
|
|
17357
17807
|
if (!currentAgentId) {
|
|
@@ -18433,7 +18883,7 @@ Selection: ${val}`,
|
|
|
18433
18883
|
}
|
|
18434
18884
|
)));
|
|
18435
18885
|
default:
|
|
18436
|
-
return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box14, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React15.createElement(Text15, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), /* @__PURE__ */ React15.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Box14, null, statusText ? /* @__PURE__ */ React15.createElement(Box14, { gap: 1 }, /* @__PURE__ */ React15.createElement(build_default, null), /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, italic: true }, statusText.trimEnd()), /* @__PURE__ */ React15.createElement(Text15, { color: "gray" }, activeTime > 0 ? `[${activeTime.toFixed(0)}s]` : "")) : /* @__PURE__ */ React15.createElement(Text15, { color: "white", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : hasPasteBlock ? "Press CTRL + O to expand" : "Waiting for input...")), /* @__PURE__ */ React15.createElement(Box14, null, wittyPhrase && /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Text15, { color: "gray", italic: true }, wittyPhrase), /* @__PURE__ */ React15.createElement(Text15, { color: "gray", dimColor: true }, " \u2503 ")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, tempModelOverride || activeModel))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Box14, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text15, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React15.createElement(
|
|
18886
|
+
return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box14, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React15.createElement(Text15, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), activeSubagents.filter((sa) => sa.status === "running").length > 0 && /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 0, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box14, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true }, "ACTIVE SUBAGENTS")), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1, width: "100%" }, activeSubagents.filter((sa) => sa.status === "running").map((sa) => /* @__PURE__ */ React15.createElement(Box14, { key: sa.id, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " \u2022 ", sa.title, " ", /* @__PURE__ */ React15.createElement(Text15, { color: "white", dimColor: true }, "(", sa.id, ")")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, "Executing: ", /* @__PURE__ */ React15.createElement(Text15, { color: "white", dimColor: true, bold: true }, sa.currentTool || "Active")))))), /* @__PURE__ */ React15.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Box14, null, statusText ? /* @__PURE__ */ React15.createElement(Box14, { gap: 1 }, /* @__PURE__ */ React15.createElement(build_default, null), /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, italic: true }, statusText.trimEnd()), /* @__PURE__ */ React15.createElement(Text15, { color: "gray" }, activeTime > 0 ? `[${activeTime.toFixed(0)}s]` : "")) : /* @__PURE__ */ React15.createElement(Text15, { color: "white", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : hasPasteBlock ? "Press CTRL + O to expand" : "Waiting for input...")), /* @__PURE__ */ React15.createElement(Box14, null, wittyPhrase && /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Text15, { color: "gray", italic: true }, wittyPhrase), /* @__PURE__ */ React15.createElement(Text15, { color: "gray", dimColor: true }, " \u2503 ")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, tempModelOverride || activeModel))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Box14, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text15, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React15.createElement(
|
|
18437
18887
|
Box14,
|
|
18438
18888
|
{
|
|
18439
18889
|
backgroundColor: "#555555",
|
|
@@ -18612,6 +19062,7 @@ var init_app = __esm({
|
|
|
18612
19062
|
init_AskUserModal();
|
|
18613
19063
|
init_secrets();
|
|
18614
19064
|
await init_ai();
|
|
19065
|
+
init_subagent_state();
|
|
18615
19066
|
init_settings();
|
|
18616
19067
|
init_history();
|
|
18617
19068
|
init_ResumeModal();
|
|
@@ -18751,7 +19202,7 @@ var init_app = __esm({
|
|
|
18751
19202
|
)));
|
|
18752
19203
|
parseAgentText = (text) => {
|
|
18753
19204
|
const blocks = [];
|
|
18754
|
-
const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
|
|
19205
|
+
const toolRegex = /\[\s*(?:tool:functions\.|agent:generalist\.)([a-z0-9_]+)\s*\(/gi;
|
|
18755
19206
|
let lastIdx = 0;
|
|
18756
19207
|
let match;
|
|
18757
19208
|
while ((match = toolRegex.exec(text)) !== null) {
|